diff --git a/packages/ui/src/lib/git-diff-lowlight.ts b/packages/ui/src/lib/git-diff-lowlight.ts new file mode 100644 index 00000000..e998e3a9 --- /dev/null +++ b/packages/ui/src/lib/git-diff-lowlight.ts @@ -0,0 +1,200 @@ +import { createLowlight, common } from "lowlight" + +type AstNode = { + type: string + value?: string + children?: AstNode[] + startIndex?: number + endIndex?: number + lineNumber?: number +} + +type SyntaxNodeEntry = { + node: AstNode + wrapper?: AstNode +} + +type SyntaxFileLine = { + value: string + lineNumber: number + valueLength: number + nodeList: SyntaxNodeEntry[] +} + +type LowlightApi = ReturnType + +export function processAST(ast: { children: AstNode[] }) { + let lineNumber = 1 + const syntaxObj: Record = {} + + const loopAST = (nodes: AstNode[], wrapper?: AstNode) => { + nodes.forEach((node) => { + if (node.type === "text") { + const textValue = node.value ?? "" + if (!textValue.includes("\n")) { + const valueLength = textValue.length + if (!syntaxObj[lineNumber]) { + node.startIndex = 0 + node.endIndex = valueLength - 1 + syntaxObj[lineNumber] = { + value: textValue, + lineNumber, + valueLength, + nodeList: [{ node, wrapper }], + } + } else { + node.startIndex = syntaxObj[lineNumber].valueLength + node.endIndex = node.startIndex + valueLength - 1 + syntaxObj[lineNumber].value += textValue + syntaxObj[lineNumber].valueLength += valueLength + syntaxObj[lineNumber].nodeList.push({ node, wrapper }) + } + node.lineNumber = lineNumber + return + } + + const lines = textValue.split("\n") + node.children = node.children || [] + for (let index = 0; index < lines.length; index++) { + const value = index === lines.length - 1 ? lines[index] : `${lines[index]}\n` + const currentLineNumber = index === 0 ? lineNumber : ++lineNumber + const valueLength = value.length + const childNode: AstNode = { + type: "text", + value, + startIndex: Infinity, + endIndex: Infinity, + lineNumber: currentLineNumber, + } + + if (!syntaxObj[currentLineNumber]) { + childNode.startIndex = 0 + childNode.endIndex = valueLength - 1 + syntaxObj[currentLineNumber] = { + value, + lineNumber: currentLineNumber, + valueLength, + nodeList: [{ node: childNode, wrapper }], + } + } else { + childNode.startIndex = syntaxObj[currentLineNumber].valueLength + childNode.endIndex = childNode.startIndex + valueLength - 1 + syntaxObj[currentLineNumber].value += value + syntaxObj[currentLineNumber].valueLength += valueLength + syntaxObj[currentLineNumber].nodeList.push({ node: childNode, wrapper }) + } + + node.children.push(childNode) + } + + node.lineNumber = lineNumber + return + } + + if (node.children) { + loopAST(node.children, node) + node.lineNumber = lineNumber + } + }) + } + + loopAST(ast.children) + return { syntaxFileObject: syntaxObj, syntaxFileLineNumber: lineNumber } +} + +export function _getAST() { + return {} +} + +const lowlight = createLowlight(common) + +lowlight.register("vue", function hljsDefineVue(hljs: any) { + return { + subLanguage: "xml", + contains: [ + hljs.COMMENT("", { relevance: 10 }), + { + begin: /^(\s*)(