prism-code-editor
Version:
Lightweight, extensible code editor component for the web using Prism
183 lines (182 loc) • 6.28 kB
JavaScript
import { e as escapeHtml, t as tokenizeText, l as languages, h as highlightTokens } from "../index-C1_GGQ8y.js";
import { t as testBracket } from "../bracket-BPYnIBjq.js";
import { getIndentGuides } from "../extensions/guides.js";
let stack = [];
let sp;
const addAlias = (token, newAlias = "bracket-error") => {
let alias = token.alias;
token.alias = (alias ? alias + " " : "") + newAlias;
};
const matchRecursive = (tokens, pairs) => {
let token;
let i = 0;
for (; token = tokens[i++]; ) {
if (typeof token == "string") continue;
let content = token.content;
let alias = token.alias;
if (Array.isArray(content)) {
matchRecursive(content, pairs);
} else if ((alias || token.type) == "punctuation") {
let last = token.length - 1;
let bracketType = testBracket(content, pairs, last);
if (bracketType) {
if (bracketType % 2) stack[sp++] = [token, bracketType + 1];
else {
let i2 = sp;
let found;
while (i2) {
let entry = stack[--i2];
if (bracketType == entry[1]) {
let alias2 = "bracket-level-" + i2 % 12;
let j = i2;
while (++j < sp) {
addAlias(stack[j][0]);
}
addAlias(token, alias2);
addAlias(entry[0], alias2);
sp = i2;
i2 = 0;
found = true;
}
}
if (!found) addAlias(token);
}
}
}
}
};
const rainbowBrackets = (pairs = "()[]{}") => {
return (tokens) => {
sp = 0;
matchRecursive(tokens, pairs);
stack = [];
};
};
const escapeQuotes = (html) => {
return escapeHtml(html, /"/g, """);
};
const renderCodeBlock = (options) => {
let {
language,
value,
tabSize,
lineNumbers,
lineNumberStart = 1,
wordWrap,
preserveIndent = wordWrap,
guideIndents,
rtl,
class: userClass,
tokenizeCallback,
addLineClass,
...rest
} = options;
tabSize = +tabSize || 2;
let html = `<pre class="prism-code-editor language-${escapeQuotes(language)}${lineNumbers ? " show-line-numbers" : ""} pce-${wordWrap ? "" : "no"}wrap${rtl ? " pce-rtl" : ""}${preserveIndent ? " pce-preserve" : ""}${guideIndents && !rtl ? " pce-guides" : ""}${userClass ? " " + escapeQuotes(userClass) : ""}" data-props='${escapeHtml(JSON.stringify(rest), /'/g, "'")}' `;
let indents = preserveIndent || guideIndents && !rtl ? getIndents(value, tabSize) : null;
if (preserveIndent) value = value.replace(/ /g, " ".repeat(tabSize));
let tokens = tokenizeText(
value.includes("\r") ? value.replace(/\r\n?/g, "\n") : value,
languages[language] || {}
);
tokenizeCallback?.(tokens, language);
let lines = highlightTokens(tokens).split("\n");
let l = lines.length;
let i = 0;
html += `style="--tab-size:${tabSize}${lineNumbers ? `;--number-width:${(0 | Math.log10(l + lineNumberStart - 1)) + 1}.001ch;counter-reset:line ${lineNumberStart - 1}` : ""}"><code class=pce-wrapper><div class=pce-overlays></div>`;
while (i < l) {
let lineClass = addLineClass?.(i + 1);
html += `<div class="pce-line${lineClass ? " " + escapeQuotes(lineClass) : ""}"${indents?.[i] ? ` style=--indent:${indents[i]}ch` : ""}>${lines[i++]}
</div>`;
}
return html + "</code></pre>";
};
const getIndents = (code, tabSize) => {
const lines = code.split("\n");
const l = lines.length;
const result = Array(l).fill(0);
for (let prevIndent = 0, emptyPos = -1, i = 0; i < l; i++) {
let line = lines[i];
let l2 = line.search(/\S/);
let indent = 0;
if (l2 < 0) {
if (emptyPos < 0) emptyPos = i;
} else {
for (let i2 = 0; i2 < l2; ) {
indent += line[i2++] == " " ? tabSize - indent % tabSize : 1;
}
if (emptyPos + 1) {
if (indent != prevIndent) prevIndent = Math.min(indent, prevIndent) + 1;
while (emptyPos < i) {
result[emptyPos++] = prevIndent;
}
}
result[i] = prevIndent = indent;
emptyPos = -1;
}
}
return result;
};
const indentGuides = (options) => {
if (!options.wordWrap) {
let html = "<div class=guide-indents> ";
let indents = getIndentGuides(options.value, +options.tabSize || 2);
let active;
let i = 0;
let top;
let indent;
for (; top = indents[i]?.[0], top < 2; i++) {
if (!top) active = i;
else {
if (indents[i + 1]?.[0] != 1) active = i;
break;
}
}
for (i = 0; indent = indents[i]; i++) {
html += `<div style=top:${indent[0]}00%;left:${indent[1]}00%;height:${indent[2]}00%${i == active ? " class=active-indent" : ""}></div>`;
}
return html + "</div>";
}
};
const renderEditor = (options) => {
let {
language,
value,
lineNumbers,
wordWrap,
rtl,
readOnly,
tabSize,
tokenizeCallback,
overlays,
class: userClass,
...rest
} = options;
let containerClass = `prism-code-editor language-${language}${lineNumbers == false ? "" : " show-line-numbers"} pce-${wordWrap ? "" : "no"}wrap${rtl ? " pce-rtl" : ""} pce-no-selection${readOnly ? " pce-readonly" : ""}`;
let html = `<div class="${escapeQuotes(containerClass + (userClass ? " " + userClass : ""))}"${userClass ? ` data-start=${containerClass.length + 1}` : ""} data-options='${escapeHtml(JSON.stringify(rest), /'/g, "'")}' `;
let tokens = tokenizeText(
value.includes("\r") ? value.replace(/\r\n?/g, "\n") : value,
languages[language] || {}
);
tokenizeCallback?.(tokens, language);
let lines = highlightTokens(tokens).split("\n");
let l = lines.length;
let i = 0;
html += `style=tab-size:${+tabSize || 2};--number-width:${(0 | Math.log10(l)) + 1}.001ch><div class=pce-wrapper><div class=pce-overlays><textarea class=pce-textarea spellcheck=false autocapitalize=off autocomplete=off></textarea>`;
overlays?.forEach((overlay) => {
html += overlay(options) || "";
});
html += "</div>";
while (i < l) {
html += `<div class="pce-line${i ? "" : " active-line"}" aria-hidden=true data-line=${i + 1}>${lines[i++]}
</div>`;
}
return html + "</div></div>";
};
export {
indentGuides,
rainbowBrackets,
renderCodeBlock,
renderEditor
};
//# sourceMappingURL=index.js.map