Skip to content

Commit c22653c

Browse files
committed
refactor: replace PrismJS with Hugo Chroma for syntax highlighting and add click-to-copy functionality
1 parent baac51b commit c22653c

11 files changed

Lines changed: 355 additions & 142 deletions

File tree

assets/js/click-to-copy.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
let codeListings = document.querySelectorAll('.highlight > pre');
2+
3+
for (let index = 0; index < codeListings.length; index++) {
4+
const codeSample = codeListings[index].querySelector('code');
5+
const copyButton = document.createElement('button');
6+
const buttonAttributes = {
7+
type: 'button',
8+
title: 'Copy to clipboard',
9+
'data-bs-toggle': 'tooltip',
10+
'data-bs-placement': 'top',
11+
'data-bs-container': 'body',
12+
};
13+
14+
Object.keys(buttonAttributes).forEach((key) => {
15+
copyButton.setAttribute(key, buttonAttributes[key]);
16+
});
17+
18+
copyButton.classList.add(
19+
'fas',
20+
'fa-copy',
21+
'btn',
22+
'btn-sm',
23+
'td-click-to-copy'
24+
);
25+
const tooltip = new bootstrap.Tooltip(copyButton);
26+
27+
copyButton.onclick = () => {
28+
copyCode(codeSample);
29+
copyButton.setAttribute('data-bs-original-title', 'Copied!');
30+
tooltip.show();
31+
};
32+
33+
copyButton.onmouseout = () => {
34+
copyButton.setAttribute('data-bs-original-title', 'Copy to clipboard');
35+
tooltip.hide();
36+
};
37+
38+
const buttonDiv = document.createElement('div');
39+
buttonDiv.classList.add('click-to-copy');
40+
buttonDiv.append(copyButton);
41+
codeListings[index].insertBefore(buttonDiv, codeSample);
42+
}
43+
44+
const copyCode = (codeSample) => {
45+
const isConsoleBlock = codeSample.matches(
46+
"code[data-lang='console'], code.language-console"
47+
);
48+
let text;
49+
50+
if (isConsoleBlock) {
51+
const clone = codeSample.cloneNode(true);
52+
pruneUnselectableElements(codeSample, clone);
53+
text = clone.textContent;
54+
// For each command, strip the space after the prompt and before the
55+
// command:
56+
text = text.replace(/^ /gm, '');
57+
} else {
58+
text = codeSample.textContent;
59+
}
60+
text = text ? text.trim() : '';
61+
navigator.clipboard.writeText(text + '\n');
62+
};
63+
64+
const pruneUnselectableElements = (sourceNode, cloneNode) => {
65+
const sourceChildren = sourceNode.children;
66+
const cloneChildren = cloneNode.children;
67+
68+
for (let i = sourceChildren.length - 1; i >= 0; i--) {
69+
const sourceChild = sourceChildren[i];
70+
const cloneChild = cloneChildren[i];
71+
const style = window.getComputedStyle(sourceChild);
72+
const unselectable = style.userSelect === 'none';
73+
74+
if (unselectable) {
75+
cloneChild.remove();
76+
continue;
77+
}
78+
79+
pruneUnselectableElements(sourceChild, cloneChild);
80+
}
81+
};

assets/scss/_chroma-dark.scss

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* Generated using: hugo gen chromastyles --style=github-dark */
2+
3+
/* Background */ .bg { color:#e6edf3;background-color:#0d1117; }
4+
/* PreWrapper */ .chroma { color:#e6edf3;background-color:#0d1117;-webkit-text-size-adjust:none; }
5+
/* Error */ .chroma .err { color:#f85149 }
6+
/* LineLink */ .chroma .lnlinks { outline:none;text-decoration:none;color:inherit }
7+
/* LineTableTD */ .chroma .lntd { vertical-align:top;padding:0;margin:0;border:0; }
8+
/* LineTable */ .chroma .lntable { border-spacing:0;padding:0;margin:0;border:0; }
9+
/* LineHighlight */ .chroma .hl { background-color:#6e7681 }
10+
/* LineNumbersTable */ .chroma .lnt { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679 }
11+
/* LineNumbers */ .chroma .ln { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#6e7681 }
12+
/* Line */ .chroma .line { display:flex; }
13+
/* Keyword */ .chroma .k { color:#ff7b72 }
14+
/* KeywordConstant */ .chroma .kc { color:#79c0ff }
15+
/* KeywordDeclaration */ .chroma .kd { color:#ff7b72 }
16+
/* KeywordNamespace */ .chroma .kn { color:#ff7b72 }
17+
/* KeywordPseudo */ .chroma .kp { color:#79c0ff }
18+
/* KeywordReserved */ .chroma .kr { color:#ff7b72 }
19+
/* KeywordType */ .chroma .kt { color:#ff7b72 }
20+
/* NameClass */ .chroma .nc { color:#f0883e;font-weight:bold }
21+
/* NameConstant */ .chroma .no { color:#79c0ff;font-weight:bold }
22+
/* NameDecorator */ .chroma .nd { color:#d2a8ff;font-weight:bold }
23+
/* NameEntity */ .chroma .ni { color:#ffa657 }
24+
/* NameException */ .chroma .ne { color:#f0883e;font-weight:bold }
25+
/* NameLabel */ .chroma .nl { color:#79c0ff;font-weight:bold }
26+
/* NameNamespace */ .chroma .nn { color:#ff7b72 }
27+
/* NameProperty */ .chroma .py { color:#79c0ff }
28+
/* NameTag */ .chroma .nt { color:#7ee787 }
29+
/* NameVariable */ .chroma .nv { color:#79c0ff }
30+
/* NameVariableClass */ .chroma .vc { color:#79c0ff }
31+
/* NameVariableGlobal */ .chroma .vg { color:#79c0ff }
32+
/* NameVariableInstance */ .chroma .vi { color:#79c0ff }
33+
/* NameVariableMagic */ .chroma .vm { color:#79c0ff }
34+
/* NameFunction */ .chroma .nf { color:#d2a8ff;font-weight:bold }
35+
/* NameFunctionMagic */ .chroma .fm { color:#d2a8ff;font-weight:bold }
36+
/* Literal */ .chroma .l { color:#a5d6ff }
37+
/* LiteralDate */ .chroma .ld { color:#79c0ff }
38+
/* LiteralString */ .chroma .s { color:#a5d6ff }
39+
/* LiteralStringAffix */ .chroma .sa { color:#79c0ff }
40+
/* LiteralStringBacktick */ .chroma .sb { color:#a5d6ff }
41+
/* LiteralStringChar */ .chroma .sc { color:#a5d6ff }
42+
/* LiteralStringDelimiter */ .chroma .dl { color:#79c0ff }
43+
/* LiteralStringDoc */ .chroma .sd { color:#a5d6ff }
44+
/* LiteralStringDouble */ .chroma .s2 { color:#a5d6ff }
45+
/* LiteralStringEscape */ .chroma .se { color:#79c0ff }
46+
/* LiteralStringHeredoc */ .chroma .sh { color:#79c0ff }
47+
/* LiteralStringInterpol */ .chroma .si { color:#a5d6ff }
48+
/* LiteralStringOther */ .chroma .sx { color:#a5d6ff }
49+
/* LiteralStringRegex */ .chroma .sr { color:#79c0ff }
50+
/* LiteralStringSingle */ .chroma .s1 { color:#a5d6ff }
51+
/* LiteralStringSymbol */ .chroma .ss { color:#a5d6ff }
52+
/* LiteralNumber */ .chroma .m { color:#a5d6ff }
53+
/* LiteralNumberBin */ .chroma .mb { color:#a5d6ff }
54+
/* LiteralNumberFloat */ .chroma .mf { color:#a5d6ff }
55+
/* LiteralNumberHex */ .chroma .mh { color:#a5d6ff }
56+
/* LiteralNumberInteger */ .chroma .mi { color:#a5d6ff }
57+
/* LiteralNumberIntegerLong */ .chroma .il { color:#a5d6ff }
58+
/* LiteralNumberOct */ .chroma .mo { color:#a5d6ff }
59+
/* Operator */ .chroma .o { color:#ff7b72;font-weight:bold }
60+
/* OperatorWord */ .chroma .ow { color:#ff7b72;font-weight:bold }
61+
/* Comment */ .chroma .c { color:#8b949e;font-style:italic }
62+
/* CommentHashbang */ .chroma .ch { color:#8b949e;font-style:italic }
63+
/* CommentMultiline */ .chroma .cm { color:#8b949e;font-style:italic }
64+
/* CommentSingle */ .chroma .c1 { color:#8b949e;font-style:italic }
65+
/* CommentSpecial */ .chroma .cs { color:#8b949e;font-weight:bold;font-style:italic }
66+
/* CommentPreproc */ .chroma .cp { color:#8b949e;font-weight:bold;font-style:italic }
67+
/* CommentPreprocFile */ .chroma .cpf { color:#8b949e;font-weight:bold;font-style:italic }
68+
/* GenericDeleted */ .chroma .gd { color:#ffa198;background-color:#490202 }
69+
/* GenericEmph */ .chroma .ge { font-style:italic }
70+
/* GenericError */ .chroma .gr { color:#ffa198 }
71+
/* GenericHeading */ .chroma .gh { color:#79c0ff;font-weight:bold }
72+
/* GenericInserted */ .chroma .gi { color:#56d364;background-color:#0f5323 }
73+
/* GenericOutput */ .chroma .go { color:#8b949e }
74+
/* GenericPrompt */ .chroma .gp { color:#8b949e }
75+
/* GenericStrong */ .chroma .gs { font-weight:bold }
76+
/* GenericSubheading */ .chroma .gu { color:#79c0ff }
77+
/* GenericTraceback */ .chroma .gt { color:#ff7b72 }
78+
/* GenericUnderline */ .chroma .gl { text-decoration:underline }
79+
/* TextWhitespace */ .chroma .w { color:#6e7681 }

assets/scss/_chroma-light.scss

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* Generated using: hugo gen chromastyles --style=github */
2+
3+
/* Background */ .bg { background-color:#f7f7f7; }
4+
/* PreWrapper */ .chroma { background-color:#f7f7f7;-webkit-text-size-adjust:none; }
5+
/* Error */ .chroma .err { color:#f6f8fa;background-color:#82071e }
6+
/* LineLink */ .chroma .lnlinks { outline:none;text-decoration:none;color:inherit }
7+
/* LineTableTD */ .chroma .lntd { vertical-align:top;padding:0;margin:0;border:0; }
8+
/* LineTable */ .chroma .lntable { border-spacing:0;padding:0;margin:0;border:0; }
9+
/* LineHighlight */ .chroma .hl { background-color:#dedede }
10+
/* LineNumbersTable */ .chroma .lnt { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f }
11+
/* LineNumbers */ .chroma .ln { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f }
12+
/* Line */ .chroma .line { display:flex; }
13+
/* Keyword */ .chroma .k { color:#cf222e }
14+
/* KeywordConstant */ .chroma .kc { color:#cf222e }
15+
/* KeywordDeclaration */ .chroma .kd { color:#cf222e }
16+
/* KeywordNamespace */ .chroma .kn { color:#cf222e }
17+
/* KeywordPseudo */ .chroma .kp { color:#cf222e }
18+
/* KeywordReserved */ .chroma .kr { color:#cf222e }
19+
/* KeywordType */ .chroma .kt { color:#cf222e }
20+
/* NameAttribute */ .chroma .na { color:#1f2328 }
21+
/* NameClass */ .chroma .nc { color:#1f2328 }
22+
/* NameConstant */ .chroma .no { color:#0550ae }
23+
/* NameDecorator */ .chroma .nd { color:#0550ae }
24+
/* NameEntity */ .chroma .ni { color:#6639ba }
25+
/* NameLabel */ .chroma .nl { color:#900;font-weight:bold }
26+
/* NameNamespace */ .chroma .nn { color:#24292e }
27+
/* NameOther */ .chroma .nx { color:#1f2328 }
28+
/* NameTag */ .chroma .nt { color:#0550ae }
29+
/* NameBuiltin */ .chroma .nb { color:#6639ba }
30+
/* NameBuiltinPseudo */ .chroma .bp { color:#6a737d }
31+
/* NameVariable */ .chroma .nv { color:#953800 }
32+
/* NameVariableClass */ .chroma .vc { color:#953800 }
33+
/* NameVariableGlobal */ .chroma .vg { color:#953800 }
34+
/* NameVariableInstance */ .chroma .vi { color:#953800 }
35+
/* NameVariableMagic */ .chroma .vm { color:#953800 }
36+
/* NameFunction */ .chroma .nf { color:#6639ba }
37+
/* NameFunctionMagic */ .chroma .fm { color:#6639ba }
38+
/* LiteralString */ .chroma .s { color:#0a3069 }
39+
/* LiteralStringAffix */ .chroma .sa { color:#0a3069 }
40+
/* LiteralStringBacktick */ .chroma .sb { color:#0a3069 }
41+
/* LiteralStringChar */ .chroma .sc { color:#0a3069 }
42+
/* LiteralStringDelimiter */ .chroma .dl { color:#0a3069 }
43+
/* LiteralStringDoc */ .chroma .sd { color:#0a3069 }
44+
/* LiteralStringDouble */ .chroma .s2 { color:#0a3069 }
45+
/* LiteralStringEscape */ .chroma .se { color:#0a3069 }
46+
/* LiteralStringHeredoc */ .chroma .sh { color:#0a3069 }
47+
/* LiteralStringInterpol */ .chroma .si { color:#0a3069 }
48+
/* LiteralStringOther */ .chroma .sx { color:#0a3069 }
49+
/* LiteralStringRegex */ .chroma .sr { color:#0a3069 }
50+
/* LiteralStringSingle */ .chroma .s1 { color:#0a3069 }
51+
/* LiteralStringSymbol */ .chroma .ss { color:#032f62 }
52+
/* LiteralNumber */ .chroma .m { color:#0550ae }
53+
/* LiteralNumberBin */ .chroma .mb { color:#0550ae }
54+
/* LiteralNumberFloat */ .chroma .mf { color:#0550ae }
55+
/* LiteralNumberHex */ .chroma .mh { color:#0550ae }
56+
/* LiteralNumberInteger */ .chroma .mi { color:#0550ae }
57+
/* LiteralNumberIntegerLong */ .chroma .il { color:#0550ae }
58+
/* LiteralNumberOct */ .chroma .mo { color:#0550ae }
59+
/* Operator */ .chroma .o { color:#0550ae }
60+
/* OperatorWord */ .chroma .ow { color:#0550ae }
61+
/* Punctuation */ .chroma .p { color:#1f2328 }
62+
/* Comment */ .chroma .c { color:#57606a }
63+
/* CommentHashbang */ .chroma .ch { color:#57606a }
64+
/* CommentMultiline */ .chroma .cm { color:#57606a }
65+
/* CommentSingle */ .chroma .c1 { color:#57606a }
66+
/* CommentSpecial */ .chroma .cs { color:#57606a }
67+
/* CommentPreproc */ .chroma .cp { color:#57606a }
68+
/* CommentPreprocFile */ .chroma .cpf { color:#57606a }
69+
/* GenericDeleted */ .chroma .gd { color:#82071e;background-color:#ffebe9 }
70+
/* GenericEmph */ .chroma .ge { color:#1f2328 }
71+
/* GenericInserted */ .chroma .gi { color:#116329;background-color:#dafbe1 }
72+
/* GenericOutput */ .chroma .go { color:#1f2328 }
73+
/* GenericUnderline */ .chroma .gl { text-decoration:underline }
74+
/* TextWhitespace */ .chroma .w { color:#fff }

0 commit comments

Comments
 (0)