UNPKG

prism-code-editor

Version:

Lightweight, extensible code editor component for the web using Prism

183 lines (182 loc) 6.28 kB
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, "&quot;"); }; 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, "&#39;")}' `; 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, "&#39;")}' `; 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