mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-12 20:15:25 +00:00
chore: adopt Biome + Stylelint, modernize CI/CD, add security/support docs, minor JS fixes
- Linting/format - Replace ESLint/Prettier with Biome; remove old configs; add `biome.json`; update scripts - Tailwind-friendly `.stylelintrc.yaml`; Stylelint and Biome pass - Enable Biome across `modules/**`; prune legacy JS globals; ignore oversized `devicon.json` - Code fixes - `hb-theme.js`: avoid assignment-in-expressions; clearer dataset updates - `hugoblox-slides.js`: fix inner var scope (var → let); apply formatting - CI/CD - Split lint/build workflows; add path filters; Node via Corepack (pnpm from package.json) - Hugo pinned to env `HUGO_VERSION`; add consistency check vs `starters/academic-cv/hugoblox.yaml` - Nightly starters matrix build (academic-cv, landing-page); CodeQL weekly; resource caches - Workflows/Community - Greeter: switch to `pull_request_target`; add Contributor Guide to PR message - PR labeler for path-based labels - Repo policies/docs - `CODEOWNERS` for `@gcushen` - `SECURITY.md`, `SUPPORT.md` - Documented branch protection in `.github/settings.yml` - Move `CODE_OF_CONDUCT.md` to `.github/` - docs(zh): update `README.zh.md` translation Notes: - pnpm is sourced from `package.json: packageManager` via Corepack; no hard-coded pnpm versions in CI.
This commit is contained in:
1 parent
db8a975a9f
commit
d5d2f04c2d
91 files changed
+2957
-1993
No files matched your search
@@ -1,85 +1,256 @@
|
||||
/* Background */ .bg { color: #f8f8f2; background-color: #282a36 }
|
||||
/* PreWrapper */ .chroma { color: #f8f8f2; background-color: #282a36; }
|
||||
/* Other */ .chroma .x { }
|
||||
/* Error */ .chroma .err { }
|
||||
/* CodeLine */ .chroma .cl { }
|
||||
/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
|
||||
/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
|
||||
/* LineHighlight */ .chroma .hl { background-color: #ffc }
|
||||
/* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
|
||||
/* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
|
||||
/* Line */ .chroma .line { display: flex; }
|
||||
/* Keyword */ .chroma .k { color: #ff79c6 }
|
||||
/* KeywordConstant */ .chroma .kc { color: #ff79c6 }
|
||||
/* KeywordDeclaration */ .chroma .kd { color: #8be9fd; font-style: italic }
|
||||
/* KeywordNamespace */ .chroma .kn { color: #ff79c6 }
|
||||
/* KeywordPseudo */ .chroma .kp { color: #ff79c6 }
|
||||
/* KeywordReserved */ .chroma .kr { color: #ff79c6 }
|
||||
/* KeywordType */ .chroma .kt { color: #8be9fd }
|
||||
/* Name */ .chroma .n { }
|
||||
/* NameAttribute */ .chroma .na { color: #50fa7b }
|
||||
/* NameBuiltin */ .chroma .nb { color: #8be9fd; font-style: italic }
|
||||
/* NameBuiltinPseudo */ .chroma .bp { }
|
||||
/* NameClass */ .chroma .nc { color: #50fa7b }
|
||||
/* NameConstant */ .chroma .no { }
|
||||
/* NameDecorator */ .chroma .nd { }
|
||||
/* NameEntity */ .chroma .ni { }
|
||||
/* NameException */ .chroma .ne { }
|
||||
/* NameFunction */ .chroma .nf { color: #50fa7b }
|
||||
/* NameFunctionMagic */ .chroma .fm { }
|
||||
/* NameLabel */ .chroma .nl { color: #8be9fd; font-style: italic }
|
||||
/* NameNamespace */ .chroma .nn { }
|
||||
/* NameOther */ .chroma .nx { }
|
||||
/* NameProperty */ .chroma .py { }
|
||||
/* NameTag */ .chroma .nt { color: #ff79c6 }
|
||||
/* NameVariable */ .chroma .nv { color: #8be9fd; font-style: italic }
|
||||
/* NameVariableClass */ .chroma .vc { color: #8be9fd; font-style: italic }
|
||||
/* NameVariableGlobal */ .chroma .vg { color: #8be9fd; font-style: italic }
|
||||
/* NameVariableInstance */ .chroma .vi { color: #8be9fd; font-style: italic }
|
||||
/* NameVariableMagic */ .chroma .vm { }
|
||||
/* Literal */ .chroma .l { }
|
||||
/* LiteralDate */ .chroma .ld { }
|
||||
/* LiteralString */ .chroma .s { color: #f1fa8c }
|
||||
/* LiteralStringAffix */ .chroma .sa { color: #f1fa8c }
|
||||
/* LiteralStringBacktick */ .chroma .sb { color: #f1fa8c }
|
||||
/* LiteralStringChar */ .chroma .sc { color: #f1fa8c }
|
||||
/* LiteralStringDelimiter */ .chroma .dl { color: #f1fa8c }
|
||||
/* LiteralStringDoc */ .chroma .sd { color: #f1fa8c }
|
||||
/* LiteralStringDouble */ .chroma .s2 { color: #f1fa8c }
|
||||
/* LiteralStringEscape */ .chroma .se { color: #f1fa8c }
|
||||
/* LiteralStringHeredoc */ .chroma .sh { color: #f1fa8c }
|
||||
/* LiteralStringInterpol */ .chroma .si { color: #f1fa8c }
|
||||
/* LiteralStringOther */ .chroma .sx { color: #f1fa8c }
|
||||
/* LiteralStringRegex */ .chroma .sr { color: #f1fa8c }
|
||||
/* LiteralStringSingle */ .chroma .s1 { color: #f1fa8c }
|
||||
/* LiteralStringSymbol */ .chroma .ss { color: #f1fa8c }
|
||||
/* LiteralNumber */ .chroma .m { color: #bd93f9 }
|
||||
/* LiteralNumberBin */ .chroma .mb { color: #bd93f9 }
|
||||
/* LiteralNumberFloat */ .chroma .mf { color: #bd93f9 }
|
||||
/* LiteralNumberHex */ .chroma .mh { color: #bd93f9 }
|
||||
/* LiteralNumberInteger */ .chroma .mi { color: #bd93f9 }
|
||||
/* LiteralNumberIntegerLong */ .chroma .il { color: #bd93f9 }
|
||||
/* LiteralNumberOct */ .chroma .mo { color: #bd93f9 }
|
||||
/* Operator */ .chroma .o { color: #ff79c6 }
|
||||
/* OperatorWord */ .chroma .ow { color: #ff79c6 }
|
||||
/* Punctuation */ .chroma .p { }
|
||||
/* Comment */ .chroma .c { color: #6272a4 }
|
||||
/* CommentHashbang */ .chroma .ch { color: #6272a4 }
|
||||
/* CommentMultiline */ .chroma .cm { color: #6272a4 }
|
||||
/* CommentSingle */ .chroma .c1 { color: #6272a4 }
|
||||
/* CommentSpecial */ .chroma .cs { color: #6272a4 }
|
||||
/* CommentPreproc */ .chroma .cp { color: #ff79c6 }
|
||||
/* CommentPreprocFile */ .chroma .cpf { color: #ff79c6 }
|
||||
/* Generic */ .chroma .g { }
|
||||
/* GenericDeleted */ .chroma .gd { color: #f55 }
|
||||
/* GenericEmph */ .chroma .ge { text-decoration: underline }
|
||||
/* GenericError */ .chroma .gr { }
|
||||
/* GenericHeading */ .chroma .gh { font-weight: bold }
|
||||
/* GenericInserted */ .chroma .gi { color: #50fa7b; font-weight: bold }
|
||||
/* GenericOutput */ .chroma .go { color: #44475a }
|
||||
/* GenericPrompt */ .chroma .gp { }
|
||||
/* GenericStrong */ .chroma .gs { }
|
||||
/* GenericSubheading */ .chroma .gu { font-weight: bold }
|
||||
/* GenericTraceback */ .chroma .gt { }
|
||||
/* GenericUnderline */ .chroma .gl { text-decoration: underline }
|
||||
/* TextWhitespace */ .chroma .w { }
|
||||
/* Background */ .bg {
|
||||
color: #f8f8f2;
|
||||
background-color: #282a36;
|
||||
}
|
||||
/* PreWrapper */ .chroma {
|
||||
color: #f8f8f2;
|
||||
background-color: #282a36;
|
||||
}
|
||||
/* Other */ .chroma .x {
|
||||
}
|
||||
/* Error */ .chroma .err {
|
||||
}
|
||||
/* CodeLine */ .chroma .cl {
|
||||
}
|
||||
/* LineTableTD */ .chroma .lntd {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
/* LineTable */ .chroma .lntable {
|
||||
border-spacing: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
/* LineHighlight */ .chroma .hl {
|
||||
background-color: #ffc;
|
||||
}
|
||||
/* LineNumbersTable */ .chroma .lnt {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: #7f7f7f;
|
||||
}
|
||||
/* LineNumbers */ .chroma .ln {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: #7f7f7f;
|
||||
}
|
||||
/* Line */ .chroma .line {
|
||||
display: flex;
|
||||
}
|
||||
/* Keyword */ .chroma .k {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* KeywordConstant */ .chroma .kc {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* KeywordDeclaration */ .chroma .kd {
|
||||
color: #8be9fd;
|
||||
font-style: italic;
|
||||
}
|
||||
/* KeywordNamespace */ .chroma .kn {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* KeywordPseudo */ .chroma .kp {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* KeywordReserved */ .chroma .kr {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* KeywordType */ .chroma .kt {
|
||||
color: #8be9fd;
|
||||
}
|
||||
/* Name */ .chroma .n {
|
||||
}
|
||||
/* NameAttribute */ .chroma .na {
|
||||
color: #50fa7b;
|
||||
}
|
||||
/* NameBuiltin */ .chroma .nb {
|
||||
color: #8be9fd;
|
||||
font-style: italic;
|
||||
}
|
||||
/* NameBuiltinPseudo */ .chroma .bp {
|
||||
}
|
||||
/* NameClass */ .chroma .nc {
|
||||
color: #50fa7b;
|
||||
}
|
||||
/* NameConstant */ .chroma .no {
|
||||
}
|
||||
/* NameDecorator */ .chroma .nd {
|
||||
}
|
||||
/* NameEntity */ .chroma .ni {
|
||||
}
|
||||
/* NameException */ .chroma .ne {
|
||||
}
|
||||
/* NameFunction */ .chroma .nf {
|
||||
color: #50fa7b;
|
||||
}
|
||||
/* NameFunctionMagic */ .chroma .fm {
|
||||
}
|
||||
/* NameLabel */ .chroma .nl {
|
||||
color: #8be9fd;
|
||||
font-style: italic;
|
||||
}
|
||||
/* NameNamespace */ .chroma .nn {
|
||||
}
|
||||
/* NameOther */ .chroma .nx {
|
||||
}
|
||||
/* NameProperty */ .chroma .py {
|
||||
}
|
||||
/* NameTag */ .chroma .nt {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* NameVariable */ .chroma .nv {
|
||||
color: #8be9fd;
|
||||
font-style: italic;
|
||||
}
|
||||
/* NameVariableClass */ .chroma .vc {
|
||||
color: #8be9fd;
|
||||
font-style: italic;
|
||||
}
|
||||
/* NameVariableGlobal */ .chroma .vg {
|
||||
color: #8be9fd;
|
||||
font-style: italic;
|
||||
}
|
||||
/* NameVariableInstance */ .chroma .vi {
|
||||
color: #8be9fd;
|
||||
font-style: italic;
|
||||
}
|
||||
/* NameVariableMagic */ .chroma .vm {
|
||||
}
|
||||
/* Literal */ .chroma .l {
|
||||
}
|
||||
/* LiteralDate */ .chroma .ld {
|
||||
}
|
||||
/* LiteralString */ .chroma .s {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringAffix */ .chroma .sa {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringBacktick */ .chroma .sb {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringChar */ .chroma .sc {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringDelimiter */ .chroma .dl {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringDoc */ .chroma .sd {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringDouble */ .chroma .s2 {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringEscape */ .chroma .se {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringHeredoc */ .chroma .sh {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringInterpol */ .chroma .si {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringOther */ .chroma .sx {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringRegex */ .chroma .sr {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringSingle */ .chroma .s1 {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralStringSymbol */ .chroma .ss {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
/* LiteralNumber */ .chroma .m {
|
||||
color: #bd93f9;
|
||||
}
|
||||
/* LiteralNumberBin */ .chroma .mb {
|
||||
color: #bd93f9;
|
||||
}
|
||||
/* LiteralNumberFloat */ .chroma .mf {
|
||||
color: #bd93f9;
|
||||
}
|
||||
/* LiteralNumberHex */ .chroma .mh {
|
||||
color: #bd93f9;
|
||||
}
|
||||
/* LiteralNumberInteger */ .chroma .mi {
|
||||
color: #bd93f9;
|
||||
}
|
||||
/* LiteralNumberIntegerLong */ .chroma .il {
|
||||
color: #bd93f9;
|
||||
}
|
||||
/* LiteralNumberOct */ .chroma .mo {
|
||||
color: #bd93f9;
|
||||
}
|
||||
/* Operator */ .chroma .o {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* OperatorWord */ .chroma .ow {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* Punctuation */ .chroma .p {
|
||||
}
|
||||
/* Comment */ .chroma .c {
|
||||
color: #6272a4;
|
||||
}
|
||||
/* CommentHashbang */ .chroma .ch {
|
||||
color: #6272a4;
|
||||
}
|
||||
/* CommentMultiline */ .chroma .cm {
|
||||
color: #6272a4;
|
||||
}
|
||||
/* CommentSingle */ .chroma .c1 {
|
||||
color: #6272a4;
|
||||
}
|
||||
/* CommentSpecial */ .chroma .cs {
|
||||
color: #6272a4;
|
||||
}
|
||||
/* CommentPreproc */ .chroma .cp {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* CommentPreprocFile */ .chroma .cpf {
|
||||
color: #ff79c6;
|
||||
}
|
||||
/* Generic */ .chroma .g {
|
||||
}
|
||||
/* GenericDeleted */ .chroma .gd {
|
||||
color: #f55;
|
||||
}
|
||||
/* GenericEmph */ .chroma .ge {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* GenericError */ .chroma .gr {
|
||||
}
|
||||
/* GenericHeading */ .chroma .gh {
|
||||
font-weight: bold;
|
||||
}
|
||||
/* GenericInserted */ .chroma .gi {
|
||||
color: #50fa7b;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* GenericOutput */ .chroma .go {
|
||||
color: #44475a;
|
||||
}
|
||||
/* GenericPrompt */ .chroma .gp {
|
||||
}
|
||||
/* GenericStrong */ .chroma .gs {
|
||||
}
|
||||
/* GenericSubheading */ .chroma .gu {
|
||||
font-weight: bold;
|
||||
}
|
||||
/* GenericTraceback */ .chroma .gt {
|
||||
}
|
||||
/* GenericUnderline */ .chroma .gl {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* TextWhitespace */ .chroma .w {
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
.chroma .hl {
|
||||
width: 100%;
|
||||
display: block;
|
||||
background-color: rgba(110,118,129,0.1);
|
||||
background-color: rgba(110, 118, 129, 0.1);
|
||||
}
|
||||
.chroma .lnt {
|
||||
color: #8b949e;
|
||||
|
||||
@@ -1,85 +1,286 @@
|
||||
/* Background */ .bg { background-color: #fff }
|
||||
/* PreWrapper */ .chroma { background-color: #fff; }
|
||||
/* Other */ .chroma .x { }
|
||||
/* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 }
|
||||
/* CodeLine */ .chroma .cl { }
|
||||
/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
|
||||
/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
|
||||
/* LineHighlight */ .chroma .hl { background-color: #ffc }
|
||||
/* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em;color: #7f7f7f }
|
||||
/* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em;color: #7f7f7f }
|
||||
/* Line */ .chroma .line { display: flex; }
|
||||
/* Keyword */ .chroma .k { color: #000; font-weight: bold }
|
||||
/* KeywordConstant */ .chroma .kc { color: #000; font-weight: bold }
|
||||
/* KeywordDeclaration */ .chroma .kd { color: #000; font-weight: bold }
|
||||
/* KeywordNamespace */ .chroma .kn { color: #000; font-weight: bold }
|
||||
/* KeywordPseudo */ .chroma .kp { color: #000; font-weight: bold }
|
||||
/* KeywordReserved */ .chroma .kr { color: #000; font-weight: bold }
|
||||
/* KeywordType */ .chroma .kt { color: #458; font-weight: bold }
|
||||
/* Name */ .chroma .n { }
|
||||
/* NameAttribute */ .chroma .na { color: #008080 }
|
||||
/* NameBuiltin */ .chroma .nb { color: #0086b3 }
|
||||
/* NameBuiltinPseudo */ .chroma .bp { color: #999 }
|
||||
/* NameClass */ .chroma .nc { color: #458; font-weight: bold }
|
||||
/* NameConstant */ .chroma .no { color: #008080 }
|
||||
/* NameDecorator */ .chroma .nd { color: #3c5d5d; font-weight: bold }
|
||||
/* NameEntity */ .chroma .ni { color: #800080 }
|
||||
/* NameException */ .chroma .ne { color: #900; font-weight: bold }
|
||||
/* NameFunction */ .chroma .nf { color: #900; font-weight: bold }
|
||||
/* NameFunctionMagic */ .chroma .fm { }
|
||||
/* NameLabel */ .chroma .nl { color: #900; font-weight: bold }
|
||||
/* NameNamespace */ .chroma .nn { color: #555 }
|
||||
/* NameOther */ .chroma .nx { }
|
||||
/* NameProperty */ .chroma .py { }
|
||||
/* NameTag */ .chroma .nt { color: #000080 }
|
||||
/* NameVariable */ .chroma .nv { color: #008080 }
|
||||
/* NameVariableClass */ .chroma .vc { color: #008080 }
|
||||
/* NameVariableGlobal */ .chroma .vg { color: #008080 }
|
||||
/* NameVariableInstance */ .chroma .vi { color: #008080 }
|
||||
/* NameVariableMagic */ .chroma .vm { }
|
||||
/* Literal */ .chroma .l { }
|
||||
/* LiteralDate */ .chroma .ld { }
|
||||
/* LiteralString */ .chroma .s { color: #d14 }
|
||||
/* LiteralStringAffix */ .chroma .sa { color: #d14 }
|
||||
/* LiteralStringBacktick */ .chroma .sb { color: #d14 }
|
||||
/* LiteralStringChar */ .chroma .sc { color: #d14 }
|
||||
/* LiteralStringDelimiter */ .chroma .dl { color: #d14 }
|
||||
/* LiteralStringDoc */ .chroma .sd { color: #d14 }
|
||||
/* LiteralStringDouble */ .chroma .s2 { color: #d14 }
|
||||
/* LiteralStringEscape */ .chroma .se { color: #d14 }
|
||||
/* LiteralStringHeredoc */ .chroma .sh { color: #d14 }
|
||||
/* LiteralStringInterpol */ .chroma .si { color: #d14 }
|
||||
/* LiteralStringOther */ .chroma .sx { color: #d14 }
|
||||
/* LiteralStringRegex */ .chroma .sr { color: #009926 }
|
||||
/* LiteralStringSingle */ .chroma .s1 { color: #d14 }
|
||||
/* LiteralStringSymbol */ .chroma .ss { color: #990073 }
|
||||
/* LiteralNumber */ .chroma .m { color: #099 }
|
||||
/* LiteralNumberBin */ .chroma .mb { color: #099 }
|
||||
/* LiteralNumberFloat */ .chroma .mf { color: #099 }
|
||||
/* LiteralNumberHex */ .chroma .mh { color: #099 }
|
||||
/* LiteralNumberInteger */ .chroma .mi { color: #099 }
|
||||
/* LiteralNumberIntegerLong */ .chroma .il { color: #099 }
|
||||
/* LiteralNumberOct */ .chroma .mo { color: #099 }
|
||||
/* Operator */ .chroma .o { color: #000; font-weight: bold }
|
||||
/* OperatorWord */ .chroma .ow { color: #000; font-weight: bold }
|
||||
/* Punctuation */ .chroma .p { }
|
||||
/* Comment */ .chroma .c { color: #998; font-style: italic }
|
||||
/* CommentHashbang */ .chroma .ch { color: #998; font-style: italic }
|
||||
/* CommentMultiline */ .chroma .cm { color: #998; font-style: italic }
|
||||
/* CommentSingle */ .chroma .c1 { color: #998; font-style: italic }
|
||||
/* CommentSpecial */ .chroma .cs { color: #999; font-weight: bold; font-style: italic }
|
||||
/* CommentPreproc */ .chroma .cp { color: #999; font-weight: bold; font-style: italic }
|
||||
/* CommentPreprocFile */ .chroma .cpf { color: #999; font-weight: bold; font-style: italic }
|
||||
/* Generic */ .chroma .g { }
|
||||
/* GenericDeleted */ .chroma .gd { color: #000; background-color: #fdd }
|
||||
/* GenericEmph */ .chroma .ge { color: #000; font-style: italic }
|
||||
/* GenericError */ .chroma .gr { color: #a00 }
|
||||
/* GenericHeading */ .chroma .gh { color: #999 }
|
||||
/* GenericInserted */ .chroma .gi { color: #000; background-color: #dfd }
|
||||
/* GenericOutput */ .chroma .go { color: #888 }
|
||||
/* GenericPrompt */ .chroma .gp { color: #555 }
|
||||
/* GenericStrong */ .chroma .gs { font-weight: bold }
|
||||
/* GenericSubheading */ .chroma .gu { color: #aaa }
|
||||
/* GenericTraceback */ .chroma .gt { color: #a00 }
|
||||
/* GenericUnderline */ .chroma .gl { text-decoration: underline }
|
||||
/* TextWhitespace */ .chroma .w { color: #bbb }
|
||||
/* Background */ .bg {
|
||||
background-color: #fff;
|
||||
}
|
||||
/* PreWrapper */ .chroma {
|
||||
background-color: #fff;
|
||||
}
|
||||
/* Other */ .chroma .x {
|
||||
}
|
||||
/* Error */ .chroma .err {
|
||||
color: #a61717;
|
||||
background-color: #e3d2d2;
|
||||
}
|
||||
/* CodeLine */ .chroma .cl {
|
||||
}
|
||||
/* LineTableTD */ .chroma .lntd {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
/* LineTable */ .chroma .lntable {
|
||||
border-spacing: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
/* LineHighlight */ .chroma .hl {
|
||||
background-color: #ffc;
|
||||
}
|
||||
/* LineNumbersTable */ .chroma .lnt {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em;
|
||||
color: #7f7f7f;
|
||||
}
|
||||
/* LineNumbers */ .chroma .ln {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em;
|
||||
color: #7f7f7f;
|
||||
}
|
||||
/* Line */ .chroma .line {
|
||||
display: flex;
|
||||
}
|
||||
/* Keyword */ .chroma .k {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* KeywordConstant */ .chroma .kc {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* KeywordDeclaration */ .chroma .kd {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* KeywordNamespace */ .chroma .kn {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* KeywordPseudo */ .chroma .kp {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* KeywordReserved */ .chroma .kr {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* KeywordType */ .chroma .kt {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* Name */ .chroma .n {
|
||||
}
|
||||
/* NameAttribute */ .chroma .na {
|
||||
color: #008080;
|
||||
}
|
||||
/* NameBuiltin */ .chroma .nb {
|
||||
color: #0086b3;
|
||||
}
|
||||
/* NameBuiltinPseudo */ .chroma .bp {
|
||||
color: #999;
|
||||
}
|
||||
/* NameClass */ .chroma .nc {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* NameConstant */ .chroma .no {
|
||||
color: #008080;
|
||||
}
|
||||
/* NameDecorator */ .chroma .nd {
|
||||
color: #3c5d5d;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* NameEntity */ .chroma .ni {
|
||||
color: #800080;
|
||||
}
|
||||
/* NameException */ .chroma .ne {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* NameFunction */ .chroma .nf {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* NameFunctionMagic */ .chroma .fm {
|
||||
}
|
||||
/* NameLabel */ .chroma .nl {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* NameNamespace */ .chroma .nn {
|
||||
color: #555;
|
||||
}
|
||||
/* NameOther */ .chroma .nx {
|
||||
}
|
||||
/* NameProperty */ .chroma .py {
|
||||
}
|
||||
/* NameTag */ .chroma .nt {
|
||||
color: #000080;
|
||||
}
|
||||
/* NameVariable */ .chroma .nv {
|
||||
color: #008080;
|
||||
}
|
||||
/* NameVariableClass */ .chroma .vc {
|
||||
color: #008080;
|
||||
}
|
||||
/* NameVariableGlobal */ .chroma .vg {
|
||||
color: #008080;
|
||||
}
|
||||
/* NameVariableInstance */ .chroma .vi {
|
||||
color: #008080;
|
||||
}
|
||||
/* NameVariableMagic */ .chroma .vm {
|
||||
}
|
||||
/* Literal */ .chroma .l {
|
||||
}
|
||||
/* LiteralDate */ .chroma .ld {
|
||||
}
|
||||
/* LiteralString */ .chroma .s {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringAffix */ .chroma .sa {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringBacktick */ .chroma .sb {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringChar */ .chroma .sc {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringDelimiter */ .chroma .dl {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringDoc */ .chroma .sd {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringDouble */ .chroma .s2 {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringEscape */ .chroma .se {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringHeredoc */ .chroma .sh {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringInterpol */ .chroma .si {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringOther */ .chroma .sx {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringRegex */ .chroma .sr {
|
||||
color: #009926;
|
||||
}
|
||||
/* LiteralStringSingle */ .chroma .s1 {
|
||||
color: #d14;
|
||||
}
|
||||
/* LiteralStringSymbol */ .chroma .ss {
|
||||
color: #990073;
|
||||
}
|
||||
/* LiteralNumber */ .chroma .m {
|
||||
color: #099;
|
||||
}
|
||||
/* LiteralNumberBin */ .chroma .mb {
|
||||
color: #099;
|
||||
}
|
||||
/* LiteralNumberFloat */ .chroma .mf {
|
||||
color: #099;
|
||||
}
|
||||
/* LiteralNumberHex */ .chroma .mh {
|
||||
color: #099;
|
||||
}
|
||||
/* LiteralNumberInteger */ .chroma .mi {
|
||||
color: #099;
|
||||
}
|
||||
/* LiteralNumberIntegerLong */ .chroma .il {
|
||||
color: #099;
|
||||
}
|
||||
/* LiteralNumberOct */ .chroma .mo {
|
||||
color: #099;
|
||||
}
|
||||
/* Operator */ .chroma .o {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* OperatorWord */ .chroma .ow {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* Punctuation */ .chroma .p {
|
||||
}
|
||||
/* Comment */ .chroma .c {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
/* CommentHashbang */ .chroma .ch {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
/* CommentMultiline */ .chroma .cm {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
/* CommentSingle */ .chroma .c1 {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
/* CommentSpecial */ .chroma .cs {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
/* CommentPreproc */ .chroma .cp {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
/* CommentPreprocFile */ .chroma .cpf {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
/* Generic */ .chroma .g {
|
||||
}
|
||||
/* GenericDeleted */ .chroma .gd {
|
||||
color: #000;
|
||||
background-color: #fdd;
|
||||
}
|
||||
/* GenericEmph */ .chroma .ge {
|
||||
color: #000;
|
||||
font-style: italic;
|
||||
}
|
||||
/* GenericError */ .chroma .gr {
|
||||
color: #a00;
|
||||
}
|
||||
/* GenericHeading */ .chroma .gh {
|
||||
color: #999;
|
||||
}
|
||||
/* GenericInserted */ .chroma .gi {
|
||||
color: #000;
|
||||
background-color: #dfd;
|
||||
}
|
||||
/* GenericOutput */ .chroma .go {
|
||||
color: #888;
|
||||
}
|
||||
/* GenericPrompt */ .chroma .gp {
|
||||
color: #555;
|
||||
}
|
||||
/* GenericStrong */ .chroma .gs {
|
||||
font-weight: bold;
|
||||
}
|
||||
/* GenericSubheading */ .chroma .gu {
|
||||
color: #aaa;
|
||||
}
|
||||
/* GenericTraceback */ .chroma .gt {
|
||||
color: #a00;
|
||||
}
|
||||
/* GenericUnderline */ .chroma .gl {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* TextWhitespace */ .chroma .w {
|
||||
color: #bbb;
|
||||
}
|
||||
@@ -9,13 +9,19 @@
|
||||
global RevealMarkdown, RevealSearch, RevealNotes, RevealMath, RevealZoom, Reveal, mermaid, RevealMenu
|
||||
*/
|
||||
|
||||
import * as params from '@params';
|
||||
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';
|
||||
return o === Object(o) && !isArray(o) && typeof o !== "function";
|
||||
};
|
||||
|
||||
const isArray = function (a) {
|
||||
@@ -24,7 +30,7 @@ const isArray = function (a) {
|
||||
|
||||
const toCamelCase = function (s) {
|
||||
return s.replace(/([-_][a-z])/gi, function (term) {
|
||||
return term.toUpperCase().replace('-', '').replace('_', '');
|
||||
return term.toUpperCase().replace("-", "").replace("_", "");
|
||||
});
|
||||
};
|
||||
|
||||
@@ -48,14 +54,14 @@ const keysToCamelCase = function (o) {
|
||||
|
||||
// reveal configurations can be included in front matter under slides.reveal
|
||||
var pluginOptions = {};
|
||||
if (typeof params.slides.reveal_options !== 'undefined') {
|
||||
if (typeof params.slides.reveal_options !== "undefined") {
|
||||
pluginOptions = params.slides.reveal_options;
|
||||
}
|
||||
|
||||
pluginOptions = keysToCamelCase(pluginOptions);
|
||||
|
||||
//enable menu by default if not set
|
||||
if (typeof pluginOptions.menu_enabled === 'undefined') {
|
||||
if (typeof pluginOptions.menu_enabled === "undefined") {
|
||||
pluginOptions.menu_enabled = true;
|
||||
}
|
||||
|
||||
@@ -64,12 +70,12 @@ if (pluginOptions.menu_enabled) {
|
||||
enabledPlugins.push(RevealMenu);
|
||||
}
|
||||
|
||||
pluginOptions['plugins'] = enabledPlugins;
|
||||
pluginOptions["plugins"] = enabledPlugins;
|
||||
|
||||
Reveal.initialize(pluginOptions);
|
||||
|
||||
// Disable Mermaid by default.
|
||||
if (typeof params.slides.diagram === 'undefined') {
|
||||
if (typeof params.slides.diagram === "undefined") {
|
||||
params.slides.diagram = false;
|
||||
}
|
||||
|
||||
@@ -78,36 +84,40 @@ if (params.slides.diagram) {
|
||||
//mermaid options
|
||||
// mermaid: front matter configuration can be used to set mermaid options
|
||||
// You can also use directives (see mermaid documentation)
|
||||
var mermaidOptions = {};
|
||||
if (typeof params.slides.diagram_options !== 'undefined') {
|
||||
let mermaidOptions = {};
|
||||
if (typeof params.slides.diagram_options !== "undefined") {
|
||||
mermaidOptions = params.slides.diagram_options;
|
||||
}
|
||||
|
||||
// `startOnLoad` must be false since diagrams are lazily rendered.
|
||||
mermaidOptions['startOnLoad'] = false;
|
||||
mermaidOptions["startOnLoad"] = false;
|
||||
|
||||
mermaid.initialize(mermaidOptions);
|
||||
|
||||
// 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}`
|
||||
let pageno = `${indices.h}-${indices.v}`;
|
||||
|
||||
mermaidDivs.forEach(function (mermaidDiv, i) {
|
||||
|
||||
let insertSvg = function (svgCode) {
|
||||
mermaidDiv.innerHTML = svgCode;
|
||||
mermaidDiv.classList.add('done');
|
||||
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();
|
||||
};
|
||||
|
||||
Reveal.on('ready', event => renderMermaidDiagrams(event));
|
||||
Reveal.on('slidechanged', event => renderMermaidDiagrams(event));
|
||||
Reveal.on("ready", (event) => renderMermaidDiagrams(event));
|
||||
Reveal.on("slidechanged", (event) => renderMermaidDiagrams(event));
|
||||
}
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
/* Enhanced backdrop blur support */
|
||||
@supports (backdrop-filter: blur(10px)) {
|
||||
.resume-biography-modern [class*='backdrop-blur'] {
|
||||
.resume-biography-modern [class*="backdrop-blur"] {
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
}
|
||||
@@ -152,12 +152,14 @@
|
||||
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 */
|
||||
@@ -168,7 +170,7 @@
|
||||
}
|
||||
|
||||
.hbx-bg-gradient::before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -182,16 +184,22 @@
|
||||
|
||||
/* 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%),
|
||||
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%),
|
||||
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%);
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
[data-search-toggle],
|
||||
#search-toggle,
|
||||
[data-te-collapse-init],
|
||||
.nav-dropdown > .nav-link[role='button'] {
|
||||
.nav-dropdown > .nav-link[role="button"] {
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import './libs/chroma/light.css';
|
||||
@import './libs/chroma/dark.css';
|
||||
@import "./libs/chroma/light.css";
|
||||
@import "./libs/chroma/dark.css";
|
||||
|
||||
/* Code Blocks: Apply theme background */
|
||||
/* Requires relative position for Code Copy button */
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@import 'page.css';
|
||||
@import 'task-list.css';
|
||||
@import 'copy.css';
|
||||
@import 'sidebar-left.css';
|
||||
@import 'charts.css';
|
||||
@import 'steps.css';
|
||||
@import 'cards.css';
|
||||
@import 'math.css';
|
||||
@import 'author-notes.css';
|
||||
@import 'glassmorphism.css';
|
||||
@import "page.css";
|
||||
@import "task-list.css";
|
||||
@import "copy.css";
|
||||
@import "sidebar-left.css";
|
||||
@import "charts.css";
|
||||
@import "steps.css";
|
||||
@import "cards.css";
|
||||
@import "math.css";
|
||||
@import "author-notes.css";
|
||||
@import "glassmorphism.css";
|
||||
@@ -35,7 +35,7 @@
|
||||
.author-notes {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Show author notes as superscript numbers in print */
|
||||
.author-notes::after {
|
||||
display: inline;
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
--hb-cols: 2;
|
||||
}
|
||||
|
||||
|
||||
.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 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 2025 Hugo Blox Glassmorphism Utility Classes
|
||||
*
|
||||
*
|
||||
* Modern glassmorphism effects for Hugo Blox CTA cards and other components
|
||||
*/
|
||||
|
||||
@@ -21,9 +21,14 @@
|
||||
}
|
||||
|
||||
.glassmorphism-primary::before {
|
||||
content: '';
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -40,37 +45,62 @@
|
||||
}
|
||||
|
||||
.glassmorphism-secondary::before {
|
||||
content: '';
|
||||
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);
|
||||
}
|
||||
|
||||
.glassmorphism-dark::before {
|
||||
content: '';
|
||||
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);
|
||||
}
|
||||
|
||||
.glassmorphism-light::before {
|
||||
content: '';
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -83,9 +113,9 @@
|
||||
}
|
||||
|
||||
.noise-texture::after {
|
||||
content: '';
|
||||
content: "";
|
||||
@apply absolute inset-0 pointer-events-none;
|
||||
background-image: url('/media/textures/noise-pattern.svg');
|
||||
background-image: url("/media/textures/noise-pattern.svg");
|
||||
background-size: 100px 100px;
|
||||
background-repeat: repeat;
|
||||
opacity: 0.03;
|
||||
@@ -106,13 +136,13 @@
|
||||
}
|
||||
|
||||
.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);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
@@ -139,8 +169,8 @@
|
||||
|
||||
/* 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 {
|
||||
@@ -153,8 +183,8 @@
|
||||
);
|
||||
|
||||
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 */
|
||||
@@ -167,8 +197,8 @@
|
||||
);
|
||||
|
||||
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 {
|
||||
@@ -201,20 +231,23 @@
|
||||
/* 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 {
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
/* Prevent long equations overflowing on small screens by scrolling horizontally instead. */
|
||||
.katex-display { overflow: auto hidden; }
|
||||
.katex-display {
|
||||
overflow: auto hidden;
|
||||
}
|
||||
@@ -7,11 +7,11 @@ ul.task-list {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
ul.task-list li input[type='checkbox'] {
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
ul.task-list input[type='checkbox']:checked {
|
||||
ul.task-list input[type="checkbox"]:checked {
|
||||
appearance: none;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
@@ -20,11 +20,11 @@ ul.task-list input[type='checkbox']:checked {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
ul.task-list input[type='checkbox']:not(:checked) {
|
||||
ul.task-list input[type="checkbox"]:not(:checked) {
|
||||
width: 0.9em;
|
||||
height: 0.9em;
|
||||
}
|
||||
|
||||
ul.task-list input[type='checkbox']:checked::after {
|
||||
content: '✅';
|
||||
ul.task-list input[type="checkbox"]:checked::after {
|
||||
content: "✅";
|
||||
}
|
||||
@@ -220,11 +220,11 @@
|
||||
|
||||
/* Support for dual light/dark background colors in parse_block_v2.html */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.home-section-bg[style*='--dark-bg-color'] {
|
||||
.home-section-bg[style*="--dark-bg-color"] {
|
||||
background-color: var(--dark-bg-color) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.dark .home-section-bg[style*='--dark-bg-color'] {
|
||||
.dark .home-section-bg[style*="--dark-bg-color"] {
|
||||
background-color: var(--dark-bg-color) !important;
|
||||
}
|
||||
@@ -320,7 +320,8 @@
|
||||
/* 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,
|
||||
--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 */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizelegibility;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
line-height: 1.5;
|
||||
}
|
||||
@@ -25,28 +25,28 @@
|
||||
text-decoration-color: rgb(var(--color-primary-300));
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
.prose a:hover {
|
||||
color: rgb(var(--color-primary-600));
|
||||
text-decoration: none;
|
||||
border-radius: 0.09rem;
|
||||
}
|
||||
|
||||
|
||||
.prose mark {
|
||||
color: rgb(var(--color-neutral-900));
|
||||
background-color: rgb(var(--color-primary-200));
|
||||
padding: 0.1rem 0.2rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
|
||||
.dark .prose-invert a {
|
||||
text-decoration-color: rgb(var(--color-neutral-500));
|
||||
}
|
||||
|
||||
|
||||
.dark .prose-invert a:hover {
|
||||
color: rgb(var(--color-primary-300));
|
||||
}
|
||||
|
||||
|
||||
.dark .prose-invert mark {
|
||||
background-color: rgb(var(--color-primary-400));
|
||||
color: black;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
|
||||
/* 2025 Glassmorphism texture support - disable conflicting defaults */
|
||||
.home-section-bg.bg-image[style*='background-size'][style*='background-repeat'] {
|
||||
.home-section-bg.bg-image[style*="background-size"][style*="background-repeat"] {
|
||||
background-size: revert !important;
|
||||
background-repeat: revert !important;
|
||||
background-position: revert !important;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
/* LineHighlight */
|
||||
|
||||
.chroma .hl {
|
||||
background-color: #ffc
|
||||
background-color: #ffc;
|
||||
}
|
||||
|
||||
/* LineNumbersTable */
|
||||
@@ -49,7 +49,7 @@
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: #7f7f7f
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
/* LineNumbers */
|
||||
@@ -59,7 +59,7 @@
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: #7f7f7f
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
/* Line */
|
||||
@@ -71,44 +71,44 @@
|
||||
/* Keyword */
|
||||
|
||||
.chroma .k {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* KeywordConstant */
|
||||
|
||||
.chroma .kc {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* KeywordDeclaration */
|
||||
|
||||
.chroma .kd {
|
||||
color: #8be9fd;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* KeywordNamespace */
|
||||
|
||||
.chroma .kn {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* KeywordPseudo */
|
||||
|
||||
.chroma .kp {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* KeywordReserved */
|
||||
|
||||
.chroma .kr {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* KeywordType */
|
||||
|
||||
.chroma .kt {
|
||||
color: #8be9fd
|
||||
color: #8be9fd;
|
||||
}
|
||||
|
||||
/* Name */
|
||||
@@ -119,14 +119,14 @@
|
||||
/* NameAttribute */
|
||||
|
||||
.chroma .na {
|
||||
color: #50fa7b
|
||||
color: #50fa7b;
|
||||
}
|
||||
|
||||
/* NameBuiltin */
|
||||
|
||||
.chroma .nb {
|
||||
color: #8be9fd;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* NameBuiltinPseudo */
|
||||
@@ -137,7 +137,7 @@
|
||||
/* NameClass */
|
||||
|
||||
.chroma .nc {
|
||||
color: #50fa7b
|
||||
color: #50fa7b;
|
||||
}
|
||||
|
||||
/* NameConstant */
|
||||
@@ -163,7 +163,7 @@
|
||||
/* NameFunction */
|
||||
|
||||
.chroma .nf {
|
||||
color: #50fa7b
|
||||
color: #50fa7b;
|
||||
}
|
||||
|
||||
/* NameFunctionMagic */
|
||||
@@ -175,7 +175,7 @@
|
||||
|
||||
.chroma .nl {
|
||||
color: #8be9fd;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* NameNamespace */
|
||||
@@ -196,35 +196,35 @@
|
||||
/* NameTag */
|
||||
|
||||
.chroma .nt {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* NameVariable */
|
||||
|
||||
.chroma .nv {
|
||||
color: #8be9fd;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* NameVariableClass */
|
||||
|
||||
.chroma .vc {
|
||||
color: #8be9fd;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* NameVariableGlobal */
|
||||
|
||||
.chroma .vg {
|
||||
color: #8be9fd;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* NameVariableInstance */
|
||||
|
||||
.chroma .vi {
|
||||
color: #8be9fd;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* NameVariableMagic */
|
||||
@@ -245,139 +245,139 @@
|
||||
/* LiteralString */
|
||||
|
||||
.chroma .s {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringAffix */
|
||||
|
||||
.chroma .sa {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringBacktick */
|
||||
|
||||
.chroma .sb {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringChar */
|
||||
|
||||
.chroma .sc {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringDelimiter */
|
||||
|
||||
.chroma .dl {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringDoc */
|
||||
|
||||
.chroma .sd {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringDouble */
|
||||
|
||||
.chroma .s2 {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringEscape */
|
||||
|
||||
.chroma .se {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringHeredoc */
|
||||
|
||||
.chroma .sh {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringInterpol */
|
||||
|
||||
.chroma .si {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringOther */
|
||||
|
||||
.chroma .sx {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringRegex */
|
||||
|
||||
.chroma .sr {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringSingle */
|
||||
|
||||
.chroma .s1 {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralStringSymbol */
|
||||
|
||||
.chroma .ss {
|
||||
color: #f1fa8c
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* LiteralNumber */
|
||||
|
||||
.chroma .m {
|
||||
color: #bd93f9
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* LiteralNumberBin */
|
||||
|
||||
.chroma .mb {
|
||||
color: #bd93f9
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* LiteralNumberFloat */
|
||||
|
||||
.chroma .mf {
|
||||
color: #bd93f9
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* LiteralNumberHex */
|
||||
|
||||
.chroma .mh {
|
||||
color: #bd93f9
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* LiteralNumberInteger */
|
||||
|
||||
.chroma .mi {
|
||||
color: #bd93f9
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* LiteralNumberIntegerLong */
|
||||
|
||||
.chroma .il {
|
||||
color: #bd93f9
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* LiteralNumberOct */
|
||||
|
||||
.chroma .mo {
|
||||
color: #bd93f9
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* Operator */
|
||||
|
||||
.chroma .o {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* OperatorWord */
|
||||
|
||||
.chroma .ow {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* Punctuation */
|
||||
@@ -388,43 +388,43 @@
|
||||
/* Comment */
|
||||
|
||||
.chroma .c {
|
||||
color: #6272a4
|
||||
color: #6272a4;
|
||||
}
|
||||
|
||||
/* CommentHashbang */
|
||||
|
||||
.chroma .ch {
|
||||
color: #6272a4
|
||||
color: #6272a4;
|
||||
}
|
||||
|
||||
/* CommentMultiline */
|
||||
|
||||
.chroma .cm {
|
||||
color: #6272a4
|
||||
color: #6272a4;
|
||||
}
|
||||
|
||||
/* CommentSingle */
|
||||
|
||||
.chroma .c1 {
|
||||
color: #6272a4
|
||||
color: #6272a4;
|
||||
}
|
||||
|
||||
/* CommentSpecial */
|
||||
|
||||
.chroma .cs {
|
||||
color: #6272a4
|
||||
color: #6272a4;
|
||||
}
|
||||
|
||||
/* CommentPreproc */
|
||||
|
||||
.chroma .cp {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* CommentPreprocFile */
|
||||
|
||||
.chroma .cpf {
|
||||
color: #ff79c6
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* Generic */
|
||||
@@ -435,13 +435,13 @@
|
||||
/* GenericDeleted */
|
||||
|
||||
.chroma .gd {
|
||||
color: #f55
|
||||
color: #f55;
|
||||
}
|
||||
|
||||
/* GenericEmph */
|
||||
|
||||
.chroma .ge {
|
||||
text-decoration: underline
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* GenericError */
|
||||
@@ -452,20 +452,20 @@
|
||||
/* GenericHeading */
|
||||
|
||||
.chroma .gh {
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* GenericInserted */
|
||||
|
||||
.chroma .gi {
|
||||
color: #50fa7b;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* GenericOutput */
|
||||
|
||||
.chroma .go {
|
||||
color: #44475a
|
||||
color: #44475a;
|
||||
}
|
||||
|
||||
/* GenericPrompt */
|
||||
@@ -481,7 +481,7 @@
|
||||
/* GenericSubheading */
|
||||
|
||||
.chroma .gu {
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* GenericTraceback */
|
||||
@@ -492,7 +492,7 @@
|
||||
/* GenericUnderline */
|
||||
|
||||
.chroma .gl {
|
||||
text-decoration: underline
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* TextWhitespace */
|
||||
|
||||
@@ -12,7 +12,7 @@ html:not(.dark) .highlight {
|
||||
|
||||
.chroma .err {
|
||||
color: #a61717;
|
||||
background-color: #e3d2d2
|
||||
background-color: #e3d2d2;
|
||||
}
|
||||
|
||||
/* CodeLine */
|
||||
@@ -41,7 +41,7 @@ html:not(.dark) .highlight {
|
||||
/* LineHighlight */
|
||||
|
||||
.chroma .hl {
|
||||
background-color: #ffc
|
||||
background-color: #ffc;
|
||||
}
|
||||
|
||||
/* LineNumbersTable */
|
||||
@@ -51,7 +51,7 @@ html:not(.dark) .highlight {
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em;
|
||||
color: #7f7f7f
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
/* LineNumbers */
|
||||
@@ -61,7 +61,7 @@ html:not(.dark) .highlight {
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em;
|
||||
color: #7f7f7f
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
/* Line */
|
||||
@@ -74,49 +74,49 @@ html:not(.dark) .highlight {
|
||||
|
||||
.chroma .k {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* KeywordConstant */
|
||||
|
||||
.chroma .kc {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* KeywordDeclaration */
|
||||
|
||||
.chroma .kd {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* KeywordNamespace */
|
||||
|
||||
.chroma .kn {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* KeywordPseudo */
|
||||
|
||||
.chroma .kp {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* KeywordReserved */
|
||||
|
||||
.chroma .kr {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* KeywordType */
|
||||
|
||||
.chroma .kt {
|
||||
color: #458;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Name */
|
||||
@@ -127,59 +127,59 @@ html:not(.dark) .highlight {
|
||||
/* NameAttribute */
|
||||
|
||||
.chroma .na {
|
||||
color: #008080
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
/* NameBuiltin */
|
||||
|
||||
.chroma .nb {
|
||||
color: #0086b3
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
/* NameBuiltinPseudo */
|
||||
|
||||
.chroma .bp {
|
||||
color: #999
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* NameClass */
|
||||
|
||||
.chroma .nc {
|
||||
color: #458;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* NameConstant */
|
||||
|
||||
.chroma .no {
|
||||
color: #008080
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
/* NameDecorator */
|
||||
|
||||
.chroma .nd {
|
||||
color: #3c5d5d;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* NameEntity */
|
||||
|
||||
.chroma .ni {
|
||||
color: #800080
|
||||
color: #800080;
|
||||
}
|
||||
|
||||
/* NameException */
|
||||
|
||||
.chroma .ne {
|
||||
color: #900;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* NameFunction */
|
||||
|
||||
.chroma .nf {
|
||||
color: #900;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* NameFunctionMagic */
|
||||
@@ -191,13 +191,13 @@ html:not(.dark) .highlight {
|
||||
|
||||
.chroma .nl {
|
||||
color: #900;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* NameNamespace */
|
||||
|
||||
.chroma .nn {
|
||||
color: #555
|
||||
color: #555;
|
||||
}
|
||||
|
||||
/* NameOther */
|
||||
@@ -213,31 +213,31 @@ html:not(.dark) .highlight {
|
||||
/* NameTag */
|
||||
|
||||
.chroma .nt {
|
||||
color: #000080
|
||||
color: #000080;
|
||||
}
|
||||
|
||||
/* NameVariable */
|
||||
|
||||
.chroma .nv {
|
||||
color: #008080
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
/* NameVariableClass */
|
||||
|
||||
.chroma .vc {
|
||||
color: #008080
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
/* NameVariableGlobal */
|
||||
|
||||
.chroma .vg {
|
||||
color: #008080
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
/* NameVariableInstance */
|
||||
|
||||
.chroma .vi {
|
||||
color: #008080
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
/* NameVariableMagic */
|
||||
@@ -258,141 +258,141 @@ html:not(.dark) .highlight {
|
||||
/* LiteralString */
|
||||
|
||||
.chroma .s {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringAffix */
|
||||
|
||||
.chroma .sa {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringBacktick */
|
||||
|
||||
.chroma .sb {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringChar */
|
||||
|
||||
.chroma .sc {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringDelimiter */
|
||||
|
||||
.chroma .dl {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringDoc */
|
||||
|
||||
.chroma .sd {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringDouble */
|
||||
|
||||
.chroma .s2 {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringEscape */
|
||||
|
||||
.chroma .se {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringHeredoc */
|
||||
|
||||
.chroma .sh {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringInterpol */
|
||||
|
||||
.chroma .si {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringOther */
|
||||
|
||||
.chroma .sx {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringRegex */
|
||||
|
||||
.chroma .sr {
|
||||
color: #009926
|
||||
color: #009926;
|
||||
}
|
||||
|
||||
/* LiteralStringSingle */
|
||||
|
||||
.chroma .s1 {
|
||||
color: #d14
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
/* LiteralStringSymbol */
|
||||
|
||||
.chroma .ss {
|
||||
color: #990073
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
/* LiteralNumber */
|
||||
|
||||
.chroma .m {
|
||||
color: #099
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/* LiteralNumberBin */
|
||||
|
||||
.chroma .mb {
|
||||
color: #099
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/* LiteralNumberFloat */
|
||||
|
||||
.chroma .mf {
|
||||
color: #099
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/* LiteralNumberHex */
|
||||
|
||||
.chroma .mh {
|
||||
color: #099
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/* LiteralNumberInteger */
|
||||
|
||||
.chroma .mi {
|
||||
color: #099
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/* LiteralNumberIntegerLong */
|
||||
|
||||
.chroma .il {
|
||||
color: #099
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/* LiteralNumberOct */
|
||||
|
||||
.chroma .mo {
|
||||
color: #099
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/* Operator */
|
||||
|
||||
.chroma .o {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* OperatorWord */
|
||||
|
||||
.chroma .ow {
|
||||
color: #000;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Punctuation */
|
||||
@@ -404,28 +404,28 @@ html:not(.dark) .highlight {
|
||||
|
||||
.chroma .c {
|
||||
color: #998;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* CommentHashbang */
|
||||
|
||||
.chroma .ch {
|
||||
color: #998;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* CommentMultiline */
|
||||
|
||||
.chroma .cm {
|
||||
color: #998;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* CommentSingle */
|
||||
|
||||
.chroma .c1 {
|
||||
color: #998;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* CommentSpecial */
|
||||
@@ -433,7 +433,7 @@ html:not(.dark) .highlight {
|
||||
.chroma .cs {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* CommentPreproc */
|
||||
@@ -441,7 +441,7 @@ html:not(.dark) .highlight {
|
||||
.chroma .cp {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* CommentPreprocFile */
|
||||
@@ -449,7 +449,7 @@ html:not(.dark) .highlight {
|
||||
.chroma .cpf {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Generic */
|
||||
@@ -461,74 +461,74 @@ html:not(.dark) .highlight {
|
||||
|
||||
.chroma .gd {
|
||||
color: #000;
|
||||
background-color: #fdd
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
/* GenericEmph */
|
||||
|
||||
.chroma .ge {
|
||||
color: #000;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* GenericError */
|
||||
|
||||
.chroma .gr {
|
||||
color: #a00
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
/* GenericHeading */
|
||||
|
||||
.chroma .gh {
|
||||
color: #999
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* GenericInserted */
|
||||
|
||||
.chroma .gi {
|
||||
color: #000;
|
||||
background-color: #dfd
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
/* GenericOutput */
|
||||
|
||||
.chroma .go {
|
||||
color: #888
|
||||
color: #888;
|
||||
}
|
||||
|
||||
/* GenericPrompt */
|
||||
|
||||
.chroma .gp {
|
||||
color: #555
|
||||
color: #555;
|
||||
}
|
||||
|
||||
/* GenericStrong */
|
||||
|
||||
.chroma .gs {
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* GenericSubheading */
|
||||
|
||||
.chroma .gu {
|
||||
color: #aaa
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* GenericTraceback */
|
||||
|
||||
.chroma .gt {
|
||||
color: #a00
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
/* GenericUnderline */
|
||||
|
||||
.chroma .gl {
|
||||
text-decoration: underline
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* TextWhitespace */
|
||||
|
||||
.chroma .w {
|
||||
color: #bbb
|
||||
color: #bbb;
|
||||
}
|
||||
}
|
||||
@@ -11,26 +11,26 @@
|
||||
*/
|
||||
|
||||
/* Tailwind CSS v4 Base */
|
||||
@import 'tailwindcss';
|
||||
@import "tailwindcss";
|
||||
|
||||
/* Configuration */
|
||||
@import 'config/tailwind.css';
|
||||
@import 'config/theme.css';
|
||||
@import "config/tailwind.css";
|
||||
@import "config/theme.css";
|
||||
|
||||
/* Base styles and utilities */
|
||||
@import 'framework/base.css';
|
||||
@import "framework/base.css";
|
||||
|
||||
/* Hugo Blox theme system (color utilities) */
|
||||
@import 'color-utilities.css';
|
||||
@import "color-utilities.css";
|
||||
|
||||
/* Hugo Blox framework components */
|
||||
@import 'framework/components.css';
|
||||
@import "framework/components.css";
|
||||
|
||||
/* Hugo Blox module components */
|
||||
@import 'components/all.css';
|
||||
@import 'blox/all.css';
|
||||
@import 'views/all.css';
|
||||
@import 'chroma.css';
|
||||
@import "components/all.css";
|
||||
@import "blox/all.css";
|
||||
@import "views/all.css";
|
||||
@import "chroma.css";
|
||||
|
||||
/* Safelist for dynamic classes */
|
||||
@import 'config/safelist.css';
|
||||
@import "config/safelist.css";
|
||||
@@ -3,31 +3,31 @@
|
||||
* Copies BibTeX citation to clipboard when cite button is clicked
|
||||
*/
|
||||
|
||||
import { hugoEnvironment, i18n } from '@params';
|
||||
import { showNotification } from './hb-notifier.js';
|
||||
import { copyToClipboardSync, ClipboardCache } from './hb-clipboard.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';
|
||||
const isDebugMode = hugoEnvironment === "development";
|
||||
|
||||
// Cache for citation content
|
||||
const citationCache = new ClipboardCache();
|
||||
|
||||
// Initialize citation handlers when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initializeCitation);
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initializeCitation);
|
||||
} else {
|
||||
initializeCitation();
|
||||
}
|
||||
|
||||
function initializeCitation() {
|
||||
// Handle citation button clicks using event delegation
|
||||
document.addEventListener('click', handleCiteClick);
|
||||
|
||||
document.addEventListener("click", handleCiteClick);
|
||||
|
||||
// Prefetch citations on hover/focus for better UX and Safari compatibility
|
||||
document.addEventListener('mouseover', prefetchOnHover);
|
||||
document.addEventListener('focusin', prefetchOnHover);
|
||||
|
||||
document.addEventListener("mouseover", prefetchOnHover);
|
||||
document.addEventListener("focusin", prefetchOnHover);
|
||||
|
||||
// Prefetch all citations on page load
|
||||
prefetchAllCitations();
|
||||
}
|
||||
@@ -36,9 +36,11 @@ function initializeCitation() {
|
||||
* Prefetch all citations on page load
|
||||
*/
|
||||
function prefetchAllCitations() {
|
||||
const citeButtons = document.querySelectorAll('.js-cite-clipboard[data-filename]');
|
||||
citeButtons.forEach(button => {
|
||||
const filename = button.getAttribute('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)) {
|
||||
// Fetch in background, don't await
|
||||
fetchAndCacheCitation(filename);
|
||||
@@ -51,10 +53,10 @@ function prefetchAllCitations() {
|
||||
* @param {Event} e - Hover or focus event
|
||||
*/
|
||||
function prefetchOnHover(e) {
|
||||
const citeButton = e.target.closest('.js-cite-clipboard');
|
||||
const citeButton = e.target.closest(".js-cite-clipboard");
|
||||
if (!citeButton) return;
|
||||
|
||||
const filename = citeButton.getAttribute('data-filename');
|
||||
|
||||
const filename = citeButton.getAttribute("data-filename");
|
||||
if (filename && !citationCache.has(filename)) {
|
||||
// Fetch in background, don't await
|
||||
fetchAndCacheCitation(filename);
|
||||
@@ -89,32 +91,32 @@ async function fetchAndCacheCitation(filename) {
|
||||
*/
|
||||
function handleCiteClick(e) {
|
||||
// Check if clicked element or its parent is a cite button
|
||||
const citeButton = e.target.closest('.js-cite-clipboard');
|
||||
const citeButton = e.target.closest(".js-cite-clipboard");
|
||||
if (!citeButton) return;
|
||||
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const filename = citeButton.getAttribute('data-filename');
|
||||
|
||||
const filename = citeButton.getAttribute("data-filename");
|
||||
if (!filename) {
|
||||
if (isDebugMode) {
|
||||
console.error('No filename specified for citation');
|
||||
console.error("No filename specified for citation");
|
||||
}
|
||||
showNotification('Citation file not found', 'error');
|
||||
showNotification("Citation file not found", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Check if citation is cached
|
||||
const cachedCitation = citationCache.get(filename);
|
||||
|
||||
|
||||
if (cachedCitation) {
|
||||
// Citation is cached, copy immediately (synchronous for Safari)
|
||||
copyToClipboardSync(cachedCitation).then(success => {
|
||||
copyToClipboardSync(cachedCitation).then((success) => {
|
||||
if (success) {
|
||||
showNotification(i18n?.copied || 'Citation copied!', 'success');
|
||||
showNotification(i18n?.copied || "Citation copied!", "success");
|
||||
updateButtonText(citeButton);
|
||||
} else {
|
||||
showNotification('Failed to copy citation', 'error');
|
||||
showNotification("Failed to copy citation", "error");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -135,23 +137,26 @@ async function fetchAndCopyWithFallback(filename, button) {
|
||||
// Try to copy (might fail in Safari due to lost user activation)
|
||||
const success = await copyToClipboardSync(citation);
|
||||
if (success) {
|
||||
showNotification(i18n?.copied || 'Citation copied!', 'success');
|
||||
showNotification(i18n?.copied || "Citation copied!", "success");
|
||||
updateButtonText(button);
|
||||
} else {
|
||||
showNotification('Failed to copy citation', 'error');
|
||||
showNotification("Failed to copy citation", "error");
|
||||
}
|
||||
} else {
|
||||
showNotification('Failed to load citation', 'error');
|
||||
showNotification("Failed to load citation", "error");
|
||||
}
|
||||
} catch (error) {
|
||||
if (isDebugMode) {
|
||||
console.error('Failed to copy citation:', error);
|
||||
console.error("Failed to copy citation:", error);
|
||||
}
|
||||
// If it's a NotAllowedError, suggest hovering first
|
||||
if (error.name === 'NotAllowedError') {
|
||||
showNotification('Please hover over the button first, then click', 'info');
|
||||
if (error.name === "NotAllowedError") {
|
||||
showNotification(
|
||||
"Please hover over the button first, then click",
|
||||
"info",
|
||||
);
|
||||
} else {
|
||||
showNotification('Failed to copy citation', 'error');
|
||||
showNotification("Failed to copy citation", "error");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,29 +166,29 @@ async function fetchAndCopyWithFallback(filename, button) {
|
||||
* @param {HTMLElement} button - The cite button element
|
||||
*/
|
||||
function updateButtonText(button) {
|
||||
const copiedText = i18n?.copied || 'Copied!';
|
||||
|
||||
const copiedText = i18n?.copied || "Copied!";
|
||||
|
||||
// Find text element to update (skip icon)
|
||||
const textElement = button.querySelector('span');
|
||||
const textElement = button.querySelector("span");
|
||||
if (!textElement) {
|
||||
if (isDebugMode) {
|
||||
console.warn('Could not find text element in cite button');
|
||||
console.warn("Could not find text element in cite button");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const originalText = textElement.textContent;
|
||||
textElement.textContent = copiedText;
|
||||
|
||||
|
||||
// Add visual feedback
|
||||
button.classList.add('opacity-70');
|
||||
|
||||
button.classList.add("opacity-70");
|
||||
|
||||
// Revert after 2 seconds
|
||||
setTimeout(() => {
|
||||
textElement.textContent = originalText;
|
||||
button.classList.remove('opacity-70');
|
||||
button.classList.remove("opacity-70");
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// Export functions for potential reuse
|
||||
export { handleCiteClick, prefetchAllCitations };
|
||||
export { handleCiteClick, prefetchAllCitations };
|
||||
@@ -3,10 +3,10 @@
|
||||
* Provides cross-browser clipboard functionality
|
||||
*/
|
||||
|
||||
import { hugoEnvironment } from '@params';
|
||||
import { hugoEnvironment } from "@params";
|
||||
|
||||
// Debug mode based on environment
|
||||
const isDebugMode = hugoEnvironment === 'development';
|
||||
const isDebugMode = hugoEnvironment === "development";
|
||||
|
||||
/**
|
||||
* Copy text to clipboard with multiple fallback methods
|
||||
@@ -19,16 +19,16 @@ export async function copyToClipboard(text) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
if (isDebugMode) {
|
||||
console.log('Copied using Clipboard API');
|
||||
console.log("Copied using Clipboard API");
|
||||
}
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (isDebugMode) {
|
||||
console.warn('Clipboard API failed:', err);
|
||||
console.warn("Clipboard API failed:", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Method 2: execCommand fallback
|
||||
return copyUsingExecCommand(text);
|
||||
}
|
||||
@@ -42,16 +42,17 @@ export function copyToClipboardSync(text) {
|
||||
return new Promise((resolve) => {
|
||||
// Try modern clipboard API first
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
navigator.clipboard.writeText(text)
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
if (isDebugMode) {
|
||||
console.log('Copied using Clipboard API (sync)');
|
||||
console.log("Copied using Clipboard API (sync)");
|
||||
}
|
||||
resolve(true);
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
if (isDebugMode) {
|
||||
console.warn('Clipboard API failed:', err);
|
||||
console.warn("Clipboard API failed:", err);
|
||||
}
|
||||
// Fallback to execCommand
|
||||
resolve(copyUsingExecCommand(text));
|
||||
@@ -69,30 +70,30 @@ export function copyToClipboardSync(text) {
|
||||
* @returns {boolean} - Success status
|
||||
*/
|
||||
export function copyUsingExecCommand(text) {
|
||||
const textarea = document.createElement('textarea');
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.value = text;
|
||||
|
||||
|
||||
// Make it invisible but copyable
|
||||
Object.assign(textarea.style, {
|
||||
position: 'fixed',
|
||||
top: '0',
|
||||
left: '0',
|
||||
width: '2em',
|
||||
height: '2em',
|
||||
padding: '0',
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
boxShadow: 'none',
|
||||
background: 'transparent',
|
||||
fontSize: '16px', // Prevent zoom on iOS
|
||||
position: "fixed",
|
||||
top: "0",
|
||||
left: "0",
|
||||
width: "2em",
|
||||
height: "2em",
|
||||
padding: "0",
|
||||
border: "none",
|
||||
outline: "none",
|
||||
boxShadow: "none",
|
||||
background: "transparent",
|
||||
fontSize: "16px", // Prevent zoom on iOS
|
||||
});
|
||||
|
||||
|
||||
document.body.appendChild(textarea);
|
||||
|
||||
|
||||
// Select the text
|
||||
textarea.focus();
|
||||
textarea.select();
|
||||
|
||||
|
||||
// For iOS
|
||||
if (navigator.userAgent.match(/ipad|iphone/i)) {
|
||||
const range = document.createRange();
|
||||
@@ -102,19 +103,19 @@ export function copyUsingExecCommand(text) {
|
||||
selection.addRange(range);
|
||||
textarea.setSelectionRange(0, 999999);
|
||||
}
|
||||
|
||||
|
||||
let success = false;
|
||||
try {
|
||||
success = document.execCommand('copy');
|
||||
success = document.execCommand("copy");
|
||||
if (isDebugMode) {
|
||||
console.log(`execCommand copy ${success ? 'succeeded' : 'failed'}`);
|
||||
console.log(`execCommand copy ${success ? "succeeded" : "failed"}`);
|
||||
}
|
||||
} catch (err) {
|
||||
if (isDebugMode) {
|
||||
console.error('execCommand failed:', err);
|
||||
console.error("execCommand failed:", err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.body.removeChild(textarea);
|
||||
return success;
|
||||
}
|
||||
@@ -135,7 +136,7 @@ export class ClipboardCache {
|
||||
constructor() {
|
||||
this.cache = new Map();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add content to cache
|
||||
* @param {string} key - Cache key
|
||||
@@ -147,7 +148,7 @@ export class ClipboardCache {
|
||||
console.log(`Cached clipboard content for: ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get content from cache
|
||||
* @param {string} key - Cache key
|
||||
@@ -156,7 +157,7 @@ export class ClipboardCache {
|
||||
get(key) {
|
||||
return this.cache.get(key) || null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if content is cached
|
||||
* @param {string} key - Cache key
|
||||
@@ -165,14 +166,14 @@ export class ClipboardCache {
|
||||
has(key) {
|
||||
return this.cache.has(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the cache
|
||||
*/
|
||||
clear() {
|
||||
this.cache.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get cache size
|
||||
* @returns {number} - Number of cached items
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { hugoEnvironment, i18n } from '@params';
|
||||
import { hugoEnvironment, i18n } from "@params";
|
||||
|
||||
// Constants
|
||||
const NOTIFICATION_DURATION = 2000; // milliseconds
|
||||
const DEBOUNCE_DELAY = 300; // milliseconds
|
||||
|
||||
// Debug mode based on environment
|
||||
const isDebugMode = hugoEnvironment === 'development';
|
||||
const isDebugMode = hugoEnvironment === "development";
|
||||
|
||||
/**
|
||||
* Debounce function to prevent rapid clicking
|
||||
@@ -33,37 +33,37 @@ const debounce = (func, wait) => {
|
||||
*/
|
||||
async function copyCodeToClipboard(button, codeWrapper) {
|
||||
if (!button || !(button instanceof HTMLElement)) {
|
||||
throw new Error('Invalid button element');
|
||||
throw new Error("Invalid button element");
|
||||
}
|
||||
if (!codeWrapper || !(codeWrapper instanceof HTMLElement)) {
|
||||
throw new Error('Invalid code wrapper element');
|
||||
throw new Error("Invalid code wrapper element");
|
||||
}
|
||||
|
||||
// Clone the wrapper to avoid modifying the displayed content
|
||||
const tempWrapper = codeWrapper.cloneNode(true);
|
||||
|
||||
// Remove the copy button from the cloned wrapper
|
||||
const copyButton = tempWrapper.querySelector('.copy-button');
|
||||
const copyButton = tempWrapper.querySelector(".copy-button");
|
||||
if (copyButton) {
|
||||
copyButton.remove();
|
||||
}
|
||||
|
||||
const codeToCopy = tempWrapper.textContent?.trim() ?? '';
|
||||
const codeToCopy = tempWrapper.textContent?.trim() ?? "";
|
||||
|
||||
if (!codeToCopy) {
|
||||
throw new Error('No code content found to copy');
|
||||
throw new Error("No code content found to copy");
|
||||
}
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(codeToCopy);
|
||||
copiedNotification(button);
|
||||
isDebugMode && console.debug('Code copied successfully');
|
||||
isDebugMode && console.debug("Code copied successfully");
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
||||
console.error('Failed to copy:', errorMessage);
|
||||
button.innerHTML = i18n['copyFailed'] || 'Failed';
|
||||
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
||||
console.error("Failed to copy:", errorMessage);
|
||||
button.innerHTML = i18n["copyFailed"] || "Failed";
|
||||
setTimeout(() => {
|
||||
button.innerHTML = i18n['copy'];
|
||||
button.innerHTML = i18n["copy"];
|
||||
}, NOTIFICATION_DURATION);
|
||||
throw err; // Re-throw for potential error boundary handling
|
||||
}
|
||||
@@ -74,14 +74,14 @@ async function copyCodeToClipboard(button, codeWrapper) {
|
||||
* @param {HTMLElement} copyBtn - The copy button element
|
||||
*/
|
||||
function copiedNotification(copyBtn) {
|
||||
copyBtn.innerHTML = i18n['copied'];
|
||||
copyBtn.innerHTML = i18n["copied"];
|
||||
copyBtn.disabled = true;
|
||||
copyBtn.classList.add('copied');
|
||||
copyBtn.classList.add("copied");
|
||||
|
||||
setTimeout(() => {
|
||||
copyBtn.innerHTML = i18n['copy'];
|
||||
copyBtn.innerHTML = i18n["copy"];
|
||||
copyBtn.disabled = false;
|
||||
copyBtn.classList.remove('copied');
|
||||
copyBtn.classList.remove("copied");
|
||||
}, NOTIFICATION_DURATION);
|
||||
}
|
||||
|
||||
@@ -90,11 +90,14 @@ function copiedNotification(copyBtn) {
|
||||
* @returns {HTMLButtonElement} The created button
|
||||
*/
|
||||
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('type', 'button'); // Explicit button type
|
||||
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("type", "button"); // Explicit button type
|
||||
return copyBtn;
|
||||
}
|
||||
|
||||
@@ -106,25 +109,25 @@ function createCopyButton() {
|
||||
function getCodeWrapper(codeblock) {
|
||||
const container = codeblock.parentNode?.parentNode;
|
||||
if (!container) {
|
||||
throw new Error('Invalid code block structure');
|
||||
throw new Error("Invalid code block structure");
|
||||
}
|
||||
|
||||
if (container.classList.contains('highlight')) {
|
||||
if (container.classList.contains("highlight")) {
|
||||
return container;
|
||||
}
|
||||
|
||||
const tableWrapper = container.closest('table');
|
||||
const tableWrapper = container.closest("table");
|
||||
if (tableWrapper) {
|
||||
return tableWrapper;
|
||||
}
|
||||
|
||||
const preElement = codeblock.parentElement;
|
||||
if (preElement) {
|
||||
preElement.classList.add('highlight');
|
||||
preElement.classList.add("highlight");
|
||||
return preElement;
|
||||
}
|
||||
|
||||
throw new Error('Could not determine code wrapper');
|
||||
throw new Error("Could not determine code wrapper");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +135,7 @@ function getCodeWrapper(codeblock) {
|
||||
*/
|
||||
function initializeCodeCopyButtons() {
|
||||
try {
|
||||
const codeBlocks = document.querySelectorAll('pre > code');
|
||||
const codeBlocks = document.querySelectorAll("pre > code");
|
||||
isDebugMode && console.debug(`Found ${codeBlocks.length} code blocks`);
|
||||
|
||||
codeBlocks.forEach((codeblock, index) => {
|
||||
@@ -143,23 +146,26 @@ function initializeCodeCopyButtons() {
|
||||
// Use debounced version of copy function
|
||||
const debouncedCopy = debounce(
|
||||
() => copyCodeToClipboard(copyBtn, wrapper),
|
||||
DEBOUNCE_DELAY
|
||||
DEBOUNCE_DELAY,
|
||||
);
|
||||
|
||||
copyBtn.addEventListener('click', debouncedCopy);
|
||||
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) {
|
||||
console.error('Failed to initialize code copy buttons:', err);
|
||||
console.error("Failed to initialize code copy buttons:", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
window.addEventListener('DOMContentLoaded', initializeCodeCopyButtons);
|
||||
if (document.readyState === "loading") {
|
||||
window.addEventListener("DOMContentLoaded", initializeCodeCopyButtons);
|
||||
} else {
|
||||
initializeCodeCopyButtons();
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
import {initTheme, applyHugoStyleFixes} from './hb-init.js';
|
||||
import { applyHugoStyleFixes, initTheme } from "./hb-init.js";
|
||||
|
||||
// Initialize Hugo Blox Builder global object
|
||||
const root = document.documentElement;
|
||||
const defaultTheme = root.dataset.wcThemeDefault || 'system';
|
||||
const defaultTheme = root.dataset.wcThemeDefault || "system";
|
||||
|
||||
// Create global HBB object with theme functions
|
||||
window.hbb = {
|
||||
defaultTheme: defaultTheme,
|
||||
setDarkTheme: function () {
|
||||
root.classList.add('dark');
|
||||
root.style.colorScheme = 'dark';
|
||||
root.classList.add("dark");
|
||||
root.style.colorScheme = "dark";
|
||||
},
|
||||
setLightTheme: function () {
|
||||
root.classList.remove('dark');
|
||||
root.style.colorScheme = 'light';
|
||||
root.classList.remove("dark");
|
||||
root.style.colorScheme = "light";
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
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) => {
|
||||
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');
|
||||
languageOptions.classList.toggle("hidden");
|
||||
const languageChooserRect = languageChooser.getBoundingClientRect();
|
||||
const translateY = languageChooserRect.bottom - window.innerHeight + 40;
|
||||
languageOptions.style.transform = `translate3d(${languageChooserRect.left}px, ${translateY}px, 0)`;
|
||||
@@ -15,12 +18,12 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||
});
|
||||
|
||||
// Handle clicks outside chooser
|
||||
document.addEventListener('click', (e) => {
|
||||
if (e.target.closest('[data-hb-language-chooser]') === null) {
|
||||
document.addEventListener("click", (e) => {
|
||||
if (e.target.closest("[data-hb-language-chooser]") === null) {
|
||||
languageChoosers.forEach((languageChooser) => {
|
||||
languageChooser.dataset.state = 'closed';
|
||||
languageChooser.dataset.state = "closed";
|
||||
const languageOptions = languageChooser.nextElementSibling;
|
||||
languageOptions.classList.add('hidden');
|
||||
languageOptions.classList.add("hidden");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3,40 +3,47 @@ export function initTheme() {
|
||||
const root = document.documentElement;
|
||||
const defaultTheme = root.dataset.wcThemeDefault;
|
||||
const setDark = () => {
|
||||
root.classList.add('dark');
|
||||
root.style.colorScheme = 'dark';
|
||||
root.classList.add("dark");
|
||||
root.style.colorScheme = "dark";
|
||||
};
|
||||
const setLight = () => {
|
||||
root.classList.remove('dark');
|
||||
root.style.colorScheme = 'light';
|
||||
root.classList.remove("dark");
|
||||
root.style.colorScheme = "light";
|
||||
};
|
||||
|
||||
if ('wc-color-theme' in localStorage) {
|
||||
localStorage.getItem('wc-color-theme') === 'dark' ? setDark() : setLight();
|
||||
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();
|
||||
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]");
|
||||
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');
|
||||
if (parent) parent.classList.add("task-list");
|
||||
});
|
||||
|
||||
const liNodes = document.querySelectorAll('.task-list li');
|
||||
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,
|
||||
(node) =>
|
||||
node.nodeType === 3 &&
|
||||
node.textContent &&
|
||||
node.textContent.trim().length > 1,
|
||||
);
|
||||
if (textNodes.length > 0) {
|
||||
const span = document.createElement('label');
|
||||
const span = document.createElement("label");
|
||||
textNodes[0].after(span);
|
||||
const input = nodes.querySelector("input[type='checkbox']");
|
||||
if (input) span.appendChild(input);
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
function getCssVar(name) {
|
||||
const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
||||
return value ? 'rgb(' + value + ')' : null;
|
||||
const value = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue(name)
|
||||
.trim();
|
||||
return value ? "rgb(" + value + ")" : null;
|
||||
}
|
||||
|
||||
window.mermaid.initialize({
|
||||
theme: 'base',
|
||||
theme: "base",
|
||||
themeVariables: {
|
||||
background: getCssVar('--color-neutral-50') || '#fafafa',
|
||||
primaryColor: getCssVar('--color-primary-200') || '#bfdbfe',
|
||||
secondaryColor: getCssVar('--color-secondary-200') || '#a5f3fc',
|
||||
tertiaryColor: getCssVar('--color-neutral-100') || '#f5f5f5',
|
||||
primaryBorderColor: getCssVar('--color-primary-400') || '#60a5fa',
|
||||
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'),
|
||||
fontSize: '16px',
|
||||
background: getCssVar("--color-neutral-50") || "#fafafa",
|
||||
primaryColor: getCssVar("--color-primary-200") || "#bfdbfe",
|
||||
secondaryColor: getCssVar("--color-secondary-200") || "#a5f3fc",
|
||||
tertiaryColor: getCssVar("--color-neutral-100") || "#f5f5f5",
|
||||
primaryBorderColor: getCssVar("--color-primary-400") || "#60a5fa",
|
||||
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",
|
||||
),
|
||||
fontSize: "16px",
|
||||
},
|
||||
});
|
||||
@@ -1,11 +1,12 @@
|
||||
// Navigation
|
||||
|
||||
const applyScrollPadding = () => {
|
||||
const header = document.querySelector('.page-header');
|
||||
const header = document.querySelector(".page-header");
|
||||
let position = header.getBoundingClientRect();
|
||||
document.documentElement.style.scrollPaddingTop = position.height.toString() + 'px';
|
||||
const r = document.querySelector(':root');
|
||||
r.style.setProperty('--navbar-height', 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", () => {
|
||||
@@ -40,5 +41,5 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||
});
|
||||
});
|
||||
|
||||
applyScrollPadding()
|
||||
applyScrollPadding();
|
||||
});
|
||||
@@ -3,10 +3,10 @@
|
||||
* Provides reusable notification functionality
|
||||
*/
|
||||
|
||||
import { hugoEnvironment } from '@params';
|
||||
import { hugoEnvironment } from "@params";
|
||||
|
||||
// Debug mode based on environment
|
||||
const isDebugMode = hugoEnvironment === 'development';
|
||||
const isDebugMode = hugoEnvironment === "development";
|
||||
|
||||
/**
|
||||
* Show a notification message using Tailwind styles
|
||||
@@ -15,37 +15,40 @@ const isDebugMode = hugoEnvironment === 'development';
|
||||
* @param {number} duration - Duration in milliseconds (default 3000)
|
||||
* @returns {HTMLElement} - The notification element
|
||||
*/
|
||||
export function showNotification(message, type = 'success', duration = 3000) {
|
||||
export function showNotification(message, type = "success", duration = 3000) {
|
||||
// Get or create the notification container
|
||||
const container = getOrCreateContainer();
|
||||
|
||||
|
||||
// Remove any existing notifications with same message
|
||||
const existingNotification = container.querySelector('.hb-notification');
|
||||
if (existingNotification && existingNotification.textContent.includes(message)) {
|
||||
const existingNotification = container.querySelector(".hb-notification");
|
||||
if (
|
||||
existingNotification &&
|
||||
existingNotification.textContent.includes(message)
|
||||
) {
|
||||
existingNotification.remove();
|
||||
}
|
||||
|
||||
|
||||
// Create notification element
|
||||
const notification = createNotificationElement(message, type);
|
||||
|
||||
|
||||
// Add to container
|
||||
container.appendChild(notification);
|
||||
|
||||
|
||||
// Handle close button
|
||||
const closeBtn = notification.querySelector('.hb-notification-close');
|
||||
const closeBtn = notification.querySelector(".hb-notification-close");
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', () => {
|
||||
closeBtn.addEventListener("click", () => {
|
||||
removeNotification(notification);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Auto-remove after duration
|
||||
if (duration > 0) {
|
||||
setTimeout(() => {
|
||||
removeNotification(notification);
|
||||
}, duration);
|
||||
}
|
||||
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
@@ -54,20 +57,20 @@ export function showNotification(message, type = 'success', duration = 3000) {
|
||||
* @returns {HTMLElement} - The container element
|
||||
*/
|
||||
function getOrCreateContainer() {
|
||||
let container = document.getElementById('hb-notification-container');
|
||||
|
||||
let container = document.getElementById("hb-notification-container");
|
||||
|
||||
if (!container) {
|
||||
if (isDebugMode) {
|
||||
console.warn('Notification container not found, creating fallback');
|
||||
console.warn("Notification container not found, creating fallback");
|
||||
}
|
||||
container = document.createElement('div');
|
||||
container.id = 'hb-notification-container';
|
||||
container.className = 'fixed top-20 right-4 z-[9999] pointer-events-none';
|
||||
container.setAttribute('aria-live', 'polite');
|
||||
container.setAttribute('aria-atomic', 'true');
|
||||
container = document.createElement("div");
|
||||
container.id = "hb-notification-container";
|
||||
container.className = "fixed top-20 right-4 z-[9999] pointer-events-none";
|
||||
container.setAttribute("aria-live", "polite");
|
||||
container.setAttribute("aria-atomic", "true");
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
@@ -78,22 +81,22 @@ function getOrCreateContainer() {
|
||||
* @returns {HTMLElement} - The notification element
|
||||
*/
|
||||
function createNotificationElement(message, type) {
|
||||
const notification = document.createElement('div');
|
||||
notification.setAttribute('role', 'alert');
|
||||
|
||||
const notification = document.createElement("div");
|
||||
notification.setAttribute("role", "alert");
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
// Set classes
|
||||
notification.className = `hb-notification pointer-events-auto flex items-center gap-2 px-4 py-3 text-white rounded-lg shadow-lg ${color.bgClass} animate-slide-in`;
|
||||
|
||||
|
||||
// Add inline styles as fallback
|
||||
notification.style.cssText = `
|
||||
background-color: ${color.bg};
|
||||
@@ -107,17 +110,20 @@ function createNotificationElement(message, type) {
|
||||
margin-bottom: 0.5rem;
|
||||
pointer-events: auto;
|
||||
`;
|
||||
|
||||
|
||||
// Add icon based on type
|
||||
const icons = {
|
||||
success: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path></svg>',
|
||||
error: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path></svg>',
|
||||
success:
|
||||
'<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path></svg>',
|
||||
error:
|
||||
'<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path></svg>',
|
||||
info: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>',
|
||||
warning: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path></svg>'
|
||||
warning:
|
||||
'<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path></svg>',
|
||||
};
|
||||
|
||||
|
||||
const icon = icons[type] || icons.info;
|
||||
|
||||
|
||||
notification.innerHTML = `
|
||||
${icon}
|
||||
<span class="text-sm font-medium">${message}</span>
|
||||
@@ -127,10 +133,10 @@ function createNotificationElement(message, type) {
|
||||
</svg>
|
||||
</button>
|
||||
`;
|
||||
|
||||
|
||||
// Ensure animation styles exist
|
||||
ensureAnimationStyles();
|
||||
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
@@ -140,10 +146,10 @@ function createNotificationElement(message, type) {
|
||||
*/
|
||||
export function removeNotification(notification) {
|
||||
if (!notification || !notification.parentNode) return;
|
||||
|
||||
notification.classList.remove('animate-slide-in');
|
||||
notification.classList.add('animate-slide-out');
|
||||
|
||||
|
||||
notification.classList.remove("animate-slide-in");
|
||||
notification.classList.add("animate-slide-out");
|
||||
|
||||
setTimeout(() => {
|
||||
if (notification.parentNode) {
|
||||
notification.remove();
|
||||
@@ -155,9 +161,9 @@ export function removeNotification(notification) {
|
||||
* Ensure animation styles are in the document
|
||||
*/
|
||||
function ensureAnimationStyles() {
|
||||
if (!document.querySelector('#hb-notification-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'hb-notification-styles';
|
||||
if (!document.querySelector("#hb-notification-styles")) {
|
||||
const style = document.createElement("style");
|
||||
style.id = "hb-notification-styles";
|
||||
style.textContent = `
|
||||
@keyframes slide-in {
|
||||
from {
|
||||
|
||||
@@ -2,59 +2,64 @@
|
||||
// Initialize search wrapper element globally
|
||||
let searchWrapper = null;
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const configScript = document.getElementById('search-config');
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const configScript = document.getElementById("search-config");
|
||||
if (!configScript) {
|
||||
// No search on this page.
|
||||
return;
|
||||
}
|
||||
|
||||
const searchConfig = JSON.parse(configScript.textContent);
|
||||
if (!searchConfig || typeof searchConfig.baseUrl === 'undefined') {
|
||||
console.error('Pagefind search config is missing or invalid.', searchConfig);
|
||||
if (!searchConfig || typeof searchConfig.baseUrl === "undefined") {
|
||||
console.error(
|
||||
"Pagefind search config is missing or invalid.",
|
||||
searchConfig,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
new PagefindUI({
|
||||
element: '#search',
|
||||
element: "#search",
|
||||
showSubResults: true,
|
||||
baseUrl: searchConfig.baseUrl,
|
||||
bundlePath: searchConfig.baseUrl + 'pagefind/',
|
||||
bundlePath: searchConfig.baseUrl + "pagefind/",
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Failed to initialize PagefindUI:', e);
|
||||
console.error("Failed to initialize PagefindUI:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get search wrapper element
|
||||
searchWrapper = document.getElementById('search-wrapper');
|
||||
searchWrapper = document.getElementById("search-wrapper");
|
||||
|
||||
// Add click handlers to triggers
|
||||
let triggers = document.querySelectorAll('[data-search-toggle]');
|
||||
triggers.forEach((trigger) => trigger.addEventListener('click', handleSearchToggle));
|
||||
let triggers = document.querySelectorAll("[data-search-toggle]");
|
||||
triggers.forEach((trigger) =>
|
||||
trigger.addEventListener("click", handleSearchToggle),
|
||||
);
|
||||
});
|
||||
|
||||
function handleSearchToggle() {
|
||||
if (!searchWrapper) return;
|
||||
|
||||
const isHidden = searchWrapper.classList.contains('hidden');
|
||||
searchWrapper.classList.toggle('hidden');
|
||||
document.body.style.overflow = isHidden ? 'hidden' : '';
|
||||
const isHidden = searchWrapper.classList.contains("hidden");
|
||||
searchWrapper.classList.toggle("hidden");
|
||||
document.body.style.overflow = isHidden ? "hidden" : "";
|
||||
|
||||
const searchInput = searchWrapper.querySelector('input');
|
||||
const searchInput = searchWrapper.querySelector("input");
|
||||
if (searchInput) {
|
||||
searchInput.value = '';
|
||||
searchInput.value = "";
|
||||
searchInput.focus();
|
||||
}
|
||||
|
||||
if (!searchWrapper.classList.contains('hidden')) {
|
||||
let clearTrigger = document.querySelector('.pagefind-ui__search-clear');
|
||||
if (!searchWrapper.classList.contains("hidden")) {
|
||||
let clearTrigger = document.querySelector(".pagefind-ui__search-clear");
|
||||
|
||||
if (clearTrigger && !clearTrigger.hasAttribute('listenerOnClick')) {
|
||||
clearTrigger.setAttribute('listenerOnClick', 'true');
|
||||
if (clearTrigger && !clearTrigger.hasAttribute("listenerOnClick")) {
|
||||
clearTrigger.setAttribute("listenerOnClick", "true");
|
||||
|
||||
clearTrigger.addEventListener('click', () => {
|
||||
clearTrigger.addEventListener("click", () => {
|
||||
searchInput.focus();
|
||||
});
|
||||
}
|
||||
@@ -62,8 +67,12 @@ 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')) {
|
||||
searchWrapper.classList.add('hidden');
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (
|
||||
event.key === "Escape" &&
|
||||
searchWrapper &&
|
||||
!searchWrapper.classList.contains("hidden")
|
||||
) {
|
||||
searchWrapper.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
@@ -5,25 +5,31 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
e.preventDefault();
|
||||
const parent = button.parentElement.parentElement;
|
||||
if (parent) {
|
||||
parent.classList.toggle("open")
|
||||
parent.classList.toggle("open");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Hamburger menu for mobile navigation
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const menu = document.querySelector('#nav-toggle');
|
||||
const overlay = document.querySelector('.hb-sidebar-mobile-menu');
|
||||
const sidebarContainer = document.querySelector('.hb-sidebar-container');
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const menu = document.querySelector("#nav-toggle");
|
||||
const overlay = document.querySelector(".hb-sidebar-mobile-menu");
|
||||
const sidebarContainer = document.querySelector(".hb-sidebar-container");
|
||||
|
||||
if (!overlay){
|
||||
if (!overlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the overlay
|
||||
const overlayClasses = ['fixed', 'z-10', 'inset-0', 'bg-white', 'dark:bg-black/80'];
|
||||
overlay.classList.add('bg-transparent');
|
||||
const overlayClasses = [
|
||||
"fixed",
|
||||
"z-10",
|
||||
"inset-0",
|
||||
"bg-white",
|
||||
"dark:bg-black/80",
|
||||
];
|
||||
overlay.classList.add("bg-transparent");
|
||||
overlay.classList.remove("hidden", ...overlayClasses);
|
||||
|
||||
function toggleMenu() {
|
||||
@@ -31,36 +37,38 @@ 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,0,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
|
||||
document.body.classList.toggle('overflow-hidden');
|
||||
document.body.classList.toggle('lg:overflow-auto');
|
||||
document.body.classList.toggle("overflow-hidden");
|
||||
document.body.classList.toggle("lg:overflow-auto");
|
||||
}
|
||||
|
||||
menu.addEventListener('click', (e) => {
|
||||
console.debug("Hamburger clicked.");
|
||||
menu.addEventListener("click", (e) => {
|
||||
console.debug("Hamburger clicked.");
|
||||
e.preventDefault();
|
||||
toggleMenu();
|
||||
|
||||
if (overlay.classList.contains('bg-transparent')) {
|
||||
if (overlay.classList.contains("bg-transparent")) {
|
||||
// Show overlay
|
||||
overlay.classList.add(...overlayClasses);
|
||||
overlay.classList.remove('bg-transparent');
|
||||
overlay.classList.remove("bg-transparent");
|
||||
} else {
|
||||
// Hide overlay
|
||||
overlay.classList.remove(...overlayClasses);
|
||||
overlay.classList.add('bg-transparent');
|
||||
overlay.classList.add("bg-transparent");
|
||||
}
|
||||
});
|
||||
|
||||
overlay.addEventListener('click', (e) => {
|
||||
overlay.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
toggleMenu();
|
||||
|
||||
// Hide overlay
|
||||
overlay.classList.remove(...overlayClasses);
|
||||
overlay.classList.add('bg-transparent');
|
||||
overlay.classList.add("bg-transparent");
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
// Hugo Blox Builder Light / Dark theme toggle
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
addThemeToggleListener();
|
||||
});
|
||||
|
||||
@@ -11,17 +11,23 @@ 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");
|
||||
themeToggleButtons.forEach((el) => {
|
||||
el.dataset.theme = "dark";
|
||||
});
|
||||
} else {
|
||||
themeToggleButtons.forEach((el) => el.dataset.theme = "light");
|
||||
themeToggleButtons.forEach((el) => {
|
||||
el.dataset.theme = "light";
|
||||
});
|
||||
}
|
||||
|
||||
// Add click event handler to the light/dark buttons
|
||||
themeToggleButtons.forEach((el) => {
|
||||
el.addEventListener("click", function () {
|
||||
console.debug('Theme toggled');
|
||||
console.debug("Theme toggled");
|
||||
if (localStorage.getItem("wc-color-theme")) {
|
||||
if (localStorage.getItem("wc-color-theme") === "light") {
|
||||
window.hbb.setDarkTheme();
|
||||
@@ -39,21 +45,31 @@ 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")}});
|
||||
const themeChangeEvent = new CustomEvent("hbThemeChange", {
|
||||
detail: {
|
||||
isDarkTheme: () =>
|
||||
document.documentElement.classList.contains("dark"),
|
||||
},
|
||||
});
|
||||
document.dispatchEvent(themeChangeEvent);
|
||||
});
|
||||
});
|
||||
|
||||
// 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) =>
|
||||
el.dataset.theme = document.documentElement.classList.contains("dark") ? "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,5 +1,2 @@
|
||||
// Dummy entry for Vite lib mode. We copy vendor libraries via vite-plugin-static-copy.
|
||||
export default {}
|
||||
|
||||
|
||||
|
||||
export default {};
|
||||
@@ -4,11 +4,25 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -115,4 +115,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,25 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -46,4 +46,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,18 @@
|
||||
"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/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": ["hugo", "cta", "marketing", "conversion", "banner", "card"]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,25 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -73,4 +73,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,18 @@
|
||||
"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/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": ["hugo", "features", "grid", "services", "benefits", "product"]
|
||||
}
|
||||
|
||||
@@ -54,4 +54,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,18 @@
|
||||
"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/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": ["hugo", "hero", "landing-page", "cta", "marketing", "headlines"]
|
||||
}
|
||||
|
||||
@@ -91,4 +91,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,18 @@
|
||||
"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/",
|
||||
"repository": "https://github.com/HugoBlox/hugo-blox-builder",
|
||||
"keywords": ["hugo", "markdown", "content", "typography", "prose", "text"]
|
||||
}
|
||||
|
||||
@@ -32,4 +32,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,25 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -53,4 +53,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,27 @@
|
||||
"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,11 +4,27 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -97,4 +97,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,27 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -54,4 +54,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,27 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -36,4 +36,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,27 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -53,4 +53,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -181,4 +181,3 @@
|
||||
"required": ["block"],
|
||||
"additionalProperties": true
|
||||
}
|
||||
|
||||
@@ -100,4 +100,3 @@
|
||||
"required": ["type", "sections"],
|
||||
"additionalProperties": true
|
||||
}
|
||||
|
||||
@@ -6,22 +6,21 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"$ref": "../hero/schema.json"},
|
||||
{"$ref": "../features/schema.json"},
|
||||
{"$ref": "../collection/schema.json"},
|
||||
{"$ref": "../markdown/schema.json"},
|
||||
{"$ref": "../stats/schema.json"},
|
||||
{"$ref": "../testimonials/schema.json"},
|
||||
{"$ref": "../cta-button-list/schema.json"},
|
||||
{"$ref": "../cta-card/schema.json"},
|
||||
{"$ref": "../cta-image-paragraph/schema.json"},
|
||||
{"$ref": "../resume-experience/schema.json"},
|
||||
{"$ref": "../resume-biography/schema.json"},
|
||||
{"$ref": "../resume-biography-3/schema.json"},
|
||||
{"$ref": "../resume-skills/schema.json"},
|
||||
{"$ref": "../resume-awards/schema.json"},
|
||||
{"$ref": "../resume-languages/schema.json"}
|
||||
{ "$ref": "../hero/schema.json" },
|
||||
{ "$ref": "../features/schema.json" },
|
||||
{ "$ref": "../collection/schema.json" },
|
||||
{ "$ref": "../markdown/schema.json" },
|
||||
{ "$ref": "../stats/schema.json" },
|
||||
{ "$ref": "../testimonials/schema.json" },
|
||||
{ "$ref": "../cta-button-list/schema.json" },
|
||||
{ "$ref": "../cta-card/schema.json" },
|
||||
{ "$ref": "../cta-image-paragraph/schema.json" },
|
||||
{ "$ref": "../resume-experience/schema.json" },
|
||||
{ "$ref": "../resume-biography/schema.json" },
|
||||
{ "$ref": "../resume-biography-3/schema.json" },
|
||||
{ "$ref": "../resume-skills/schema.json" },
|
||||
{ "$ref": "../resume-awards/schema.json" },
|
||||
{ "$ref": "../resume-languages/schema.json" }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,25 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -50,4 +50,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,25 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -58,4 +58,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -13,15 +13,8 @@
|
||||
"spdx": "MIT",
|
||||
"url": "https://github.com/tailwindlabs/heroicons/blob/master/LICENSE"
|
||||
},
|
||||
"samples": [
|
||||
"camera",
|
||||
"building-library",
|
||||
"receipt-refund"
|
||||
],
|
||||
"height": [
|
||||
24,
|
||||
20
|
||||
],
|
||||
"samples": ["camera", "building-library", "receipt-refund"],
|
||||
"height": [24, 20],
|
||||
"category": "General",
|
||||
"palette": false
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user