Files
helder/design_handoff_helder_workbench/design/src/highlight.js
2026-06-15 09:43:01 +02:00

80 lines
2.8 KiB
JavaScript

/* Syntax highlighting (Prism) + file-type icon metadata. */
(function () {
const EXT_LANG = {
php: "php", js: "javascript", mjs: "javascript", cjs: "javascript",
jsx: "jsx", ts: "typescript", tsx: "tsx", py: "python",
html: "markup", xml: "markup", svg: "markup", vue: "markup",
css: "css", scss: "css", json: "json", md: "markdown",
sh: "bash", bash: "bash", yml: "yaml", yaml: "yaml", env: "bash",
};
function ext(path) {
const base = path.split("/").pop() || "";
if (base === ".env" || base.startsWith(".env")) return "env";
const i = base.lastIndexOf(".");
return i >= 0 ? base.slice(i + 1).toLowerCase() : "";
}
function langFor(path) { return EXT_LANG[ext(path)] || null; }
function langLabel(path) {
const e = ext(path);
const map = {
php: "PHP", js: "JavaScript", mjs: "JavaScript", ts: "TypeScript",
tsx: "TypeScript", jsx: "JavaScript", py: "Python", html: "HTML",
css: "CSS", json: "JSON", md: "Markdown", sh: "Shell", env: "Dotenv",
yml: "YAML", yaml: "YAML",
};
return map[e] || (e ? e.toUpperCase() : "Plain Text");
}
function escapeHtml(s) {
return s.replace(/[&<>]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;" }[c]));
}
// highlight a single line independently (keeps line numbering robust)
function hlLine(line, lang) {
if (line === "") return "&nbsp;";
try {
const grammar = lang && window.Prism && Prism.languages[lang];
if (grammar) return Prism.highlight(line, grammar, lang);
} catch (e) { /* fall through */ }
return escapeHtml(line);
}
// ---- file-type icon: colored monogram chip --------------------------
const ICONS = {
php: { c: "#a78bdb", t: "php" },
js: { c: "#e6c860", t: "js" },
mjs: { c: "#e6c860", t: "js" },
ts: { c: "#5a9bd6", t: "ts" },
tsx: { c: "#5a9bd6", t: "ts" },
jsx: { c: "#5a9bd6", t: "jsx" },
py: { c: "#5fa8d6", t: "py" },
html: { c: "#e08b6a", t: "<>" },
css: { c: "#5a9bd6", t: "{}" },
scss: { c: "#d6699e", t: "{}" },
json: { c: "#d8a85c", t: "{}" },
md: { c: "#9aa0a8", t: "md" },
env: { c: "#7fc6a0", t: "$" },
sh: { c: "#7fc6a0", t: "$" },
yml: { c: "#cf7a6a", t: "yml" },
yaml: { c: "#cf7a6a", t: "yml" },
lock: { c: "#8a8f98", t: "lk" },
};
const NAME_ICONS = {
"composer.json": { c: "#a78bdb", t: "co" },
"package.json": { c: "#cf7a6a", t: "pk" },
"README.md": { c: "#5a9bd6", t: "md" },
".env": { c: "#7fc6a0", t: "$" },
};
function iconFor(path) {
const base = path.split("/").pop() || "";
if (NAME_ICONS[base]) return NAME_ICONS[base];
return ICONS[ext(path)] || { c: "#7d838c", t: base.slice(0, 2) || "·" };
}
window.HL = { ext, langFor, langLabel, hlLine, iconFor, escapeHtml };
})();