zoeys.computer/assets/js/hooks/code_block_hook.js

68 lines
1.9 KiB
JavaScript
Raw Normal View History

2024-10-26 15:01:33 -04:00
// assets/js/hooks/code_block_hook.js
import { codeToHtml } from "shiki";
const CodeBlockHook = {
mounted() {
const code = this.el.dataset.code;
const language = this.el.dataset.language;
const highlightedLines = JSON.parse(
this.el.dataset.highlightedLines || "[]",
);
const lines = code.split("\n");
2024-10-26 21:41:22 -04:00
console.log(lines.length, lines);
2024-10-26 15:01:33 -04:00
// Convert line numbers to decorations
const decorations = highlightedLines
.map((line) => {
// Convert to 0-based index and ensure valid line number
const lineIndex = line - 1;
if (lineIndex < 0 || lineIndex >= lines.length) return null;
// Get the actual line length
const lineLength = lines[lineIndex].length;
return {
// Line numbers are 0-indexed
start: { line: lineIndex, character: 0 },
end: { line: lineIndex, character: lineLength },
properties: {
// Apply both background color and a class for flexibility
class: "highlight",
style: "background-color: rgba(200,200,255,0.1);",
},
};
})
.filter(Boolean); // Remove any null entries from invalid line numbers
codeToHtml(code, {
lang: language,
theme: "catppuccin-mocha",
2024-10-26 21:41:22 -04:00
transformers: [
{
line(node, line) {
node.properties["data-line"] = line;
if (highlightedLines.includes(line)) {
this.addClassToHast(node, "highlighted");
}
},
},
],
2024-10-26 15:01:33 -04:00
}).then((html) => {
console.log(html);
// Replace the code content while preserving the pre/code structure
const tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
const codeContent = tempDiv.querySelector("code");
if (codeContent) {
this.el.querySelector("code").innerHTML = codeContent.innerHTML;
}
});
},
};
export default CodeBlockHook;