Skip to content

Commit a2aaa83

Browse files
committed
feat(preact+landing): enable Preact block rendering + reusable landing page content system
## Preact Block Integration - Enable Preact component detection for data-driven pages: - Fix init.html to resolve sections_source + per-section ref before Preact detection - Correct resource paths: blox/* → js/hbx/blocks/* (Hugo module mounts) - Update libraries.html to load Preact core + compiled block scripts - Add dynamic icon rendering for Preact components: - Create Icon.jsx component with SVG decoding - Add get_icon_data.html partial for passing icon strings to Preact props - Update preact-wrapper.html to fetch icon data and inject into props - Wire hero component to render dynamic icons via <Icon svg={icon_svg} /> - Centralized logging system: - Add functions/logger.html to wrap warnf/errorf safely - Degrade to HTML comments in constrained contexts (content adapters) ## Reusable Landing Page Content System - Add sections_source support: - Page front matter: sections_source: pages/<key> loads base from data/pages/<key>.yaml - Inline sections deep-merge over base by position; extras appended - Add per-section ref system: - Any section: ref: blocks/<slug> loads from data/blocks/<slug>.yaml - Inline section properties deep-merge over ref (content/design submaps) - Enable content reuse across multiple landing pages - Create reusable block library: - Add test/data/blocks/: hero_basic.yaml, features_basic.yaml - Add test/content/linked/index.md demo using refs with overrides - Add pragmatic deep merge for content/design override handling ## Infrastructure & Schemas - Update base-block.json schema: - Fix gradient structure: flat → nested (gradient.start/end/direction) - Fix color structure: string|{light,dark} (matches parse_block_v3.html) - Update hero schema to properly extend base via $ref - Fix Tailwind source path generation: - Add tailwind_sources.html with test vs starter site logic - scripts/view-test.sh: export HUGO_BLOX_TEST_SITE=true - Update block directory structure: - blox/<name>/config.html (was blox/<name>--CONFIG.html) - Apply to init.html + parse_block_v2.html - Code quality improvements: - Biome config: match Prettier rules ## Content Adapters (Removed) - Investigated Hugo content adapters for landing pages - Found execution context limitations (early build phase, limited site methods) - Archived to backups/content-adapters-*.zip and removed from test site - Decision: use standard pages + data linking instead of adapters This enables dynamic Preact rendering with proper icon support while providing a flexible, reusable content system for landing pages that maintains the "single file = page" mental model with optional advanced linking.
1 parent 0c43c90 commit a2aaa83

53 files changed

Lines changed: 8825 additions & 5637 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,4 @@ pids
9494
tmp/
9595
temp/
9696
.tmp/
97+
backups/

.prettierignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Vendor directories
2+
_vendor/
3+
vendor/
4+
5+
# Generated directories
6+
public/
7+
resources/
8+
node_modules/
9+
10+
# We use go-template parser for HTML, but still ignore some specific files
11+
modules/blox-tailwind/assets/dist/
12+
13+
# JSON files with specific formats (although typically Biome now processes JSON)
14+
modules/blox-tailwind/layouts/index.json
15+
modules/blox-tailwind/layouts/index.webmanifest

.prettierrc.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module.exports = {
2+
bracketSpacing: false,
3+
singleQuote: false,
4+
jsxBracketSameLine: true,
5+
trailingComma: "all",
6+
printWidth: 150,
7+
overrides: [
8+
{
9+
files: ["*.html"],
10+
options: {
11+
parser: "go-template",
12+
},
13+
},
14+
{
15+
files: ["*.md"],
16+
options: {
17+
proseWrap: "preserve",
18+
},
19+
},
20+
],
21+
};

biome.json

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
"**/_vendor/**",
1313
"**/vendor/**",
1414
"**/*.html",
15+
"**/layouts/**/*.html",
16+
"**/layouts/**/*.htm",
1517
"**/*.webmanifest",
1618
"**/*.backlinks.json",
1719
"**/hugo_stats.json",
@@ -25,7 +27,22 @@
2527
},
2628
"formatter": {
2729
"enabled": true,
28-
"indentStyle": "space"
30+
"indentStyle": "space",
31+
"indentWidth": 2,
32+
"lineWidth": 150
33+
},
34+
"javascript": {
35+
"formatter": {
36+
"quoteStyle": "double",
37+
"trailingCommas": "all",
38+
"bracketSpacing": false
39+
},
40+
"globals": ["PagefindUI"]
41+
},
42+
"json": {
43+
"formatter": {
44+
"trailingCommas": "none"
45+
}
2946
},
3047
"linter": {
3148
"enabled": true,
@@ -40,8 +57,5 @@
4057
},
4158
"organizeImports": {
4259
"enabled": true
43-
},
44-
"javascript": {
45-
"globals": ["PagefindUI"]
4660
}
4761
}

hugo-blox-builder.code-workspace

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@
3838
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
3939
"[json]": { "editor.defaultFormatter": "biomejs.biome" },
4040
"[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
41-
"[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
41+
"[html]": {
42+
"editor.defaultFormatter": "esbenp.prettier-vscode",
43+
"editor.formatOnSave": true
44+
},
4245
"[markdown]": {
4346
"editor.defaultFormatter": "esbenp.prettier-vscode",
4447
"files.trimTrailingWhitespace": false
@@ -47,6 +50,12 @@
4750
"editor.tabSize": 4,
4851
"editor.insertSpaces": true
4952
},
53+
"[yaml]": {
54+
"editor.defaultFormatter": "esbenp.prettier-vscode"
55+
},
56+
"[toml]": {
57+
"editor.defaultFormatter": "esbenp.prettier-vscode"
58+
},
5059

5160
"eslint.workingDirectories": [{ "mode": "auto" }],
5261
"eslint.validate": [

modules/blox-tailwind/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,25 @@ hugo server --disableFastRender
6565
# Build for production
6666
hugo --minify
6767
```
68+
69+
## Vendor Libraries
70+
71+
The module includes several third-party vendor libraries that are distributed with the module. These are copied from node_modules to the assets/dist/lib directory during the build process.
72+
73+
To update the vendor libraries:
74+
75+
```bash
76+
# Update vendor libraries to the latest versions and rebuild
77+
pnpm vendor:update-and-build
78+
79+
# Just rebuild vendor libraries without updating versions
80+
pnpm vendor:libs
81+
```
82+
83+
The following libraries are included:
84+
- mermaid (diagrams)
85+
- plotly.js (interactive charts)
86+
- katex (math rendering)
87+
- markmap-autoloader (mind maps)
88+
- alpinejs (interactivity)
89+
- preact (interactive components)

modules/blox-tailwind/assets/css/config/safelist.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* Note: In v4, we use @source inline to ensure these are included */
33
/* This ensures Tailwind generates these classes even if not found in templates */
44

5+
/* Inline safelist for classes used in dynamic content and YAML configuration */
56
@source inline("<div class='block hidden dark:block dark:hidden'></div><div class='task-list'></div><div class='pl-4 pl-8 pl-12'></div><div class='min-h-screen'></div><div class='md:grid-cols-1 md:grid-cols-2 md:grid-cols-3 md:grid-cols-4 md:grid-cols-5 md:grid-cols-6'></div><div class='bg-white bg-gray-50 bg-gray-100 bg-gray-200 bg-gray-300 bg-gray-400 bg-gray-500 bg-gray-600 bg-gray-700 bg-gray-800 bg-gray-900'></div><div class='bg-neutral-50 bg-neutral-100 bg-neutral-200 bg-neutral-300 bg-neutral-400 bg-neutral-500 bg-neutral-600 bg-neutral-700 bg-neutral-800 bg-neutral-900'></div><div class='dark:bg-neutral-700 dark:bg-neutral-800 dark:bg-neutral-900'></div><div class='bg-primary-50 bg-primary-100 bg-primary-200 bg-primary-300 bg-primary-400 bg-primary-500 bg-primary-600 bg-primary-700 bg-primary-800 bg-primary-900'></div><div class='bg-secondary-50 bg-secondary-100 bg-secondary-200 bg-secondary-300 bg-secondary-400 bg-secondary-500 bg-secondary-600 bg-secondary-700 bg-secondary-800 bg-secondary-900'></div><div class='text-primary-50 text-primary-100 text-primary-200 text-primary-300 text-primary-400 text-primary-500 text-primary-600 text-primary-700 text-primary-800 text-primary-900'></div><div class='text-secondary-50 text-secondary-100 text-secondary-200 text-secondary-300 text-secondary-400 text-secondary-500 text-secondary-600 text-secondary-700 text-secondary-800 text-secondary-900'></div><div class='text-neutral-50 text-neutral-100 text-neutral-200 text-neutral-300 text-neutral-400 text-neutral-500 text-neutral-600 text-neutral-700 text-neutral-800 text-neutral-900'></div><div class='text-white text-black dark:text-white'></div><div class='dark:text-neutral-300 dark:text-neutral-400'></div><div class='border-primary-50 border-primary-100 border-primary-200 border-primary-300 border-primary-400 border-primary-500 border-primary-600 border-primary-700 border-primary-800 border-primary-900'></div><div class='border-secondary-50 border-secondary-100 border-secondary-200 border-secondary-300 border-secondary-400 border-secondary-500 border-secondary-600 border-secondary-700 border-secondary-800 border-secondary-900'></div><div class='border-neutral-50 border-neutral-100 border-neutral-200 border-neutral-300 border-neutral-400 border-neutral-500 border-neutral-600 border-neutral-700 border-neutral-800 border-neutral-900'></div><div class='bg-gradient-to-t bg-gradient-to-tr bg-gradient-to-r bg-gradient-to-br bg-gradient-to-b bg-gradient-to-bl bg-gradient-to-l bg-gradient-to-tl'></div><div class='from-primary-50 from-primary-100 from-primary-200 from-primary-300 from-primary-400 from-primary-500 from-primary-600 from-primary-700 from-primary-800 from-primary-900'></div><div class='from-secondary-50 from-secondary-100 from-secondary-200 from-secondary-300 from-secondary-400 from-secondary-500 from-secondary-600 from-secondary-700 from-secondary-800 from-secondary-900'></div><div class='to-primary-50 to-primary-100 to-primary-200 to-primary-300 to-primary-400 to-primary-500 to-primary-600 to-primary-700 to-primary-800 to-primary-900'></div><div class='to-secondary-50 to-secondary-100 to-secondary-200 to-secondary-300 to-secondary-400 to-secondary-500 to-secondary-600 to-secondary-700 to-secondary-800 to-secondary-900'></div><div class='hover:from-primary-500 hover:from-secondary-500 hover:to-primary-500 hover:to-secondary-500'></div><div class='hover:bg-primary-50 hover:bg-primary-100 hover:bg-primary-200 hover:bg-primary-300 hover:bg-primary-400 hover:bg-primary-500 hover:bg-primary-600 hover:bg-primary-700 hover:bg-primary-800 hover:bg-primary-900'></div><div class='hover:bg-neutral-50 hover:bg-neutral-100 hover:bg-neutral-200 hover:bg-neutral-300 hover:bg-neutral-400 hover:bg-neutral-500 hover:bg-neutral-600 hover:bg-neutral-700 hover:bg-neutral-800 hover:bg-neutral-900'></div><div class='hover:text-primary hover:text-primary-50 hover:text-primary-100 hover:text-primary-200 hover:text-primary-300 hover:text-primary-400 hover:text-primary-500 hover:text-primary-600 hover:text-primary-700 hover:text-primary-800 hover:text-primary-900'></div><div class='hover:text-neutral-50 hover:text-neutral-100 hover:text-neutral-200 hover:text-neutral-300 hover:text-neutral-400 hover:text-neutral-500 hover:text-neutral-600 hover:text-neutral-700 hover:text-neutral-800 hover:text-neutral-900'></div><div class='dark:hover:bg-primary-50 dark:hover:bg-primary-100 dark:hover:bg-primary-200 dark:hover:bg-primary-300 dark:hover:bg-primary-400 dark:hover:bg-primary-500 dark:hover:bg-primary-600 dark:hover:bg-primary-700 dark:hover:bg-primary-800 dark:hover:bg-primary-900'></div><div class='dark:hover:text-neutral-50 dark:hover:text-neutral-100 dark:hover:text-neutral-200 dark:hover:text-neutral-300 dark:hover:text-neutral-400 dark:hover:text-neutral-500 dark:hover:text-neutral-600 dark:hover:text-neutral-700 dark:hover:text-neutral-800 dark:hover:text-neutral-900'></div><div class='bg-indigo-50 bg-indigo-100 bg-indigo-200 bg-indigo-300 bg-indigo-400 bg-indigo-500 bg-indigo-600 bg-indigo-700 bg-indigo-800 bg-indigo-900 bg-indigo-950'></div><div class='bg-purple-50 bg-purple-100 bg-purple-200 bg-purple-300 bg-purple-400 bg-purple-500 bg-purple-600 bg-purple-700 bg-purple-800 bg-purple-900 bg-purple-950'></div><div class='bg-pink-50 bg-pink-100 bg-pink-200 bg-pink-300 bg-pink-400 bg-pink-500 bg-pink-600 bg-pink-700 bg-pink-800 bg-pink-900 bg-pink-950'></div><div class='bg-red-50 bg-red-100 bg-red-200 bg-red-300 bg-red-400 bg-red-500 bg-red-600 bg-red-700 bg-red-800 bg-red-900 bg-red-950'></div><div class='bg-orange-50 bg-orange-100 bg-orange-200 bg-orange-300 bg-orange-400 bg-orange-500 bg-orange-600 bg-orange-700 bg-orange-800 bg-orange-900 bg-orange-950'></div><div class='bg-amber-50 bg-amber-100 bg-amber-200 bg-amber-300 bg-amber-400 bg-amber-500 bg-amber-600 bg-amber-700 bg-amber-800 bg-amber-900 bg-amber-950'></div><div class='bg-yellow-50 bg-yellow-100 bg-yellow-200 bg-yellow-300 bg-yellow-400 bg-yellow-500 bg-yellow-600 bg-yellow-700 bg-yellow-800 bg-yellow-900 bg-yellow-950'></div><div class='bg-lime-50 bg-lime-100 bg-lime-200 bg-lime-300 bg-lime-400 bg-lime-500 bg-lime-600 bg-lime-700 bg-lime-800 bg-lime-900 bg-lime-950'></div><div class='bg-green-50 bg-green-100 bg-green-200 bg-green-300 bg-green-400 bg-green-500 bg-green-600 bg-green-700 bg-green-800 bg-green-900 bg-green-950'></div><div class='bg-emerald-50 bg-emerald-100 bg-emerald-200 bg-emerald-300 bg-emerald-400 bg-emerald-500 bg-emerald-600 bg-emerald-700 bg-emerald-800 bg-emerald-900 bg-emerald-950'></div><div class='bg-teal-50 bg-teal-100 bg-teal-200 bg-teal-300 bg-teal-400 bg-teal-500 bg-teal-600 bg-teal-700 bg-teal-800 bg-teal-900 bg-teal-950'></div><div class='bg-cyan-50 bg-cyan-100 bg-cyan-200 bg-cyan-300 bg-cyan-400 bg-cyan-500 bg-cyan-600 bg-cyan-700 bg-cyan-800 bg-cyan-900 bg-cyan-950'></div><div class='bg-sky-50 bg-sky-100 bg-sky-200 bg-sky-300 bg-sky-400 bg-sky-500 bg-sky-600 bg-sky-700 bg-sky-800 bg-sky-900 bg-sky-950'></div><div class='bg-blue-50 bg-blue-100 bg-blue-200 bg-blue-300 bg-blue-400 bg-blue-500 bg-blue-600 bg-blue-700 bg-blue-800 bg-blue-900 bg-blue-950'></div><div class='bg-violet-50 bg-violet-100 bg-violet-200 bg-violet-300 bg-violet-400 bg-violet-500 bg-violet-600 bg-violet-700 bg-violet-800 bg-violet-900 bg-violet-950'></div><div class='from-indigo-950 from-purple-900 to-indigo-950 to-purple-900'></div>");
67

78
/* Force generation of all CSS custom properties for dynamic usage in YAML front matter */

modules/blox-tailwind/assets/css/main.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
/* Tailwind CSS v4 Base */
1414
@import "tailwindcss";
1515

16+
/* Dynamic sources are injected by the css.html partial */
17+
/* This handles both monorepo dev and end-user environments */
18+
1619
/* Configuration */
1720
@import "config/tailwind.css";
1821
@import "config/theme.css";

0 commit comments

Comments
 (0)