mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-04 12:13:01 +00:00
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.
This commit is contained in:
1 parent
0c43c902ce
commit
a2aaa838c0
53 files changed
+9341
-6153
No files matched your search
@@ -94,3 +94,4 @@ pids
|
||||
tmp/
|
||||
temp/
|
||||
.tmp/
|
||||
backups/
|
||||
@@ -0,0 +1,15 @@
|
||||
# Vendor directories
|
||||
_vendor/
|
||||
vendor/
|
||||
|
||||
# Generated directories
|
||||
public/
|
||||
resources/
|
||||
node_modules/
|
||||
|
||||
# We use go-template parser for HTML, but still ignore some specific files
|
||||
modules/blox-tailwind/assets/dist/
|
||||
|
||||
# JSON files with specific formats (although typically Biome now processes JSON)
|
||||
modules/blox-tailwind/layouts/index.json
|
||||
modules/blox-tailwind/layouts/index.webmanifest
|
||||
@@ -0,0 +1,21 @@
|
||||
module.exports = {
|
||||
bracketSpacing: false,
|
||||
singleQuote: false,
|
||||
jsxBracketSameLine: true,
|
||||
trailingComma: "all",
|
||||
printWidth: 150,
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.html"],
|
||||
options: {
|
||||
parser: "go-template",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["*.md"],
|
||||
options: {
|
||||
proseWrap: "preserve",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
+18
-4
@@ -12,6 +12,8 @@
|
||||
"**/_vendor/**",
|
||||
"**/vendor/**",
|
||||
"**/*.html",
|
||||
"**/layouts/**/*.html",
|
||||
"**/layouts/**/*.htm",
|
||||
"**/*.webmanifest",
|
||||
"**/*.backlinks.json",
|
||||
"**/hugo_stats.json",
|
||||
@@ -25,7 +27,22 @@
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "space"
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 150
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "double",
|
||||
"trailingCommas": "all",
|
||||
"bracketSpacing": false
|
||||
},
|
||||
"globals": ["PagefindUI"]
|
||||
},
|
||||
"json": {
|
||||
"formatter": {
|
||||
"trailingCommas": "none"
|
||||
}
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
@@ -40,8 +57,5 @@
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"javascript": {
|
||||
"globals": ["PagefindUI"]
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,10 @@
|
||||
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
|
||||
"[json]": { "editor.defaultFormatter": "biomejs.biome" },
|
||||
"[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||
"[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"files.trimTrailingWhitespace": false
|
||||
@@ -47,6 +50,12 @@
|
||||
"editor.tabSize": 4,
|
||||
"editor.insertSpaces": true
|
||||
},
|
||||
"[yaml]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[toml]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
|
||||
"eslint.workingDirectories": [{ "mode": "auto" }],
|
||||
"eslint.validate": [
|
||||
|
||||
@@ -65,3 +65,25 @@ hugo server --disableFastRender
|
||||
# Build for production
|
||||
hugo --minify
|
||||
```
|
||||
|
||||
## Vendor Libraries
|
||||
|
||||
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.
|
||||
|
||||
To update the vendor libraries:
|
||||
|
||||
```bash
|
||||
# Update vendor libraries to the latest versions and rebuild
|
||||
pnpm vendor:update-and-build
|
||||
|
||||
# Just rebuild vendor libraries without updating versions
|
||||
pnpm vendor:libs
|
||||
```
|
||||
|
||||
The following libraries are included:
|
||||
- mermaid (diagrams)
|
||||
- plotly.js (interactive charts)
|
||||
- katex (math rendering)
|
||||
- markmap-autoloader (mind maps)
|
||||
- alpinejs (interactivity)
|
||||
- preact (interactive components)
|
||||
@@ -2,6 +2,7 @@
|
||||
/* Note: In v4, we use @source inline to ensure these are included */
|
||||
/* This ensures Tailwind generates these classes even if not found in templates */
|
||||
|
||||
/* Inline safelist for classes used in dynamic content and YAML configuration */
|
||||
@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-Line truncated
|
||||
|
||||
/* Force generation of all CSS custom properties for dynamic usage in YAML front matter */
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
/* Tailwind CSS v4 Base */
|
||||
@import "tailwindcss";
|
||||
|
||||
/* Dynamic sources are injected by the css.html partial */
|
||||
/* This handles both monorepo dev and end-user environments */
|
||||
|
||||
/* Configuration */
|
||||
@import "config/tailwind.css";
|
||||
@import "config/theme.css";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(()=>{var rt=!1,nt=!1,U=[],it=-1;function qt(e){On(e)}function On(e){U.includes(e)||U.push(e),Cn()}function Ee(e){let t=U.indexOf(e);t!==-1&&t>it&&U.splice(t,1)}function Cn(){!nt&&!rt&&(rt=!0,queueMicrotask(Tn))}function Tn(){rt=!1,nt=!0;for(let e=0;e<U.length;e++)U[e](),it=e;U.length=0,it=-1,nt=!1}var R,D,L,st,ot=!0;function Ut(e){ot=!1,e(),ot=!0}function Wt(e){R=e.reactive,L=e.release,D=t=>e.effect(t,{scheduler:r=>{ot?qt(r):r()}}),st=e.raw}function at(e){D=e}function Gt(e){let t=()=>{};return[n=>{let i=D(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),L(i))},i},()=>{t()}]}function Se(e,t){let r=!0,n,i=D(()=>{let o=e();JSON.stringify(o),r?n=o:queueMicrotask(()=>{t(o,n),n=o}),r=!1});return()=>L(i)}var Jt=[],Yt=[],Xt=[];function Zt(e){Xt.push(e)}function ee(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,Yt.push(t))}function Ae(e){Jt.push(e)}function Oe(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function ct(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}function Qt(e){if(e._x_cleanups)for(;e._x_cleanups.length;)e._x_cleanups.pop()()}var lt=new MutationObserver(pt),ut=!1;function le(){lt.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),ut=!0}function ft(){Rn(),lt.disconnect(),ut=!1}var ce=[];function Rn(){let e=lt.takeRecords();ce.push(()=>e.length>0&&pt(e));let t=ce.length;queueMicrotask(()=>{if(ce.length===t)for(;ce.length>0;)ce.shift()()})}function _(e){if(!ut)return e();ft();let t=e();return le(),t}var dt=!1,ve=[];function er(){dt=!0}function tr(){dt=!1,pt(ve),ve=[]}function pt(e){if(dt){ve=ve.concat(e);return}let t=new Set,r=new Set,n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].addedNodes.forEach(s=>s.nodeType===1&&t.add(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.add(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{ct(s,o)}),n.forEach((o,s)=>{Jt.forEach(a=>a(s,o))});for(let o of r)t.has(o)||Yt.forEach(s=>s(o));t.forEach(o=>{o._x_ignoreSelf=!0,o._x_ignore=!0});for(let o of t)r.has(o)||o.isConnected&&(delete o._x_ignoreSelf,delete o._x_ignore,Xt.forEach(s=>s(o)),o._x_ignore=!0,o._x_ignoreSelf=!0);t.forEach(o=>{delete o._x_ignoreSelf,delete o._x_ignore}),t=null,r=null,n=null,i=null}function Ce(e){return F(j(e))}function P(e,t,r){return e._x_dataStack=[t,...j(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function j(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?j(e.host):e.parentNode?j(e.parentNode):[]}function F(e){return new Proxy({objects:e},Mn)}var Mn={ownKeys({objects:e}){return Array.from(new Set(e.flatMap(t=>Object.keys(t))))},has({objects:e},t){return t==Symbol.unscopables?!1:e.some(r=>Object.prototype.hasOwnProperty.call(r,t)||Reflect.has(r,t))},get({objects:e},t,r){return t=="toJSON"?Nn:Reflect.get(e.find(n=>Reflect.has(n,t))||{},t,r)},set({objects:e},t,r,n){let i=e.find(s=>Object.prototype.hasOwnProperty.call(s,t))||e[e.length-1],o=Object.getOwnPropertyDescriptor(i,t);return o?.set&&o?.get?Reflect.set(i,t,r,n):Reflect.set(i,t,r)}};function Nn(){return Reflect.ownKeys(this).reduce((t,r)=>(t[r]=Reflect.get(this,r),t),{})}function Te(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0||typeof s=="object"&&s!==null&&s.__v_skip)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function Re(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>Dn(n,i),s=>mt(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function Dn(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function mt(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),mt(e[t[0]],t.slice(1),r)}}var rr={};function y(e,t){rr[e]=t}function ue(e,t){return Object.entries(rr).forEach(([r,n])=>{let i=null;function o(){if(i)return i;{let[s,a]=_t(t);return i={interceptor:Re,...s},ee(t,a),i}}Object.defineProperty(e,`$${rLine truncated
|
||||
(()=>{var nt=!1,it=!1,W=[],ot=-1;function Ut(e){Rn(e)}function Rn(e){W.includes(e)||W.push(e),Mn()}function Wt(e){let t=W.indexOf(e);t!==-1&&t>ot&&W.splice(t,1)}function Mn(){!it&&!nt&&(nt=!0,queueMicrotask(Nn))}function Nn(){nt=!1,it=!0;for(let e=0;e<W.length;e++)W[e](),ot=e;W.length=0,ot=-1,it=!1}var T,N,$,at,st=!0;function Gt(e){st=!1,e(),st=!0}function Jt(e){T=e.reactive,$=e.release,N=t=>e.effect(t,{scheduler:r=>{st?Ut(r):r()}}),at=e.raw}function ct(e){N=e}function Yt(e){let t=()=>{};return[n=>{let i=N(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),$(i))},i},()=>{t()}]}function ve(e,t){let r=!0,n,i=N(()=>{let o=e();JSON.stringify(o),r?n=o:queueMicrotask(()=>{t(o,n),n=o}),r=!1});return()=>$(i)}var Xt=[],Zt=[],Qt=[];function er(e){Qt.push(e)}function te(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,Zt.push(t))}function Ae(e){Xt.push(e)}function Oe(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function lt(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}function tr(e){for(e._x_effects?.forEach(Wt);e._x_cleanups?.length;)e._x_cleanups.pop()()}var ut=new MutationObserver(mt),ft=!1;function ue(){ut.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),ft=!0}function dt(){kn(),ut.disconnect(),ft=!1}var le=[];function kn(){let e=ut.takeRecords();le.push(()=>e.length>0&&mt(e));let t=le.length;queueMicrotask(()=>{if(le.length===t)for(;le.length>0;)le.shift()()})}function m(e){if(!ft)return e();dt();let t=e();return ue(),t}var pt=!1,Se=[];function rr(){pt=!0}function nr(){pt=!1,mt(Se),Se=[]}function mt(e){if(pt){Se=Se.concat(e);return}let t=[],r=new Set,n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].removedNodes.forEach(s=>{s.nodeType===1&&s._x_marker&&r.add(s)}),e[o].addedNodes.forEach(s=>{if(s.nodeType===1){if(r.has(s)){r.delete(s);return}s._x_marker||t.push(s)}})),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{lt(s,o)}),n.forEach((o,s)=>{Xt.forEach(a=>a(s,o))});for(let o of r)t.some(s=>s.contains(o))||Zt.forEach(s=>s(o));for(let o of t)o.isConnected&&Qt.forEach(s=>s(o));t=null,r=null,n=null,i=null}function Ce(e){return z(B(e))}function k(e,t,r){return e._x_dataStack=[t,...B(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function B(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?B(e.host):e.parentNode?B(e.parentNode):[]}function z(e){return new Proxy({objects:e},Dn)}var Dn={ownKeys({objects:e}){return Array.from(new Set(e.flatMap(t=>Object.keys(t))))},has({objects:e},t){return t==Symbol.unscopables?!1:e.some(r=>Object.prototype.hasOwnProperty.call(r,t)||Reflect.has(r,t))},get({objects:e},t,r){return t=="toJSON"?Pn:Reflect.get(e.find(n=>Reflect.has(n,t))||{},t,r)},set({objects:e},t,r,n){let i=e.find(s=>Object.prototype.hasOwnProperty.call(s,t))||e[e.length-1],o=Object.getOwnPropertyDescriptor(i,t);return o?.set&&o?.get?o.set.call(n,r)||!0:Reflect.set(i,t,r)}};function Pn(){return Reflect.ownKeys(this).reduce((t,r)=>(t[r]=Reflect.get(this,r),t),{})}function Te(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0||typeof s=="object"&&s!==null&&s.__v_skip)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function Re(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>In(n,i),s=>ht(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function In(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function ht(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),ht(e[t[0]],t.slice(1),r)}}var ir={};function y(e,t){ir[e]=t}function fe(e,t){let r=Ln(t);return Object.entries(ir).forEach(([n,i])=>{Object.defineProperty(e,`$${n}`,{get(){return i(t,r)},enumerable:!1})}),e}function Ln(e){let[t,r]=_t(e),n={interceptor:Re,...t};return te(e,r),n}function or(e,t,r,...n){try{return r(...n)}catch(i){re(i,e,t)}}function re(e,tLine truncated
|
||||
|
||||
${r?'Expression: "'+r+`"
|
||||
|
||||
`:""}`,t),setTimeout(()=>{throw e},0)}var Me=!0;function De(e){let t=Me;Me=!1;let r=e();return Me=t,r}function M(e,t,r={}){let n;return x(e,t)(i=>n=i,r),n}function x(...e){return ir(...e)}var ir=gt;function or(e){ir=e}function gt(e,t){let r={};ue(r,e);let n=[r,...j(e)],i=typeof t=="function"?Pn(n,t):kn(n,t,e);return nr.bind(null,e,t,i)}function Pn(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(F([n,...e]),i);Ne(r,o)}}var ht={};function In(e,t){if(ht[e])return ht[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e.trim())||/^(let|const)\s/.test(e.trim())?`(async()=>{ ${e} })()`:e,o=(()=>{try{let s=new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`);return Object.defineProperty(s,"name",{value:`[Alpine] ${e}`}),s}catch(s){return te(s,t,e),Promise.resolve()}})();return ht[e]=o,o}function kn(e,t,r){let n=In(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=F([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>te(l,r,t));n.finished?(Ne(i,n.result,a,s,r),n.result=void 0):c.then(l=>{Ne(i,l,a,s,r)}).catch(l=>te(l,r,t)).finally(()=>n.result=void 0)}}}function Ne(e,t,r,n,i){if(Me&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Ne(e,s,r,n)).catch(s=>te(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}var bt="x-";function C(e=""){return bt+e}function sr(e){bt=e}var Pe={};function d(e,t){return Pe[e]=t,{before(r){if(!Pe[r]){console.warn(String.raw`Cannot find directive \`${r}\`. \`${e}\` will use the default order of execution`);return}let n=W.indexOf(r);W.splice(n>=0?n:W.indexOf("DEFAULT"),0,e)}}}function ar(e){return Object.keys(Pe).includes(e)}function de(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,c])=>({name:a,value:c})),s=wt(o);o=o.map(a=>s.find(c=>c.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(ur((o,s)=>n[o]=s)).filter(dr).map($n(n,r)).sort(jn).map(o=>Ln(e,o))}function wt(e){return Array.from(e).map(ur()).filter(t=>!dr(t))}var xt=!1,fe=new Map,cr=Symbol();function lr(e){xt=!0;let t=Symbol();cr=t,fe.set(t,[]);let r=()=>{for(;fe.get(t).length;)fe.get(t).shift()();fe.delete(t)},n=()=>{xt=!1,r()};e(r),n()}function _t(e){let t=[],r=a=>t.push(a),[n,i]=Gt(e);return t.push(i),[{Alpine:B,effect:n,cleanup:r,evaluateLater:x.bind(x,e),evaluate:M.bind(M,e)},()=>t.forEach(a=>a())]}function Ln(e,t){let r=()=>{},n=Pe[t.type]||r,[i,o]=_t(e);Oe(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),xt?fe.get(cr).push(n):n())};return s.runCleanups=o,s}var Ie=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),ke=e=>e;function ur(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=fr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var fr=[];function re(e){fr.push(e)}function dr({name:e}){return pr().test(e)}var pr=()=>new RegExp(`^${bt}([^:^.]+)\\b`);function $n(e,t){return({name:r,value:n})=>{let i=r.match(pr()),o=r.match(/:([a-zA-Z0-9\-_:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var yt="DEFAULT",W=["ignore","ref","data","id","anchor","bind","init","for","model","modelable","transition","show","if",yt,"teleport"];function jn(e,t){let r=W.indexOf(e.type)===-1?yt:e.type,n=W.indexOf(t.type)===-1?yt:t.type;return W.indexOf(r)-W.indexOf(n)}function G(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function T(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>T(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)T(n,t,!1),n=n.nextElementSibling}function E(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}var mr=!1;function _r(){mr&&E("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),mr=!0,document.body||E("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),G(document,"alpine:init"),G(document,"alpine:initializing"),le(),Zt(t=>v(t,T)),ee(t=>St(t)),Ae((t,r)=>{de(t,r).forEach(n=>n())});let e=t=>!J(t.parentElement,!0);Array.from(document.querySelectorAll(xr().join(","))).filter(e).forEach(t=>{v(t)}),G(document,"alpine:initialized"),setTimeout(()=>{Fn()})}var Et=[],hr=[];function gr(){return Et.map(e=>e())}function xr(){return Et.concat(hr).map(e=>e())}function Le(e){Et.push(e)}function $e(e){hr.push(e)}function J(e,t=!1){return z(e,r=>{if((t?xr():gr()).some(i=>r.matches(i)))return!0})}function z(e,t){if(e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),!!e.parentElement)return z(e.parentElement,t)}}function yLine truncated
|
||||
`:""}`,t),setTimeout(()=>{throw e},0)}var Me=!0;function ke(e){let t=Me;Me=!1;let r=e();return Me=t,r}function R(e,t,r={}){let n;return x(e,t)(i=>n=i,r),n}function x(...e){return sr(...e)}var sr=xt;function ar(e){sr=e}function xt(e,t){let r={};fe(r,e);let n=[r,...B(e)],i=typeof t=="function"?$n(n,t):Fn(n,t,e);return or.bind(null,e,t,i)}function $n(e,t){return(r=()=>{},{scope:n={},params:i=[],context:o}={})=>{let s=t.apply(z([n,...e]),i);Ne(r,s)}}var gt={};function jn(e,t){if(gt[e])return gt[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e.trim())||/^(let|const)\s/.test(e.trim())?`(async()=>{ ${e} })()`:e,o=(()=>{try{let s=new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`);return Object.defineProperty(s,"name",{value:`[Alpine] ${e}`}),s}catch(s){return re(s,t,e),Promise.resolve()}})();return gt[e]=o,o}function Fn(e,t,r){let n=jn(t,r);return(i=()=>{},{scope:o={},params:s=[],context:a}={})=>{n.result=void 0,n.finished=!1;let c=z([o,...e]);if(typeof n=="function"){let l=n.call(a,n,c).catch(u=>re(u,r,t));n.finished?(Ne(i,n.result,c,s,r),n.result=void 0):l.then(u=>{Ne(i,u,c,s,r)}).catch(u=>re(u,r,t)).finally(()=>n.result=void 0)}}}function Ne(e,t,r,n,i){if(Me&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Ne(e,s,r,n)).catch(s=>re(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}var wt="x-";function C(e=""){return wt+e}function cr(e){wt=e}var De={};function d(e,t){return De[e]=t,{before(r){if(!De[r]){console.warn(String.raw`Cannot find directive \`${r}\`. \`${e}\` will use the default order of execution`);return}let n=G.indexOf(r);G.splice(n>=0?n:G.indexOf("DEFAULT"),0,e)}}}function lr(e){return Object.keys(De).includes(e)}function pe(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,c])=>({name:a,value:c})),s=Et(o);o=o.map(a=>s.find(c=>c.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(dr((o,s)=>n[o]=s)).filter(mr).map(zn(n,r)).sort(Kn).map(o=>Bn(e,o))}function Et(e){return Array.from(e).map(dr()).filter(t=>!mr(t))}var yt=!1,de=new Map,ur=Symbol();function fr(e){yt=!0;let t=Symbol();ur=t,de.set(t,[]);let r=()=>{for(;de.get(t).length;)de.get(t).shift()();de.delete(t)},n=()=>{yt=!1,r()};e(r),n()}function _t(e){let t=[],r=a=>t.push(a),[n,i]=Yt(e);return t.push(i),[{Alpine:K,effect:n,cleanup:r,evaluateLater:x.bind(x,e),evaluate:R.bind(R,e)},()=>t.forEach(a=>a())]}function Bn(e,t){let r=()=>{},n=De[t.type]||r,[i,o]=_t(e);Oe(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),yt?de.get(ur).push(n):n())};return s.runCleanups=o,s}var Pe=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Ie=e=>e;function dr(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=pr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var pr=[];function ne(e){pr.push(e)}function mr({name:e}){return hr().test(e)}var hr=()=>new RegExp(`^${wt}([^:^.]+)\\b`);function zn(e,t){return({name:r,value:n})=>{let i=r.match(hr()),o=r.match(/:([a-zA-Z0-9\-_:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var bt="DEFAULT",G=["ignore","ref","data","id","anchor","bind","init","for","model","modelable","transition","show","if",bt,"teleport"];function Kn(e,t){let r=G.indexOf(e.type)===-1?bt:e.type,n=G.indexOf(t.type)===-1?bt:t.type;return G.indexOf(r)-G.indexOf(n)}function J(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function D(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>D(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)D(n,t,!1),n=n.nextElementSibling}function E(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}var _r=!1;function gr(){_r&&E("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),_r=!0,document.body||E("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),J(document,"alpine:init"),J(document,"alpine:initializing"),ue(),er(t=>S(t,D)),te(t=>P(t)),Ae((t,r)=>{pe(t,r).forEach(n=>n())});let e=t=>!Y(t.parentElement,!0);Array.from(document.querySelectorAll(br().join(","))).filter(e).forEach(t=>{S(t)}),J(document,"alpine:initialized"),setTimeout(()=>{Vn()})}var vt=[],xr=[];function yr(){return vt.map(e=>e())}function br(){return vt.concat(xr).map(e=>e())}function Le(e){vt.push(e)}function $e(e){xr.push(e)}function Y(e,t=!1){return j(e,r=>{if((t?br():yr()).some(i=>r.matches(i)))return!0})}function j(e,t){if(e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),!!e.parentElement)return j(e.paLine truncated
|
||||
@@ -1 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var i=r[e];if(void 0!==i)return i.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var i={};return function(){n.d(i,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,i=0,a=e.length;n<t.length;){var o=t[n];if(i<=0&&t.slice(n,n+a)===e)return n;"\\"===o?n++:"{"===o?i++:"}"===o&&i--,n++}return-1},a=/^\\begin{/,o=function(e,t){for(var n,i=[],o=new RegExp("("+t.map((function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")})).join("|")+")");-1!==(n=e.search(o));){n>0&&(i.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=a.test(d)?d:e.slice(t[l].left.length,n);i.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&i.push({type:"text",data:e}),i},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var i=document.createDocumentFragment(),a=0;a<n.length;a++)if("text"===n[a].type)i.appendChild(document.createTextNode(n[a].data));else{var l=document.createElement("span"),d=n[a].data;r.displayMode=n[a].display;try{r.preProcess&&(d=r.preProcess(d)),t().render(d,l,r)}catch(e){if(!(e instanceof t().ParseError))throw e;r.errorCallback("KaTeX auto-render: Failed to parse `"+n[a].data+"` with ",e),i.appendChild(document.createTextNode(n[a].rawData));continue}i.appendChild(l)}return i},d=function e(t,r){for(var n=0;n<t.childNodes.length;n++){var i=t.childNodes[n];if(3===i.nodeType){for(var a=i.textContent,o=i.nextSibling,d=0;o&&o.nodeType===Node.TEXT_NODE;)a+=o.textContent,o=o.nextSibling,d++;var s=l(a,r);if(s){for(var f=0;f<d;f++)i.nextSibling.remove();n+=s.childNodes.length-1,t.replaceChild(s,i)}else n+=d}else 1===i.nodeType&&function(){var t=" "+i.className+" ";-1===r.ignoredTags.indexOf(i.nodeName.toLowerCase())&&r.ignoredClasses.every((function(e){return-1===t.indexOf(" "+e+" ")}))&&e(i,r)}()}},s=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},d(e,r)}}(),i=i.default}()}));
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={757:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};r.d(o,{default:function(){return p}});var i=r(757),a=r.n(i);const l=function(e,t,n){let r=n,o=0;const i=e.length;for(;r<t.length;){const n=t[r];if(o<=0&&t.slice(r,r+i)===e)return r;"\\"===n?r++:"{"===n?o++:"}"===n&&o--,r++}return-1},s=/^\\begin{/;var d=function(e,t){let n;const r=[],o=new RegExp("("+t.map((e=>e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;n=e.search(o),-1!==n;){n>0&&(r.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));const o=t.findIndex((t=>e.startsWith(t.left)));if(n=l(t[o].right,e,t[o].left.length),-1===n)break;const i=e.slice(0,n+t[o].right.length),a=s.test(i)?i:e.slice(t[o].left.length,n);r.push({type:"math",data:a,rawData:i,display:t[o].display}),e=e.slice(n+t[o].right.length)}return""!==e&&r.push({type:"text",data:e}),r};const c=function(e,t){const n=d(e,t.delimiters);if(1===n.length&&"text"===n[0].type)return null;const r=document.createDocumentFragment();for(let e=0;e<n.length;e++)if("text"===n[e].type)r.appendChild(document.createTextNode(n[e].data));else{const o=document.createElement("span");let i=n[e].data;t.displayMode=n[e].display;try{t.preProcess&&(i=t.preProcess(i)),a().render(i,o,t)}catch(o){if(!(o instanceof a().ParseError))throw o;t.errorCallback("KaTeX auto-render: Failed to parse `"+n[e].data+"` with ",o),r.appendChild(document.createTextNode(n[e].rawData));continue}r.appendChild(o)}return r},f=function(e,t){for(let n=0;n<e.childNodes.length;n++){const r=e.childNodes[n];if(3===r.nodeType){let o=r.textContent,i=r.nextSibling,a=0;for(;i&&i.nodeType===Node.TEXT_NODE;)o+=i.textContent,i=i.nextSibling,a++;const l=c(o,t);if(l){for(let e=0;e<a;e++)r.nextSibling.remove();n+=l.childNodes.length-1,e.replaceChild(l,r)}else n+=a}else if(1===r.nodeType){const e=" "+r.className+" ";-1===t.ignoredTags.indexOf(r.nodeName.toLowerCase())&&t.ignoredClasses.every((t=>-1===e.indexOf(" "+t+" ")))&&f(r,t)}}};var p=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},f(e,n)};return o=o.default}()}));
|
||||
@@ -1 +1 @@
|
||||
@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(fonts/KaTeX_AMS-Regular.woff) format("woff"),url(fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(fonts/KaTeX_Main-Bold.woff) format("woff"),url(fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(fonts/KaTeX_Main-Italic.woff) format("woff"),url(fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(fonts/KaTeX_Main-Regular.woff) format("woff"),url(fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(fonts/KaTeX_Math-Italic.woff) format("woff"),url(fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(fonts/KaTeX_Script-Regular.woff) format("woff"),url(fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size1-Regular.woff) format("woff"),url(fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size2-Regular.woff) format("woff"),url(fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size3-Regular.woff) format("woff"),url(fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size4-Regular.woff) format("woff"),url(fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{text-rendering:auto;font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.16.9"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1pxLine truncated
|
||||
@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(fonts/KaTeX_AMS-Regular.woff) format("woff"),url(fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(fonts/KaTeX_Main-Bold.woff) format("woff"),url(fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(fonts/KaTeX_Main-Italic.woff) format("woff"),url(fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(fonts/KaTeX_Main-Regular.woff) format("woff"),url(fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(fonts/KaTeX_Math-Italic.woff) format("woff"),url(fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(fonts/KaTeX_Script-Regular.woff) format("woff"),url(fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size1-Regular.woff) format("woff"),url(fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size2-Regular.woff) format("woff"),url(fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size3-Regular.woff) format("woff"),url(fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size4-Regular.woff) format("woff"),url(fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.16.22"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1pLine truncated
|
||||
@@ -1 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.katex=t():e.katex=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return na}});var r=function e(t,r){this.name=void 0,this.position=void 0,this.length=void 0,this.rawMessage=void 0;var n,a,i="KaTeX parse error: "+t,o=r&&r.loc;if(o&&o.start<=o.end){var s=o.lexer.input;n=o.start,a=o.end,n===s.length?i+=" at end of input: ":i+=" at position "+(n+1)+": ";var l=s.slice(n,a).replace(/[^]/g,"$&\u0332");i+=(n>15?"\u2026"+s.slice(n-15,n):s.slice(0,n))+l+(a+15<s.length?s.slice(a,a+15)+"\u2026":s.slice(a))}var h=new Error(i);return h.name="ParseError",h.__proto__=e.prototype,h.position=n,null!=n&&null!=a&&(h.length=a-n),h.rawMessage=t,h};r.prototype.__proto__=Error.prototype;var n=r,a=/([A-Z])/g,i={"&":"&",">":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format <type>"},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color <color>",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:function(e){return"#"+e}},macros:{type:"object",cli:"-m, --macro <def>",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:function(e,t){return t.push(e),t}},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:function(e){return Math.max(0,e)},cli:"--min-rule-thickness <size>",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:function(e){return Math.max(0,e)},cli:"-s, --max-size <n>",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:function(e){return Math.max(0,e)},cli:"-e, --max-expand <n>",cliProcessor:function(e){return"Infinity"===e?1/0:parseInt(e)}},globalGroup:{type:"boolean",cli:!1}};function c(e){if(e.default)return e.default;var t=e.type,r=Array.isArray(t)?t[0]:t;if("string"!=typeof r)return r.enum[0];switch(r){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}var m=function(){function e(e){for(var t in this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void
Line truncated
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.katex=t():e.katex=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return Wn}});class r{constructor(e,t){this.name=void 0,this.position=void 0,this.length=void 0,this.rawMessage=void 0;let n,o,s="KaTeX parse error: "+e;const i=t&&t.loc;if(i&&i.start<=i.end){const e=i.lexer.input;n=i.start,o=i.end,n===e.length?s+=" at end of input: ":s+=" at position "+(n+1)+": ";const t=e.slice(n,o).replace(/[^]/g,"$&\u0332");let r,a;r=n>15?"\u2026"+e.slice(n-15,n):e.slice(0,n),a=o+15<e.length?e.slice(o,o+15)+"\u2026":e.slice(o),s+=r+t+a}const a=new Error(s);return a.name="ParseError",a.__proto__=r.prototype,a.position=n,null!=n&&null!=o&&(a.length=o-n),a.rawMessage=e,a}}r.prototype.__proto__=Error.prototype;var n=r;const o=/([A-Z])/g,s={"&":"&",">":">","<":"<",'"':""","'":"'"},i=/[&><"']/g;const a=function(e){return"ordgroup"===e.type||"color"===e.type?1===e.body.length?a(e.body[0]):e:"font"===e.type?a(e.body):e};var l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(i,(e=>s[e]))},hyphenate:function(e){return e.replace(o,"-$1").toLowerCase()},getBaseElem:a,isCharacterBox:function(e){const t=a(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){const t=/^[\x00-\x20]*([^\\/#?]*?)(:|�*58|�*3a|&colon)/i.exec(e);return t?":"!==t[2]?null:/^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(t[1])?t[1].toLowerCase():null:"_relative"}};const h={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format <type>"},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color <color>",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:e=>"#"+e},macros:{type:"object",cli:"-m, --macro <def>",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:(e,t)=>(t.push(e),t)},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:e=>Math.max(0,e),cli:"--min-rule-thickness <size>",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:e=>Math.max(0,e),cli:"-s, --max-size <n>",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:e=>Math.max(0,e),cli:"-e, --max-expand <n>",cliProcessor:e=>"Infinity"===e?1/0:parseInt(e)},globalGroup:{type:"boolean",cli:!1}};function c(e){if(e.default)return e.default;const t=e.type,r=Array.isArray(t)?t[0]:t;if("string"!=typeof r)return r.enum[0];switch(r){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}class m{constructor(e){this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0Line truncated
|
||||
+433
-430
@@ -1,459 +1,462 @@
|
||||
/*! markmap-autoloader v0.15.4 | MIT License */
|
||||
this.markmap = this.markmap || {};
|
||||
(function (exports) {
|
||||
'use strict';
|
||||
|
||||
function _extends$1() {
|
||||
_extends$1 = Object.assign ? Object.assign.bind() : function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
for (var key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
(function(exports) {
|
||||
"use strict";
|
||||
var _a;
|
||||
const testPath = "npm2url/dist/index.cjs";
|
||||
const defaultProviders = {
|
||||
jsdelivr: (path) => `https://cdn.jsdelivr.net/npm/${path}`,
|
||||
unpkg: (path) => `https://unpkg.com/${path}`
|
||||
};
|
||||
return _extends$1.apply(this, arguments);
|
||||
}
|
||||
|
||||
/*! markmap-common v0.15.3 | MIT License */
|
||||
function _extends() {
|
||||
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
for (var key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
return _extends.apply(this, arguments);
|
||||
}
|
||||
const testPath = "npm2url/dist/index.cjs";
|
||||
const defaultProviders = {
|
||||
jsdelivr: path => `https://cdn.jsdelivr.net/npm/${path}`,
|
||||
unpkg: path => `https://unpkg.com/${path}`
|
||||
};
|
||||
class UrlBuilder {
|
||||
constructor() {
|
||||
this.providers = _extends({}, defaultProviders);
|
||||
this.provider = "jsdelivr";
|
||||
}
|
||||
getFastestProvider(timeout = 5e3, path = testPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Promise.all(Object.entries(this.providers).map(async ([name, factory]) => {
|
||||
try {
|
||||
const res = await fetch(factory(path));
|
||||
if (!res.ok) {
|
||||
throw res;
|
||||
}
|
||||
await res.text();
|
||||
resolve(name);
|
||||
} catch (_unused) {}
|
||||
})).then(() => reject(new Error("All providers failed")));
|
||||
setTimeout(reject, timeout, new Error("Timed out"));
|
||||
async function checkUrl(url, signal) {
|
||||
const res = await fetch(url, {
|
||||
signal
|
||||
});
|
||||
}
|
||||
async findFastestProvider(timeout) {
|
||||
this.provider = await this.getFastestProvider(timeout);
|
||||
return this.provider;
|
||||
}
|
||||
setProvider(name, factory) {
|
||||
if (factory) {
|
||||
this.providers[name] = factory;
|
||||
} else {
|
||||
delete this.providers[name];
|
||||
if (!res.ok) {
|
||||
throw res;
|
||||
}
|
||||
await res.text();
|
||||
}
|
||||
getFullUrl(path, provider = this.provider) {
|
||||
if (path.includes("://")) {
|
||||
return path;
|
||||
class UrlBuilder {
|
||||
constructor() {
|
||||
this.providers = { ...defaultProviders };
|
||||
this.provider = "jsdelivr";
|
||||
}
|
||||
const factory = this.providers[provider];
|
||||
if (!factory) {
|
||||
throw new Error(`Provider ${provider} not found`);
|
||||
}
|
||||
return factory(path);
|
||||
}
|
||||
}
|
||||
const urlBuilder = new UrlBuilder();
|
||||
Math.random().toString(36).slice(2, 8);
|
||||
function memoize(fn) {
|
||||
const cache = {};
|
||||
return function memoized(...args) {
|
||||
const key = `${args[0]}`;
|
||||
let data = cache[key];
|
||||
if (!data) {
|
||||
data = {
|
||||
value: fn(...args)
|
||||
};
|
||||
cache[key] = data;
|
||||
}
|
||||
return data.value;
|
||||
};
|
||||
}
|
||||
|
||||
/*! @gera2ld/jsx-dom v2.2.2 | ISC License */
|
||||
const VTYPE_ELEMENT = 1;
|
||||
const VTYPE_FUNCTION = 2;
|
||||
const SVG_NS = 'http://www.w3.org/2000/svg';
|
||||
const XLINK_NS = 'http://www.w3.org/1999/xlink';
|
||||
const NS_ATTRS = {
|
||||
show: XLINK_NS,
|
||||
actuate: XLINK_NS,
|
||||
href: XLINK_NS
|
||||
};
|
||||
const isLeaf = c => typeof c === 'string' || typeof c === 'number';
|
||||
const isElement = c => (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT;
|
||||
const isRenderFunction = c => (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION;
|
||||
function h(type, props, ...children) {
|
||||
props = Object.assign({}, props, {
|
||||
children: children.length === 1 ? children[0] : children
|
||||
});
|
||||
return jsx(type, props);
|
||||
}
|
||||
function jsx(type, props) {
|
||||
let vtype;
|
||||
if (typeof type === 'string') vtype = VTYPE_ELEMENT;else if (typeof type === 'function') vtype = VTYPE_FUNCTION;else throw new Error('Invalid VNode type');
|
||||
return {
|
||||
vtype,
|
||||
type,
|
||||
props
|
||||
};
|
||||
}
|
||||
function Fragment(props) {
|
||||
return props.children;
|
||||
}
|
||||
const DEFAULT_ENV = {
|
||||
isSvg: false
|
||||
};
|
||||
function insertDom(parent, nodes) {
|
||||
if (!Array.isArray(nodes)) nodes = [nodes];
|
||||
nodes = nodes.filter(Boolean);
|
||||
if (nodes.length) parent.append(...nodes);
|
||||
}
|
||||
function mountAttributes(domElement, props, env) {
|
||||
for (const key in props) {
|
||||
if (key === 'key' || key === 'children' || key === 'ref') continue;
|
||||
if (key === 'dangerouslySetInnerHTML') {
|
||||
domElement.innerHTML = props[key].__html;
|
||||
} else if (key === 'innerHTML' || key === 'textContent' || key === 'innerText' || key === 'value' && ['textarea', 'select'].includes(domElement.tagName)) {
|
||||
const value = props[key];
|
||||
if (value != null) domElement[key] = value;
|
||||
} else if (key.startsWith('on')) {
|
||||
domElement[key.toLowerCase()] = props[key];
|
||||
} else {
|
||||
setDOMAttribute(domElement, key, props[key], env.isSvg);
|
||||
}
|
||||
}
|
||||
}
|
||||
const attrMap = {
|
||||
className: 'class',
|
||||
labelFor: 'for'
|
||||
};
|
||||
function setDOMAttribute(el, attr, value, isSVG) {
|
||||
attr = attrMap[attr] || attr;
|
||||
if (value === true) {
|
||||
el.setAttribute(attr, '');
|
||||
} else if (value === false) {
|
||||
el.removeAttribute(attr);
|
||||
} else {
|
||||
const namespace = isSVG ? NS_ATTRS[attr] : undefined;
|
||||
if (namespace !== undefined) {
|
||||
el.setAttributeNS(namespace, attr, value);
|
||||
} else {
|
||||
el.setAttribute(attr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
function flatten(arr) {
|
||||
return arr.reduce((prev, item) => prev.concat(item), []);
|
||||
}
|
||||
function mountChildren(children, env) {
|
||||
return Array.isArray(children) ? flatten(children.map(child => mountChildren(child, env))) : mount(children, env);
|
||||
}
|
||||
function mount(vnode, env = DEFAULT_ENV) {
|
||||
if (vnode == null || typeof vnode === 'boolean') {
|
||||
return null;
|
||||
}
|
||||
if (vnode instanceof Node) {
|
||||
return vnode;
|
||||
}
|
||||
if (isRenderFunction(vnode)) {
|
||||
const {
|
||||
type,
|
||||
props
|
||||
} = vnode;
|
||||
if (type === Fragment) {
|
||||
const node = document.createDocumentFragment();
|
||||
if (props.children) {
|
||||
const children = mountChildren(props.children, env);
|
||||
insertDom(node, children);
|
||||
/**
|
||||
* Get the fastest provider name.
|
||||
* If none of the providers returns a valid response within `timeout`, an error will be thrown.
|
||||
*/
|
||||
async getFastestProvider(timeout = 5e3, path = testPath) {
|
||||
const controller = new AbortController();
|
||||
let timer = 0;
|
||||
try {
|
||||
return await new Promise((resolve, reject) => {
|
||||
Promise.all(
|
||||
Object.entries(this.providers).map(async ([name, factory]) => {
|
||||
try {
|
||||
await checkUrl(factory(path), controller.signal);
|
||||
resolve(name);
|
||||
} catch {
|
||||
}
|
||||
})
|
||||
).then(() => reject(new Error("All providers failed")));
|
||||
timer = setTimeout(reject, timeout, new Error("Timed out"));
|
||||
});
|
||||
} finally {
|
||||
controller.abort();
|
||||
clearTimeout(timer);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
const childVNode = type(props);
|
||||
return mount(childVNode, env);
|
||||
/**
|
||||
* Set the current provider to the fastest provider found by `getFastestProvider`.
|
||||
*/
|
||||
async findFastestProvider(timeout, path) {
|
||||
this.provider = await this.getFastestProvider(timeout, path);
|
||||
return this.provider;
|
||||
}
|
||||
setProvider(name, factory) {
|
||||
if (factory) {
|
||||
this.providers[name] = factory;
|
||||
} else {
|
||||
delete this.providers[name];
|
||||
}
|
||||
}
|
||||
getFullUrl(path, provider = this.provider) {
|
||||
if (path.includes("://")) {
|
||||
return path;
|
||||
}
|
||||
const factory = this.providers[provider];
|
||||
if (!factory) {
|
||||
throw new Error(`Provider ${provider} not found`);
|
||||
}
|
||||
return factory(path);
|
||||
}
|
||||
}
|
||||
if (isLeaf(vnode)) {
|
||||
return document.createTextNode(`${vnode}`);
|
||||
const urlBuilder = new UrlBuilder();
|
||||
Math.random().toString(36).slice(2, 8);
|
||||
function defer() {
|
||||
const obj = {};
|
||||
obj.promise = new Promise((resolve, reject) => {
|
||||
obj.resolve = resolve;
|
||||
obj.reject = reject;
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
if (isElement(vnode)) {
|
||||
let node;
|
||||
const {
|
||||
function memoize(fn) {
|
||||
const cache = {};
|
||||
return function memoized(...args) {
|
||||
const key = `${args[0]}`;
|
||||
let data = cache[key];
|
||||
if (!data) {
|
||||
data = {
|
||||
value: fn(...args)
|
||||
};
|
||||
cache[key] = data;
|
||||
}
|
||||
return data.value;
|
||||
};
|
||||
}
|
||||
/*! @gera2ld/jsx-dom v2.2.2 | ISC License */
|
||||
const VTYPE_ELEMENT = 1;
|
||||
const VTYPE_FUNCTION = 2;
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
const XLINK_NS = "http://www.w3.org/1999/xlink";
|
||||
const NS_ATTRS = {
|
||||
show: XLINK_NS,
|
||||
actuate: XLINK_NS,
|
||||
href: XLINK_NS
|
||||
};
|
||||
const isLeaf = (c) => typeof c === "string" || typeof c === "number";
|
||||
const isElement = (c) => (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT;
|
||||
const isRenderFunction = (c) => (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION;
|
||||
function h(type, props, ...children) {
|
||||
props = Object.assign({}, props, {
|
||||
children: children.length === 1 ? children[0] : children
|
||||
});
|
||||
return jsx(type, props);
|
||||
}
|
||||
function jsx(type, props) {
|
||||
let vtype;
|
||||
if (typeof type === "string") vtype = VTYPE_ELEMENT;
|
||||
else if (typeof type === "function") vtype = VTYPE_FUNCTION;
|
||||
else throw new Error("Invalid VNode type");
|
||||
return {
|
||||
vtype,
|
||||
type,
|
||||
props
|
||||
} = vnode;
|
||||
if (!env.isSvg && type === 'svg') {
|
||||
env = Object.assign({}, env, {
|
||||
isSvg: true
|
||||
});
|
||||
};
|
||||
}
|
||||
function Fragment(props) {
|
||||
return props.children;
|
||||
}
|
||||
const DEFAULT_ENV = {
|
||||
isSvg: false
|
||||
};
|
||||
function insertDom(parent, nodes) {
|
||||
if (!Array.isArray(nodes)) nodes = [nodes];
|
||||
nodes = nodes.filter(Boolean);
|
||||
if (nodes.length) parent.append(...nodes);
|
||||
}
|
||||
function mountAttributes(domElement, props, env) {
|
||||
for (const key in props) {
|
||||
if (key === "key" || key === "children" || key === "ref") continue;
|
||||
if (key === "dangerouslySetInnerHTML") {
|
||||
domElement.innerHTML = props[key].__html;
|
||||
} else if (key === "innerHTML" || key === "textContent" || key === "innerText" || key === "value" && ["textarea", "select"].includes(domElement.tagName)) {
|
||||
const value = props[key];
|
||||
if (value != null) domElement[key] = value;
|
||||
} else if (key.startsWith("on")) {
|
||||
domElement[key.toLowerCase()] = props[key];
|
||||
} else {
|
||||
setDOMAttribute(domElement, key, props[key], env.isSvg);
|
||||
}
|
||||
}
|
||||
if (!env.isSvg) {
|
||||
node = document.createElement(type);
|
||||
}
|
||||
const attrMap = {
|
||||
className: "class",
|
||||
labelFor: "for"
|
||||
};
|
||||
function setDOMAttribute(el, attr, value, isSVG) {
|
||||
attr = attrMap[attr] || attr;
|
||||
if (value === true) {
|
||||
el.setAttribute(attr, "");
|
||||
} else if (value === false) {
|
||||
el.removeAttribute(attr);
|
||||
} else {
|
||||
node = document.createElementNS(SVG_NS, type);
|
||||
const namespace = isSVG ? NS_ATTRS[attr] : void 0;
|
||||
if (namespace !== void 0) {
|
||||
el.setAttributeNS(namespace, attr, value);
|
||||
} else {
|
||||
el.setAttribute(attr, value);
|
||||
}
|
||||
}
|
||||
mountAttributes(node, props, env);
|
||||
if (props.children) {
|
||||
let childEnv = env;
|
||||
if (env.isSvg && type === 'foreignObject') {
|
||||
childEnv = Object.assign({}, childEnv, {
|
||||
isSvg: false
|
||||
}
|
||||
function flatten(arr) {
|
||||
return arr.reduce((prev, item) => prev.concat(item), []);
|
||||
}
|
||||
function mountChildren(children, env) {
|
||||
return Array.isArray(children) ? flatten(children.map((child) => mountChildren(child, env))) : mount(children, env);
|
||||
}
|
||||
function mount(vnode, env = DEFAULT_ENV) {
|
||||
if (vnode == null || typeof vnode === "boolean") {
|
||||
return null;
|
||||
}
|
||||
if (vnode instanceof Node) {
|
||||
return vnode;
|
||||
}
|
||||
if (isRenderFunction(vnode)) {
|
||||
const {
|
||||
type,
|
||||
props
|
||||
} = vnode;
|
||||
if (type === Fragment) {
|
||||
const node = document.createDocumentFragment();
|
||||
if (props.children) {
|
||||
const children = mountChildren(props.children, env);
|
||||
insertDom(node, children);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
const childVNode = type(props);
|
||||
return mount(childVNode, env);
|
||||
}
|
||||
if (isLeaf(vnode)) {
|
||||
return document.createTextNode(`${vnode}`);
|
||||
}
|
||||
if (isElement(vnode)) {
|
||||
let node;
|
||||
const {
|
||||
type,
|
||||
props
|
||||
} = vnode;
|
||||
if (!env.isSvg && type === "svg") {
|
||||
env = Object.assign({}, env, {
|
||||
isSvg: true
|
||||
});
|
||||
}
|
||||
const children = mountChildren(props.children, childEnv);
|
||||
if (children != null) insertDom(node, children);
|
||||
}
|
||||
const {
|
||||
ref
|
||||
} = props;
|
||||
if (typeof ref === 'function') ref(node);
|
||||
return node;
|
||||
}
|
||||
throw new Error('mount: Invalid Vnode!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mount vdom as real DOM nodes.
|
||||
*/
|
||||
function mountDom(vnode) {
|
||||
return mount(vnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render and mount without returning VirtualDOM, useful when you don't need SVG support.
|
||||
*/
|
||||
function hm(...args) {
|
||||
return mountDom(h(...args));
|
||||
}
|
||||
const memoizedPreloadJS = memoize(url => {
|
||||
document.head.append(hm('link', {
|
||||
rel: 'preload',
|
||||
as: 'script',
|
||||
href: url
|
||||
}));
|
||||
});
|
||||
const jsCache = {};
|
||||
const cssCache = {};
|
||||
async function loadJSItem(item, context) {
|
||||
var _item$data;
|
||||
const src = item.type === 'script' && ((_item$data = item.data) == null ? void 0 : _item$data.src) || '';
|
||||
item.loaded || (item.loaded = jsCache[src]);
|
||||
if (!item.loaded) {
|
||||
if (item.type === 'script') {
|
||||
item.loaded = new Promise((resolve, reject) => {
|
||||
document.head.append(hm('script', _extends({}, item.data, {
|
||||
onLoad: resolve,
|
||||
onError: reject
|
||||
})));
|
||||
if (!src) {
|
||||
// Run inline script synchronously
|
||||
resolve(undefined);
|
||||
if (!env.isSvg) {
|
||||
node = document.createElement(type);
|
||||
} else {
|
||||
node = document.createElementNS(SVG_NS, type);
|
||||
}
|
||||
mountAttributes(node, props, env);
|
||||
if (props.children) {
|
||||
let childEnv = env;
|
||||
if (env.isSvg && type === "foreignObject") {
|
||||
childEnv = Object.assign({}, childEnv, {
|
||||
isSvg: false
|
||||
});
|
||||
}
|
||||
}).then(() => {
|
||||
item.loaded = true;
|
||||
});
|
||||
if (src) jsCache[src] = item.loaded;
|
||||
}
|
||||
if (item.type === 'iife') {
|
||||
const children = mountChildren(props.children, childEnv);
|
||||
if (children != null) insertDom(node, children);
|
||||
}
|
||||
const {
|
||||
fn,
|
||||
getParams
|
||||
} = item.data;
|
||||
fn(...((getParams == null ? void 0 : getParams(context)) || []));
|
||||
item.loaded = true;
|
||||
ref
|
||||
} = props;
|
||||
if (typeof ref === "function") ref(node);
|
||||
return node;
|
||||
}
|
||||
throw new Error("mount: Invalid Vnode!");
|
||||
}
|
||||
await item.loaded;
|
||||
}
|
||||
function loadCSSItem(item) {
|
||||
const url = item.type === 'stylesheet' && item.data.href || '';
|
||||
item.loaded || (item.loaded = cssCache[url]);
|
||||
if (item.loaded) return;
|
||||
item.loaded = true;
|
||||
if (url) cssCache[url] = true;
|
||||
if (item.type === 'style') {
|
||||
document.head.append(hm('style', {
|
||||
textContent: item.data
|
||||
}));
|
||||
} else if (item.type === 'stylesheet') {
|
||||
document.head.append(hm('link', _extends({
|
||||
rel: 'stylesheet'
|
||||
}, item.data)));
|
||||
function mountDom(vnode) {
|
||||
return mount(vnode);
|
||||
}
|
||||
}
|
||||
async function loadJS(items, context) {
|
||||
items.forEach(item => {
|
||||
var _item$data2;
|
||||
if (item.type === 'script' && (_item$data2 = item.data) != null && _item$data2.src) {
|
||||
memoizedPreloadJS(item.data.src);
|
||||
}
|
||||
function hm(...args) {
|
||||
return mountDom(h(...args));
|
||||
}
|
||||
const memoizedPreloadJS = memoize((url) => {
|
||||
document.head.append(
|
||||
hm("link", {
|
||||
rel: "preload",
|
||||
as: "script",
|
||||
href: url
|
||||
})
|
||||
);
|
||||
});
|
||||
context = _extends({
|
||||
getMarkmap: () => window.markmap
|
||||
}, context);
|
||||
for (const item of items) {
|
||||
await loadJSItem(item, context);
|
||||
}
|
||||
}
|
||||
function loadCSS(items) {
|
||||
for (const item of items) {
|
||||
loadCSSItem(item);
|
||||
}
|
||||
}
|
||||
function buildJSItem(path) {
|
||||
return {
|
||||
type: 'script',
|
||||
data: {
|
||||
src: path
|
||||
}
|
||||
};
|
||||
}
|
||||
function buildCSSItem(path) {
|
||||
return {
|
||||
type: 'stylesheet',
|
||||
data: {
|
||||
href: path
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var _window$markmap;
|
||||
const enabled = {};
|
||||
const autoLoaderOptions = _extends$1({
|
||||
baseJs: [`d3@${"7.8.5"}`, `markmap-lib@${"0.15.4"}`, `markmap-view@${"0.15.4"}`, `markmap-toolbar@${"0.15.4"}`],
|
||||
baseCss: [`markmap-toolbar@${"0.15.4"}/dist/style.css`],
|
||||
manual: false,
|
||||
toolbar: false
|
||||
}, (_window$markmap = window.markmap) == null ? void 0 : _window$markmap.autoLoader);
|
||||
async function initialize() {
|
||||
if (typeof autoLoaderOptions.provider === 'function') {
|
||||
urlBuilder.setProvider(urlBuilder.provider = 'autoLoader', autoLoaderOptions.provider);
|
||||
} else if (typeof autoLoaderOptions.provider === 'string') {
|
||||
urlBuilder.provider = autoLoaderOptions.provider;
|
||||
} else {
|
||||
try {
|
||||
await urlBuilder.findFastestProvider();
|
||||
} catch (_unused) {
|
||||
// ignore
|
||||
const jsCache = {};
|
||||
const cssCache = {};
|
||||
async function loadJSItem(item, context) {
|
||||
var _a2;
|
||||
const src = item.type === "script" && ((_a2 = item.data) == null ? void 0 : _a2.src) || "";
|
||||
item.loaded || (item.loaded = jsCache[src]);
|
||||
if (!item.loaded) {
|
||||
const deferred = defer();
|
||||
item.loaded = deferred.promise;
|
||||
if (item.type === "script") {
|
||||
document.head.append(
|
||||
hm("script", {
|
||||
...item.data,
|
||||
onLoad: () => deferred.resolve(),
|
||||
onError: deferred.reject
|
||||
})
|
||||
);
|
||||
if (!src) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
jsCache[src] = item.loaded;
|
||||
}
|
||||
}
|
||||
if (item.type === "iife") {
|
||||
const { fn, getParams } = item.data;
|
||||
fn(...(getParams == null ? void 0 : getParams(context)) || []);
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
await item.loaded;
|
||||
}
|
||||
await Promise.all([loadJS(autoLoaderOptions.baseJs.map(item => typeof item === 'string' ? buildJSItem(urlBuilder.getFullUrl(item)) : item)), loadCSS(autoLoaderOptions.baseCss.map(item => typeof item === 'string' ? buildCSSItem(urlBuilder.getFullUrl(item)) : item))]);
|
||||
const {
|
||||
markmap
|
||||
} = window;
|
||||
const style = document.createElement('style');
|
||||
style.textContent = markmap.globalCSS;
|
||||
// Insert global CSS to body so it has higher priority than prism.css, etc.
|
||||
document.body.prepend(style);
|
||||
autoLoaderOptions.onReady == null ? void 0 : autoLoaderOptions.onReady();
|
||||
}
|
||||
const ready = initialize();
|
||||
function transform(transformer, content) {
|
||||
const result = transformer.transform(content);
|
||||
const keys = Object.keys(result.features).filter(key => !enabled[key]);
|
||||
keys.forEach(key => {
|
||||
enabled[key] = true;
|
||||
});
|
||||
const {
|
||||
styles,
|
||||
scripts
|
||||
} = transformer.getAssets(keys);
|
||||
const {
|
||||
markmap
|
||||
} = window;
|
||||
if (styles) markmap.loadCSS(styles);
|
||||
if (scripts) markmap.loadJS(scripts);
|
||||
return result;
|
||||
}
|
||||
function render(el) {
|
||||
var _el$textContent;
|
||||
const {
|
||||
Transformer,
|
||||
Markmap,
|
||||
deriveOptions,
|
||||
Toolbar
|
||||
} = window.markmap;
|
||||
const lines = ((_el$textContent = el.textContent) == null ? void 0 : _el$textContent.split('\n')) || [];
|
||||
let indent = Infinity;
|
||||
lines.forEach(line => {
|
||||
var _line$match;
|
||||
const spaces = ((_line$match = line.match(/^\s*/)) == null ? void 0 : _line$match[0].length) || 0;
|
||||
if (spaces < line.length) indent = Math.min(indent, spaces);
|
||||
});
|
||||
const content = lines.map(line => line.slice(indent)).join('\n').trim();
|
||||
const transformer = new Transformer(autoLoaderOptions.transformPlugins);
|
||||
transformer.urlBuilder = urlBuilder;
|
||||
el.innerHTML = '<svg></svg>';
|
||||
const svg = el.firstChild;
|
||||
const mm = Markmap.create(svg, {
|
||||
embedGlobalCSS: false
|
||||
});
|
||||
if (autoLoaderOptions.toolbar) {
|
||||
const {
|
||||
el: toolbar
|
||||
} = Toolbar.create(mm);
|
||||
Object.assign(toolbar.style, {
|
||||
position: 'absolute',
|
||||
right: '20px',
|
||||
bottom: '20px'
|
||||
async function loadCSSItem(item) {
|
||||
const url = item.type === "stylesheet" && item.data.href || "";
|
||||
item.loaded || (item.loaded = cssCache[url]);
|
||||
if (!item.loaded) {
|
||||
const deferred = defer();
|
||||
item.loaded = deferred.promise;
|
||||
if (url) cssCache[url] = item.loaded;
|
||||
if (item.type === "style") {
|
||||
document.head.append(
|
||||
hm("style", {
|
||||
textContent: item.data
|
||||
})
|
||||
);
|
||||
deferred.resolve();
|
||||
} else if (url) {
|
||||
document.head.append(
|
||||
hm("link", {
|
||||
rel: "stylesheet",
|
||||
...item.data
|
||||
})
|
||||
);
|
||||
fetch(url).then((res) => {
|
||||
if (res.ok) return res.text();
|
||||
throw res;
|
||||
}).then(() => deferred.resolve(), deferred.reject);
|
||||
}
|
||||
}
|
||||
await item.loaded;
|
||||
}
|
||||
async function loadJS(items, context) {
|
||||
items.forEach((item) => {
|
||||
var _a2;
|
||||
if (item.type === "script" && ((_a2 = item.data) == null ? void 0 : _a2.src)) {
|
||||
memoizedPreloadJS(item.data.src);
|
||||
}
|
||||
});
|
||||
el.append(toolbar);
|
||||
context = {
|
||||
getMarkmap: () => window.markmap,
|
||||
...context
|
||||
};
|
||||
for (const item of items) {
|
||||
await loadJSItem(item, context);
|
||||
}
|
||||
}
|
||||
const doRender = () => {
|
||||
const {
|
||||
root,
|
||||
frontmatter
|
||||
} = transform(transformer, content);
|
||||
const markmapOptions = frontmatter == null ? void 0 : frontmatter.markmap;
|
||||
const frontmatterOptions = deriveOptions(markmapOptions);
|
||||
mm.setData(root, frontmatterOptions);
|
||||
mm.fit();
|
||||
async function loadCSS(items) {
|
||||
await Promise.all(items.map((item) => loadCSSItem(item)));
|
||||
}
|
||||
function buildJSItem(path) {
|
||||
return {
|
||||
type: "script",
|
||||
data: {
|
||||
src: path
|
||||
}
|
||||
};
|
||||
}
|
||||
function buildCSSItem(path) {
|
||||
return {
|
||||
type: "stylesheet",
|
||||
data: {
|
||||
href: path
|
||||
}
|
||||
};
|
||||
}
|
||||
const enabled = {};
|
||||
const autoLoaderOptions = {
|
||||
baseJs: [
|
||||
`d3@${"7.9.0"}`,
|
||||
`markmap-lib@${"0.18.12"}`,
|
||||
`markmap-view@${"0.18.12"}`,
|
||||
`markmap-toolbar@${"0.18.12"}`
|
||||
],
|
||||
baseCss: [`markmap-toolbar@${"0.18.12"}/dist/style.css`],
|
||||
manual: false,
|
||||
toolbar: false,
|
||||
...(_a = window.markmap) == null ? void 0 : _a.autoLoader
|
||||
};
|
||||
transformer.hooks.retransform.tap(doRender);
|
||||
doRender();
|
||||
}
|
||||
async function renderAllUnder(container) {
|
||||
await ready;
|
||||
container.querySelectorAll('.markmap').forEach(render);
|
||||
}
|
||||
function renderAll() {
|
||||
return renderAllUnder(document);
|
||||
}
|
||||
if (!autoLoaderOptions.manual) {
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', () => {
|
||||
renderAll();
|
||||
});else renderAll();
|
||||
}
|
||||
|
||||
exports.ready = ready;
|
||||
exports.render = render;
|
||||
exports.renderAll = renderAll;
|
||||
exports.renderAllUnder = renderAllUnder;
|
||||
|
||||
async function initialize() {
|
||||
var _a2;
|
||||
if (typeof autoLoaderOptions.provider === "function") {
|
||||
urlBuilder.setProvider(
|
||||
urlBuilder.provider = "autoLoader",
|
||||
autoLoaderOptions.provider
|
||||
);
|
||||
} else if (typeof autoLoaderOptions.provider === "string") {
|
||||
urlBuilder.provider = autoLoaderOptions.provider;
|
||||
} else {
|
||||
try {
|
||||
await urlBuilder.findFastestProvider();
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
await Promise.all([
|
||||
loadJS(
|
||||
autoLoaderOptions.baseJs.map(
|
||||
(item) => typeof item === "string" ? buildJSItem(urlBuilder.getFullUrl(item)) : item
|
||||
)
|
||||
),
|
||||
loadCSS(
|
||||
autoLoaderOptions.baseCss.map(
|
||||
(item) => typeof item === "string" ? buildCSSItem(urlBuilder.getFullUrl(item)) : item
|
||||
)
|
||||
)
|
||||
]);
|
||||
const { markmap } = window;
|
||||
const style = document.createElement("style");
|
||||
style.textContent = markmap.globalCSS;
|
||||
document.body.prepend(style);
|
||||
(_a2 = autoLoaderOptions.onReady) == null ? void 0 : _a2.call(autoLoaderOptions);
|
||||
}
|
||||
const ready = initialize();
|
||||
function transform(transformer, content) {
|
||||
const result = transformer.transform(content);
|
||||
const keys = Object.keys(result.features).filter((key) => !enabled[key]);
|
||||
keys.forEach((key) => {
|
||||
enabled[key] = true;
|
||||
});
|
||||
const { styles, scripts } = transformer.getAssets(keys);
|
||||
const { markmap } = window;
|
||||
if (styles) markmap.loadCSS(styles);
|
||||
if (scripts) markmap.loadJS(scripts);
|
||||
return result;
|
||||
}
|
||||
function render(el) {
|
||||
var _a2;
|
||||
const { Transformer, Markmap, deriveOptions, Toolbar } = window.markmap;
|
||||
const lines = ((_a2 = el.textContent) == null ? void 0 : _a2.split("\n")) || [];
|
||||
let indent = Infinity;
|
||||
lines.forEach((line) => {
|
||||
var _a3;
|
||||
const spaces = ((_a3 = line.match(/^\s*/)) == null ? void 0 : _a3[0].length) || 0;
|
||||
if (spaces < line.length) indent = Math.min(indent, spaces);
|
||||
});
|
||||
const content = lines.map((line) => line.slice(indent)).join("\n").trim();
|
||||
const transformer = new Transformer(autoLoaderOptions.transformPlugins);
|
||||
transformer.urlBuilder = urlBuilder;
|
||||
el.innerHTML = "<svg></svg>";
|
||||
const svg = el.firstChild;
|
||||
const mm = Markmap.create(svg, { embedGlobalCSS: false });
|
||||
if (autoLoaderOptions.toolbar) {
|
||||
const { el: toolbar } = Toolbar.create(mm);
|
||||
Object.assign(toolbar.style, {
|
||||
position: "absolute",
|
||||
right: "20px",
|
||||
bottom: "20px"
|
||||
});
|
||||
el.append(toolbar);
|
||||
}
|
||||
const doRender = async () => {
|
||||
const { root, frontmatter } = transform(transformer, content);
|
||||
const markmapOptions = frontmatter == null ? void 0 : frontmatter.markmap;
|
||||
const frontmatterOptions = deriveOptions(markmapOptions);
|
||||
await mm.setData(root, frontmatterOptions);
|
||||
mm.fit();
|
||||
};
|
||||
transformer.hooks.retransform.tap(doRender);
|
||||
doRender();
|
||||
}
|
||||
async function renderAllUnder(container) {
|
||||
await ready;
|
||||
container.querySelectorAll(".markmap").forEach(render);
|
||||
}
|
||||
function renderAll() {
|
||||
return renderAllUnder(document);
|
||||
}
|
||||
if (!autoLoaderOptions.manual) {
|
||||
if (document.readyState === "loading")
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
renderAll();
|
||||
});
|
||||
else renderAll();
|
||||
}
|
||||
exports.ready = ready;
|
||||
exports.render = render;
|
||||
exports.renderAll = renderAll;
|
||||
exports.renderAllUnder = renderAllUnder;
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
})(this.markmap.autoLoader = this.markmap.autoLoader || {});
|
||||
+2691
-1526
File diff suppressed because it is too large.
Load diff
+3878
-4
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,2 @@
|
||||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("preact")):"function"==typeof define&&define.amd?define(["exports","preact"],t):t((n||self).preactHooks={},n.preact)}(this,function(n,t){var u,i,r,o,f=0,c=[],e=t.options,a=e.__b,v=e.__r,l=e.diffed,d=e.__c,s=e.unmount,p=e.__;function y(n,t){e.__h&&e.__h(i,n,f||t),f=0;var u=i.__H||(i.__H={__:[],__h:[]});return n>=u.__.length&&u.__.push({}),u.__[n]}function h(n){return f=1,m(j,n)}function m(n,t,r){var o=y(u++,2);if(o.t=n,!o.__c&&(o.__=[r?r(t):j(void 0,t),function(n){var t=o.__N?o.__N[0]:o.__[0],u=o.t(t,n);t!==u&&(o.__N=[u,o.__[1]],o.__c.setState({}))}],o.__c=i,!i.__f)){var f=function(n,t,u){if(!o.__c.__H)return!0;var i=o.__c.__H.__.filter(function(n){return!!n.__c});if(i.every(function(n){return!n.__N}))return!c||c.call(this,n,t,u);var r=o.__c.props!==n;return i.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(r=!0)}}),c&&c.call(this,n,t,u)||r};i.__f=!0;var c=i.shouldComponentUpdate,e=i.componentWillUpdate;i.componentWillUpdate=function(n,t,u){if(this.__e){var i=c;c=void 0,f(n,t,u),c=i}e&&e.call(this,n,t,u)},i.shouldComponentUpdate=f}return o.__N||o.__}function T(n,t){var r=y(u++,4);!e.__s&&g(r.__H,t)&&(r.__=n,r.u=t,i.__h.push(r))}function _(n,t){var i=y(u++,7);return g(i.__H,t)&&(i.__=n(),i.__H=t,i.__h=n),i.__}function b(){for(var n;n=c.shift();)if(n.__P&&n.__H)try{n.__H.__h.forEach(A),n.__H.__h.forEach(F),n.__H.__h=[]}catch(t){n.__H.__h=[],e.__e(t,n.__v)}}e.__b=function(n){i=null,a&&a(n)},e.__=function(n,t){n&&t.__k&&t.__k.__m&&(n.__m=t.__k.__m),p&&p(n,t)},e.__r=function(n){v&&v(n),u=0;var t=(i=n.__c).__H;t&&(r===i?(t.__h=[],i.__h=[],t.__.forEach(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.forEach(A),t.__h.forEach(F),t.__h=[],u=0)),r=i},e.diffed=function(n){l&&l(n);var t=n.__c;t&&t.__H&&(t.__H.__h.length&&(1!==c.push(t)&&o===e.requestAnimationFrame||((o=e.requestAnimationFrame)||x)(b)),t.__H.__.forEach(function(n){n.u&&(n.__H=n.u),n.u=void 0})),r=i=null},e.__c=function(n,t){t.some(function(n){try{n.__h.forEach(A),n.__h=n.__h.filter(function(n){return!n.__||F(n)})}catch(u){t.some(function(n){n.__h&&(n.__h=[])}),t=[],e.__e(u,n.__v)}}),d&&d(n,t)},e.unmount=function(n){s&&s(n);var t,u=n.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{A(n)}catch(n){t=n}}),u.__H=void 0,t&&e.__e(t,u.__v))};var q="function"==typeof requestAnimationFrame;function x(n){var t,u=function(){clearTimeout(i),q&&cancelAnimationFrame(t),setTimeout(n)},i=setTimeout(u,35);q&&(t=requestAnimationFrame(u))}function A(n){var t=i,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),i=t}function F(n){var t=i;n.__c=n.__(),i=t}function g(n,t){return!n||n.length!==t.length||t.some(function(t,u){return t!==n[u]})}function j(n,t){return"function"==typeof t?t(n):t}n.useCallback=function(n,t){return f=8,_(function(){return n},t)},n.useContext=function(n){var t=i.context[n.__c],r=y(u++,9);return r.c=n,t?(null==r.__&&(r.__=!0,t.sub(i)),t.props.value):n.__},n.useDebugValue=function(n,t){e.useDebugValue&&e.useDebugValue(t?t(n):n)},n.useEffect=function(n,t){var r=y(u++,3);!e.__s&&g(r.__H,t)&&(r.__=n,r.u=t,i.__H.__h.push(r))},n.useErrorBoundary=function(n){var t=y(u++,10),r=h();return t.__=n,i.componentDidCatch||(i.componentDidCatch=function(n,u){t.__&&t.__(n,u),r[1](n)}),[r[0],function(){r[1](void 0)}]},n.useId=function(){var n=y(u++,11);if(!n.__){for(var t=i.__v;null!==t&&!t.__m&&null!==t.__;)t=t.__;var r=t.__m||(t.__m=[0,0]);n.__="P"+r[0]+"-"+r[1]++}return n.__},n.useImperativeHandle=function(n,t,u){f=6,T(function(){if("function"==typeof n){var u=n(t());return function(){n(null),u&&"function"==typeof u&&u()}}if(n)return n.current=t(),function(){return n.current=null}},null==u?u:u.concat(n))},n.useLayoutEffect=T,n.useMemo=_,n.useReducer=m,n.useRef=function(n){return f=5,_(function(){return{current:n}},[])},n.useState=h});
|
||||
//# sourceMappingURL=hooks.umd.js.map
|
||||
@@ -0,0 +1,2 @@
|
||||
!function(){var n,t,e,i,r,o,f,u,c,s,a,h,l,p,y="http://www.w3.org/2000/svg",v="http://www.w3.org/1999/xhtml",d=null,w=void 0,_={},m=[],g=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,b=Array.isArray;function k(n,t){for(var e in t)n[e]=t[e];return n}function C(n){n&&n.parentNode&&n.parentNode.removeChild(n)}function x(t,e,i){var r,o,f,u={};for(f in e)"key"==f?r=e[f]:"ref"==f?o=e[f]:u[f]=e[f];if(arguments.length>2&&(u.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof t&&t.defaultProps!=d)for(f in t.defaultProps)u[f]===w&&(u[f]=t.defaultProps[f]);return S(t,u,r,o,d)}function S(n,i,r,o,f){var u={type:n,props:i,key:r,ref:o,__k:d,__:d,__b:0,__e:d,__c:d,constructor:w,__v:f==d?++e:f,__i:-1,__u:0};return f==d&&t.vnode!=d&&t.vnode(u),u}function M(n){return n.children}function $(n,t){this.props=n,this.context=t}function A(n,t){if(t==d)return n.__?A(n.__,n.__i+1):d;for(var e;t<n.__k.length;t++)if((e=n.__k[t])!=d&&e.__e!=d)return e.__e;return"function"==typeof n.type?A(n):d}function I(n){var t,e;if((n=n.__)!=d&&n.__c!=d){for(n.__e=n.__c.base=d,t=0;t<n.__k.length;t++)if((e=n.__k[t])!=d&&e.__e!=d){n.__e=n.__c.base=e.__e;break}return I(n)}}function P(n){(!n.__d&&(n.__d=!0)&&r.push(n)&&!E.__r++||o!=t.debounceRendering)&&((o=t.debounceRendering)||f)(E)}function E(){for(var n,e,i,o,f,c,s,a=1;r.length;)r.length>a&&r.sort(u),n=r.shift(),a=r.length,n.__d&&(i=void 0,o=void 0,f=(o=(e=n).__v).__e,c=[],s=[],e.__P&&((i=k({},o)).__v=o.__v+1,t.vnode&&t.vnode(i),z(e.__P,i,o,e.__n,e.__P.namespaceURI,32&o.__u?[f]:d,c,f==d?A(o):f,!!(32&o.__u),s),i.__v=o.__v,i.__.__k[i.__i]=i,R(c,i,s),o.__e=o.__=null,i.__e!=f&&I(i)));E.__r=0}function F(n,t,e,i,r,o,f,u,c,s,a){var h,l,p,y,v,g,b,k=i&&i.__k||m,C=t.length;for(c=H(e,t,k,c,C),h=0;h<C;h++)(p=e.__k[h])!=d&&(l=-1==p.__i?_:k[p.__i]||_,p.__i=h,g=z(n,p,l,r,o,f,u,c,s,a),y=p.__e,p.ref&&l.ref!=p.ref&&(l.ref&&D(l.ref,d,p),a.push(p.ref,p.__c||y,p)),v==d&&y!=d&&(v=y),(b=!!(4&p.__u))||l.__k===p.__k?c=L(p,c,n,b):"function"==typeof p.type&&g!==w?c=g:y&&(c=y.nextSibling),p.__u&=-7);return e.__e=v,c}function H(n,t,e,i,r){var o,f,u,c,s,a=e.length,h=a,l=0;for(n.__k=new Array(r),o=0;o<r;o++)(f=t[o])!=d&&"boolean"!=typeof f&&"function"!=typeof f?(c=o+l,(f=n.__k[o]="string"==typeof f||"number"==typeof f||"bigint"==typeof f||f.constructor==String?S(d,f,d,d,d):b(f)?S(M,{children:f},d,d,d):f.constructor==w&&f.__b>0?S(f.type,f.props,f.key,f.ref?f.ref:d,f.__v):f).__=n,f.__b=n.__b+1,s=f.__i=T(f,e,c,h),u=d,-1!=s&&(h--,(u=e[s])&&(u.__u|=2)),u==d||u.__v==d?(-1==s&&(r>a?l--:r<a&&l++),"function"!=typeof f.type&&(f.__u|=4)):s!=c&&(s==c-1?l--:s==c+1?l++:(s>c?l--:l++,f.__u|=4))):n.__k[o]=d;if(h)for(o=0;o<a;o++)(u=e[o])!=d&&0==(2&u.__u)&&(u.__e==i&&(i=A(u)),G(u,u));return i}function L(n,t,e,i){var r,o;if("function"==typeof n.type){for(r=n.__k,o=0;r&&o<r.length;o++)r[o]&&(r[o].__=n,t=L(r[o],t,e,i));return t}n.__e!=t&&(i&&(t&&n.type&&!t.parentNode&&(t=A(n)),e.insertBefore(n.__e,t||d)),t=n.__e);do{t=t&&t.nextSibling}while(t!=d&&8==t.nodeType);return t}function T(n,t,e,i){var r,o,f,u=n.key,c=n.type,s=t[e],a=s!=d&&0==(2&s.__u);if(s===d&&null==n.key||a&&u==s.key&&c==s.type)return e;if(i>(a?1:0))for(r=e-1,o=e+1;r>=0||o<t.length;)if((s=t[f=r>=0?r--:o++])!=d&&0==(2&s.__u)&&u==s.key&&c==s.type)return f;return-1}function j(n,t,e){"-"==t[0]?n.setProperty(t,e==d?"":e):n[t]=e==d?"":"number"!=typeof e||g.test(t)?e:e+"px"}function O(n,t,e,i,r){var o,f;n:if("style"==t)if("string"==typeof e)n.style.cssText=e;else{if("string"==typeof i&&(n.style.cssText=i=""),i)for(t in i)e&&t in e||j(n.style,t,"");if(e)for(t in e)i&&e[t]==i[t]||j(n.style,t,e[t])}else if("o"==t[0]&&"n"==t[1])o=t!=(t=t.replace(c,"$1")),f=t.toLowerCase(),t=f in n||"onFocusOut"==t||"onFocusIn"==t?f.slice(2):t.slice(2),n.l||(n.l={}),n.l[t+o]=e,e?i?e.t=i.t:(e.t=s,n.addEventListener(t,o?h:a,o)):n.removeEventListener(t,o?h:a,o);else{if(r==y)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!=t&&"height"!=t&&"href"!=t&&"list"!=t&&"form"!=t&&"tabIndex"!=t&&"download"!=t&&"rowSpan"!=t&&"colSpan"!=t&&"role"!=t&&"popover"!=t&&t in n)try{n[t]=e==d?"":e;break n}catch(n){}"function"==typeof e||(e==d||!1===e&&"-"!=t[4]?n.removeAttribute(t):n.setAttribute(t,"popover"==t&&1==e?"":e))}}function V(n){return function(e){if(this.l){var i=this.l[e.type+n];if(e.i==d)e.i=s++;else if(e.i<i.t)return;return i(t.event?t.event(e):e)}}}function z(n,e,i,r,o,f,u,c,s,a){var h,l,p,y,v,_,m,g,x,S,A,I,P,E,H,L,T,j=e.type;if(e.constructor!=w)return d;128&i.__u&&(s=!!(32&i.__u),f=[c=e.__e=i.__e]),(h=t.__b)&&h(e);n:if("function"==typeof j)try{if(g=e.props,x="prototype"in j&&j.prototype.render,S=(h=j.contextType)&&r[h.__c],A=h?S?S.props.value:h.__:r,i.__c?m=(l=e.__c=i.__c).__=l.__E:(x?e.__c=l=new j(g,A):(e.__c=l=new $(g,A),l.constructor=j,l.render=J),S&&S.sub(l),l.props=g,l.state||(l.state={}),l.context=A,l.__n=r,p=l.__d=!0,l.__h=[],l._sb=[]),x&&l.__s==d&&(l.__s=l.state),x&&j.getDerivedStateFromProps!=d&&(l.__s==l.state&&(l.__s=k({},l.__s)),k(l.__s,j.getDerivedStateFroLine truncated
|
||||
//# sourceMappingURL=preact.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"preact.min.js","sources":["../src/util.js","../src/options.js","../src/create-element.js","../src/component.js","../src/diff/props.js","../src/create-context.js","../src/constants.js","../src/diff/children.js","../src/diff/index.js","../src/render.js","../src/diff/catch-error.js","../src/clone-element.js","../src/cjs.js"],"sourcesContent":["import { EMPTY_ARR } from './constants';\n\nexport const isArray = Array.isArray;\n\n/**\n * Assign properties from `props` to `obj`\n * @template O, P The obj and props types\n * @param {O} obj The object to copy properties to\n * @param {P} props The object to copy properties from\n * @returns {O & P}\n */\nexport function assign(obj, props) {\n\t// @ts-expect-error We change the type of `obj` to be `O & P`\n\tfor (let i in props) obj[i] = props[i];\n\treturn /** @type {O & P} */ (obj);\n}\n\n/**\n * Remove a child node from its parent if attached. This is a workaround for\n * IE11 which doesn't support `Element.prototype.remove()`. Using this function\n * is smaller than including a dedicated polyfill.\n * @param {import('./index').ContainerNode} node The node to remove\n */\nexport function removeNode(node) {\n\tif (node && node.parentNode) node.parentNode.removeChild(node);\n}\n\nexport const slice = EMPTY_ARR.slice;\n","import { _catchError } from './diff/catch-error';\n\n/**\n * The `option` object can potentially contain callback functions\n * that are called during various stages of our renderer. This is the\n * foundation on which all our addons like `preact/debug`, `preact/compat`,\n * and `preact/hooks` are based on. See the `Options` type in `internal.d.ts`\n * for a full list of available option hooks (most editors/IDEs allow you to\n * ctrl+click or cmd+click on mac the type definition below).\n * @type {import('./internal').Options}\n */\nconst options = {\n\t_catchError\n};\n\nexport default options;\n","import { slice } from './util';\nimport options from './options';\nimport { NULL, UNDEFINED } from './constants';\n\nlet vnodeId = 0;\n\n/**\n * Create an virtual node (used for JSX)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component constructor for this\n * virtual node\n * @param {object | null | undefined} [props] The properties of the virtual node\n * @param {Array<import('.').ComponentChildren>} [children] The children of the\n * virtual node\n * @returns {import('./internal').VNode}\n */\nexport function createElement(type, props, children) {\n\tlet normalizedProps = {},\n\t\tkey,\n\t\tref,\n\t\ti;\n\tfor (i in props) {\n\t\tif (i == 'key') key = props[i];\n\t\telse if (i == 'ref') ref = props[i];\n\t\telse normalizedProps[i] = props[i];\n\t}\n\n\tif (arguments.length > 2) {\n\t\tnormalizedProps.children =\n\t\t\targuments.length > 3 ? slice.call(arguments, 2) : children;\n\t}\n\n\t// If a Component VNode, check for and apply defaultProps\n\t// Note: type may be undefined in development, must never error here.\n\tif (typeof type == 'function' && type.defaultProps != NULL) {\n\t\tfor (i in type.defaultProps) {\n\t\t\tif (normalizedProps[i] === UNDEFINED) {\n\t\t\t\tnormalizedProps[i] = type.defaultProps[i];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn createVNode(type, normalizedProps, key, ref, NULL);\n}\n\n/**\n * Create a VNode (used internally by Preact)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * Constructor for this virtual node\n * @param {object | string | number | null} props The properties of this virtual node.\n * If this virtual node represents a text node, this is the text of the node (string or number).\n * @param {string | number | null} key The key for this virtual node, used when\n * diffing it against its children\n * @param {import('./internal').VNode[\"ref\"]} ref The ref property that will\n * receive a reference to its created child\n * @returns {import('./internal').VNode}\n */\nexport function createVNode(type, props, key, ref, original) {\n\t// V8 seems to be better at detecting type shapes if the object is allocated from the same call site\n\t// Do not inline into createElement and coerceToVNode!\n\t/** @type {import('./internal').VNode} */\n\tconst vnode = {\n\t\ttype,\n\t\tprops,\n\t\tkey,\n\t\tref,\n\t\t_children: NULL,\n\t\t_parent: NULL,\n\t\t_depth: 0,\n\t\t_dom: NULL,\n\t\t_component: NULL,\n\t\tconstructor: UNDEFINED,\n\t\t_original: original == NULL ? ++vnodeId : original,\n\t\t_index: -1,\n\t\t_flags: 0\n\t};\n\n\t// Only invoke the vnode hook if this was *not* a direct copy:\n\tif (original == NULL && options.vnode != NULL) options.vnode(vnode);\n\n\treturn vnode;\n}\n\nexport function createRef() {\n\treturn { current: NULL };\n}\n\nexport function Fragment(props) {\n\treturn props.children;\n}\n\n/**\n * Check if a the argument is a valid Preact VNode.\n * @param {*} vnode\n * @returns {vnode is VNode}\n */\nexport const isValidElement = vnode =>\n\tvnode != NULL && vnode.constructor == UNDEFINED;\n","import { assign } from './utLine truncated
|
||||
@@ -0,0 +1,4 @@
|
||||
const e = {};
|
||||
export {
|
||||
e as default
|
||||
};
|
||||
@@ -1,2 +1,11 @@
|
||||
// Dummy entry for Vite lib mode. We copy vendor libraries via vite-plugin-static-copy.
|
||||
/**
|
||||
* Dummy entry file for Vite lib mode.
|
||||
*
|
||||
* This file exists as an entry point for the Vite build process.
|
||||
* The actual vendor libraries are copied to their respective directories
|
||||
* using vite-plugin-static-copy, while this file generates the empty
|
||||
* vendor-libs.mjs module in the dist directory.
|
||||
*
|
||||
* See vite.config.js for the build configuration.
|
||||
*/
|
||||
export default {};
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Hero Block - Client-side Hydration
|
||||
* Uses the shared component for consistency
|
||||
*/
|
||||
|
||||
import { render } from "preact";
|
||||
import { HeroBlock } from "./component.jsx";
|
||||
|
||||
// Render function - immediately renders Hero components
|
||||
function renderHeroBlocks() {
|
||||
// Find all hero block containers (using both old and new selectors for compatibility)
|
||||
const heroBlocks = document.querySelectorAll(
|
||||
'[data-block-type="hero"], [data-hero-render="immediate"]',
|
||||
);
|
||||
|
||||
heroBlocks.forEach((block) => {
|
||||
const propsData = block.dataset.props;
|
||||
if (propsData) {
|
||||
try {
|
||||
const props = JSON.parse(propsData);
|
||||
|
||||
// Render the Preact component into the container
|
||||
render(<HeroBlock {...props} />, block);
|
||||
console.debug(`✓ Hero block "${block.id}" rendered with Preact`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to render Hero block "${block.id}":`, error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (heroBlocks.length > 0) {
|
||||
console.debug(`✓ ${heroBlocks.length} Hero blocks initialized with Preact`);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize immediately when script loads
|
||||
// The script is already deferred, so DOM is ready
|
||||
renderHeroBlocks();
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* Hero Block Component - Single source of truth
|
||||
* Used for both SSR and client-side hydration
|
||||
*/
|
||||
|
||||
import { Icon } from "../../shared/components/Icon.jsx";
|
||||
|
||||
// Simple markdown renderer
|
||||
export function renderText(text) {
|
||||
if (!text) return "";
|
||||
return text
|
||||
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
||||
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
||||
.replace(/`(.*?)`/g, "<code>$1</code>");
|
||||
}
|
||||
|
||||
// Process URLs
|
||||
export function processUrl(url) {
|
||||
if (!url) return { href: "#" };
|
||||
|
||||
if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
return {
|
||||
href: url,
|
||||
target: "_blank",
|
||||
rel: "noopener",
|
||||
};
|
||||
}
|
||||
|
||||
if (url.startsWith("#")) {
|
||||
return { href: url };
|
||||
}
|
||||
|
||||
return { href: url };
|
||||
}
|
||||
|
||||
// Hero Block Component - Single implementation
|
||||
export const HeroBlock = ({ content, design, id, icon_svg }) => {
|
||||
const paddingClasses = design?.no_padding ? "" : "py-32 sm:py-48 lg:py-56";
|
||||
|
||||
return (
|
||||
<div class="relative isolate px-6 pt-14 lg:px-8" id={id}>
|
||||
<div class={`mx-auto max-w-2xl ${paddingClasses}`}>
|
||||
{/* Announcement Banner */}
|
||||
{content.announcement?.text && (
|
||||
<div class="hidden sm:mb-8 sm:flex sm:justify-center">
|
||||
<div class="relative rounded-full px-3 py-1 text-sm leading-6 text-gray-600 dark:text-gray-300 ring-1 ring-gray-900/10 dark:ring-gray-300 hover:ring-gray-900/20 dark:hover:ring-gray-400">
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: renderText(content.announcement.text),
|
||||
}}
|
||||
/>
|
||||
{content.announcement.link?.text && (
|
||||
<a
|
||||
href={processUrl(content.announcement.link.url).href}
|
||||
{...(processUrl(content.announcement.link.url).target && {
|
||||
target: processUrl(content.announcement.link.url).target,
|
||||
rel: processUrl(content.announcement.link.url).rel,
|
||||
})}
|
||||
class="pl-2 font-semibold text-primary-600 dark:text-primary-300"
|
||||
>
|
||||
<span class="absolute inset-0" aria-hidden="true"></span>
|
||||
{content.announcement.link.text}{" "}
|
||||
<span aria-hidden="true">→</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Main Content */}
|
||||
<div class="text-center">
|
||||
{/* Title */}
|
||||
{content.title && (
|
||||
<h1
|
||||
class="text-4xl font-bold tracking-tight text-gray-900 dark:text-gray-100 sm:text-6xl"
|
||||
dangerouslySetInnerHTML={{ __html: renderText(content.title) }}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Subtitle/Text */}
|
||||
{content.text && (
|
||||
<p
|
||||
class="mt-6 text-lg leading-8 text-gray-600 dark:text-gray-300"
|
||||
dangerouslySetInnerHTML={{ __html: renderText(content.text) }}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Action Buttons */}
|
||||
{(content.primary_action?.url || content.secondary_action?.url) && (
|
||||
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||
{/* Primary CTA */}
|
||||
{content.primary_action?.url && (
|
||||
<a
|
||||
href={processUrl(content.primary_action.url).href}
|
||||
{...(processUrl(content.primary_action.url).target && {
|
||||
target: processUrl(content.primary_action.url).target,
|
||||
rel: processUrl(content.primary_action.url).rel,
|
||||
})}
|
||||
class="rounded-md bg-primary-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600"
|
||||
>
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: renderText(content.primary_action.text),
|
||||
}}
|
||||
/>
|
||||
{content.primary_action.icon && (
|
||||
<span class="inline-block pl-2">
|
||||
<Icon svg={icon_svg} />
|
||||
</span>
|
||||
)}
|
||||
</a>
|
||||
)}
|
||||
|
||||
{/* Secondary CTA */}
|
||||
{content.secondary_action?.url && (
|
||||
<a
|
||||
href={processUrl(content.secondary_action.url).href}
|
||||
{...(processUrl(content.secondary_action.url).target && {
|
||||
target: processUrl(content.secondary_action.url).target,
|
||||
rel: processUrl(content.secondary_action.url).rel,
|
||||
})}
|
||||
class="text-sm font-semibold leading-6 text-gray-900 dark:text-gray-100 hover:dark:text-gray-200 hover:text-gray-800"
|
||||
>
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: renderText(content.secondary_action.text),
|
||||
}}
|
||||
/>
|
||||
<span aria-hidden="true"> →</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -11,7 +11,8 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"block": {
|
||||
"const": "hero"
|
||||
"const": "hero",
|
||||
"description": "Block type identifier"
|
||||
},
|
||||
"content": {
|
||||
"type": "object",
|
||||
@@ -46,10 +47,12 @@
|
||||
"description": "Link URL"
|
||||
}
|
||||
},
|
||||
"required": ["text", "url"]
|
||||
"required": ["text", "url"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["text"]
|
||||
"required": ["text"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"primary_action": {
|
||||
"type": "object",
|
||||
@@ -68,7 +71,8 @@
|
||||
"description": "Optional button icon (icon pack format: pack/icon-name)"
|
||||
}
|
||||
},
|
||||
"required": ["url", "text"]
|
||||
"required": ["url", "text"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"secondary_action": {
|
||||
"type": "object",
|
||||
@@ -83,11 +87,15 @@
|
||||
"description": "Link text (supports Markdown)"
|
||||
}
|
||||
},
|
||||
"required": ["url", "text"]
|
||||
"required": ["url", "text"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["content"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { h } from "preact";
|
||||
|
||||
/**
|
||||
* Icon component
|
||||
* Renders an SVG icon from a raw SVG string passed from Hugo.
|
||||
* Decodes JSON-escaped sequences (\u003c) and HTML entities (<, ", ").
|
||||
*/
|
||||
export const Icon = ({ svg, attributes }) => {
|
||||
if (!svg) return null;
|
||||
|
||||
let decoded = String(svg)
|
||||
.replace(/\\u003c/gi, "<")
|
||||
.replace(/\\u003e/gi, ">")
|
||||
.replace(/\\u0026/gi, "&")
|
||||
.replace(/</gi, "<")
|
||||
.replace(/>/gi, ">")
|
||||
.replace(/&/gi, "&")
|
||||
.replace(/"/gi, '"')
|
||||
.replace(/"/gi, '"');
|
||||
|
||||
const hasWrapper = /<svg[\s>]/i.test(decoded);
|
||||
|
||||
if (hasWrapper) {
|
||||
if (/<svg[^>]*class=/i.test(decoded)) {
|
||||
decoded = decoded.replace(
|
||||
/<svg([^>]*?)class=\"([^\"]*)\"([^>]*)>/i,
|
||||
'<svg$1class="$2 inline-block w-4 h-4"$3>'
|
||||
);
|
||||
} else {
|
||||
decoded = decoded.replace(/<svg\b/i, '<svg class="inline-block w-4 h-4"');
|
||||
}
|
||||
|
||||
return (
|
||||
<span class="inline-block" dangerouslySetInnerHTML={{ __html: decoded }} />
|
||||
);
|
||||
}
|
||||
|
||||
const finalAttributes = {
|
||||
class: "inline-block w-4 h-4",
|
||||
fill: "currentColor",
|
||||
viewBox: "0 0 20 20",
|
||||
...(attributes || {}),
|
||||
};
|
||||
|
||||
const attrs = Object.entries(finalAttributes)
|
||||
.map(([k, v]) => `${k}="${String(v)}"`)
|
||||
.join(" ");
|
||||
|
||||
return (
|
||||
<span
|
||||
class="inline-block"
|
||||
dangerouslySetInnerHTML={{ __html: `<svg ${attrs}>${decoded}</svg>` }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -32,23 +32,48 @@
|
||||
"description": "Background styling options",
|
||||
"properties": {
|
||||
"color": {
|
||||
"type": "string",
|
||||
"description": "Background color (any valid CSS color)"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Single color value"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"light": {
|
||||
"type": "string",
|
||||
"description": "Light mode color"
|
||||
},
|
||||
"dark": {
|
||||
"type": "string",
|
||||
"description": "Dark mode color"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"description": "Background color (supports Tailwind colors, hex, rgb)"
|
||||
},
|
||||
"gradient_start": {
|
||||
"type": "string",
|
||||
"description": "Gradient start color"
|
||||
},
|
||||
"gradient_end": {
|
||||
"type": "string",
|
||||
"description": "Gradient end color"
|
||||
},
|
||||
"gradient_angle": {
|
||||
"type": "number",
|
||||
"description": "Gradient angle in degrees",
|
||||
"minimum": 0,
|
||||
"maximum": 360,
|
||||
"default": 90
|
||||
"gradient": {
|
||||
"type": "object",
|
||||
"description": "Gradient configuration",
|
||||
"properties": {
|
||||
"start": {
|
||||
"type": "string",
|
||||
"description": "Gradient start color"
|
||||
},
|
||||
"end": {
|
||||
"type": "string",
|
||||
"description": "Gradient end color"
|
||||
},
|
||||
"direction": {
|
||||
"type": "string",
|
||||
"description": "Gradient direction in degrees",
|
||||
"default": "135"
|
||||
}
|
||||
},
|
||||
"required": ["start", "end"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"text_color_light": {
|
||||
"type": "boolean",
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{{/* Hugo Blox: Hero Block - Preact Wrapper */}}
|
||||
{{/* Single source of truth - Preact component handles everything */}}
|
||||
{{/* Documentation: https://hugoblox.com/blocks/ */}}
|
||||
{{/* License: https://github.com/HugoBlox/hugo-blox-builder/blob/main/LICENSE.md */}}
|
||||
|
||||
{{/* Initialize variables */}}
|
||||
{{ $page := .wcPage }}
|
||||
{{ $block := .wcBlock }}
|
||||
{{ $block_id := .wcIdentifier | default (printf "hero-%d" (now.Unix)) }}
|
||||
|
||||
{{/* Prepare props for the Preact component */}}
|
||||
{{ $props := dict
|
||||
"content" $block.content
|
||||
"design" $block.design
|
||||
"id" $block_id
|
||||
}}
|
||||
|
||||
{{/* Convert props to JSON for client-side rendering */}}
|
||||
{{ $propsJSON := $props | jsonify }}
|
||||
|
||||
{{/* Render a container that Preact will populate */}}
|
||||
{{/* The component will be rendered immediately on page load */}}
|
||||
<div
|
||||
id="{{ $block_id }}"
|
||||
class="hero-block-container"
|
||||
data-props='{{ $propsJSON | safeHTML }}'
|
||||
data-hero-render="immediate"
|
||||
>
|
||||
{{/* Empty - Preact renders everything */}}
|
||||
</div>
|
||||
|
||||
{{/* Preact script loading is handled by libraries.html */}}
|
||||
@@ -0,0 +1,46 @@
|
||||
{{/* Hugo Blox: Generic Preact Block Wrapper */}}
|
||||
{{/* Single wrapper for all Preact-based blocks */}}
|
||||
{{/* Documentation: https://hugoblox.com/blocks/ */}}
|
||||
{{/* License: https://github.com/HugoBlox/hugo-blox-builder/blob/main/LICENSE.md */}}
|
||||
|
||||
{{/* Initialize variables */}}
|
||||
{{ $page := .wcPage }}
|
||||
{{ $block := .wcBlock }}
|
||||
{{ $block_type := .wcBlockType }}
|
||||
{{ $block_id := .wcIdentifier | default (printf "%s-%d" $block_type (now.Unix)) }}
|
||||
|
||||
{{/* Prepare props for the Preact component */}}
|
||||
{{ $props := dict
|
||||
"content" $block.content
|
||||
"design" $block.design
|
||||
"id" $block_id
|
||||
"type" $block_type
|
||||
}}
|
||||
|
||||
{{/* If an icon is specified, fetch its SVG data and add it to the props */}}
|
||||
{{/* TODO: Generalize this to work with all block icon fields */}}
|
||||
{{ with $block.content.primary_action.icon }}
|
||||
{{ $icon_data := partial "functions/get_icon_data" (dict "name" .) }}
|
||||
{{ if $icon_data }}
|
||||
{{ $props = merge $props (dict "icon_svg" $icon_data) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Convert props to JSON for client-side rendering */}}
|
||||
{{ $propsJSON := $props | jsonify }}
|
||||
|
||||
{{/* Render a container that Preact will populate */}}
|
||||
<div
|
||||
id="{{ $block_id }}"
|
||||
class="{{ $block_type }}-block-container preact-block"
|
||||
data-block-type="{{ $block_type }}"
|
||||
data-props='{{ $propsJSON | safeHTML }}'
|
||||
data-preact-render="true"
|
||||
>
|
||||
{{/* Empty - Preact renders everything */}}
|
||||
{{/* Could add a loading skeleton here if desired */}}
|
||||
</div>
|
||||
|
||||
{{/* Preact script loading is handled by libraries.html */}}
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
{{/* HB Tailwind CSS v4 Processing with Hugo's Native Function */}}
|
||||
{{ with resources.Get "css/main.css" }}
|
||||
{{/* Build dynamic @source list and prepend it before main.css */}}
|
||||
{{ $dynamic_sources_str := partial "tailwind_sources.html" . }}
|
||||
{{ $dynamic_sources_res := resources.FromString "css/_dynamic_sources.css" $dynamic_sources_str }}
|
||||
{{ $main_css := . }}
|
||||
{{ $entry := slice $dynamic_sources_res $main_css | resources.Concat "css/_entry.css" }}
|
||||
{{ $opts := dict "minify" (not hugo.IsDevelopment) }}
|
||||
{{ with . | css.TailwindCSS $opts }}
|
||||
{{ with $entry | css.TailwindCSS $opts }}
|
||||
{{ if hugo.IsDevelopment }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{ else }}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{{/* Pragmatic deep merge for block sections: shallow merge + merge 'content' and 'design' submaps if present. b overrides a. */}}
|
||||
{{- $a := .a -}}
|
||||
{{- $b := .b -}}
|
||||
{{- if and (reflect.IsMap $a) (reflect.IsMap $b) -}}
|
||||
{{- $result := merge $a $b -}}
|
||||
{{- /* merge 'content' submap */ -}}
|
||||
{{- $ac := index $a "content" -}}
|
||||
{{- $bc := index $b "content" -}}
|
||||
{{- if and (reflect.IsMap $ac) (reflect.IsMap $bc) -}}
|
||||
{{- $result = merge $result (dict "content" (merge $ac $bc)) -}}
|
||||
{{- end -}}
|
||||
{{- /* merge 'design' submap */ -}}
|
||||
{{- $ad := index $a "design" -}}
|
||||
{{- $bd := index $b "design" -}}
|
||||
{{- if and (reflect.IsMap $ad) (reflect.IsMap $bd) -}}
|
||||
{{- $result = merge $result (dict "design" (merge $ad $bd)) -}}
|
||||
{{- end -}}
|
||||
{{- return $result -}}
|
||||
{{- else -}}
|
||||
{{- return $b -}}
|
||||
{{- end -}}
|
||||
@@ -23,7 +23,7 @@
|
||||
{{ with resources.GetMatch (path.Join "media" "icons" $pack (printf "%s.svg" $name)) }}
|
||||
{{ $icon = .Content }}
|
||||
{{else}}
|
||||
{{ warnf "The icon `%s.svg` was not found in your `assets/media/icons/%s/` folder" $name $pack }}
|
||||
{{ partial "functions/logger" (dict "page" $.Page "level" "warn" "message" (printf "The icon `%s.svg` was not found in your `assets/media/icons/%s/` folder" $name $pack)) }}
|
||||
{{ $icon = index (index site.Data.icons.brands "icons") "hugo" }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
{{/* Hugo Blox: Get Icon Data for Preact Components */}}
|
||||
{{/* Documentation: https://hugoblox.com/blocks/ */}}
|
||||
{{/* License: https://github.com/HugoBlox/hugo-blox-builder/blob/main/LICENSE.md */}}
|
||||
|
||||
{{/*
|
||||
This partial returns raw SVG content for icons, designed for Preact component integration.
|
||||
|
||||
PURPOSE:
|
||||
- Provides SVG strings that can be passed as props to Preact components
|
||||
- Enables dynamic icon rendering in client-side Preact blocks
|
||||
- Mirrors get_icon.html logic but returns raw content instead of safeHTML
|
||||
|
||||
DIFFERENCE FROM get_icon.html:
|
||||
- get_icon.html: Returns safeHTML for direct template rendering in Go HTML templates
|
||||
- get_icon_data.html: Returns raw SVG string for JavaScript/Preact component consumption
|
||||
|
||||
USAGE:
|
||||
{{ $icon_svg := partial "functions/get_icon_data" (dict "name" "arrow-right" "pack" "hero") }}
|
||||
Then pass $icon_svg as a prop to Preact components for client-side rendering.
|
||||
|
||||
ICON PACK HANDLING:
|
||||
1. Hero pack (heroicons): Assembles <svg> wrapper around "body" content using pack "height"
|
||||
2. HB/Brands packs: Returns stored SVG strings as-is
|
||||
3. User assets: Returns content from assets/media/icons/{pack}/{name}.svg
|
||||
4. Fallback: Returns Hugo brand icon if not found
|
||||
|
||||
PARAMETERS:
|
||||
- name: Icon name, optionally with pack prefix (e.g., "arrow-right" or "hero/arrow-right")
|
||||
- pack: Icon pack name (defaults to "hero" if not specified in name)
|
||||
*/}}
|
||||
|
||||
{{/* Return the raw SVG content for a requested icon */}}
|
||||
{{- $name := .name | default "" -}}
|
||||
{{- $icon_content := "" -}}
|
||||
|
||||
{{- if $name -}}
|
||||
{{- $dirFile := path.Split $name -}}
|
||||
{{- $pack := .pack | default (strings.Replace $dirFile.Dir "/" "") | default "hero" -}}
|
||||
{{- $iconName := $dirFile.File -}}
|
||||
{{- $icon_pack := index site.Data.icons $pack -}}
|
||||
|
||||
{{- with index (index $icon_pack "icons") $iconName -}}
|
||||
{{- /* If this pack stores full SVG strings (hb/brands), return as-is. */ -}}
|
||||
{{- if in (slice "hb" "brands") $pack -}}
|
||||
{{- $icon_content = . -}}
|
||||
{{- else -}}
|
||||
{{- $icon_body := index . "body" -}}
|
||||
{{- $icon_size := index $icon_pack "height" -}}
|
||||
{{- $icon_content = printf `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %s %s">%s</svg>` (cast.ToString $icon_size) (cast.ToString $icon_size) $icon_body -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- with resources.GetMatch (path.Join "media" "icons" $pack (printf "%s.svg" $iconName)) -}}
|
||||
{{- $icon_content = .Content -}}
|
||||
{{- else -}}
|
||||
{{- /* Fallback to a default icon if not found. */ -}}
|
||||
{{- with index (index site.Data.icons.brands "icons") "hugo" -}}
|
||||
{{- $icon_content = . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $icon_content -}}
|
||||
@@ -0,0 +1,38 @@
|
||||
{{/* Hugo Blox Logger: centralized logging helper
|
||||
Usage: partial "functions/logger" (dict "page" . "level" "warn" "message" (printf "..." args...))
|
||||
- level: "warn" (default) or "error"
|
||||
- page: optional; current page. Defaults to dot. Used to detect adapter pages
|
||||
- adapter: optional bool to force adapter-safe mode (e.g., from _content.gotmpl)
|
||||
*/}}
|
||||
{{- $level := lower (.level | default "warn") -}}
|
||||
{{- $msg := .message | default "" -}}
|
||||
{{- $page := .page | default . -}}
|
||||
{{- $forceAdapter := .adapter | default false -}}
|
||||
{{- $isDev := or hugo.IsServer (eq hugo.Environment "development") -}}
|
||||
|
||||
{{/* Detect adapter-generated pages via explicit flag or page param */}}
|
||||
{{- $isAdapter := $forceAdapter -}}
|
||||
{{- if not $isAdapter -}}
|
||||
{{- with $page -}}
|
||||
{{- with .Params -}}
|
||||
{{- if or (index . "hb_adapter") (eq (printf "%T" .) "map[string]interface {}" | and (index . "hb_adapter")) -}}
|
||||
{{- $isAdapter = true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $level "error" -}}
|
||||
{{- if not $isAdapter -}}
|
||||
{{- errorf "%s" $msg -}}
|
||||
{{- else -}}
|
||||
{{- if $isDev -}}<!-- HBX log:error: {{ $msg }} -->{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- if not $isAdapter -}}
|
||||
{{- warnf "%s" $msg -}}
|
||||
{{- else -}}
|
||||
{{- if $isDev -}}<!-- HBX log:warn: {{ $msg }} -->{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- "" -}}
|
||||
@@ -332,7 +332,7 @@
|
||||
|
||||
{{/* Now loaded in `init.html` */}}
|
||||
{{/*
|
||||
{{ $widget_config_file := printf "blox/%s--CONFIG.html" $block_type }}
|
||||
{{ $widget_config_file := printf "blox/%s/config.html" $block_type }}
|
||||
{{ if templates.Exists (printf "_partials/%s" $widget_config_file) }}
|
||||
{{ $cfg := partial $widget_config_file $widget_args }}
|
||||
{{ with $cfg.use_container }}{{ $use_container = . }}{{ end }}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
{{/* Hugo Blox Parser v3 - Preact Component Support */}}
|
||||
{{/* Documentation: https://hugoblox.com/blocks/ */}}
|
||||
{{/* License: https://github.com/HugoBlox/hugo-blox-builder/blob/main/LICENSE.md */}}
|
||||
|
||||
{{ $page := .page }}
|
||||
{{ $block := .block }}
|
||||
|
||||
{{- $block_type := partial "hbx/resolve-block-param" (dict "config" $block "context" "content section") | default "markdown" -}}
|
||||
{{ $block_type = lower $block_type }}
|
||||
|
||||
{{/* Handle block renames/aliases */}}
|
||||
{{ range $r := site.Data.blox_aliases.renames }}
|
||||
{{ $block_type = cond (eq $block_type $r.old) $r.new $block_type }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Check if this is a Preact-enabled block by looking for component file */}}
|
||||
{{ $component_path := printf "js/hbx/blocks/%s/component.jsx" $block_type }}
|
||||
{{ $is_preact := resources.Get $component_path }}
|
||||
|
||||
{{/* Apply styling wrapper for all blocks (both Preact and traditional) */}}
|
||||
{{ $bg := $block.design.background }}
|
||||
{{ $style := "" }}
|
||||
{{ $style_bg := "" }}
|
||||
|
||||
{{/* Process background colors */}}
|
||||
{{ if $bg.color }}
|
||||
{{ $color_type := printf "%T" $bg.color }}
|
||||
{{ if eq $color_type "map[string]interface {}" }}
|
||||
{{ if and $bg.color.light $bg.color.dark }}
|
||||
{{ $light_color := $bg.color.light }}
|
||||
{{ $dark_color := $bg.color.dark }}
|
||||
|
||||
{{ $style_bg = printf "background-color: %s;" $light_color }}
|
||||
{{ $style_bg = printf "%s--dark-bg-color: %s;" $style_bg $dark_color }}
|
||||
{{ else if $bg.color.light }}
|
||||
{{ $light_color := $bg.color.light }}
|
||||
{{ $style_bg = printf "background-color: %s;" $light_color }}
|
||||
{{ else if $bg.color.dark }}
|
||||
{{ $dark_color := $bg.color.dark }}
|
||||
{{ $style_bg = printf "--dark-bg-color: %s; background-color: var(--dark-bg-color);" $dark_color }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ $bg_color := $bg.color }}
|
||||
{{ $style_bg = printf "background-color: %s;" $bg_color }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Process gradients and images */}}
|
||||
{{ $background_layers := slice }}
|
||||
{{ $gradient_layer := "" }}
|
||||
|
||||
{{ if and $bg.gradient.start $bg.gradient.end }}
|
||||
{{ $angle := string $bg.gradient.direction | default "135" }}
|
||||
{{ $start_color := $bg.gradient.start }}
|
||||
{{ $end_color := $bg.gradient.end }}
|
||||
{{ $gradient_layer = printf "linear-gradient(%sdeg, %s, %s)" $angle $start_color $end_color }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $bg.image.filename }}
|
||||
{{ $bg_img := resources.Get (printf "media/%s" $bg.image.filename) }}
|
||||
{{ if $bg_img }}
|
||||
{{ if ne $bg_img.MediaType.SubType "svg" }}
|
||||
{{ $bg_img = $bg_img.Fit "1920x1920 webp" }}
|
||||
{{ end }}
|
||||
{{ $image_layer := printf "url('%s')" $bg_img.Permalink }}
|
||||
{{ $background_layers = $background_layers | append $image_layer }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if or $background_layers $gradient_layer }}
|
||||
{{ $all_layers := $background_layers }}
|
||||
{{ if $gradient_layer }}
|
||||
{{ $all_layers = $all_layers | append $gradient_layer }}
|
||||
{{ end }}
|
||||
{{ if $all_layers }}
|
||||
{{ $combined_backgrounds := delimit $all_layers ", " }}
|
||||
{{ $style_bg = printf "%sbackground-image: %s;" $style_bg $combined_backgrounds }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ with $block.design.spacing.padding }}
|
||||
{{ $style_pad := printf "padding: %s;" (delimit . " ") }}
|
||||
{{ $style = print $style $style_pad }}
|
||||
{{ end }}
|
||||
|
||||
{{ with $block.design.css_style }}
|
||||
{{ $style = print $style . }}
|
||||
{{ end }}
|
||||
|
||||
{{ $hash_id := $block.id | default (printf "section-%s" (replace $block_type "." "-")) }}
|
||||
{{ $css_classes := $block.design.css_class | default "" }}
|
||||
{{ $widget_class := printf "blox-%s" (replace (replace $block_type "." "-") "_" "-") }}
|
||||
|
||||
{{/* Route to appropriate handler */}}
|
||||
{{ if $is_preact }}
|
||||
{{/* Render Preact block with styling wrapper */}}
|
||||
<section id="{{$hash_id}}" class="relative hbb-section {{$widget_class}} {{if $bg.text_color_light}}dark{{else if (eq $bg.text_color_light false)}}light{{end}} {{with $css_classes}}{{.}}{{end}}" {{with $style}}style="{{. | safeCSS}}"{{end}}>
|
||||
<div class="home-section-bg {{if $bg.image}} bg-image{{if ($bg.image.parallax | default true) }} parallax{{end}}{{end}}" {{with $style_bg}}style="{{. | safeCSS}}"{{end}}></div>
|
||||
{{/* Use generic Preact wrapper for content */}}
|
||||
{{ partial "blox/preact-wrapper" (dict "wcPage" $page "wcBlock" $block "wcBlockType" $block_type "wcIdentifier" $hash_id) }}
|
||||
</section>
|
||||
{{ else }}
|
||||
{{/* Fall back to traditional Go template blocks */}}
|
||||
{{ $block_path := printf "hbx/blocks/%s/block.html" $block_type }}
|
||||
{{ if not (templates.Exists (printf "_partials/%s" $block_path)) }}
|
||||
{{ errorf "%s uses a `%s` block but the `%s` block was not found at `%s`. Check the name of the block and ensure it exists in the blox/%s/ directory." $page.File.Path $block_type $block_type $block_path $block_type }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Handle legacy block requirements */}}
|
||||
{{ if $block.Page.Store.Get "has_mermaid" }}
|
||||
{{ $page.Page.Store.Set "has_mermaid" true }}
|
||||
{{ end }}
|
||||
|
||||
{{ if (gt (len (findRE `\{\{< gallery` $block.content.text 1)) 0) }}
|
||||
{{ $page.Page.Store.Set "has_gallery" true }}
|
||||
{{ end }}
|
||||
|
||||
{{ $widget_args := dict "wcPage" $page "wcBlock" $block "wcIdentifier" $hash_id }}
|
||||
|
||||
{{/* Render traditional block with wrapper */}}
|
||||
<section id="{{$hash_id}}" class="relative hbb-section {{$widget_class}} {{if $bg.text_color_light}}dark{{else if (eq $bg.text_color_light false)}}light{{end}} {{with $css_classes}}{{.}}{{end}}" {{with $style}}style="{{. | safeCSS}}"{{end}}>
|
||||
<div class="home-section-bg {{if $bg.image}} bg-image{{if ($bg.image.parallax | default true) }} parallax{{end}}{{end}}" {{with $style_bg}}style="{{. | safeCSS}}"{{end}}></div>
|
||||
{{ partial $block_path $widget_args }}
|
||||
</section>
|
||||
{{ end }}
|
||||
@@ -1,11 +1,105 @@
|
||||
{{/* Returns sections from front matter or from data. */}}
|
||||
{{/* Returns sections from front matter, linked data, or from data. */}}
|
||||
{{- $sections := .Params.sections -}}
|
||||
{{- if not $sections -}}
|
||||
{{/* Data-driven pages. */}}
|
||||
{{- $p := .File.PathBase -}}
|
||||
{{- with index site.Data.pages $p -}}
|
||||
{{- $sections = .sections -}}
|
||||
{{- warnf "HBX: Using data-driven sections from data/pages/%s for page %s" $p $.RelPermalink -}}
|
||||
{{- $source := "front matter" -}}
|
||||
|
||||
{{/* 1) Linked-data: sections_source */}}
|
||||
{{- with .Params.sections_source -}}
|
||||
{{- $key := . -}}
|
||||
{{- if hasPrefix $key "pages/" -}}{{- $key = (replace $key "pages/" "") -}}{{- end -}}
|
||||
{{- with index site.Data.pages $key -}}
|
||||
{{- $base := .sections -}}
|
||||
{{- if $sections -}}
|
||||
{{- $merged := slice -}}
|
||||
{{- range $i, $b := $base -}}
|
||||
{{- $ov := index $sections $i -}}
|
||||
{{- if $ov -}}
|
||||
{{- $merged = $merged | append (partial "functions/deep_merge" (dict "a" $b "b" $ov)) -}}
|
||||
{{- else -}}
|
||||
{{- $merged = $merged | append $b -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if gt (len $sections) (len $base) -}}
|
||||
{{- range $i, $ov := $sections -}}
|
||||
{{- if ge $i (len $base) -}}
|
||||
{{- $merged = $merged | append $ov -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $sections = $merged -}}
|
||||
{{- else -}}
|
||||
{{- $sections = $base -}}
|
||||
{{- end -}}
|
||||
{{- $source = printf "data/pages/%s.yaml (sections_source)" $key -}}
|
||||
{{- else -}}
|
||||
{{- partial "functions/logger" (dict "page" . "level" "warn" "message" (printf "HBX: sections_source '%s' not found under data/pages/" $key)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* 2) Fallbacks if still no sections */}}
|
||||
{{- if not $sections -}}
|
||||
{{/* Fallback: Legacy data-driven pages */}}
|
||||
{{- $p := "home" -}}{{/* Default to "home" for homepage */}}
|
||||
{{- with .File -}}
|
||||
{{- $basename := .ContentBaseName -}}
|
||||
{{- if $basename -}}
|
||||
{{- $p = $basename -}}
|
||||
{{/* Special case: homepage _index.md should use "home" data file */}}
|
||||
{{- if eq $p "_index" -}}
|
||||
{{- $p = "home" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{/* Ensure homepage always uses "home" data file */}}
|
||||
{{- if eq $.RelPermalink "/" -}}
|
||||
{{- $p = "home" -}}
|
||||
{{- end -}}
|
||||
{{- with index site.Data.pages $p -}}
|
||||
{{- $sections = .sections -}}
|
||||
{{- $source = printf "data/pages/%s.yaml" $p -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* 3) Per-section ref: load from data/blocks/<slug>.yaml and deep-merge with inline (inline wins) */}}
|
||||
{{- if $sections -}}
|
||||
{{- $resolved := slice -}}
|
||||
{{- range $i, $s := $sections -}}
|
||||
{{- $sec := $s -}}
|
||||
{{- with $s.ref -}}
|
||||
{{- $ref := . | lower -}}
|
||||
{{- $path := cond (hasPrefix $ref "blocks/") $ref (printf "blocks/%s" $ref) -}}
|
||||
{{- $parts := split $path "/" -}}
|
||||
{{- $data := site.Data -}}
|
||||
{{- range $j, $p := $parts -}}
|
||||
{{- if $data -}}
|
||||
{{- $data = index $data $p -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if $data -}}
|
||||
{{- /* shallow merge */ -}}
|
||||
{{- $merged := merge $data $sec -}}
|
||||
{{- /* merge 'content' */ -}}
|
||||
{{- $ac := index $data "content" -}}{{- $bc := index $sec "content" -}}
|
||||
{{- if and (reflect.IsMap $ac) (reflect.IsMap $bc) -}}
|
||||
{{- $merged = merge $merged (dict "content" (merge $ac $bc)) -}}
|
||||
{{- end -}}
|
||||
{{- /* merge 'design' */ -}}
|
||||
{{- $ad := index $data "design" -}}{{- $bd := index $sec "design" -}}
|
||||
{{- if and (reflect.IsMap $ad) (reflect.IsMap $bd) -}}
|
||||
{{- $merged = merge $merged (dict "design" (merge $ad $bd)) -}}
|
||||
{{- end -}}
|
||||
{{- $sec = $merged -}}
|
||||
{{- else -}}
|
||||
{{- partial "functions/logger" (dict "page" $ "level" "warn" "message" (printf "HBX: section ref '%s' not found under data/blocks/" $ref)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $resolved = $resolved | append $sec -}}
|
||||
{{- end -}}
|
||||
{{- $sections = $resolved -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $sections -}}
|
||||
{{- partial "functions/logger" (dict "page" . "level" "warn" "message" (printf "HBX: Using sections from %s for page %s (found %d sections)" $source $.RelPermalink (len $sections))) -}}
|
||||
{{- else -}}
|
||||
{{- partial "functions/logger" (dict "page" . "level" "warn" "message" (printf "HBX: No sections found for page %s (checked %s)" $.RelPermalink $source)) -}}
|
||||
{{- end -}}
|
||||
{{- return $sections -}}
|
||||
@@ -10,7 +10,79 @@
|
||||
{{/* Preload block configs for landing pages */}}
|
||||
{{- range where .Site.Pages "Type" "landing" -}}
|
||||
{{ $page := . }}
|
||||
{{ range $index, $block := .Params.sections }}
|
||||
{{/* Resolve sections: front matter, sections_source, fallback to data/pages */}}
|
||||
{{ $sections := $page.Params.sections }}
|
||||
|
||||
{{/* Linked-data: sections_source support */}}
|
||||
{{ with $page.Params.sections_source }}
|
||||
{{ $key := . }}
|
||||
{{ if hasPrefix $key "pages/" }}{{ $key = replace $key "pages/" "" }}{{ end }}
|
||||
{{ with index $.Site.Data.pages $key }}
|
||||
{{ $base := .sections }}
|
||||
{{ if $sections }}
|
||||
{{ $merged := slice }}
|
||||
{{ range $i, $b := $base }}
|
||||
{{ $ov := index $sections $i }}
|
||||
{{ if $ov }}
|
||||
{{ $merged = $merged | append (merge $b $ov) }}
|
||||
{{ else }}
|
||||
{{ $merged = $merged | append $b }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if gt (len $sections) (len $base) }}
|
||||
{{ range $i, $ov := $sections }}
|
||||
{{ if ge $i (len $base) }}
|
||||
{{ $merged = $merged | append $ov }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ $sections = $merged }}
|
||||
{{ else }}
|
||||
{{ $sections = $base }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if not $sections }}
|
||||
{{/* Data-driven fallback (home) */}}
|
||||
{{ $p := "home" }}
|
||||
{{ with $page.File }}
|
||||
{{ $basename := .ContentBaseName }}
|
||||
{{ if $basename }}
|
||||
{{ $p = $basename }}
|
||||
{{ if eq $p "_index" }}{{ $p = "home" }}{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if eq $page.RelPermalink "/" }}{{ $p = "home" }}{{ end }}
|
||||
{{ with index $.Site.Data.pages $p }}
|
||||
{{ $sections = .sections }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Resolve per-section ref from data/blocks/* for block detection */}}
|
||||
{{ if $sections }}
|
||||
{{ $resolved := slice }}
|
||||
{{ range $i, $s := $sections }}
|
||||
{{ $sec := $s }}
|
||||
{{ with $s.ref }}
|
||||
{{ $ref := lower . }}
|
||||
{{ $path := cond (hasPrefix $ref "blocks/") $ref (printf "blocks/%s" $ref) }}
|
||||
{{ $parts := split $path "/" }}
|
||||
{{ $data := $.Site.Data }}
|
||||
{{ range $j, $p := $parts }}
|
||||
{{ if $data }}{{ $data = index $data $p }}{{ end }}
|
||||
{{ end }}
|
||||
{{ if $data }}
|
||||
{{/* Shallow merge so base can provide block type */}}
|
||||
{{ $sec = merge $data $sec }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ $resolved = $resolved | append $sec }}
|
||||
{{ end }}
|
||||
{{ $sections = $resolved }}
|
||||
{{ end }}
|
||||
|
||||
{{ range $index, $block := $sections }}
|
||||
{{/* Do not show sections intended only for the demo site. */}}
|
||||
{{ if or (not $block.demo) ($block.demo | and (eq (os.Getenv "HUGO_BLOX_DEMO") "true")) }}
|
||||
{{- $block_type := partial "hbx/resolve-block-param" (dict "config" $block "context" "content section") | default "markdown" -}}
|
||||
@@ -23,7 +95,19 @@
|
||||
{{ $current_blocks := $page.Store.Get "block_types" | default (slice) }}
|
||||
{{ $page.Store.Set "block_types" ($current_blocks | append $block_type) }}
|
||||
|
||||
{{ $widget_config_file := printf "blox/%s--CONFIG.html" $block_type }}
|
||||
{{/* Check if this is a Preact-enabled block that needs hydration */}}
|
||||
{{ $component_path := printf "js/hbx/blocks/%s/client.jsx" $block_type }}
|
||||
{{ if resources.Get $component_path }}
|
||||
{{ $page.Store.Set "needs_preact" true }}
|
||||
{{/* Store which Preact blocks are used on this page */}}
|
||||
{{ $preact_blocks := $page.Store.Get "preact_blocks" | default slice }}
|
||||
{{ if not (in $preact_blocks $block_type) }}
|
||||
{{ $preact_blocks = $preact_blocks | append $block_type }}
|
||||
{{ $page.Store.Set "preact_blocks" $preact_blocks }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ $widget_config_file := printf "blox/%s/config.html" $block_type }}
|
||||
{{ if templates.Exists (printf "_partials/%s" $widget_config_file) }}
|
||||
{{ $hash_id := $block.id | default (printf "section-%s" (replace $block_type "." "-")) }}
|
||||
{{ $widget_args := dict "wcPage" $page "wcBlock" $block "wcIdentifier" $hash_id }}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
{{ range $index, $block := $sections }}
|
||||
{{/* Do not show sections intended only for the demo site. */}}
|
||||
{{ if or (not $block.demo) ($block.demo | and (eq (os.Getenv "HUGO_BLOX_DEMO") "true")) }}
|
||||
{{ partial "functions/parse_block_v2" (dict "page" $ "block" $block) }}
|
||||
{{ partial "functions/parse_block_v3" (dict "page" $ "block" $block) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
@@ -1,3 +1,46 @@
|
||||
{{/* Load Preact for component-based blocks */}}
|
||||
{{/* Check if any blocks on this page use Preact (set by init.html) */}}
|
||||
{{ if .Page.Store.Get "needs_preact" }}
|
||||
{{ $preact_blocks := .Page.Store.Get "preact_blocks" | default slice }}
|
||||
|
||||
{{/* Load Preact core library */}}
|
||||
{{ $preact_core := resources.Get "dist/lib/preact/preact.min.js" }}
|
||||
{{ if $preact_core }}
|
||||
{{ $preact_core = $preact_core | resources.Fingerprint "sha256" }}
|
||||
<script src="{{ $preact_core.RelPermalink }}" integrity="{{ $preact_core.Data.Integrity }}"></script>
|
||||
|
||||
{{/* Publish the source map so the browser can load it at the expected path */}}
|
||||
{{ $preact_map := resources.Get "dist/lib/preact/preact.min.js.map" }}
|
||||
{{ if $preact_map }}
|
||||
{{ $preact_map.Publish }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{/* Build and load each Preact block's client script */}}
|
||||
{{ range $block_type := $preact_blocks }}
|
||||
{{ $client_path := printf "js/hbx/blocks/%s/client.jsx" $block_type }}
|
||||
{{ $client_jsx := resources.Get $client_path }}
|
||||
|
||||
{{ if $client_jsx }}
|
||||
{{/* Build the client-side JSX using Hugo's official integration */}}
|
||||
{{ $jsx_opts := dict
|
||||
"targetPath" (printf "js/%s-preact.js" $block_type)
|
||||
"JSX" "automatic"
|
||||
"JSXImportSource" "preact"
|
||||
"format" "iife"
|
||||
"minify" hugo.IsProduction
|
||||
"sourceMap" (cond hugo.IsDevelopment "external" "")
|
||||
}}
|
||||
{{ $built_jsx := $client_jsx | js.Build $jsx_opts }}
|
||||
{{ if hugo.IsProduction }}
|
||||
{{ $built_jsx = $built_jsx | fingerprint "sha256" }}
|
||||
{{ end }}
|
||||
<script defer src="{{ $built_jsx.RelPermalink }}"{{ if hugo.IsProduction }} integrity="{{ $built_jsx.Data.Integrity }}"{{ end }}></script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Load Alpine JS extension? */}}
|
||||
{{ if (.Page.Store.Get "has_alpine") }}
|
||||
<script>console.log('✓ Alpine.js loading on demand');</script>
|
||||
@@ -100,4 +143,4 @@
|
||||
{{ $plotly_js := resources.Get "dist/lib/plotly/plotly.min.js" }}
|
||||
{{ $plotly_js = $plotly_js | resources.Fingerprint "sha256" }}
|
||||
<script defer src="{{ $plotly_js.RelPermalink }}" integrity="{{ $plotly_js.Data.Integrity }}"></script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
@@ -176,7 +176,6 @@
|
||||
{{ $font_type = "woff2" }}
|
||||
{{end}}
|
||||
{{ $font := resources.Get (printf "dist/font/%s" $font_file) }}
|
||||
<link rel="preload" href="{{ $font.RelPermalink }}" as="font" type="font/{{ $font_type }}" crossorigin>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: '{{$font_family}}';
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
{{/* Hugo Blox: Dynamic Tailwind @source generation for Hugo modules */}}
|
||||
{{/* Documentation: https://hugoblox.com/docs/ */}}
|
||||
{{/* License: https://github.com/HugoBlox/hugo-blox-builder/blob/main/LICENSE.md */}}
|
||||
|
||||
{{/*
|
||||
This partial generates Tailwind CSS @source directives that tell Tailwind where to scan for CSS classes.
|
||||
|
||||
CRITICAL: Tailwind scans the actual filesystem (relative to main.css), while Hugo operates on a virtual
|
||||
filesystem with module mounts. This file bridges that gap by translating Hugo's virtual paths to actual
|
||||
filesystem paths that Tailwind can find.
|
||||
|
||||
Environments handled:
|
||||
1. Test site (HUGO_BLOX_TEST_SITE=true): runs from test/, so ../modules/blox-tailwind/ for theme files
|
||||
2. Starter sites (HUGO_BLOX_MONOREPO=true): run from starters/[name]/, so ../../../modules/blox-tailwind/
|
||||
3. End-user sites: use virtual mounted paths from Hugo modules (standard content/, layouts/, assets/)
|
||||
|
||||
Without this, Tailwind would miss classes from:
|
||||
* Hugo Blox theme templates (layouts/, blox/)
|
||||
* Preact components (blox/** /*.jsx) - intentional space due to Hugo bug thinking '* /' is commend end
|
||||
* Site content (content/** /*.md) - intentional space due to Hugo bug thinking '* /' is commend end
|
||||
* Generated HTML classes (hugo_stats.json)
|
||||
*/}}
|
||||
{{ $is_monorepo := eq (os.Getenv "HUGO_BLOX_MONOREPO") "true" }}
|
||||
{{ $is_test_site := eq (os.Getenv "HUGO_BLOX_TEST_SITE") "true" }}
|
||||
{{ $paths := slice }}
|
||||
|
||||
{{/* 1. Always add paths relative to the current site's root (content, layouts, etc.) */}}
|
||||
{{ $paths = $paths | append `content/**/*.md` }}
|
||||
{{ $paths = $paths | append `layouts/**/*.html` }}
|
||||
{{ $paths = $paths | append `assets/js/**/*.js` }}
|
||||
{{ $paths = $paths | append `hugo_stats.json` }}
|
||||
|
||||
{{/* 2. If in monorepo, add relative paths to the blox-tailwind module source */}}
|
||||
{{ if $is_monorepo }}
|
||||
{{ $module_path_prefix := "" }}
|
||||
{{ if $is_test_site }}
|
||||
{{/* Test site is at `test/`, so one level up to repo root */}}
|
||||
{{ $module_path_prefix = "../" }}
|
||||
{{ else }}
|
||||
{{/* Starter sites are at `starters/[name]/`, so three levels up */}}
|
||||
{{ $module_path_prefix = "../../../" }}
|
||||
{{ end }}
|
||||
|
||||
{{ $module_path := printf "%smodules/blox-tailwind" $module_path_prefix }}
|
||||
{{ $paths = $paths | append (printf `%s/layouts/**/*.html` $module_path) }}
|
||||
{{ $paths = $paths | append (printf `%s/assets/js/**/*.js` $module_path) }}
|
||||
{{ $paths = $paths | append (printf `%s/blox/**/*.html` $module_path) }}
|
||||
{{ $paths = $paths | append (printf `%s/blox/**/*.jsx` $module_path) }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Generate the @source rules */}}
|
||||
{{ range $paths }}
|
||||
@source "{{ . }}";
|
||||
{{ end }}
|
||||
@@ -1,33 +1,22 @@
|
||||
{
|
||||
"name": "blox-tailwind",
|
||||
"description": "Hugo Blox Tailwind UI",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"packageManager": "pnpm@10.14.0",
|
||||
"name": "@hugoblox/blox-tailwind",
|
||||
"version": "1.0.0",
|
||||
"description": "Hugo Blox Tailwind UI Components",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "hugo server --source=../../test --config=../../test/config.yaml --themesDir=../.. --buildDrafts --buildFuture --disableFastRender",
|
||||
"build": "hugo --source=../../test --config=../../test/config.yaml --themesDir=../.. --minify",
|
||||
"type-check": "tsc --noEmit",
|
||||
"lint": "biome check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"tailwindcss": "^4.1.12",
|
||||
"@tailwindcss/cli": "^4.1.12",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"alpinejs": "^3.13.10",
|
||||
"katex": "^0.16.9",
|
||||
"markmap-autoloader": "^0.15.4",
|
||||
"mermaid": "^10.6.0",
|
||||
"plotly.js": "^2.27.0",
|
||||
"vite": "^7.1.2",
|
||||
"vite-plugin-static-copy": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
"@preact/preset-vite": "^2.8.1",
|
||||
"@types/node": "^20.10.5",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"homepage": "https://hugoblox.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/HugoBlox/hugo-blox-builder.git"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "hugo server --disableFastRender",
|
||||
"build": "hugo --minify",
|
||||
"assets:dist": "vite build"
|
||||
},
|
||||
"browserslist": "last 2 versions"
|
||||
}
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
}
|
||||
Generated
+464
-3148
File diff suppressed because it is too large.
Load diff
+9
-7
@@ -14,12 +14,13 @@
|
||||
"url": "git+https://github.com/HugoBlox/hugo-blox-builder.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"katex": "^0.16.9",
|
||||
"alpinejs": "^3.15.0",
|
||||
"katex": "^0.16.22",
|
||||
"markmap-autoloader": "^0.18.12",
|
||||
"medium-zoom": "^1.0.8",
|
||||
"mermaid": "^10.6.0",
|
||||
"markmap-autoloader": "^0.15.4",
|
||||
"alpinejs": "^3.13.10",
|
||||
"plotly.js": "^2.27.0",
|
||||
"mermaid": "^11.12.0",
|
||||
"plotly.js": "^3.1.0",
|
||||
"preact": "^10.27.2",
|
||||
"rollup-plugin-delete": "^2.0.0",
|
||||
"vite": "^7.1.2",
|
||||
"vite-hugo-plugin": "^3.1.0",
|
||||
@@ -34,7 +35,7 @@
|
||||
"scripts": {
|
||||
"prod": "scripts/view-starter-prod.sh",
|
||||
"dev": "scripts/view-starter-dev.sh",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"test": "scripts/view-test.sh",
|
||||
"lint": "pnpm run lint:code && pnpm run lint:style",
|
||||
"lint:code": "biome check --reporter=summary .",
|
||||
"lint:code:fix": "biome check --write .",
|
||||
@@ -43,7 +44,8 @@
|
||||
"format": "pnpm run lint:code:fix && pnpm run lint:style:fix",
|
||||
"update:starters": "poetry run python ./scripts/update.py",
|
||||
"vendor:libs": "vite build --config vite.config.js",
|
||||
"vendor:libs:watch": "vite build --config vite.config.js --watch"
|
||||
"vendor:libs:watch": "vite build --config vite.config.js --watch",
|
||||
"vendor:update-and-build": "pnpm up katex mermaid markmap-autoloader alpinejs plotly.js preact --latest && pnpm vendor:libs"
|
||||
},
|
||||
"browserslist": "> 1%"
|
||||
}
|
||||
Generated
+592
-944
File diff suppressed because it is too large.
Load diff
@@ -70,6 +70,7 @@ fi
|
||||
export HUGO_BLOX_DEMO=true
|
||||
export HUGO_BLOX_DEBUG=true
|
||||
export HUGO_ENVIRONMENT=development
|
||||
export HUGO_BLOX_MONOREPO=true
|
||||
export HUGOxPARAMSxDECAP_CMSxLOCAL_BACKEND=true
|
||||
|
||||
# Link local modules for development (Hugo module replacements)
|
||||
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
INITIAL_DIR="$(pwd)"
|
||||
|
||||
cleanup() {
|
||||
cd "$INITIAL_DIR" || true
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
usage() {
|
||||
echo "View the test site with local development modules."
|
||||
echo ""
|
||||
echo "Usage: ./scripts/view-test.sh [--debug]"
|
||||
echo "Example: ./scripts/view-test.sh --debug"
|
||||
echo ""
|
||||
echo "This script uses:"
|
||||
echo " • Local development modules (via go.mod replace directives)"
|
||||
echo " • Development environment for testing"
|
||||
}
|
||||
|
||||
DEBUG_MODE=false
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--)
|
||||
# Skip the -- separator from pnpm
|
||||
shift
|
||||
;;
|
||||
--debug)
|
||||
DEBUG_MODE=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Unexpected argument: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Run Hugo from the test dir
|
||||
cd "test"
|
||||
|
||||
# Ensure dependencies are installed if needed
|
||||
if [ -f "package.json" ] && [ ! -x "node_modules/.bin/tailwindcss" ]; then
|
||||
echo "📦 Installing dependencies in test directory..."
|
||||
if command -v pnpm >/dev/null 2>&1; then
|
||||
pnpm install
|
||||
else
|
||||
npm install
|
||||
fi
|
||||
fi
|
||||
|
||||
# Core environment for local dev
|
||||
export HUGO_ENVIRONMENT=development
|
||||
export HUGO_BLOX_MONOREPO=true
|
||||
export HUGO_BLOX_TEST_SITE=true
|
||||
|
||||
# Note: The test/go.mod already has replace directives for local modules,
|
||||
# so we don't need HUGO_MODULE_REPLACEMENTS here
|
||||
|
||||
# Compose Hugo server args
|
||||
HUGO_ARGS=(
|
||||
server
|
||||
--disableFastRender
|
||||
--printI18nWarnings
|
||||
--printPathWarnings
|
||||
--gc
|
||||
-F
|
||||
--port 8082
|
||||
--bind 0.0.0.0
|
||||
)
|
||||
|
||||
if [ "$DEBUG_MODE" = true ]; then
|
||||
HUGO_ARGS+=(
|
||||
--logLevel debug
|
||||
--panicOnWarning
|
||||
--templateMetrics
|
||||
--templateMetricsHints
|
||||
--ignoreCache
|
||||
--noHTTPCache
|
||||
--renderStaticToDisk
|
||||
-D
|
||||
-E
|
||||
)
|
||||
fi
|
||||
|
||||
echo "🚀 Starting test site on http://localhost:8082"
|
||||
hugo "${HUGO_ARGS[@]}"
|
||||
+5
-14
@@ -1,18 +1,9 @@
|
||||
---
|
||||
title: Home
|
||||
date: 2023-11-01
|
||||
type: landing
|
||||
|
||||
sections:
|
||||
- block: markdown
|
||||
content:
|
||||
title: ⚡️ Section 1
|
||||
text: |
|
||||
Hello world 1 😃
|
||||

|
||||
- block: markdown
|
||||
content:
|
||||
title: 🎉 Section 2
|
||||
text: |
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi lacinia tortor a leo elementum, vitae sollicitudin diam posuere. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas blandit quam sed justo blandit, sed tincidunt metus accumsan. Aenean at lacus nec neque mollis consectetur. Nullam non lorem dignissim, hendrerit nibh ut, ultricies augue. Integer finibus pellentesque mauris, et consectetur orci. Etiam id massa elementum, dapibus velit quis, vestibulum neque. Aenean scelerisque et quam vel vehicula. Sed rutrum et eros vulputate mattis. In finibus metus vel orci porttitor cursus. Duis commodo sed urna at cursus. Quisque et est eget elit pharetra volutpat. Fusce eleifend, eros non tristique interdum, justo lectus convallis turpis, sit amet sagittis ante mauris scelerisque enim. Suspendisse volutpat ultrices urna ac vehicula.
|
||||
date: 2023-11-01
|
||||
# Sections are loaded from data/pages/home.yaml via hbx/sections.html
|
||||
---
|
||||
|
||||
This is the Hugo Blox test site home page.
|
||||
The page sections are dynamically loaded from `data/pages/home.yaml`.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Linked Blocks Demo
|
||||
type: landing
|
||||
date: 2025-09-22
|
||||
|
||||
# Test per-section refs (linked-data) with inline overrides (titles)
|
||||
sections:
|
||||
- ref: blocks/hero_basic
|
||||
content:
|
||||
title: "**Linked Blocks** Test Page"
|
||||
- ref: blocks/features_basic
|
||||
content:
|
||||
title: "What You Get"
|
||||
---
|
||||
@@ -0,0 +1,17 @@
|
||||
# Features block configuration using re-usable blocks approach (data/blocks/features_basic.yaml)
|
||||
block: features
|
||||
id: features
|
||||
content:
|
||||
title: "Why Choose Hugo Blox?"
|
||||
items:
|
||||
- name: "Lightning Fast"
|
||||
description: "Static site generation with Preact hydration"
|
||||
icon: "bolt"
|
||||
- name: "Type Safe"
|
||||
description: "Full TypeScript support for all components"
|
||||
icon: "shield-check"
|
||||
- name: "SEO Optimized"
|
||||
description: "Server-side rendering with progressive enhancement"
|
||||
icon: "magnifying-glass"
|
||||
design:
|
||||
columns: "3"
|
||||
@@ -0,0 +1,21 @@
|
||||
# Hero block configuration using re-usable blocks approach (data/blocks/hero_basic.yaml)
|
||||
block: hero
|
||||
content:
|
||||
title: "**Build Anything** with Hugo Blox"
|
||||
text: |
|
||||
Create stunning websites with our Preact-powered components.
|
||||
Fast, flexible, and future-proof.
|
||||
primary_action:
|
||||
text: "Get Started"
|
||||
url: "#features"
|
||||
icon: "arrow-right"
|
||||
secondary_action:
|
||||
text: "View Documentation"
|
||||
url: "/"
|
||||
design:
|
||||
css_class: "hero-gradient"
|
||||
background:
|
||||
gradient:
|
||||
start: "primary-600"
|
||||
end: "primary-400"
|
||||
direction: "135"
|
||||
@@ -0,0 +1,61 @@
|
||||
# Home page configuration using data-driven approach (data/pages/home.yaml)
|
||||
title: Home
|
||||
type: landing
|
||||
date: 2023-11-01
|
||||
|
||||
sections:
|
||||
- block: hero
|
||||
content:
|
||||
title: "**Build Anything** with Hugo Blox"
|
||||
text: |
|
||||
Create stunning websites with our Preact-powered components.
|
||||
Fast, flexible, and future-proof.
|
||||
announcement:
|
||||
text: "🎉 Introducing Preact Components"
|
||||
link:
|
||||
text: "Learn more"
|
||||
url: "/linked"
|
||||
primary_action:
|
||||
text: "Get Started"
|
||||
url: "#features"
|
||||
icon: "hero/arrow-right"
|
||||
secondary_action:
|
||||
text: "View Documentation"
|
||||
url: "/linked"
|
||||
design:
|
||||
css_class: "hero-gradient"
|
||||
background:
|
||||
gradient:
|
||||
start: "primary-600"
|
||||
end: "primary-400"
|
||||
direction: "135"
|
||||
|
||||
- block: features
|
||||
id: features
|
||||
content:
|
||||
title: "Why Choose Hugo Blox?"
|
||||
items:
|
||||
- name: "Lightning Fast"
|
||||
description: "Static site generation with Preact hydration"
|
||||
icon: "bolt"
|
||||
- name: "Type Safe"
|
||||
description: "Full TypeScript support for all components"
|
||||
icon: "shield-check"
|
||||
- name: "SEO Optimized"
|
||||
description: "Server-side rendering with progressive enhancement"
|
||||
icon: "magnifying-glass"
|
||||
design:
|
||||
columns: "3"
|
||||
|
||||
- block: cta-card
|
||||
content:
|
||||
title: "Ready to get started?"
|
||||
text: "Join 250,000+ users building with Hugo Blox"
|
||||
button:
|
||||
text: "Start Building"
|
||||
url: "https://hugoblox.com"
|
||||
design:
|
||||
background:
|
||||
color:
|
||||
light: "gray-50"
|
||||
dark: "gray-900"
|
||||
+1
-2
@@ -2,6 +2,5 @@ module github.com/HugoBlox/hugo-blox-builder/test
|
||||
|
||||
go 1.15
|
||||
|
||||
require github.com/HugoBlox/hugo-blox-builder/modules/blox-tailwind main
|
||||
|
||||
require github.com/HugoBlox/hugo-blox-builder/modules/blox-tailwind v0.0.0
|
||||
replace github.com/HugoBlox/hugo-blox-builder/modules/blox-tailwind => ../modules/blox-tailwind
|
||||
@@ -80,6 +80,21 @@ export default defineConfig({
|
||||
src: "node_modules/alpinejs/dist/cdn.min.js",
|
||||
dest: "alpinejs/",
|
||||
},
|
||||
|
||||
// Preact for interactive components
|
||||
{
|
||||
src: "node_modules/preact/dist/preact.min.js",
|
||||
dest: "preact/",
|
||||
},
|
||||
{
|
||||
src: "node_modules/preact/dist/preact.min.js.map",
|
||||
dest: "preact/",
|
||||
},
|
||||
{
|
||||
src: "node_modules/preact/hooks/dist/hooks.umd.js",
|
||||
dest: "preact/",
|
||||
rename: "hooks.min.js",
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
|
||||
Reference in new issue
Block a user