mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-11 12:11:45 +00:00
refactor: implement multi-tier logging and drop panicOnWarning
- Centralize logger: warnf/errorf for normal pages; HTML comments for adapters - Add dev console logs and export structured logs to /hbx-debug.json - Remove --panicOnWarning from dev scripts; builds no longer fail on warnings - Fix prior lint/format issues across scripts and templates
This commit is contained in:
1 parent
0fc34ba8c8
commit
220330d872
47 files changed
+217
-501
No files matched your search
+6
-1
@@ -22,7 +22,9 @@
|
||||
"starters/**",
|
||||
"test/**",
|
||||
"modules/**/package.json",
|
||||
"**/assets/jsconfig.json"
|
||||
"**/assets/jsconfig.json",
|
||||
"docs-local",
|
||||
"backups/**"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
@@ -52,6 +54,9 @@
|
||||
"complexity": { "all": false },
|
||||
"suspicious": {
|
||||
"noEmptyBlock": "off"
|
||||
},
|
||||
"security": {
|
||||
"noDangerouslySetInnerHtml": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,13 +12,7 @@
|
||||
import * as params from "@params";
|
||||
|
||||
// Enable core slide features.
|
||||
var enabledPlugins = [
|
||||
RevealMarkdown,
|
||||
RevealSearch,
|
||||
RevealNotes,
|
||||
RevealMath.KaTeX,
|
||||
RevealZoom,
|
||||
];
|
||||
var enabledPlugins = [RevealMarkdown, RevealSearch, RevealNotes, RevealMath.KaTeX, RevealZoom];
|
||||
|
||||
const isObject = function (o) {
|
||||
return o === Object(o) && !isArray(o) && typeof o !== "function";
|
||||
@@ -97,9 +91,7 @@ if (params.slides.diagram) {
|
||||
// Lazily render Mermaid diagrams within Reveal.JS slides
|
||||
// See: https://github.com/hakimel/reveal.js/issues/2863#issuecomment-1107444425
|
||||
let renderMermaidDiagrams = function renderMermaidDiagrams(event) {
|
||||
let mermaidDivs = event.currentSlide.querySelectorAll(
|
||||
".mermaid:not(.done)",
|
||||
);
|
||||
let mermaidDivs = event.currentSlide.querySelectorAll(".mermaid:not(.done)");
|
||||
let indices = Reveal.getIndices();
|
||||
let pageno = `${indices.h}-${indices.v}`;
|
||||
|
||||
@@ -109,11 +101,7 @@ if (params.slides.diagram) {
|
||||
mermaidDiv.classList.add("done");
|
||||
};
|
||||
let graphDefinition = mermaidDiv.textContent;
|
||||
mermaid.mermaidAPI.render(
|
||||
`mermaid${pageno}-${i}`,
|
||||
graphDefinition,
|
||||
insertSvg,
|
||||
);
|
||||
mermaid.mermaidAPI.render(`mermaid${pageno}-${i}`, graphDefinition, insertSvg);
|
||||
});
|
||||
Reveal.layout();
|
||||
};
|
||||
|
||||
@@ -152,14 +152,12 @@
|
||||
font-size: 20px;
|
||||
background-color: #fff;
|
||||
color: #000; /* override parent alpha */
|
||||
box-shadow: 0 10px 20px rgb(0 0 0 / 4%), 0 2px 6px rgb(0 0 0 / 4%), 0 0 1px
|
||||
rgb(0 0 0 / 4%);
|
||||
box-shadow: 0 10px 20px rgb(0 0 0 / 4%), 0 2px 6px rgb(0 0 0 / 4%), 0 0 1px rgb(0 0 0 / 4%);
|
||||
}
|
||||
|
||||
.dark .avatar-emoji {
|
||||
background-color: #000;
|
||||
box-shadow: 0 10px 20px rgb(0 0 0 / 4%), 0 2px 6px rgb(0 0 0 / 4%), 0 0 1px
|
||||
rgb(255 255 255 / 96%);
|
||||
box-shadow: 0 10px 20px rgb(0 0 0 / 4%), 0 2px 6px rgb(0 0 0 / 4%), 0 0 1px rgb(255 255 255 / 96%);
|
||||
}
|
||||
|
||||
/* Biography Block */
|
||||
@@ -184,22 +182,14 @@
|
||||
|
||||
/* Light Mode Gradient */
|
||||
.hbx-bg-gradient::before {
|
||||
background-image: radial-gradient(
|
||||
at 20% 25%,
|
||||
hsla(212, 80%, 95%, 1) 0px,
|
||||
transparent 50%
|
||||
), radial-gradient(at 75% 30%, hsla(160, 80%, 95%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 25% 80%, hsla(280, 80%, 95%, 1) 0px, transparent 50%),
|
||||
background-image: radial-gradient(at 20% 25%, hsla(212, 80%, 95%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 75% 30%, hsla(160, 80%, 95%, 1) 0px, transparent 50%), radial-gradient(at 25% 80%, hsla(280, 80%, 95%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 75% 85%, hsla(30, 80%, 95%, 1) 0px, transparent 50%);
|
||||
}
|
||||
|
||||
/* Dark Mode Gradient */
|
||||
.dark .hbx-bg-gradient::before {
|
||||
background-image: radial-gradient(
|
||||
at 20% 25%,
|
||||
hsla(212, 35%, 15%, 1) 0px,
|
||||
transparent 50%
|
||||
), radial-gradient(at 75% 30%, hsla(160, 35%, 15%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 25% 80%, hsla(280, 35%, 15%, 1) 0px, transparent 50%),
|
||||
background-image: radial-gradient(at 20% 25%, hsla(212, 35%, 15%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 75% 30%, hsla(160, 35%, 15%, 1) 0px, transparent 50%), radial-gradient(at 25% 80%, hsla(280, 35%, 15%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 75% 85%, hsla(30, 35%, 15%, 1) 0px, transparent 50%);
|
||||
}
|
||||
@@ -3,10 +3,7 @@
|
||||
}
|
||||
|
||||
.hb-cards {
|
||||
grid-template-columns: repeat(
|
||||
auto-fill,
|
||||
minmax(max(250px, calc((100% - 1rem * 2) / var(--hb-cols))), 1fr)
|
||||
);
|
||||
grid-template-columns: repeat(auto-fill, minmax(max(250px, calc((100% - 1rem * 2) / var(--hb-cols))), 1fr));
|
||||
}
|
||||
|
||||
.hb-card {
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
|
||||
.glassmorphism-primary {
|
||||
@apply relative overflow-hidden;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgb(var(--color-primary-500) / 0.9),
|
||||
rgb(var(--color-primary-600) / 0.95),
|
||||
rgb(var(--color-primary-700) / 0.9)
|
||||
);
|
||||
background: linear-gradient(135deg, rgb(var(--color-primary-500) / 0.9), rgb(var(--color-primary-600) / 0.95), rgb(var(--color-primary-700) / 0.9));
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
}
|
||||
@@ -23,12 +18,7 @@
|
||||
.glassmorphism-primary::before {
|
||||
content: "";
|
||||
@apply absolute inset-0 pointer-events-none;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
rgb(0 0 0 / 0.1),
|
||||
transparent,
|
||||
rgb(255 255 255 / 0.1)
|
||||
);
|
||||
background: linear-gradient(45deg, rgb(0 0 0 / 0.1), transparent, rgb(255 255 255 / 0.1));
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
@@ -47,23 +37,13 @@
|
||||
.glassmorphism-secondary::before {
|
||||
content: "";
|
||||
@apply absolute inset-0 pointer-events-none;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
rgb(0 0 0 / 0.1),
|
||||
transparent,
|
||||
rgb(255 255 255 / 0.1)
|
||||
);
|
||||
background: linear-gradient(45deg, rgb(0 0 0 / 0.1), transparent, rgb(255 255 255 / 0.1));
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.glassmorphism-dark {
|
||||
@apply relative overflow-hidden;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgb(0 0 0 / 0.7),
|
||||
rgb(31 41 55 / 0.8),
|
||||
rgb(0 0 0 / 0.9)
|
||||
);
|
||||
background: linear-gradient(135deg, rgb(0 0 0 / 0.7), rgb(31 41 55 / 0.8), rgb(0 0 0 / 0.9));
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
}
|
||||
@@ -71,23 +51,13 @@
|
||||
.glassmorphism-dark::before {
|
||||
content: "";
|
||||
@apply absolute inset-0 pointer-events-none;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
rgb(255 255 255 / 0.05),
|
||||
transparent,
|
||||
rgb(255 255 255 / 0.1)
|
||||
);
|
||||
background: linear-gradient(45deg, rgb(255 255 255 / 0.05), transparent, rgb(255 255 255 / 0.1));
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.glassmorphism-light {
|
||||
@apply relative overflow-hidden;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgb(255 255 255 / 0.9),
|
||||
rgb(248 250 252 / 0.95),
|
||||
rgb(241 245 249 / 0.9)
|
||||
);
|
||||
background: linear-gradient(135deg, rgb(255 255 255 / 0.9), rgb(248 250 252 / 0.95), rgb(241 245 249 / 0.9));
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
}
|
||||
@@ -95,12 +65,7 @@
|
||||
.glassmorphism-light::before {
|
||||
content: "";
|
||||
@apply absolute inset-0 pointer-events-none;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
rgb(0 0 0 / 0.02),
|
||||
transparent,
|
||||
rgb(255 255 255 / 0.05)
|
||||
);
|
||||
background: linear-gradient(45deg, rgb(0 0 0 / 0.02), transparent, rgb(255 255 255 / 0.05));
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
@@ -136,13 +101,11 @@
|
||||
}
|
||||
|
||||
.glass-shadow {
|
||||
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25), 0 0 0 1px
|
||||
rgb(255 255 255 / 0.1), inset 0 1px 0 rgb(255 255 255 / 0.1);
|
||||
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25), 0 0 0 1px rgb(255 255 255 / 0.1), inset 0 1px 0 rgb(255 255 255 / 0.1);
|
||||
}
|
||||
|
||||
.dark .glass-shadow {
|
||||
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5), 0 0 0 1px
|
||||
rgb(255 255 255 / 0.05), inset 0 1px 0 rgb(255 255 255 / 0.05);
|
||||
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5), 0 0 0 1px rgb(255 255 255 / 0.05), inset 0 1px 0 rgb(255 255 255 / 0.05);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
@@ -169,8 +132,7 @@
|
||||
|
||||
/* Modern border and shadow for light mode */
|
||||
border: 1px solid rgb(255 255 255 / calc(var(--glassmorphism-opacity) + 0.1));
|
||||
box-shadow: 0 32px 64px -12px rgb(0 0 0 / 0.25), inset 0 1px 0
|
||||
rgb(255 255 255 / calc(var(--glassmorphism-opacity) + 0.05));
|
||||
box-shadow: 0 32px 64px -12px rgb(0 0 0 / 0.25), inset 0 1px 0 rgb(255 255 255 / calc(var(--glassmorphism-opacity) + 0.05));
|
||||
}
|
||||
|
||||
.cta-glassmorphism:hover {
|
||||
@@ -183,8 +145,7 @@
|
||||
);
|
||||
|
||||
border: 1px solid rgb(255 255 255 / calc(var(--glassmorphism-opacity) + 0.2));
|
||||
box-shadow: 0 40px 80px -16px rgb(0 0 0 / 0.3), inset 0 1px 0
|
||||
rgb(255 255 255 / calc(var(--glassmorphism-opacity) + 0.1));
|
||||
box-shadow: 0 40px 80px -16px rgb(0 0 0 / 0.3), inset 0 1px 0 rgb(255 255 255 / calc(var(--glassmorphism-opacity) + 0.1));
|
||||
}
|
||||
|
||||
/* Dark mode adjustments for CTA glassmorphism */
|
||||
@@ -197,8 +158,7 @@
|
||||
);
|
||||
|
||||
border: 1px solid rgb(255 255 255 / var(--glassmorphism-opacity));
|
||||
box-shadow: 0 32px 64px -12px rgb(0 0 0 / 0.4), inset 0 1px 0
|
||||
rgb(255 255 255 / calc(var(--glassmorphism-opacity) * 0.5));
|
||||
box-shadow: 0 32px 64px -12px rgb(0 0 0 / 0.4), inset 0 1px 0 rgb(255 255 255 / calc(var(--glassmorphism-opacity) * 0.5));
|
||||
}
|
||||
|
||||
.dark .cta-glassmorphism:hover {
|
||||
@@ -231,23 +191,20 @@
|
||||
/* Light mode button background */
|
||||
background: rgb(255 255 255 / 0.9);
|
||||
border: 1px solid rgb(0 0 0 / 0.1);
|
||||
box-shadow: 0 10px 25px -5px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.1),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.3);
|
||||
box-shadow: 0 10px 25px -5px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.1), inset 0 1px 0 rgb(255 255 255 / 0.3);
|
||||
}
|
||||
|
||||
.dark .cta-glassmorphism .group > div:first-child {
|
||||
/* Dark mode button background */
|
||||
background: rgb(0 0 0 / 0.4);
|
||||
border: 1px solid rgb(255 255 255 / 0.2);
|
||||
box-shadow: 0 10px 25px -5px rgb(0 0 0 / 0.3), 0 4px 6px -2px rgb(0 0 0 / 0.2),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.1);
|
||||
box-shadow: 0 10px 25px -5px rgb(0 0 0 / 0.3), 0 4px 6px -2px rgb(0 0 0 / 0.2), inset 0 1px 0 rgb(255 255 255 / 0.1);
|
||||
}
|
||||
|
||||
.cta-glassmorphism .group:hover > div:first-child {
|
||||
background: rgb(255 255 255);
|
||||
border: 1px solid rgb(0 0 0 / 0.15);
|
||||
box-shadow: 0 20px 40px -8px rgb(0 0 0 / 0.15), 0 8px 12px -4px
|
||||
rgb(0 0 0 / 0.1), inset 0 1px 0 rgb(255 255 255 / 0.4);
|
||||
box-shadow: 0 20px 40px -8px rgb(0 0 0 / 0.15), 0 8px 12px -4px rgb(0 0 0 / 0.1), inset 0 1px 0 rgb(255 255 255 / 0.4);
|
||||
}
|
||||
|
||||
.dark .cta-glassmorphism .group:hover > div:first-child {
|
||||
|
||||
@@ -320,9 +320,7 @@
|
||||
/* Note: Providing these palettes in @theme ensures theme-pack mappings like var(--color-rose-600) always resolve */
|
||||
|
||||
/* Font family */
|
||||
--font-family-sans:
|
||||
inter var, ui-sans-serif, system-ui, sans-serif, apple color emoji, segoe ui emoji,
|
||||
segoe ui symbol, noto color emoji;
|
||||
--font-family-sans: inter var, ui-sans-serif, system-ui, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji;
|
||||
|
||||
/* Font sizes */
|
||||
--font-size-xs: 0.75rem;
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* Copies BibTeX citation to clipboard when cite button is clicked
|
||||
*/
|
||||
|
||||
import { hugoEnvironment, i18n } from "@params";
|
||||
import { ClipboardCache, copyToClipboardSync } from "./hb-clipboard.js";
|
||||
import { showNotification } from "./hb-notifier.js";
|
||||
import {hugoEnvironment, i18n} from "@params";
|
||||
import {ClipboardCache, copyToClipboardSync} from "./hb-clipboard.js";
|
||||
import {showNotification} from "./hb-notifier.js";
|
||||
|
||||
// Debug mode based on environment
|
||||
const isDebugMode = hugoEnvironment === "development";
|
||||
@@ -36,9 +36,7 @@ function initializeCitation() {
|
||||
* Prefetch all citations on page load
|
||||
*/
|
||||
function prefetchAllCitations() {
|
||||
const citeButtons = document.querySelectorAll(
|
||||
".js-cite-clipboard[data-filename]",
|
||||
);
|
||||
const citeButtons = document.querySelectorAll(".js-cite-clipboard[data-filename]");
|
||||
citeButtons.forEach((button) => {
|
||||
const filename = button.getAttribute("data-filename");
|
||||
if (filename && !citationCache.has(filename)) {
|
||||
@@ -151,10 +149,7 @@ async function fetchAndCopyWithFallback(filename, button) {
|
||||
}
|
||||
// If it's a NotAllowedError, suggest hovering first
|
||||
if (error.name === "NotAllowedError") {
|
||||
showNotification(
|
||||
"Please hover over the button first, then click",
|
||||
"info",
|
||||
);
|
||||
showNotification("Please hover over the button first, then click", "info");
|
||||
} else {
|
||||
showNotification("Failed to copy citation", "error");
|
||||
}
|
||||
@@ -191,4 +186,4 @@ function updateButtonText(button) {
|
||||
}
|
||||
|
||||
// Export functions for potential reuse
|
||||
export { handleCiteClick, prefetchAllCitations };
|
||||
export {handleCiteClick, prefetchAllCitations};
|
||||
@@ -3,7 +3,7 @@
|
||||
* Provides cross-browser clipboard functionality
|
||||
*/
|
||||
|
||||
import { hugoEnvironment } from "@params";
|
||||
import {hugoEnvironment} from "@params";
|
||||
|
||||
// Debug mode based on environment
|
||||
const isDebugMode = hugoEnvironment === "development";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { hugoEnvironment, i18n } from "@params";
|
||||
import {hugoEnvironment, i18n} from "@params";
|
||||
|
||||
// Constants
|
||||
const NOTIFICATION_DURATION = 2000; // milliseconds
|
||||
@@ -93,10 +93,7 @@ function createCopyButton() {
|
||||
const copyBtn = document.createElement("button");
|
||||
copyBtn.classList.add("copy-button");
|
||||
copyBtn.innerHTML = i18n["copy"];
|
||||
copyBtn.setAttribute(
|
||||
"aria-label",
|
||||
i18n["copyLabel"] || "Copy code to clipboard",
|
||||
);
|
||||
copyBtn.setAttribute("aria-label", i18n["copyLabel"] || "Copy code to clipboard");
|
||||
copyBtn.setAttribute("type", "button"); // Explicit button type
|
||||
return copyBtn;
|
||||
}
|
||||
@@ -144,18 +141,12 @@ function initializeCodeCopyButtons() {
|
||||
const copyBtn = createCopyButton();
|
||||
|
||||
// Use debounced version of copy function
|
||||
const debouncedCopy = debounce(
|
||||
() => copyCodeToClipboard(copyBtn, wrapper),
|
||||
DEBOUNCE_DELAY,
|
||||
);
|
||||
const debouncedCopy = debounce(() => copyCodeToClipboard(copyBtn, wrapper), DEBOUNCE_DELAY);
|
||||
|
||||
copyBtn.addEventListener("click", debouncedCopy);
|
||||
wrapper.appendChild(copyBtn);
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Failed to initialize copy button for code block ${index}:`,
|
||||
err,
|
||||
);
|
||||
console.error(`Failed to initialize copy button for code block ${index}:`, err);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { applyHugoStyleFixes, initTheme } from "./hb-init.js";
|
||||
import {applyHugoStyleFixes, initTheme} from "./hb-init.js";
|
||||
|
||||
// Initialize Hugo Blox Builder global object
|
||||
const root = document.documentElement;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
// Toggle language chooser sub-menu
|
||||
const languageChoosers = document.querySelectorAll(
|
||||
"[data-hb-language-chooser]",
|
||||
);
|
||||
const languageChoosers = document.querySelectorAll("[data-hb-language-chooser]");
|
||||
languageChoosers.forEach((languageChooser) => {
|
||||
languageChooser.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
languageChooser.dataset.state =
|
||||
languageChooser.dataset.state === "open" ? "closed" : "open";
|
||||
languageChooser.dataset.state = languageChooser.dataset.state === "open" ? "closed" : "open";
|
||||
const languageOptions = languageChooser.nextElementSibling;
|
||||
languageOptions.classList.toggle("hidden");
|
||||
const languageChooserRect = languageChooser.getBoundingClientRect();
|
||||
|
||||
@@ -17,18 +17,14 @@ export function initTheme() {
|
||||
if (defaultTheme === "dark") setDark();
|
||||
else if (defaultTheme === "light") setLight();
|
||||
else if (defaultTheme === "system") {
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? setDark()
|
||||
: setLight();
|
||||
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]",
|
||||
);
|
||||
const checkboxes = document.querySelectorAll("li input[type='checkbox'][disabled]");
|
||||
checkboxes.forEach((e) => {
|
||||
const parent = e.parentElement?.parentElement;
|
||||
if (parent) parent.classList.add("task-list");
|
||||
@@ -36,12 +32,7 @@ export function applyHugoStyleFixes() {
|
||||
|
||||
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,
|
||||
);
|
||||
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);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
function getCssVar(name) {
|
||||
const value = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue(name)
|
||||
.trim();
|
||||
const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
||||
return value ? "rgb(" + value + ")" : null;
|
||||
}
|
||||
|
||||
@@ -16,9 +14,7 @@ window.mermaid.initialize({
|
||||
secondaryBorderColor: getCssVar("--color-secondary-400") || "#22d3ee",
|
||||
tertiaryBorderColor: getCssVar("--color-neutral-400") || "#a3a3a3",
|
||||
lineColor: getCssVar("--color-neutral-600") || "#525252",
|
||||
fontFamily: getComputedStyle(document.documentElement).getPropertyValue(
|
||||
"font-family",
|
||||
),
|
||||
fontFamily: getComputedStyle(document.documentElement).getPropertyValue("font-family"),
|
||||
fontSize: "16px",
|
||||
},
|
||||
});
|
||||
@@ -3,16 +3,13 @@
|
||||
const applyScrollPadding = () => {
|
||||
const header = document.querySelector(".page-header");
|
||||
let position = header.getBoundingClientRect();
|
||||
document.documentElement.style.scrollPaddingTop =
|
||||
position.height.toString() + "px";
|
||||
document.documentElement.style.scrollPaddingTop = position.height.toString() + "px";
|
||||
const r = document.querySelector(":root");
|
||||
r.style.setProperty("--navbar-height", position.height.toString() + "px");
|
||||
};
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const dropdownMenus = document.querySelectorAll(
|
||||
".nav-dropdown > .nav-link[role='button']",
|
||||
);
|
||||
const dropdownMenus = document.querySelectorAll(".nav-dropdown > .nav-link[role='button']");
|
||||
|
||||
dropdownMenus.forEach((toggler) => {
|
||||
const toggle = (el) => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Provides reusable notification functionality
|
||||
*/
|
||||
|
||||
import { hugoEnvironment } from "@params";
|
||||
import {hugoEnvironment} from "@params";
|
||||
|
||||
// Debug mode based on environment
|
||||
const isDebugMode = hugoEnvironment === "development";
|
||||
@@ -21,10 +21,7 @@ export function showNotification(message, type = "success", duration = 3000) {
|
||||
|
||||
// Remove any existing notifications with same message
|
||||
const existingNotification = container.querySelector(".hb-notification");
|
||||
if (
|
||||
existingNotification &&
|
||||
existingNotification.textContent.includes(message)
|
||||
) {
|
||||
if (existingNotification && existingNotification.textContent.includes(message)) {
|
||||
existingNotification.remove();
|
||||
}
|
||||
|
||||
@@ -86,10 +83,10 @@ function createNotificationElement(message, type) {
|
||||
|
||||
// Define colors for different types
|
||||
const colors = {
|
||||
success: { bg: "#10b981", bgClass: "bg-green-500" },
|
||||
error: { bg: "#ef4444", bgClass: "bg-red-500" },
|
||||
info: { bg: "#3b82f6", bgClass: "bg-blue-500" },
|
||||
warning: { bg: "#f59e0b", bgClass: "bg-amber-500" },
|
||||
success: {bg: "#10b981", bgClass: "bg-green-500"},
|
||||
error: {bg: "#ef4444", bgClass: "bg-red-500"},
|
||||
info: {bg: "#3b82f6", bgClass: "bg-blue-500"},
|
||||
warning: {bg: "#f59e0b", bgClass: "bg-amber-500"},
|
||||
};
|
||||
|
||||
const color = colors[type] || colors.info;
|
||||
|
||||
@@ -11,10 +11,7 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
const searchConfig = JSON.parse(configScript.textContent);
|
||||
if (!searchConfig || typeof searchConfig.baseUrl === "undefined") {
|
||||
console.error(
|
||||
"Pagefind search config is missing or invalid.",
|
||||
searchConfig,
|
||||
);
|
||||
console.error("Pagefind search config is missing or invalid.", searchConfig);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -35,9 +32,7 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
// Add click handlers to triggers
|
||||
let triggers = document.querySelectorAll("[data-search-toggle]");
|
||||
triggers.forEach((trigger) =>
|
||||
trigger.addEventListener("click", handleSearchToggle),
|
||||
);
|
||||
triggers.forEach((trigger) => trigger.addEventListener("click", handleSearchToggle));
|
||||
});
|
||||
|
||||
function handleSearchToggle() {
|
||||
@@ -68,11 +63,7 @@ function handleSearchToggle() {
|
||||
|
||||
// Add keyboard shortcut to close search modal with Escape key
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (
|
||||
event.key === "Escape" &&
|
||||
searchWrapper &&
|
||||
!searchWrapper.classList.contains("hidden")
|
||||
) {
|
||||
if (event.key === "Escape" && searchWrapper && !searchWrapper.classList.contains("hidden")) {
|
||||
searchWrapper.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
@@ -22,13 +22,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
|
||||
// Initialize the overlay
|
||||
const overlayClasses = [
|
||||
"fixed",
|
||||
"z-10",
|
||||
"inset-0",
|
||||
"bg-white",
|
||||
"dark:bg-black/80",
|
||||
];
|
||||
const overlayClasses = ["fixed", "z-10", "inset-0", "bg-white", "dark:bg-black/80"];
|
||||
overlay.classList.add("bg-transparent");
|
||||
overlay.classList.remove("hidden", ...overlayClasses);
|
||||
|
||||
@@ -37,9 +31,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// See `hb-nav.js` - it handles the default behavior (irrespective of if sidebar is shown).
|
||||
|
||||
// When menu is open, show the navigation sidebar
|
||||
sidebarContainer.classList.toggle(
|
||||
"max-lg:[transform:translate3d(0,-100%,0)]",
|
||||
);
|
||||
sidebarContainer.classList.toggle("max-lg:[transform:translate3d(0,-100%,0)]");
|
||||
sidebarContainer.classList.toggle("max-lg:[transform:translate3d(0,0,0)]");
|
||||
|
||||
// When menu is open, prevent body from scrolling
|
||||
|
||||
@@ -11,9 +11,7 @@ function addThemeToggleListener() {
|
||||
if (
|
||||
localStorage.getItem("wc-color-theme") === "dark" ||
|
||||
(!("wc-color-theme" in localStorage) &&
|
||||
((window.matchMedia("(prefers-color-scheme: dark)").matches &&
|
||||
defaultTheme === "system") ||
|
||||
defaultTheme === "dark"))
|
||||
((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") || defaultTheme === "dark"))
|
||||
) {
|
||||
themeToggleButtons.forEach((el) => {
|
||||
el.dataset.theme = "dark";
|
||||
@@ -45,15 +43,12 @@ function addThemeToggleListener() {
|
||||
localStorage.setItem("wc-color-theme", "dark");
|
||||
}
|
||||
}
|
||||
el.dataset.theme = document.documentElement.classList.contains("dark")
|
||||
? "dark"
|
||||
: "light";
|
||||
el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light";
|
||||
|
||||
// Dispatch `hbThemeChange` event to support themeable user plugins.
|
||||
const themeChangeEvent = new CustomEvent("hbThemeChange", {
|
||||
detail: {
|
||||
isDarkTheme: () =>
|
||||
document.documentElement.classList.contains("dark"),
|
||||
isDarkTheme: () => document.documentElement.classList.contains("dark"),
|
||||
},
|
||||
});
|
||||
document.dispatchEvent(themeChangeEvent);
|
||||
@@ -61,15 +56,13 @@ function addThemeToggleListener() {
|
||||
});
|
||||
|
||||
// Listen for dark mode toggling in OS
|
||||
window
|
||||
.matchMedia("(prefers-color-scheme: dark)")
|
||||
.addEventListener("change", (event) => {
|
||||
if (defaultTheme === "system" && !("wc-color-theme" in localStorage)) {
|
||||
event.matches ? window.hbb.setDarkTheme() : window.hbb.setLightTheme();
|
||||
themeToggleButtons.forEach((el) => {
|
||||
const isDark = document.documentElement.classList.contains("dark");
|
||||
el.dataset.theme = isDark ? "dark" : "light";
|
||||
});
|
||||
}
|
||||
});
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (event) => {
|
||||
if (defaultTheme === "system" && !("wc-color-theme" in localStorage)) {
|
||||
event.matches ? window.hbb.setDarkTheme() : window.hbb.setLightTheme();
|
||||
themeToggleButtons.forEach((el) => {
|
||||
const isDark = document.documentElement.classList.contains("dark");
|
||||
el.dataset.theme = isDark ? "dark" : "light";
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
window.renderMathInElement(document.body, {
|
||||
delimiters: [
|
||||
{ left: "$$", right: "$$", display: true },
|
||||
{ left: "$", right: "$", display: false },
|
||||
{ left: "\\(", right: "\\)", display: false },
|
||||
{ left: "\\[", right: "\\]", display: true },
|
||||
{left: "$$", right: "$$", display: true},
|
||||
{left: "$", right: "$", display: false},
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
{left: "\\[", right: "\\]", display: true},
|
||||
],
|
||||
throwOnError: false,
|
||||
});
|
||||
|
||||
@@ -4,25 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "content",
|
||||
"tags": [
|
||||
"collection",
|
||||
"blog",
|
||||
"publications",
|
||||
"filter",
|
||||
"sort",
|
||||
"content-display",
|
||||
"archive"
|
||||
],
|
||||
"tags": ["collection", "blog", "publications", "filter", "sort", "content-display", "archive"],
|
||||
"description": "Display filtered and sorted collections of pages with customizable views and pagination",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"static-site",
|
||||
"content",
|
||||
"blog",
|
||||
"publications",
|
||||
"filtering"
|
||||
]
|
||||
"keywords": ["hugo", "static-site", "content", "blog", "publications", "filtering"]
|
||||
}
|
||||
@@ -4,25 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "marketing",
|
||||
"tags": [
|
||||
"cta",
|
||||
"buttons",
|
||||
"links",
|
||||
"social",
|
||||
"marketing",
|
||||
"conversion",
|
||||
"list"
|
||||
],
|
||||
"tags": ["cta", "buttons", "links", "social", "marketing", "conversion", "list"],
|
||||
"description": "Create compelling vertical lists of call-to-action buttons with icons and hover effects",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"cta",
|
||||
"buttons",
|
||||
"conversion",
|
||||
"marketing",
|
||||
"social-links"
|
||||
]
|
||||
"keywords": ["hugo", "cta", "buttons", "conversion", "marketing", "social-links"]
|
||||
}
|
||||
@@ -4,15 +4,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "marketing",
|
||||
"tags": [
|
||||
"cta",
|
||||
"card",
|
||||
"conversion",
|
||||
"marketing",
|
||||
"hero",
|
||||
"call-to-action",
|
||||
"banner"
|
||||
],
|
||||
"tags": ["cta", "card", "conversion", "marketing", "hero", "call-to-action", "banner"],
|
||||
"description": "Create high-impact call-to-action cards with bold typography and compelling buttons",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
|
||||
@@ -120,18 +120,7 @@
|
||||
},
|
||||
"position": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"center",
|
||||
"top",
|
||||
"bottom",
|
||||
"left",
|
||||
"right",
|
||||
"repeat",
|
||||
"top left",
|
||||
"top right",
|
||||
"bottom left",
|
||||
"bottom right"
|
||||
],
|
||||
"enum": ["center", "top", "bottom", "left", "right", "repeat", "top left", "top right", "bottom left", "bottom right"],
|
||||
"description": "Background position (use 'repeat' for tiling textures)",
|
||||
"default": "center"
|
||||
},
|
||||
|
||||
@@ -4,25 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "marketing",
|
||||
"tags": [
|
||||
"cta",
|
||||
"image",
|
||||
"features",
|
||||
"alternating",
|
||||
"marketing",
|
||||
"storytelling",
|
||||
"visual"
|
||||
],
|
||||
"tags": ["cta", "image", "features", "alternating", "marketing", "storytelling", "visual"],
|
||||
"description": "Engaging alternating image and text sections with feature lists and call-to-action buttons",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"marketing",
|
||||
"images",
|
||||
"features",
|
||||
"storytelling",
|
||||
"conversion"
|
||||
]
|
||||
"keywords": ["hugo", "marketing", "images", "features", "storytelling", "conversion"]
|
||||
}
|
||||
@@ -4,15 +4,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "content",
|
||||
"tags": [
|
||||
"features",
|
||||
"grid",
|
||||
"icons",
|
||||
"benefits",
|
||||
"product",
|
||||
"services",
|
||||
"highlights"
|
||||
],
|
||||
"tags": ["features", "grid", "icons", "benefits", "product", "services", "highlights"],
|
||||
"description": "Showcase features, benefits, or services in an organized grid with icons and descriptions",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
* Uses the shared component for consistency
|
||||
*/
|
||||
|
||||
import { render } from "preact";
|
||||
import { HeroBlock } from "./component.jsx";
|
||||
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"]',
|
||||
);
|
||||
const heroBlocks = document.querySelectorAll('[data-block-type="hero"], [data-hero-render="immediate"]');
|
||||
|
||||
heroBlocks.forEach((block) => {
|
||||
const propsData = block.dataset.props;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Used for both SSR and client-side hydration
|
||||
*/
|
||||
|
||||
import { Icon } from "../../shared/components/Icon.jsx";
|
||||
import {Icon} from "../../shared/components/Icon.jsx";
|
||||
|
||||
// Simple markdown renderer
|
||||
export function renderText(text) {
|
||||
@@ -16,7 +16,7 @@ export function renderText(text) {
|
||||
|
||||
// Process URLs
|
||||
export function processUrl(url) {
|
||||
if (!url) return { href: "#" };
|
||||
if (!url) return {href: "#"};
|
||||
|
||||
if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
return {
|
||||
@@ -27,14 +27,14 @@ export function processUrl(url) {
|
||||
}
|
||||
|
||||
if (url.startsWith("#")) {
|
||||
return { href: url };
|
||||
return {href: url};
|
||||
}
|
||||
|
||||
return { href: url };
|
||||
return {href: url};
|
||||
}
|
||||
|
||||
// Hero Block Component - Single implementation
|
||||
export const HeroBlock = ({ content, design, id, icon_svg }) => {
|
||||
export const HeroBlock = ({content, design, id, icon_svg}) => {
|
||||
const paddingClasses = design?.no_padding ? "" : "py-32 sm:py-48 lg:py-56";
|
||||
|
||||
return (
|
||||
@@ -44,6 +44,7 @@ export const HeroBlock = ({ content, design, id, icon_svg }) => {
|
||||
{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">
|
||||
{/* eslint-disable-next-line lint/security/noDangerouslySetInnerHtml */}
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: renderText(content.announcement.text),
|
||||
@@ -59,8 +60,7 @@ export const HeroBlock = ({ content, design, id, icon_svg }) => {
|
||||
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>
|
||||
{content.announcement.link.text} <span aria-hidden="true">→</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
@@ -73,16 +73,13 @@ export const HeroBlock = ({ content, design, id, icon_svg }) => {
|
||||
{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) }}
|
||||
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) }}
|
||||
/>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-600 dark:text-gray-300" dangerouslySetInnerHTML={{__html: renderText(content.text)}} />
|
||||
)}
|
||||
|
||||
{/* Action Buttons */}
|
||||
|
||||
@@ -4,15 +4,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "marketing",
|
||||
"tags": [
|
||||
"hero",
|
||||
"landing",
|
||||
"cta",
|
||||
"announcement",
|
||||
"headline",
|
||||
"conversion",
|
||||
"primary"
|
||||
],
|
||||
"tags": ["hero", "landing", "cta", "announcement", "headline", "conversion", "primary"],
|
||||
"description": "Create compelling hero sections with headlines, announcements, and dual call-to-action buttons",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
|
||||
@@ -98,4 +98,4 @@
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "content",
|
||||
"tags": [
|
||||
"markdown",
|
||||
"content",
|
||||
"text",
|
||||
"prose",
|
||||
"writing",
|
||||
"simple",
|
||||
"flexible"
|
||||
],
|
||||
"tags": ["markdown", "content", "text", "prose", "writing", "simple", "flexible"],
|
||||
"description": "Display rich markdown content with beautiful typography and optional section titles",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
|
||||
@@ -4,25 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "resume",
|
||||
"tags": [
|
||||
"resume",
|
||||
"awards",
|
||||
"certifications",
|
||||
"achievements",
|
||||
"credentials",
|
||||
"professional",
|
||||
"cv"
|
||||
],
|
||||
"tags": ["resume", "awards", "certifications", "achievements", "credentials", "professional", "cv"],
|
||||
"description": "Showcase professional awards and certifications with elegant card layouts and certificate links",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"resume",
|
||||
"awards",
|
||||
"certifications",
|
||||
"cv",
|
||||
"professional"
|
||||
]
|
||||
"keywords": ["hugo", "resume", "awards", "certifications", "cv", "professional"]
|
||||
}
|
||||
@@ -4,27 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "resume",
|
||||
"tags": [
|
||||
"resume",
|
||||
"biography",
|
||||
"profile",
|
||||
"horizontal",
|
||||
"education",
|
||||
"interests",
|
||||
"cv",
|
||||
"layout"
|
||||
],
|
||||
"tags": ["resume", "biography", "profile", "horizontal", "education", "interests", "cv", "layout"],
|
||||
"description": "Horizontal biography layout with integrated education and interests sections",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"resume",
|
||||
"biography",
|
||||
"horizontal",
|
||||
"education",
|
||||
"interests",
|
||||
"cv"
|
||||
]
|
||||
"keywords": ["hugo", "resume", "biography", "horizontal", "education", "interests", "cv"]
|
||||
}
|
||||
@@ -4,27 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "resume",
|
||||
"tags": [
|
||||
"resume",
|
||||
"biography",
|
||||
"profile",
|
||||
"avatar",
|
||||
"social",
|
||||
"about",
|
||||
"personal",
|
||||
"cv"
|
||||
],
|
||||
"tags": ["resume", "biography", "profile", "avatar", "social", "about", "personal", "cv"],
|
||||
"description": "Professional biography section with customizable avatar, social links, and personal information",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"resume",
|
||||
"biography",
|
||||
"profile",
|
||||
"avatar",
|
||||
"social",
|
||||
"cv"
|
||||
]
|
||||
"keywords": ["hugo", "resume", "biography", "profile", "avatar", "social", "cv"]
|
||||
}
|
||||
@@ -4,27 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "resume",
|
||||
"tags": [
|
||||
"resume",
|
||||
"experience",
|
||||
"timeline",
|
||||
"work",
|
||||
"education",
|
||||
"career",
|
||||
"professional",
|
||||
"cv"
|
||||
],
|
||||
"tags": ["resume", "experience", "timeline", "work", "education", "career", "professional", "cv"],
|
||||
"description": "Professional timeline displaying work experience and education history in chronological order",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"resume",
|
||||
"experience",
|
||||
"timeline",
|
||||
"work",
|
||||
"education",
|
||||
"career"
|
||||
]
|
||||
"keywords": ["hugo", "resume", "experience", "timeline", "work", "education", "career"]
|
||||
}
|
||||
@@ -4,27 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "resume",
|
||||
"tags": [
|
||||
"resume",
|
||||
"languages",
|
||||
"multilingual",
|
||||
"skills",
|
||||
"fluency",
|
||||
"international",
|
||||
"cv",
|
||||
"circular-progress"
|
||||
],
|
||||
"tags": ["resume", "languages", "multilingual", "skills", "fluency", "international", "cv", "circular-progress"],
|
||||
"description": "Showcase language proficiency with beautiful circular progress indicators and percentage displays",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"resume",
|
||||
"languages",
|
||||
"multilingual",
|
||||
"fluency",
|
||||
"skills",
|
||||
"cv"
|
||||
]
|
||||
"keywords": ["hugo", "resume", "languages", "multilingual", "fluency", "skills", "cv"]
|
||||
}
|
||||
@@ -4,27 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "resume",
|
||||
"tags": [
|
||||
"resume",
|
||||
"skills",
|
||||
"technical",
|
||||
"progress-bars",
|
||||
"expertise",
|
||||
"professional",
|
||||
"competencies",
|
||||
"cv"
|
||||
],
|
||||
"tags": ["resume", "skills", "technical", "progress-bars", "expertise", "professional", "competencies", "cv"],
|
||||
"description": "Display technical and professional skills with optional progress bars and organized categories",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"resume",
|
||||
"skills",
|
||||
"technical",
|
||||
"progress",
|
||||
"expertise",
|
||||
"cv"
|
||||
]
|
||||
"keywords": ["hugo", "resume", "skills", "technical", "progress", "expertise", "cv"]
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { h } from "preact";
|
||||
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 }) => {
|
||||
export const Icon = ({svg, attributes}) => {
|
||||
if (!svg) return null;
|
||||
|
||||
let decoded = String(svg)
|
||||
@@ -22,17 +22,13 @@ export const Icon = ({ svg, attributes }) => {
|
||||
|
||||
if (hasWrapper) {
|
||||
if (/<svg[^>]*class=/i.test(decoded)) {
|
||||
decoded = decoded.replace(
|
||||
/<svg([^>]*?)class=\"([^\"]*)\"([^>]*)>/i,
|
||||
'<svg$1class="$2 inline-block w-4 h-4"$3>'
|
||||
);
|
||||
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 }} />
|
||||
);
|
||||
// eslint-disable-next-line lint/security/noDangerouslySetInnerHtml
|
||||
return <span class="inline-block" dangerouslySetInnerHTML={{__html: decoded}} />;
|
||||
}
|
||||
|
||||
const finalAttributes = {
|
||||
@@ -46,10 +42,6 @@ export const Icon = ({ svg, attributes }) => {
|
||||
.map(([k, v]) => `${k}="${String(v)}"`)
|
||||
.join(" ");
|
||||
|
||||
return (
|
||||
<span
|
||||
class="inline-block"
|
||||
dangerouslySetInnerHTML={{ __html: `<svg ${attrs}>${decoded}</svg>` }}
|
||||
/>
|
||||
);
|
||||
// eslint-disable-next-line lint/security/noDangerouslySetInnerHtml
|
||||
return <span class="inline-block" dangerouslySetInnerHTML={{__html: `<svg ${attrs}>${decoded}</svg>`}} />;
|
||||
};
|
||||
@@ -4,25 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "content",
|
||||
"tags": [
|
||||
"statistics",
|
||||
"numbers",
|
||||
"metrics",
|
||||
"achievements",
|
||||
"data",
|
||||
"showcase",
|
||||
"grid"
|
||||
],
|
||||
"tags": ["statistics", "numbers", "metrics", "achievements", "data", "showcase", "grid"],
|
||||
"description": "Showcase impressive statistics and achievements in a clean, impactful grid layout",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"statistics",
|
||||
"metrics",
|
||||
"achievements",
|
||||
"data",
|
||||
"numbers"
|
||||
]
|
||||
"keywords": ["hugo", "statistics", "metrics", "achievements", "data", "numbers"]
|
||||
}
|
||||
@@ -4,25 +4,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"category": "marketing",
|
||||
"tags": [
|
||||
"testimonials",
|
||||
"reviews",
|
||||
"social-proof",
|
||||
"quotes",
|
||||
"customers",
|
||||
"trust",
|
||||
"credibility"
|
||||
],
|
||||
"tags": ["testimonials", "reviews", "social-proof", "quotes", "customers", "trust", "credibility"],
|
||||
"description": "Build trust with authentic customer testimonials featuring quotes, names, and profile photos",
|
||||
"author": "Hugo Blox",
|
||||
"homepage": "https://hugoblox.com/blocks/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": [
|
||||
"hugo",
|
||||
"testimonials",
|
||||
"social-proof",
|
||||
"reviews",
|
||||
"customers",
|
||||
"trust"
|
||||
]
|
||||
"keywords": ["hugo", "testimonials", "social-proof", "reviews", "customers", "trust"]
|
||||
}
|
||||
@@ -6,12 +6,14 @@
|
||||
{{ $partial_dir := printf "hooks/%s/" .hook }}
|
||||
{{ $context := .context }}
|
||||
{{ $hook_dir_path := path.Join "layouts/_partials" $partial_dir }}
|
||||
{{ if fileExists $hook_dir_path }}
|
||||
{{ range os.ReadDir $hook_dir_path }}
|
||||
{{ if not .IsDir }}
|
||||
{{ $partial_path := path.Join $partial_dir .Name }}
|
||||
{{ partial $partial_path $context }}
|
||||
{{ $loaded = true }}
|
||||
{{ with try (os.ReadDir $hook_dir_path) }}
|
||||
{{ with .Value }}
|
||||
{{ range . }}
|
||||
{{ if not .IsDir }}
|
||||
{{ $partial_path := path.Join $partial_dir .Name }}
|
||||
{{ partial $partial_path $context }}
|
||||
{{ $loaded = true }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -22,6 +22,19 @@
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Store log entry for future debug widget */}}
|
||||
{{- with $page -}}
|
||||
{{- $log_entry := dict "level" $level "message" $msg "page" ($.RelPermalink | default "/") "timestamp" now.Unix -}}
|
||||
{{- $current_logs := .Store.Get "hbx_logs" | default slice -}}
|
||||
{{- .Store.Set "hbx_logs" ($current_logs | append $log_entry) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Multi-tier logging output */}}
|
||||
{{- if $isDev -}}
|
||||
{{/* Console logging for immediate dev feedback */}}
|
||||
<script>console.log('[HBX:{{ $level }}]', {{ $msg | jsonify }});</script>
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $level "error" -}}
|
||||
{{- if not $isAdapter -}}
|
||||
{{- errorf "%s" $msg -}}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{{/* Hugo Blox: Export Debug Logs for Future Debug Widget */}}
|
||||
{{/* This hook collects all HBX logs and exports them to a JSON file for tooling */}}
|
||||
|
||||
{{- if hugo.IsServer -}}
|
||||
{{/* Collect all logs from all pages */}}
|
||||
{{- $all_logs := slice -}}
|
||||
{{- range .Site.Pages -}}
|
||||
{{- $page_logs := .Store.Get "hbx_logs" | default slice -}}
|
||||
{{- $all_logs = $all_logs | append $page_logs -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $all_logs -}}
|
||||
{{/* Create debug export as a resource for tooling */}}
|
||||
{{- $debug_data := dict "logs" $all_logs "build_time" now.Unix "hugo_version" hugo.Version -}}
|
||||
{{- $debug_json := $debug_data | jsonify -}}
|
||||
{{- $debug_resource := resources.FromString "hbx-debug.json" $debug_json -}}
|
||||
{{- $debug_resource.Publish -}}
|
||||
|
||||
{{/* Also emit to console for immediate visibility */}}
|
||||
<script>
|
||||
if (window.console && console.groupCollapsed) {
|
||||
console.groupCollapsed('[HBX] Build completed with {{ len $all_logs }} log entries');
|
||||
console.log('Debug data available at:', '/hbx-debug.json');
|
||||
{{ range $all_logs }}
|
||||
console.log('[HBX:{{ .level }}]', {{ .message | jsonify }}, 'page:', {{ .page | jsonify }});
|
||||
{{ end }}
|
||||
console.groupEnd();
|
||||
}
|
||||
</script>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,31 @@
|
||||
{{/* Hugo Blox: Export Debug Logs for Future Debug Widget */}}
|
||||
{{/* This hook collects all HBX logs and exports them to a JSON file for tooling */}}
|
||||
|
||||
{{- if hugo.IsServer -}}
|
||||
{{/* Collect all logs from all pages */}}
|
||||
{{- $all_logs := slice -}}
|
||||
{{- range .Site.Pages -}}
|
||||
{{- $page_logs := .Store.Get "hbx_logs" | default slice -}}
|
||||
{{- $all_logs = $all_logs | append $page_logs -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $all_logs -}}
|
||||
{{/* Create debug export as a resource for tooling */}}
|
||||
{{- $debug_data := dict "logs" $all_logs "build_time" now.Unix "hugo_version" hugo.Version -}}
|
||||
{{- $debug_json := $debug_data | jsonify -}}
|
||||
{{- $debug_resource := resources.FromString "hbx-debug.json" $debug_json -}}
|
||||
{{- $debug_resource.Publish -}}
|
||||
|
||||
{{/* Also emit to console for immediate visibility */}}
|
||||
<script>
|
||||
if (window.console && console.groupCollapsed) {
|
||||
console.groupCollapsed('[HBX] Build completed with {{ len $all_logs }} log entries');
|
||||
console.log('Debug data available at:', '/hbx-debug.json');
|
||||
{{ range $all_logs }}
|
||||
console.log('[HBX:{{ .level }}]', {{ .message | jsonify }}, 'page:', {{ .page | jsonify }});
|
||||
{{ end }}
|
||||
console.groupEnd();
|
||||
}
|
||||
</script>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -33,5 +33,8 @@
|
||||
|
||||
{{/* EXTENSIBILITY HOOK: BODY-END */}}
|
||||
{{ partial "functions/get_hook" (dict "hook" "body-end" "context" .) }}
|
||||
|
||||
{{/* Hugo Blox Debug Export (dev only) */}}
|
||||
{{ partial "hooks/body-end/hbx-debug-export" . }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -107,7 +107,6 @@ HUGO_ARGS=(
|
||||
if [ "$DEBUG_MODE" = true ]; then
|
||||
HUGO_ARGS+=(
|
||||
--logLevel debug
|
||||
--panicOnWarning
|
||||
--templateMetrics
|
||||
--templateMetricsHints
|
||||
--ignoreCache
|
||||
|
||||
@@ -85,7 +85,6 @@ HUGO_ARGS=(
|
||||
if [ "$DEBUG_MODE" = true ]; then
|
||||
HUGO_ARGS+=(
|
||||
--logLevel debug
|
||||
--panicOnWarning
|
||||
--templateMetrics
|
||||
--templateMetricsHints
|
||||
--ignoreCache
|
||||
|
||||
+4
-10
@@ -7,10 +7,10 @@
|
||||
* Usage: pnpm run vendor:libs
|
||||
*/
|
||||
|
||||
import { resolve } from "path";
|
||||
import {resolve} from "path";
|
||||
import del from "rollup-plugin-delete";
|
||||
import { defineConfig } from "vite";
|
||||
import { viteStaticCopy } from "vite-plugin-static-copy";
|
||||
import {defineConfig} from "vite";
|
||||
import {viteStaticCopy} from "vite-plugin-static-copy";
|
||||
|
||||
const MODULE_DIR = "modules/blox-tailwind";
|
||||
const OUTPUT_DIR = resolve(MODULE_DIR, "assets/dist/lib");
|
||||
@@ -26,13 +26,7 @@ export default defineConfig({
|
||||
},
|
||||
rollupOptions: {
|
||||
// Don't bundle these libraries, just copy them
|
||||
external: [
|
||||
"mermaid",
|
||||
"plotly.js",
|
||||
"katex",
|
||||
"markmap-autoloader",
|
||||
"alpinejs",
|
||||
],
|
||||
external: ["mermaid", "plotly.js", "katex", "markmap-autoloader", "alpinejs"],
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
Reference in new issue
Block a user