UNPKG

prism-code-editor

Version:

Lightweight, extensible code editor component for the web using Prism

97 lines (96 loc) 3.55 kB
import { a as createTemplate } from "../index-Bb4AMnd0.js"; const template = createTemplate( "<div class=guide-indents style=left:var(--padding-left)><div style=position:relative;display:inline-block> " ); const indentTemplate = createTemplate( "<div style=width:1px;position:absolute;background:var(--bg-guide-indent)>" ); const indentGuides = () => { let tabSize, prevLength = 0, lineIndentMap, active = -1, currentEditor; const lines = [], indents = [], container = template(), guideHeight = container.lastChild, indentLevels = []; const update = (code) => { lineIndentMap = []; const newIndents = getIndents(code.split("\n")), l = newIndents.length; for (let i = 0, prev = [], next = newIndents[0]; next; i++) { const style = (lines[i] || (lines[i] = indentTemplate())).style, [top, height, left] = next, old = indents[i]; next = newIndents[i + 1]; if (top != old?.[0]) style.top = top + "00%"; if (height != old?.[1]) style.height = height + "00%"; if (left != old?.[2]) style.left = left * 100 + "%"; const isSingleIndent = prev[0] != top && next?.[0] != top, isSingleOutdent = prev[0] + prev[1] != top + height && next?.[0] + next?.[1] != top + height; for (let j = -isSingleIndent, l2 = height + isSingleOutdent; j < l2; j++) lineIndentMap[j + top] = i; prev = indents[i] = newIndents[i]; } for (let i = prevLength; i > l; ) lines[--i].remove(); guideHeight.append(...lines.slice(prevLength, prevLength = l)); }; const updateActive = () => { const newActive = lineIndentMap[currentEditor.activeLineNumber - 1] ?? -1; if (newActive != active) { active > -1 && (lines[active].className = ""); newActive > -1 && (lines[newActive].className = "active"); } active = newActive; }; const getIndents = (lines2) => { const l = lines2.length, stack = [], results = []; for (let prevIndent = 0, emptyPos = -1, i = 0, p = 0; ; i++) { const last = i == l, indent = last ? 0 : indentLevels[i] = getIndentCount(lines2[i]); if (indent < 0) { if (emptyPos < 0) emptyPos = i; } else { for (let j = indent; j < prevIndent; j++) { stack[j][1] = (emptyPos < 0 || j == indent && !last ? i : emptyPos) - stack[j][0]; } for (let j = prevIndent; j < indent; ) { results[p++] = stack[j] = [ emptyPos < 0 || j > prevIndent ? i : emptyPos, 0, j++ * tabSize ]; } emptyPos = -1; prevIndent = indent; } if (last) break; } indentLevels.length = l; return results; }; const getIndentCount = (text) => { let l = text.search(/\S/), result = 0; if (l < 0) return l; for (let i = 0; i < l; ) { result += text[i++] == " " ? tabSize - result % tabSize : 1; } return Math.ceil(result / tabSize); }; return { lines: guideHeight.children, indentLevels, update(editor, options) { if (!currentEditor) { currentEditor = editor; editor.extensions.indentGuides = this; editor.overlays.append(container); editor.addListener("update", update); editor.addListener("selectionChange", updateActive); } container.style.display = options.wordWrap ? "none" : ""; if (tabSize != (tabSize = options.tabSize || 2)) update(editor.value), updateActive(); } }; }; export { indentGuides }; //# sourceMappingURL=guides.js.map