build: unify vendor pipeline, externalize head JS, switch docs to pnpm

- Remove modules/blox-tailwind/vite.config.js; use root Vite vendor task
- Vendor alpinejs and markmap; add vendor-libs.js stub
- Replace inline head scripts with CSP-friendly hb-head.js; add font preload + fingerprint
- Update scripts/docs to pnpm; remove unused @tailwindcss/vite
This commit is contained in:
George Cushen committed 2025-08-20 23:54:14 +01:00
1 parent 4d11be9970
commit 88bd615768
8 files changed
+74 -96

No files matched your search

@@ -0,0 +1,7 @@
import { initTheme, applyHugoStyleFixes } from './hb-init.js'
initTheme()
applyHugoStyleFixes()
@@ -0,0 +1,44 @@
// Hugo Blox JS Global Init (CSP-friendly)
export function initTheme() {
const root = document.documentElement;
const defaultTheme = root.dataset.wcThemeDefault;
const setDark = () => { root.classList.add('dark'); root.style.colorScheme = 'dark'; };
const setLight = () => { root.classList.remove('dark'); root.style.colorScheme = 'light'; };
if ('wc-color-theme' in localStorage) {
localStorage.getItem('wc-color-theme') === 'dark' ? setDark() : setLight();
} else {
if (defaultTheme === 'dark') setDark();
else if (defaultTheme === 'light') setLight();
else if (defaultTheme === 'system') {
window.matchMedia('(prefers-color-scheme: dark)').matches ? setDark() : setLight();
}
}
}
export function applyHugoStyleFixes() {
document.addEventListener('DOMContentLoaded', function () {
const checkboxes = document.querySelectorAll("li input[type='checkbox'][disabled]");
checkboxes.forEach((e) => {
const parent = e.parentElement?.parentElement;
if (parent) parent.classList.add('task-list');
});
const liNodes = document.querySelectorAll('.task-list li');
liNodes.forEach((nodes) => {
const textNodes = Array.from(nodes.childNodes).filter(
(node) => node.nodeType === 3 && node.textContent && node.textContent.trim().length > 1,
);
if (textNodes.length > 0) {
const span = document.createElement('label');
textNodes[0].after(span);
const input = nodes.querySelector("input[type='checkbox']");
if (input) span.appendChild(input);
span.appendChild(textNodes[0]);
}
});
});
}
@@ -0,0 +1,5 @@
// Dummy entry for Vite lib mode. We copy vendor libraries via vite-plugin-static-copy.
export default {}
@@ -76,54 +76,12 @@
<link href="{{ $styles.RelPermalink }}" rel="stylesheet" />
{{ end }}
<script>
/* Hugo Blox JS Global Init */
window.hbb = {
defaultTheme: document.documentElement.dataset.wcThemeDefault,
setDarkTheme: () => {
document.documentElement.classList.add("dark");
document.documentElement.style.colorScheme = "dark";
},
setLightTheme: () => {
document.documentElement.classList.remove("dark");
document.documentElement.style.colorScheme = "light";
}
}
console.debug(`Default Hugo Blox Builder theme is ${window.hbb.defaultTheme}`);
if ("wc-color-theme" in localStorage) {
localStorage.getItem("wc-color-theme") === "dark" ? window.hbb.setDarkTheme() : window.hbb.setLightTheme();
} else {
window.hbb.defaultTheme === "dark" ? window.hbb.setDarkTheme() : window.hbb.setLightTheme();
if (window.hbb.defaultTheme === "system") {
window.matchMedia("(prefers-color-scheme: dark)").matches ? window.hbb.setDarkTheme() : window.hbb.setLightTheme();
}
}
</script>
<script>
// Apply Hugo style fixes
document.addEventListener('DOMContentLoaded', function () {
// Fix Hugo task list style
let checkboxes = document.querySelectorAll('li input[type=\'checkbox\'][disabled]');
checkboxes.forEach(e => {
e.parentElement.parentElement.classList.add('task-list');
});
// Fix Hugo missing <label> around checkbox and its text (fixes Lighthouse accessibility errors)
const liNodes = document.querySelectorAll('.task-list li');
liNodes.forEach(nodes => {
let textNodes = Array.from(nodes.childNodes).filter(node => node.nodeType === 3 && node.textContent.trim().length > 1);
if (textNodes.length > 0) {
const span = document.createElement('label');
textNodes[0].after(span); // Use first text node as label
span.appendChild(nodes.querySelector('input[type=\'checkbox\']'));
span.appendChild(textNodes[0]);
}
});
});
</script>
{{/* Externalized init scripts for CSP-friendly head */}}
{{- $hb_head := resources.Get "js/hb-head.js" | js.Build | resources.Minify -}}
{{- if hugo.IsProduction -}}
{{- $hb_head = $hb_head | fingerprint "sha256" -}}
{{- end -}}
<script defer src="{{ $hb_head.RelPermalink }}"{{ if hugo.IsProduction }} integrity="{{ $hb_head.Data.Integrity }}" crossorigin="anonymous"{{ end }}></script>
{{/* Analytics & Verification */}}
{{/* !CACHED! All analytics and verification code is at site level */}}
@@ -218,6 +176,7 @@
{{ $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}}';
+1 -1
View File
@@ -17,7 +17,7 @@
"vite-plugin-static-copy": "^3.1.1"
},
"devDependencies": {
"@tailwindcss/vite": "^4.1.12"
},
"homepage": "https://hugoblox.com",
"repository": {
-43
View File
@@ -1,43 +0,0 @@
import {defineConfig} from 'vite'
import {viteStaticCopy} from 'vite-plugin-static-copy'
import {rm} from 'node:fs/promises'
const distDir = './assets/dist/lib';
export default defineConfig({
build: {
// Wipe `assets/dist/lib/` first to remove old artifacts prior to copying latest assets across.
emptyOutDir: true,
outDir: distDir,
rollupOptions: {
// Vite requires us to provide an input even though we want to build site with Hugo instead.
input: 'layouts/index.html',
},
},
plugins: [viteStaticCopy({
targets: [{
"src": "node_modules/mermaid/dist/mermaid.min.js", "dest": "mermaid/"
}, {
"src": "node_modules/plotly.js/dist/plotly.min.js", "dest": "plotly/"
}, {
"src": "node_modules/katex/dist/katex.min.js", "dest": "katex/"
}, {
"src": "node_modules/katex/dist/katex.min.css", "dest": "katex/"
}, {
"src": "node_modules/katex/dist/contrib/auto-render.min.js", "dest": "katex/"
}, {
"src": "node_modules/katex/dist/fonts/", "dest": "katex/"
}, {
"src": "node_modules/markmap-autoloader/dist/index.js", "dest": "markmap/"
}, {
"src": "node_modules/alpinejs/dist/cdn.min.js", "dest": "alpinejs/"
},
],
hook: "buildStart", enforce: 'pre'
}), {
name: "Cleaning assets folder", async closeBundle() {
await rm(distDir + '/layouts', {recursive: true, force: true});
},
},]
})
+3 -1
View File
@@ -17,6 +17,8 @@
"katex": "^0.16.9",
"medium-zoom": "^1.0.8",
"mermaid": "^10.6.0",
"markmap-autoloader": "^0.15.4",
"alpinejs": "^3.13.10",
"plotly.js": "^2.27.0",
"rollup-plugin-delete": "^2.0.0",
"vite": "^7.1.2",
@@ -39,7 +41,7 @@
"view": "scripts/view-starter.sh",
"view:local": "scripts/view-starter-dev.sh",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "pnpm run lint:js && yarn run lint:style",
"lint": "pnpm run lint:js && pnpm run lint:style",
"lint:js": "eslint '*/**/*.{js,ts,tsx}'",
"lint:js:fix": "eslint '*/**/*.{js,ts,tsx}' --fix",
"lint:style": "stylelint 'modules/blox-tailwind/**/*.css'",
+7 -3
View File
@@ -26,7 +26,7 @@ export default defineConfig({
},
rollupOptions: {
// Don't bundle these libraries, just copy them
external: ['mermaid', 'plotly.js', 'katex', 'markmap-autoloader'],
external: ['mermaid', 'plotly.js', 'katex', 'markmap-autoloader', 'alpinejs'],
}
},
@@ -67,8 +67,12 @@ export default defineConfig({
// Markmap - Mind map rendering
{
src: 'node_modules/markmap-autoloader/dist/index.js',
dest: 'markmap/',
rename: 'markmap-autoloader.min.js'
dest: 'markmap/'
},
// Alpine.js
{
src: 'node_modules/alpinejs/dist/cdn.min.js',
dest: 'alpinejs/'
}
]
}),