@pierre/diffs 1.2.5 → 1.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CodeView.d.ts +0 -1
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +0 -23
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +7 -2
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +36 -2
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +8 -2
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +73 -1
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.js +2 -2
- package/dist/components/VirtualizedFile.d.ts +2 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +48 -48
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +1 -6
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +1 -1
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/editor/command.d.ts +6 -0
- package/dist/editor/command.d.ts.map +1 -0
- package/dist/editor/command.js +31 -0
- package/dist/editor/command.js.map +1 -0
- package/dist/editor/css.d.ts +6 -0
- package/dist/editor/css.d.ts.map +1 -0
- package/dist/editor/css.js +218 -0
- package/dist/editor/css.js.map +1 -0
- package/dist/editor/editStack.d.ts +66 -0
- package/dist/editor/editStack.d.ts.map +1 -0
- package/dist/editor/editStack.js +218 -0
- package/dist/editor/editStack.js.map +1 -0
- package/dist/editor/editor.d.ts +22 -0
- package/dist/editor/editor.d.ts.map +1 -0
- package/dist/editor/editor.js +1323 -0
- package/dist/editor/editor.js.map +1 -0
- package/dist/editor/index.d.ts +3 -0
- package/dist/editor/index.js +4 -0
- package/dist/editor/lineAnnotations.d.ts +8 -0
- package/dist/editor/lineAnnotations.d.ts.map +1 -0
- package/dist/editor/lineAnnotations.js +32 -0
- package/dist/editor/lineAnnotations.js.map +1 -0
- package/dist/editor/pieceTable.d.ts +33 -0
- package/dist/editor/pieceTable.d.ts.map +1 -0
- package/dist/editor/pieceTable.js +590 -0
- package/dist/editor/pieceTable.js.map +1 -0
- package/dist/editor/platform.d.ts +12 -0
- package/dist/editor/platform.d.ts.map +1 -0
- package/dist/editor/platform.js +44 -0
- package/dist/editor/platform.js.map +1 -0
- package/dist/editor/quickEdit.d.ts +29 -0
- package/dist/editor/quickEdit.d.ts.map +1 -0
- package/dist/editor/quickEdit.js +81 -0
- package/dist/editor/quickEdit.js.map +1 -0
- package/dist/editor/searchPanel.d.ts +30 -0
- package/dist/editor/searchPanel.d.ts.map +1 -0
- package/dist/editor/searchPanel.js +219 -0
- package/dist/editor/searchPanel.js.map +1 -0
- package/dist/editor/selection.d.ts +126 -0
- package/dist/editor/selection.d.ts.map +1 -0
- package/dist/editor/selection.js +900 -0
- package/dist/editor/selection.js.map +1 -0
- package/dist/editor/textDocument.d.ts +139 -0
- package/dist/editor/textDocument.d.ts.map +1 -0
- package/dist/editor/textDocument.js +202 -0
- package/dist/editor/textDocument.js.map +1 -0
- package/dist/editor/textMeasure.d.ts +32 -0
- package/dist/editor/textMeasure.d.ts.map +1 -0
- package/dist/editor/textMeasure.js +108 -0
- package/dist/editor/textMeasure.js.map +1 -0
- package/dist/editor/tokenzier.d.ts +37 -0
- package/dist/editor/tokenzier.d.ts.map +1 -0
- package/dist/editor/tokenzier.js +348 -0
- package/dist/editor/tokenzier.js.map +1 -0
- package/dist/editor/utils.d.ts +16 -0
- package/dist/editor/utils.d.ts.map +1 -0
- package/dist/editor/utils.js +37 -0
- package/dist/editor/utils.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/react/EditorContext.d.ts +16 -0
- package/dist/react/EditorContext.d.ts.map +1 -0
- package/dist/react/EditorContext.js +26 -0
- package/dist/react/EditorContext.js.map +1 -0
- package/dist/react/File.d.ts +2 -1
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +3 -2
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +3 -1
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +3 -2
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +3 -1
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +3 -2
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +3 -1
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +3 -2
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/index.d.ts +3 -2
- package/dist/react/index.js +2 -1
- package/dist/react/jsx.d.ts +0 -1
- package/dist/react/jsx.d.ts.map +1 -1
- package/dist/react/types.d.ts +1 -0
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/types.js +0 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +3 -1
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +31 -5
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +4 -1
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +30 -5
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +2 -2
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +5 -1
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +108 -41
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/style.js +1 -1
- package/dist/style.js.map +1 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/cleanLastNewline.js +6 -1
- package/dist/utils/cleanLastNewline.js.map +1 -1
- package/dist/utils/computeFileOffsets.d.ts +13 -0
- package/dist/utils/computeFileOffsets.d.ts.map +1 -0
- package/dist/utils/computeFileOffsets.js +33 -0
- package/dist/utils/computeFileOffsets.js.map +1 -0
- package/dist/utils/createTransformerWithState.js +9 -0
- package/dist/utils/createTransformerWithState.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +1 -1
- package/dist/utils/renderFileWithHighlighter.js +5 -14
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/worker/WorkerPoolManager.js +1 -1
- package/dist/worker/{wasm-BaDzIkIn.js → wasm-D4DU5jgR.js} +2 -2
- package/dist/worker/wasm-D4DU5jgR.js.map +1 -0
- package/dist/worker/worker-portable.js +138 -153
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +41 -64
- package/dist/worker/worker.js.map +1 -1
- package/package.json +28 -20
- package/dist/utils/iterateOverFile.d.ts +0 -50
- package/dist/utils/iterateOverFile.d.ts.map +0 -1
- package/dist/utils/iterateOverFile.js +0 -49
- package/dist/utils/iterateOverFile.js.map +0 -1
- package/dist/worker/wasm-BaDzIkIn.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pieceTable.js","names":["source: number","offset: number","length: number","lineOffsetStart: number","lineOffsetEnd: number","text: string","piece: Piece","subtreeLength: number","subtreeLineBreakCount: number","#original","#setPieces","#createPiece","#lineCount","#textFromPieces","#lastVisitedLine","#getLineOffset","#length","#findPieceAtOffset","chunks: string[]","#bufferFor","start","end","#nextNode","#forEachPieceSegment","wrappedOffset: number | undefined","foundOffset: number | undefined","pattern: RegExp","#collectSearchMatchesLineByLine","best: [number, number] | undefined","out: [number, number][]","match: RegExpExecArray | null","#add","#pieces","nextPieces: Piece[]","#lineAtOffset","#lineBreakOffset","positions: Position[]","offsets: number[]","#root","#walk","#piecesCache","#buildBalancedTree","normalized: [start: number, end: number][]","merged: [start: number, end: number][]","coalescedPieces: Piece[]"],"sources":["../../src/editor/pieceTable.ts"],"sourcesContent":["import { computeLineOffsets } from '../utils/computeFileOffsets';\nimport type { SearchParams } from './searchPanel';\nimport type { Position, Range, ResolvedTextEdit } from './textDocument';\n\nconst MAX_FIND_MATCHES = 100000;\n// TODO(ije): use Intl.Segmenter instead of regex for word separators\nconst WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?' as const;\n\n// A piece is a segment of text that is either original or added.\nclass Piece {\n static Original = 0;\n static Added = 1;\n\n constructor(\n public readonly source: number,\n public readonly offset: number,\n public readonly length: number,\n public readonly lineOffsetStart: number,\n public readonly lineOffsetEnd: number\n ) {}\n\n get lineBreakCount(): number {\n return this.lineOffsetEnd - this.lineOffsetStart;\n }\n}\n\n// A text buffer is a string with its line offsets.\nclass TextBuffer {\n lineOffsets: number[];\n\n constructor(public text: string) {\n this.lineOffsets = computeLineOffsets(text);\n }\n\n // the append operation is efficient because it only appends\n // elements to the lineOffsets array in the end\n append(text: string): number {\n const offset = this.text.length;\n const appendedLineOffsets = computeLineOffsets(text);\n for (let i = 1; i < appendedLineOffsets.length; i++) {\n this.lineOffsets.push(offset + appendedLineOffsets[i]);\n }\n this.text += text;\n return offset;\n }\n}\n\n// A node in the balanced piece tree.\nclass PieceNode {\n left: PieceNode | null = null;\n right: PieceNode | null = null;\n parent: PieceNode | null = null;\n\n constructor(\n public piece: Piece,\n public subtreeLength: number = piece.length,\n public subtreeLineBreakCount: number = piece.lineBreakCount\n ) {}\n\n updateSubtreeLength(): void {\n this.subtreeLength =\n (this.left?.subtreeLength ?? 0) +\n this.piece.length +\n (this.right?.subtreeLength ?? 0);\n this.subtreeLineBreakCount =\n (this.left?.subtreeLineBreakCount ?? 0) +\n this.piece.lineBreakCount +\n (this.right?.subtreeLineBreakCount ?? 0);\n }\n}\n\n/**\n * A piece table is a data structure that allows for efficient insertion and deletion of text.\n * It is a tree of pieces, where each piece is a segment of text that is either original or added.\n * The tree is rebuilt as a balanced tree after edits to keep lookups efficient.\n * Inspired by https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation\n */\nexport class PieceTable {\n #original: TextBuffer;\n #add = new TextBuffer('');\n #root: PieceNode | null = null;\n #piecesCache: Piece[] = [];\n #length = 0;\n #lineCount = 0;\n #lastVisitedLine: [number, string] | null = null;\n\n constructor(originalText: string) {\n this.#original = new TextBuffer(originalText);\n this.#setPieces([\n this.#createPiece(Piece.Original, 0, originalText.length),\n ]);\n }\n\n get lineCount(): number {\n return this.#lineCount;\n }\n\n getText(range?: Range): string {\n if (range === undefined) {\n return this.#textFromPieces();\n }\n const start = this.offsetAt(range.start);\n const end = this.offsetAt(range.end);\n return this.getTextSlice(start, end);\n }\n\n getLineText(line: number, trimEOF = true): string {\n if (this.#lastVisitedLine !== null && this.#lastVisitedLine[0] === line) {\n return this.#lastVisitedLine[1];\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const text = this.getTextSlice(offset[0], offset[1], trimEOF);\n this.#lastVisitedLine = [line, text];\n return text;\n }\n\n getTextSlice(start: number, end: number, trimEOF = false): string {\n if (start >= end) {\n return '';\n }\n\n const sliceStart = clamp(start, 0, this.#length);\n const sliceEnd = clamp(end, sliceStart, this.#length);\n if (sliceStart >= sliceEnd) {\n return '';\n }\n\n const location = this.#findPieceAtOffset(sliceStart);\n if (location === undefined) {\n return '';\n }\n\n const chunks: string[] = [];\n let [node, offsetInPiece] = location as [PieceNode | null, number];\n let remaining = sliceEnd - sliceStart;\n while (node !== null && remaining > 0) {\n const takeLength = Math.min(node.piece.length - offsetInPiece, remaining);\n const buffer = this.#bufferFor(node.piece.source);\n const start = node.piece.offset + offsetInPiece;\n let end = start + takeLength;\n if (trimEOF) {\n while (end > start && isEOL(buffer.text.charCodeAt(end - 1))) {\n end--;\n }\n }\n chunks.push(buffer.text.slice(start, end));\n remaining -= takeLength;\n offsetInPiece = 0;\n node = this.#nextNode(node);\n }\n\n return chunks.join('');\n }\n\n charAt(offset: number): string {\n const location = this.#findPieceAtOffset(offset);\n if (location === undefined) {\n return '';\n }\n\n const [node, offsetInPiece] = location;\n const buffer = this.#bufferFor(node.piece.source);\n return buffer.text.charAt(node.piece.offset + offsetInPiece);\n }\n\n includes(needle: string): boolean {\n if (needle.length === 0) {\n return true;\n }\n\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let found = false;\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n found = true;\n return false;\n }\n }\n return true;\n });\n return found;\n }\n\n findNextNonOverlappingSubstring(\n needle: string,\n occupied: readonly [start: number, end: number][]\n ): number | undefined {\n if (needle.length === 0 || needle.length > this.#length) {\n return undefined;\n }\n\n const ranges = normalizeRanges(occupied, this.#length);\n const pivot = ranges.reduce((max, [, end]) => Math.max(max, end), 0);\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let documentOffset = 0;\n let wrappedOffset: number | undefined;\n let foundOffset: number | undefined;\n\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n const start = documentOffset - needle.length + 1;\n if (!rangeOverlaps(ranges, start, start + needle.length)) {\n if (start >= pivot) {\n foundOffset = start;\n return false;\n }\n wrappedOffset ??= start;\n }\n matched = prefixTable[matched - 1];\n }\n documentOffset++;\n }\n return true;\n });\n\n return foundOffset ?? wrappedOffset;\n }\n\n search(\n kind: 'findNext' | 'findPrevious' | 'findAll' | 'replace' | 'replaceAll',\n searchParams: SearchParams,\n range?: Range\n ): [start: number, end: number][] {\n if (searchParams.text.length === 0 || this.#length === 0) {\n return [];\n }\n // Search currently operates line-by-line, so newline-spanning patterns are unsupported.\n if (\n searchParams.text.includes('\\n') ||\n searchParams.text.includes('\\r') ||\n (searchParams.regex &&\n (searchParams.text.includes('\\\\n') ||\n searchParams.text.includes('\\\\r')))\n ) {\n return [];\n }\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n searchParams.regex,\n searchParams.caseSensitive\n );\n } catch {\n return [];\n }\n\n const matches = this.#collectSearchMatchesLineByLine(\n pattern,\n searchParams.wholeWord,\n MAX_FIND_MATCHES\n );\n\n if (kind === 'findAll' || kind === 'replaceAll') {\n return matches;\n }\n\n const caretOffset =\n range === undefined\n ? 0\n : kind === 'findPrevious'\n ? this.offsetAt(range?.start)\n : this.offsetAt(range?.end);\n\n if (kind === 'findPrevious') {\n const refOffset = getSearchFindPreviousReferenceOffset(range, (p) =>\n this.offsetAt(p)\n );\n let best: [number, number] | undefined;\n for (const m of matches) {\n if (m[1] <= refOffset) {\n best = m;\n } else {\n break;\n }\n }\n if (best !== undefined) {\n return [best];\n }\n const last = matches[matches.length - 1];\n return last !== undefined ? [last] : [];\n }\n\n // findNext, replace — forward from caret with wrap\n for (const m of matches) {\n if (m[0] >= caretOffset) {\n return [m];\n }\n }\n const first = matches[0];\n return first !== undefined ? [first] : [];\n }\n\n #collectSearchMatchesLineByLine(\n pattern: RegExp,\n wholeWord: boolean,\n limit: number\n ): [number, number][] {\n const out: [number, number][] = [];\n const docLength = this.#length;\n const charAt = (offset: number) => this.charAt(offset);\n\n for (let line = 0; line < this.#lineCount; line++) {\n const lineText = this.getLineText(line);\n const lineStart = this.offsetAt({ line, character: 0 });\n const re = new RegExp(pattern.source, pattern.flags);\n re.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = re.exec(lineText)) !== null) {\n const rel = match.index;\n const fragment = match[0];\n if (fragment.length === 0) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n continue;\n }\n const docStart = lineStart + rel;\n if (\n !wholeWord ||\n isWholeWordAtDocOffsets(docStart, fragment.length, docLength, charAt)\n ) {\n out.push([docStart, docStart + fragment.length]);\n if (out.length >= limit) {\n return out;\n }\n }\n if (rel === re.lastIndex) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n }\n }\n }\n return out;\n }\n\n insert(text: string, offset: number): void {\n if (text.length === 0) {\n return;\n }\n\n const insertOffset = clamp(offset, 0, this.#length);\n const addOffset = this.#add.append(text);\n const insertedPiece = this.#createPiece(\n Piece.Added,\n addOffset,\n text.length\n );\n const pieces = this.#pieces();\n const nextPieces: Piece[] = [];\n\n let cursor = 0;\n let inserted = false;\n\n for (const piece of pieces) {\n const pieceEnd = cursor + piece.length;\n if (!inserted && insertOffset <= pieceEnd) {\n const splitOffset = insertOffset - cursor;\n if (splitOffset > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, splitOffset)\n );\n }\n nextPieces.push(insertedPiece);\n if (splitOffset < piece.length) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + splitOffset,\n piece.length - splitOffset\n )\n );\n }\n inserted = true;\n } else {\n nextPieces.push(piece);\n }\n cursor = pieceEnd;\n }\n\n if (!inserted) {\n nextPieces.push(insertedPiece);\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n }\n\n delete(offset: number, length: number): void {\n if (length <= 0 || this.#length === 0) {\n return;\n }\n\n const start = clamp(offset, 0, this.#length);\n const end = clamp(start + length, start, this.#length);\n if (start === end) {\n return;\n }\n\n const nextPieces: Piece[] = [];\n let cursor = 0;\n for (const piece of this.#pieces()) {\n const pieceStart = cursor;\n const pieceEnd = cursor + piece.length;\n const keepBefore = clamp(start - pieceStart, 0, piece.length);\n const keepAfter = clamp(pieceEnd - end, 0, piece.length);\n\n if (keepBefore > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, keepBefore)\n );\n }\n if (keepAfter > 0) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + piece.length - keepAfter,\n keepAfter\n )\n );\n }\n cursor = pieceEnd;\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n }\n\n applyEdits(edits: readonly ResolvedTextEdit[]): void {\n if (edits.length === 0) {\n return;\n }\n\n let pieceIndex = 0;\n let pieceStart = 0;\n let copyCursor = 0;\n\n const pieces = this.#pieces();\n const insertedPieces = edits.map((edit) =>\n edit.text.length === 0\n ? undefined\n : this.#createPiece(\n Piece.Added,\n this.#add.append(edit.text),\n edit.text.length\n )\n );\n const nextPieces: Piece[] = [];\n\n const advancePiece = () => {\n const piece = pieces[pieceIndex];\n if (piece !== undefined) {\n pieceStart += piece.length;\n pieceIndex++;\n }\n };\n\n const appendRange = (start: number, end: number) => {\n let rangeStart = clamp(start, 0, this.#length);\n const rangeEnd = clamp(end, rangeStart, this.#length);\n while (\n pieceIndex < pieces.length &&\n pieceStart + pieces[pieceIndex].length <= rangeStart\n ) {\n advancePiece();\n }\n while (pieceIndex < pieces.length && rangeStart < rangeEnd) {\n const piece = pieces[pieceIndex];\n const pieceEnd = pieceStart + piece.length;\n const offsetInPiece = clamp(rangeStart - pieceStart, 0, piece.length);\n const takeEnd = Math.min(pieceEnd, rangeEnd);\n const takeLength = takeEnd - (pieceStart + offsetInPiece);\n if (takeLength > 0) {\n nextPieces.push(\n offsetInPiece === 0 && takeLength === piece.length\n ? piece\n : this.#createPiece(\n piece.source,\n piece.offset + offsetInPiece,\n takeLength\n )\n );\n }\n rangeStart = takeEnd;\n if (rangeStart >= pieceEnd) {\n advancePiece();\n }\n }\n };\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const start = clamp(edit.start, copyCursor, this.#length);\n const end = clamp(edit.end, start, this.#length);\n appendRange(copyCursor, start);\n\n const insertedPiece = insertedPieces[i];\n if (insertedPiece !== undefined) {\n nextPieces.push(insertedPiece);\n }\n copyCursor = end;\n }\n appendRange(copyCursor, this.#length);\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n }\n\n positionAt(offset: number): Position {\n const clampedOffset = clamp(offset, 0, this.#length);\n if (this.#length === 0) {\n return { line: 0, character: 0 };\n }\n const line = this.#lineAtOffset(clampedOffset);\n const lineStart = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n return {\n line,\n character: clampedOffset - lineStart,\n };\n }\n\n positionsAt(offsets: readonly number[]): Position[] {\n const positions: Position[] = Array.from({ length: offsets.length });\n if (offsets.length === 0) {\n return positions;\n }\n if (this.#length === 0) {\n return positions.fill({ line: 0, character: 0 });\n }\n\n for (let i = 0; i < offsets.length; i++) {\n positions[i] = this.positionAt(offsets[i]);\n }\n\n return positions;\n }\n\n offsetAt(position: Position): number {\n if (position.line < 0 || this.#length === 0) {\n return 0;\n }\n if (position.line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const offset = this.#getLineOffset(position.line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const character = clamp(position.character, 0, offset[1] - offset[0]);\n return offset[0] + character;\n }\n\n offsetsAt(positions: readonly Position[]): number[] {\n const offsets: number[] = Array.from({ length: positions.length });\n if (positions.length === 0) {\n return offsets;\n }\n if (this.#length === 0) {\n return offsets.fill(0);\n }\n\n for (let i = 0; i < positions.length; i++) {\n offsets[i] = this.offsetAt(positions[i]);\n }\n\n return offsets;\n }\n\n #findPieceAtOffset(\n offset: number\n ): [node: PieceNode, offsetInPiece: number] | undefined {\n if (offset < 0 || offset >= this.#length) {\n return undefined;\n }\n\n let node = this.#root;\n let remaining = offset;\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n remaining -= leftLength;\n if (remaining < node.piece.length) {\n return [node, remaining];\n }\n\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return undefined;\n }\n\n #nextNode(node: PieceNode): PieceNode | null {\n if (node.right !== null) {\n let next = node.right;\n while (next.left !== null) {\n next = next.left;\n }\n return next;\n }\n\n let current = node;\n while (current.parent !== null && current === current.parent.right) {\n current = current.parent;\n }\n return current.parent;\n }\n\n #getLineOffset(line: number): [start: number, end: number] | undefined {\n if (line < 0) {\n throw new Error(`Line index out of range: ${line}`);\n }\n if (this.#length === 0) {\n if (line === 0) {\n return [0, 0];\n }\n throw new Error(`Line index out of range: ${line}`);\n }\n if (line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${line}`);\n }\n\n const start = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n const end =\n line < this.#lineCount - 1 ? this.#lineBreakOffset(line) : this.#length;\n return [start, end];\n }\n\n #lineAtOffset(offset: number): number {\n let node = this.#root;\n let remaining = clamp(offset, 0, this.#length);\n let line = 0;\n\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n line += node.left?.subtreeLineBreakCount ?? 0;\n remaining -= leftLength;\n if (remaining <= node.piece.length) {\n const buffer = this.#bufferFor(node.piece.source);\n line +=\n upperBound(buffer.lineOffsets, node.piece.offset + remaining) -\n node.piece.lineOffsetStart;\n return line;\n }\n\n line += node.piece.lineBreakCount;\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return this.#lineCount - 1;\n }\n\n #lineBreakOffset(lineBreakIndex: number): number {\n let node = this.#root;\n let remaining = lineBreakIndex;\n let documentOffset = 0;\n\n while (node !== null) {\n const leftLineBreakCount = node.left?.subtreeLineBreakCount ?? 0;\n if (remaining < leftLineBreakCount) {\n node = node.left;\n continue;\n }\n\n const leftLength = node.left?.subtreeLength ?? 0;\n documentOffset += leftLength;\n remaining -= leftLineBreakCount;\n\n if (remaining < node.piece.lineBreakCount) {\n const bufferLineOffset = this.#bufferFor(node.piece.source).lineOffsets[\n node.piece.lineOffsetStart + remaining\n ];\n return documentOffset + (bufferLineOffset - node.piece.offset);\n }\n\n documentOffset += node.piece.length;\n remaining -= node.piece.lineBreakCount;\n node = node.right;\n }\n\n return this.#length;\n }\n\n #textFromPieces(): string {\n const chunks: string[] = [];\n this.#forEachPieceSegment((segment) => {\n chunks.push(segment.text.slice(segment.start, segment.end));\n });\n return chunks.join('');\n }\n\n #forEachPieceSegment(\n callback: (segment: {\n readonly start: number;\n readonly end: number;\n readonly text: string;\n readonly lineOffsets: number[];\n readonly lineOffsetStart: number;\n readonly lineOffsetEnd: number;\n }) => boolean | void\n ): void {\n this.#walk(this.#root, (node) => {\n const buffer = this.#bufferFor(node.piece.source);\n return callback({\n text: buffer.text,\n lineOffsets: buffer.lineOffsets,\n lineOffsetStart: node.piece.lineOffsetStart,\n lineOffsetEnd: node.piece.lineOffsetEnd,\n start: node.piece.offset,\n end: node.piece.offset + node.piece.length,\n });\n });\n }\n\n #bufferFor(source: number): TextBuffer {\n return source === Piece.Original ? this.#original : this.#add;\n }\n\n #createPiece(source: number, offset: number, length: number): Piece {\n const buffer = this.#bufferFor(source);\n return new Piece(\n source,\n offset,\n length,\n upperBound(buffer.lineOffsets, offset),\n upperBound(buffer.lineOffsets, offset + length)\n );\n }\n\n #pieces(): Piece[] {\n return this.#piecesCache;\n }\n\n #setPieces(pieces: Piece[]): void {\n const coalescedPieces = coalescePieces(pieces);\n this.#piecesCache = coalescedPieces;\n let length = 0;\n let lineBreakCount = 0;\n for (const piece of coalescedPieces) {\n length += piece.length;\n lineBreakCount += piece.lineBreakCount;\n }\n this.#root = this.#buildBalancedTree(\n coalescedPieces,\n 0,\n coalescedPieces.length,\n null\n );\n this.#length = length;\n this.#lineCount = lineBreakCount + 1;\n }\n\n #buildBalancedTree(\n pieces: Piece[],\n start: number,\n end: number,\n parent: PieceNode | null\n ): PieceNode | null {\n if (start >= end) {\n return null;\n }\n\n const middle = start + Math.floor((end - start) / 2);\n const node = new PieceNode(pieces[middle]);\n node.parent = parent;\n node.left = this.#buildBalancedTree(pieces, start, middle, node);\n node.right = this.#buildBalancedTree(pieces, middle + 1, end, node);\n node.updateSubtreeLength();\n return node;\n }\n\n #walk(\n node: PieceNode | null,\n visit: (node: PieceNode) => boolean | void\n ): boolean {\n if (node === null) {\n return true;\n }\n if (!this.#walk(node.left, visit)) {\n return false;\n }\n if (visit(node) === false) {\n return false;\n }\n return this.#walk(node.right, visit);\n }\n}\n\nfunction isEOL(charCode: number): boolean {\n return charCode === /* \\n */ 10 || charCode === /* \\r */ 13;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction createPrefixTable(text: string): number[] {\n const table = Array.from<number>({ length: text.length }).fill(0);\n let matched = 0;\n for (let i = 1; i < text.length; i++) {\n const charCode = text.charCodeAt(i);\n while (matched > 0 && charCode !== text.charCodeAt(matched)) {\n matched = table[matched - 1];\n }\n if (charCode === text.charCodeAt(matched)) {\n matched++;\n }\n table[i] = matched;\n }\n return table;\n}\n\nfunction normalizeRanges(\n ranges: readonly [start: number, end: number][],\n length: number\n): [start: number, end: number][] {\n const normalized: [start: number, end: number][] = [];\n for (const [rawStart, rawEnd] of ranges) {\n const start = clamp(rawStart, 0, length);\n const end = clamp(rawEnd, start, length);\n if (start < end) {\n normalized.push([start, end]);\n }\n }\n normalized.sort((a, b) => a[0] - b[0]);\n\n const merged: [start: number, end: number][] = [];\n for (const range of normalized) {\n const previous = merged[merged.length - 1];\n if (previous !== undefined && range[0] <= previous[1]) {\n previous[1] = Math.max(previous[1], range[1]);\n continue;\n }\n merged.push(range);\n }\n return merged;\n}\n\nfunction rangeOverlaps(\n ranges: readonly [start: number, end: number][],\n start: number,\n end: number\n): boolean {\n let low = 0;\n let high = ranges.length;\n while (low < high) {\n const mid = low + Math.floor((high - low) / 2);\n if (ranges[mid][1] <= start) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n\n const range = ranges[low];\n return range !== undefined && range[0] < end;\n}\n\n// Keeps the table compact after repeated edits by joining neighboring pieces\n// that already point at contiguous text in the same backing buffer.\nfunction coalescePieces(pieces: Piece[]): Piece[] {\n const coalescedPieces: Piece[] = [];\n for (const piece of pieces) {\n if (piece.length === 0) {\n continue;\n }\n\n const previous = coalescedPieces[coalescedPieces.length - 1];\n if (\n previous !== undefined &&\n previous.source === piece.source &&\n previous.offset + previous.length === piece.offset\n ) {\n coalescedPieces[coalescedPieces.length - 1] = new Piece(\n previous.source,\n previous.offset,\n previous.length + piece.length,\n previous.lineOffsetStart,\n piece.lineOffsetEnd\n );\n continue;\n }\n\n coalescedPieces.push(piece);\n }\n return coalescedPieces;\n}\n\n// Returns the index of the first element in the array that is greater than the target.\nfunction upperBound(values: number[], target: number): number {\n let lo = 0;\n let hi = values.length;\n while (lo < hi) {\n const mid = lo + Math.floor((hi - lo) / 2);\n if (values[mid] <= target) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isWordSeparatorCharCode(charCode: number): boolean {\n if (charCode <= 32 || charCode === 127) {\n return true;\n }\n const ch = String.fromCharCode(charCode);\n return WORD_SEPARATORS.includes(ch);\n}\n\n// Checks if the given text is a whole word by checking if the\n// characters before and after are word separators.\nfunction isWholeWordAtDocOffsets(\n docStart: number,\n length: number,\n docLength: number,\n charAt: (offset: number) => string\n): boolean {\n const beforeOk =\n docStart <= 0 ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart - 1));\n const afterOk =\n docStart + length >= docLength ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart + length));\n return beforeOk && afterOk;\n}\n\nfunction charCodeUnitAt(\n charAt: (offset: number) => string,\n offset: number\n): number {\n const unit = charAt(offset);\n return unit.length === 0 ? 0 : unit.charCodeAt(0);\n}\n\nfunction compileSearchRegExp(\n source: string,\n isRegex: boolean,\n caseSensitive: boolean\n): RegExp {\n const body = isRegex ? source : escapeRegExp(source);\n const flags = `g${caseSensitive ? '' : 'i'}${isRegex ? 'm' : ''}`;\n return new RegExp(body, flags);\n}\n\nfunction advancePastEmptyMatch(text: string, index: number): number {\n if (index + 1 < text.length) {\n const first = text.charCodeAt(index);\n const second = text.charCodeAt(index + 1);\n if (\n first >= 0xd800 &&\n first <= 0xdbff &&\n second >= 0xdc00 &&\n second <= 0xdfff\n ) {\n return index + 2;\n }\n }\n return index + 1;\n}\n\n// Returns the leftmost UTF-16 offset of the selection; used for find-previous\n// so we skip the current match.\nfunction getSearchFindPreviousReferenceOffset(\n selection: Range | undefined,\n offsetAt: (p: Position) => number\n): number {\n if (selection === undefined) {\n return 0;\n }\n const a = offsetAt(selection.start);\n const b = offsetAt(selection.end);\n return Math.min(a, b);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/editor/platform.d.ts
|
|
2
|
+
declare function isMacLike(): boolean;
|
|
3
|
+
declare function isLinux(): boolean;
|
|
4
|
+
declare function isSafari(): boolean;
|
|
5
|
+
declare function isPrimaryModifier({
|
|
6
|
+
metaKey,
|
|
7
|
+
ctrlKey
|
|
8
|
+
}: MouseEvent | KeyboardEvent, isMac?: boolean): boolean;
|
|
9
|
+
declare function isMoveCursorShortcut(e: KeyboardEvent): 'up' | 'down' | 'left' | 'right' | 'start' | 'textStart' | 'end' | undefined;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { isLinux, isMacLike, isMoveCursorShortcut, isPrimaryModifier, isSafari };
|
|
12
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","names":["isMacLike","isLinux","isSafari","isPrimaryModifier","metaKey","ctrlKey","MouseEvent","KeyboardEvent","isMoveCursorShortcut"],"sources":["../../src/editor/platform.d.ts"],"sourcesContent":["export declare function isMacLike(): boolean;\nexport declare function isLinux(): boolean;\nexport declare function isSafari(): boolean;\nexport declare function isPrimaryModifier({ metaKey, ctrlKey }: MouseEvent | KeyboardEvent, isMac?: boolean): boolean;\nexport declare function isMoveCursorShortcut(e: KeyboardEvent): 'up' | 'down' | 'left' | 'right' | 'start' | 'textStart' | 'end' | undefined;\n//# sourceMappingURL=platform.d.ts.map"],"mappings":";iBAAwBA,SAAAA,CAAAA;AAAAA,iBACAC,OAAAA,CAAAA,CADS,EAAA,OAAA;AACTA,iBACAC,QAAAA,CAAAA,CADO,EAAA,OAAA;AACPA,iBACAC,iBAAAA,CADQ;EAAA,OAAA;EAAA;AAAA,CAAA,EACgCG,UADhC,GAC6CC,aAD7C,EAAA,KAAA,CAAA,EAAA,OAAA,CAAA,EAAA,OAAA;AACRJ,iBACAK,oBAAAA,CADiB,CAAA,EACOD,aADP,CAAA,EAAA,IAAA,GAAA,MAAA,GAAA,MAAA,GAAA,OAAA,GAAA,OAAA,GAAA,WAAA,GAAA,KAAA,GAAA,SAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/editor/platform.ts
|
|
2
|
+
let _isMacLike = void 0;
|
|
3
|
+
let _isLinux = void 0;
|
|
4
|
+
let _isSafari = void 0;
|
|
5
|
+
function isMacLike() {
|
|
6
|
+
return _isMacLike ??= /macOS|MacIntel|iPhone|iPad|iPod/i.test(getPlatform());
|
|
7
|
+
}
|
|
8
|
+
function isLinux() {
|
|
9
|
+
return _isLinux ??= /Linux/i.test(getPlatform());
|
|
10
|
+
}
|
|
11
|
+
function isSafari() {
|
|
12
|
+
return _isSafari ??= "safari" in window && "pushNotification" in window.safari || /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
13
|
+
}
|
|
14
|
+
function isPrimaryModifier({ metaKey, ctrlKey }, isMac = isMacLike()) {
|
|
15
|
+
return isMac ? metaKey && !ctrlKey : ctrlKey && !metaKey;
|
|
16
|
+
}
|
|
17
|
+
function isMoveCursorShortcut(e) {
|
|
18
|
+
if ((isMacLike() || isLinux()) && e.ctrlKey && !e.altKey && !e.metaKey) switch (e.key) {
|
|
19
|
+
case "a": return "start";
|
|
20
|
+
case "e": return "end";
|
|
21
|
+
case "p": return "up";
|
|
22
|
+
case "n": return "down";
|
|
23
|
+
case "f": return "right";
|
|
24
|
+
case "b": return "left";
|
|
25
|
+
}
|
|
26
|
+
if (!e.altKey && !e.ctrlKey && !e.metaKey) {
|
|
27
|
+
if (e.key === "ArrowUp") return "up";
|
|
28
|
+
else if (e.key === "ArrowDown") return "down";
|
|
29
|
+
else if (e.key === "ArrowLeft") return "left";
|
|
30
|
+
else if (e.key === "ArrowRight") return "right";
|
|
31
|
+
}
|
|
32
|
+
if (isPrimaryModifier(e)) {
|
|
33
|
+
if (e.key === "ArrowLeft") return "textStart";
|
|
34
|
+
else if (e.key === "ArrowRight") return "end";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function getPlatform() {
|
|
38
|
+
const navigator$1 = globalThis.navigator;
|
|
39
|
+
return navigator$1?.platform ?? navigator$1?.userAgentData?.platform ?? "unknown";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { isLinux, isMacLike, isMoveCursorShortcut, isPrimaryModifier, isSafari };
|
|
44
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","names":["_isMacLike: boolean | undefined","_isLinux: boolean | undefined","_isSafari: boolean | undefined","navigator"],"sources":["../../src/editor/platform.ts"],"sourcesContent":["let _isMacLike: boolean | undefined = undefined;\nlet _isLinux: boolean | undefined = undefined;\nlet _isSafari: boolean | undefined = undefined;\n\nexport function isMacLike(): boolean {\n return (_isMacLike ??= /macOS|MacIntel|iPhone|iPad|iPod/i.test(\n getPlatform()\n ));\n}\n\nexport function isLinux(): boolean {\n return (_isLinux ??= /Linux/i.test(getPlatform()));\n}\n\nexport function isSafari(): boolean {\n return (_isSafari ??=\n ('safari' in window && 'pushNotification' in (window as any).safari) ||\n /^((?!chrome|android).)*safari/i.test(navigator.userAgent));\n}\n\nexport function isPrimaryModifier(\n { metaKey, ctrlKey }: MouseEvent | KeyboardEvent,\n isMac: boolean = isMacLike()\n): boolean {\n return isMac ? metaKey && !ctrlKey : ctrlKey && !metaKey;\n}\n\nexport function isMoveCursorShortcut(\n e: KeyboardEvent\n):\n | 'up'\n | 'down'\n | 'left'\n | 'right'\n | 'start'\n | 'textStart'\n | 'end'\n | undefined {\n // emacs key bindings\n if ((isMacLike() || isLinux()) && e.ctrlKey && !e.altKey && !e.metaKey) {\n switch (e.key) {\n case 'a':\n return 'start';\n case 'e':\n return 'end';\n case 'p':\n return 'up';\n case 'n':\n return 'down';\n case 'f':\n return 'right';\n case 'b':\n return 'left';\n }\n }\n\n if (!e.altKey && !e.ctrlKey && !e.metaKey) {\n if (e.key === 'ArrowUp') {\n return 'up';\n } else if (e.key === 'ArrowDown') {\n return 'down';\n } else if (e.key === 'ArrowLeft') {\n return 'left';\n } else if (e.key === 'ArrowRight') {\n return 'right';\n }\n }\n\n if (isPrimaryModifier(e)) {\n if (e.key === 'ArrowLeft') {\n return 'textStart';\n } else if (e.key === 'ArrowRight') {\n return 'end';\n }\n }\n\n return undefined;\n}\n\nfunction getPlatform(): string {\n const navigator = globalThis.navigator as Navigator & {\n userAgentData?: { platform?: string };\n };\n return navigator?.platform ?? navigator?.userAgentData?.platform ?? 'unknown';\n}\n"],"mappings":";AAAA,IAAIA,aAAkC;AACtC,IAAIC,WAAgC;AACpC,IAAIC,YAAiC;AAErC,SAAgB,YAAqB;AACnC,QAAQ,eAAe,mCAAmC,KACxD,aAAa,CACd;;AAGH,SAAgB,UAAmB;AACjC,QAAQ,aAAa,SAAS,KAAK,aAAa,CAAC;;AAGnD,SAAgB,WAAoB;AAClC,QAAQ,cACL,YAAY,UAAU,sBAAuB,OAAe,UAC7D,iCAAiC,KAAK,UAAU,UAAU;;AAG9D,SAAgB,kBACd,EAAE,SAAS,WACX,QAAiB,WAAW,EACnB;AACT,QAAO,QAAQ,WAAW,CAAC,UAAU,WAAW,CAAC;;AAGnD,SAAgB,qBACd,GASY;AAEZ,MAAK,WAAW,IAAI,SAAS,KAAK,EAAE,WAAW,CAAC,EAAE,UAAU,CAAC,EAAE,QAC7D,SAAQ,EAAE,KAAV;EACE,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;;AAIb,KAAI,CAAC,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,EAAE,SAChC;MAAI,EAAE,QAAQ,UACZ,QAAO;WACE,EAAE,QAAQ,YACnB,QAAO;WACE,EAAE,QAAQ,YACnB,QAAO;WACE,EAAE,QAAQ,aACnB,QAAO;;AAIX,KAAI,kBAAkB,EAAE,EACtB;MAAI,EAAE,QAAQ,YACZ,QAAO;WACE,EAAE,QAAQ,aACnB,QAAO;;;AAOb,SAAS,cAAsB;CAC7B,MAAMC,cAAY,WAAW;AAG7B,QAAOA,aAAW,YAAYA,aAAW,eAAe,YAAY"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TextDocument, TextEdit } from "./textDocument.js";
|
|
2
|
+
import { EditorSelection } from "./selection.js";
|
|
3
|
+
|
|
4
|
+
//#region src/editor/quickEdit.d.ts
|
|
5
|
+
interface QuickEditContext<LAnnotation> {
|
|
6
|
+
/** The current selection. */
|
|
7
|
+
selection: EditorSelection;
|
|
8
|
+
/** The text document. */
|
|
9
|
+
textDocument: TextDocument<LAnnotation>;
|
|
10
|
+
/** Applies the edits to the text document. */
|
|
11
|
+
applyEdits: (edits: TextEdit[]) => void;
|
|
12
|
+
/** Gets the text of the current selection. */
|
|
13
|
+
getSelectionText: () => string;
|
|
14
|
+
/** Replaces the text of the current selection. */
|
|
15
|
+
replaceSelectionText: (text: string) => void;
|
|
16
|
+
/** Closes the quick edit. */
|
|
17
|
+
close: () => void;
|
|
18
|
+
}
|
|
19
|
+
declare class QuickEditWidget {
|
|
20
|
+
#private;
|
|
21
|
+
line: number;
|
|
22
|
+
static renderIcon(x: number, y: number, container: HTMLElement | DocumentFragment, onclick: () => void): HTMLElement;
|
|
23
|
+
constructor(line: number, quickEditElement: HTMLElement, fileContainer: HTMLElement, leadingWhitespaces: number | undefined, handleDomResize: () => void);
|
|
24
|
+
render(containerElement: HTMLElement): void;
|
|
25
|
+
cleanup(): void;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { QuickEditContext, QuickEditWidget };
|
|
29
|
+
//# sourceMappingURL=quickEdit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quickEdit.d.ts","names":["EditorSelection","TextDocument","TextEdit","QuickEditContext","LAnnotation","QuickEditWidget","HTMLElement","DocumentFragment"],"sources":["../../src/editor/quickEdit.d.ts"],"sourcesContent":["import type { EditorSelection } from './selection';\nimport type { TextDocument, TextEdit } from './textDocument';\nexport interface QuickEditContext<LAnnotation> {\n /** The current selection. */\n selection: EditorSelection;\n /** The text document. */\n textDocument: TextDocument<LAnnotation>;\n /** Applies the edits to the text document. */\n applyEdits: (edits: TextEdit[]) => void;\n /** Gets the text of the current selection. */\n getSelectionText: () => string;\n /** Replaces the text of the current selection. */\n replaceSelectionText: (text: string) => void;\n /** Closes the quick edit. */\n close: () => void;\n}\nexport declare class QuickEditWidget {\n #private;\n line: number;\n static renderIcon(x: number, y: number, container: HTMLElement | DocumentFragment, onclick: () => void): HTMLElement;\n constructor(line: number, quickEditElement: HTMLElement, fileContainer: HTMLElement, leadingWhitespaces: number | undefined, handleDomResize: () => void);\n render(containerElement: HTMLElement): void;\n cleanup(): void;\n}\n//# sourceMappingURL=quickEdit.d.ts.map"],"mappings":";;;;UAEiBG;;EAAAA,SAAAA,EAEFH,eAFkBI;EAElBJ;EAEgBI,YAAAA,EAAbH,YAAaG,CAAAA,WAAAA,CAAAA;EAAbH;EAEMC,UAAAA,EAAAA,CAAAA,KAAAA,EAAAA,QAAAA,EAAAA,EAAAA,GAAAA,IAAAA;EAAQ;EAQXG,gBAAAA,EAAe,GAAA,GAAA,MAAA;EAGmBC;EAAcC,oBAAAA,EAAAA,CAAAA,IAAAA,EAAAA,MAAAA,EAAAA,GAAAA,IAAAA;EAAwCD;EAC7DA,KAAAA,EAAAA,GAAAA,GAAAA,IAAAA;;AACnBA,cALRD,eAAAA,CAKQC;EAAW,CAAA,OAAA;;qDAFeA,cAAcC,wCAAwCD;8CAC7DA,4BAA4BA;2BAC/CA"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { h } from "./utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/editor/quickEdit.ts
|
|
4
|
+
var QuickEditWidget = class {
|
|
5
|
+
static renderIcon(x, y, container, onclick) {
|
|
6
|
+
return h("div", {
|
|
7
|
+
dataset: {
|
|
8
|
+
quickEditIcon: "",
|
|
9
|
+
visible: "false"
|
|
10
|
+
},
|
|
11
|
+
title: "Quick Edit",
|
|
12
|
+
style: { transform: `translateY(${y}px) translateX(${x}px)` },
|
|
13
|
+
innerHTML: `<svg width="16" height="16" viewBox="0 0 20 20">
|
|
14
|
+
<polygon points="11 3 9 9 16 9 9 17 11 11 4 11 11 3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" fill="currentColor"></polygon>
|
|
15
|
+
</svg>
|
|
16
|
+
`,
|
|
17
|
+
onclick
|
|
18
|
+
}, container);
|
|
19
|
+
}
|
|
20
|
+
#gutterBuffer;
|
|
21
|
+
#quickEditContainer;
|
|
22
|
+
#slot;
|
|
23
|
+
#observer;
|
|
24
|
+
#handleDomResize;
|
|
25
|
+
constructor(line, quickEditElement, fileContainer, leadingWhitespaces = 0, handleDomResize) {
|
|
26
|
+
this.line = line;
|
|
27
|
+
const slotName = "quick-edit-" + line;
|
|
28
|
+
this.#slot = h("div", {
|
|
29
|
+
dataset: "quickEditSlot",
|
|
30
|
+
slot: slotName,
|
|
31
|
+
style: "white-space: normal",
|
|
32
|
+
children: [quickEditElement]
|
|
33
|
+
}, fileContainer);
|
|
34
|
+
this.#gutterBuffer = h("div", {
|
|
35
|
+
dataset: {
|
|
36
|
+
gutterBuffer: "quickEdit",
|
|
37
|
+
bufferSize: "1"
|
|
38
|
+
},
|
|
39
|
+
style: "grid-row: span 1"
|
|
40
|
+
});
|
|
41
|
+
this.#quickEditContainer = h("div", {
|
|
42
|
+
dataset: { quickEdit: String(line) },
|
|
43
|
+
style: { paddingInlineStart: leadingWhitespaces + 1 + "ch" },
|
|
44
|
+
contentEditable: "false",
|
|
45
|
+
children: [h("slot", { name: slotName })]
|
|
46
|
+
});
|
|
47
|
+
this.#observer = new ResizeObserver(handleDomResize);
|
|
48
|
+
this.#observer.observe(this.#slot);
|
|
49
|
+
this.#handleDomResize = handleDomResize;
|
|
50
|
+
}
|
|
51
|
+
render(containerElement) {
|
|
52
|
+
const gutterElement = containerElement.previousElementSibling;
|
|
53
|
+
const lineNumber = this.line + 1;
|
|
54
|
+
const gutterLineElement = gutterElement?.querySelector(`[data-column-number="${lineNumber}"]`);
|
|
55
|
+
const contentLineElement = containerElement.querySelector(`[data-line="${lineNumber}"]`);
|
|
56
|
+
if (gutterElement != null && gutterLineElement != null && contentLineElement != null) {
|
|
57
|
+
gutterLineElement.after(this.#gutterBuffer);
|
|
58
|
+
contentLineElement.after(this.#quickEditContainer);
|
|
59
|
+
gutterElement.style.gridRow = "span " + gutterElement.children.length;
|
|
60
|
+
containerElement.style.gridRow = "span " + containerElement.children.length;
|
|
61
|
+
this.#handleDomResize();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
cleanup() {
|
|
65
|
+
const gutter = this.#gutterBuffer.parentElement;
|
|
66
|
+
const content = this.#quickEditContainer.parentElement;
|
|
67
|
+
this.#gutterBuffer.remove();
|
|
68
|
+
this.#quickEditContainer.remove();
|
|
69
|
+
if (gutter != null && content != null) {
|
|
70
|
+
gutter.style.gridRow = "span " + gutter.children.length;
|
|
71
|
+
content.style.gridRow = "span " + content.children.length;
|
|
72
|
+
}
|
|
73
|
+
this.#handleDomResize();
|
|
74
|
+
this.#slot.remove();
|
|
75
|
+
this.#observer.disconnect();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
export { QuickEditWidget };
|
|
81
|
+
//# sourceMappingURL=quickEdit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quickEdit.js","names":["line: number","#slot","#gutterBuffer","#quickEditContainer","#observer","#handleDomResize"],"sources":["../../src/editor/quickEdit.ts"],"sourcesContent":["import type { EditorSelection } from './selection';\nimport type { TextDocument, TextEdit } from './textDocument';\nimport { h } from './utils';\n\nexport interface QuickEditContext<LAnnotation> {\n /** The current selection. */\n selection: EditorSelection;\n /** The text document. */\n textDocument: TextDocument<LAnnotation>;\n /** Applies the edits to the text document. */\n applyEdits: (edits: TextEdit[]) => void;\n /** Gets the text of the current selection. */\n getSelectionText: () => string;\n /** Replaces the text of the current selection. */\n replaceSelectionText: (text: string) => void;\n /** Closes the quick edit. */\n close: () => void;\n}\n\nexport class QuickEditWidget {\n static renderIcon(\n x: number,\n y: number,\n container: HTMLElement | DocumentFragment,\n onclick: () => void\n ): HTMLElement {\n return h(\n 'div',\n {\n dataset: { quickEditIcon: '', visible: 'false' },\n title: 'Quick Edit',\n style: {\n transform: `translateY(${y}px) translateX(${x}px)`,\n },\n innerHTML: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\">\n <polygon points=\"11 3 9 9 16 9 9 17 11 11 4 11 11 3\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" fill=\"currentColor\"></polygon>\n </svg>\n `,\n onclick,\n },\n container\n );\n }\n\n #gutterBuffer: HTMLElement;\n #quickEditContainer: HTMLElement;\n #slot: HTMLElement;\n #observer: ResizeObserver;\n #handleDomResize: () => void;\n\n constructor(\n public line: number,\n quickEditElement: HTMLElement,\n fileContainer: HTMLElement,\n leadingWhitespaces = 0,\n handleDomResize: () => void\n ) {\n const slotName = 'quick-edit-' + line;\n this.#slot = h(\n 'div',\n {\n dataset: 'quickEditSlot',\n slot: slotName,\n style: 'white-space: normal',\n children: [quickEditElement],\n },\n fileContainer\n );\n this.#gutterBuffer = h('div', {\n dataset: { gutterBuffer: 'quickEdit', bufferSize: '1' },\n style: 'grid-row: span 1',\n });\n this.#quickEditContainer = h('div', {\n dataset: { quickEdit: String(line) },\n style: {\n paddingInlineStart: leadingWhitespaces + 1 + 'ch', // +1 align css `padding-inline`\n },\n contentEditable: 'false',\n children: [h('slot', { name: slotName })],\n });\n this.#observer = new ResizeObserver(handleDomResize);\n this.#observer.observe(this.#slot);\n this.#handleDomResize = handleDomResize;\n }\n\n render(containerElement: HTMLElement): void {\n const gutterElement =\n containerElement.previousElementSibling as HTMLElement | null;\n const lineNumber = this.line + 1;\n const gutterLineElement = gutterElement?.querySelector<HTMLElement>(\n `[data-column-number=\"${lineNumber}\"]`\n );\n const contentLineElement = containerElement.querySelector<HTMLElement>(\n `[data-line=\"${lineNumber}\"]`\n );\n if (\n gutterElement != null &&\n gutterLineElement != null &&\n contentLineElement != null\n ) {\n gutterLineElement.after(this.#gutterBuffer);\n contentLineElement.after(this.#quickEditContainer);\n gutterElement.style.gridRow = 'span ' + gutterElement.children.length;\n containerElement.style.gridRow =\n 'span ' + containerElement.children.length;\n this.#handleDomResize();\n }\n }\n\n cleanup(): void {\n const gutter = this.#gutterBuffer.parentElement;\n const content = this.#quickEditContainer.parentElement;\n\n this.#gutterBuffer.remove();\n this.#quickEditContainer.remove();\n\n if (gutter != null && content != null) {\n gutter.style.gridRow = 'span ' + gutter.children.length;\n content.style.gridRow = 'span ' + content.children.length;\n }\n this.#handleDomResize();\n\n this.#slot.remove();\n this.#observer.disconnect();\n }\n}\n"],"mappings":";;;AAmBA,IAAa,kBAAb,MAA6B;CAC3B,OAAO,WACL,GACA,GACA,WACA,SACa;AACb,SAAO,EACL,OACA;GACE,SAAS;IAAE,eAAe;IAAI,SAAS;IAAS;GAChD,OAAO;GACP,OAAO,EACL,WAAW,cAAc,EAAE,iBAAiB,EAAE,MAC/C;GACD,WAAW;;;;GAIX;GACD,EACD,UACD;;CAGH;CACA;CACA;CACA;CACA;CAEA,YACE,AAAOA,MACP,kBACA,eACA,qBAAqB,GACrB,iBACA;EALO;EAMP,MAAM,WAAW,gBAAgB;AACjC,QAAKC,OAAQ,EACX,OACA;GACE,SAAS;GACT,MAAM;GACN,OAAO;GACP,UAAU,CAAC,iBAAiB;GAC7B,EACD,cACD;AACD,QAAKC,eAAgB,EAAE,OAAO;GAC5B,SAAS;IAAE,cAAc;IAAa,YAAY;IAAK;GACvD,OAAO;GACR,CAAC;AACF,QAAKC,qBAAsB,EAAE,OAAO;GAClC,SAAS,EAAE,WAAW,OAAO,KAAK,EAAE;GACpC,OAAO,EACL,oBAAoB,qBAAqB,IAAI,MAC9C;GACD,iBAAiB;GACjB,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC,CAAC;GAC1C,CAAC;AACF,QAAKC,WAAY,IAAI,eAAe,gBAAgB;AACpD,QAAKA,SAAU,QAAQ,MAAKH,KAAM;AAClC,QAAKI,kBAAmB;;CAG1B,OAAO,kBAAqC;EAC1C,MAAM,gBACJ,iBAAiB;EACnB,MAAM,aAAa,KAAK,OAAO;EAC/B,MAAM,oBAAoB,eAAe,cACvC,wBAAwB,WAAW,IACpC;EACD,MAAM,qBAAqB,iBAAiB,cAC1C,eAAe,WAAW,IAC3B;AACD,MACE,iBAAiB,QACjB,qBAAqB,QACrB,sBAAsB,MACtB;AACA,qBAAkB,MAAM,MAAKH,aAAc;AAC3C,sBAAmB,MAAM,MAAKC,mBAAoB;AAClD,iBAAc,MAAM,UAAU,UAAU,cAAc,SAAS;AAC/D,oBAAiB,MAAM,UACrB,UAAU,iBAAiB,SAAS;AACtC,SAAKE,iBAAkB;;;CAI3B,UAAgB;EACd,MAAM,SAAS,MAAKH,aAAc;EAClC,MAAM,UAAU,MAAKC,mBAAoB;AAEzC,QAAKD,aAAc,QAAQ;AAC3B,QAAKC,mBAAoB,QAAQ;AAEjC,MAAI,UAAU,QAAQ,WAAW,MAAM;AACrC,UAAO,MAAM,UAAU,UAAU,OAAO,SAAS;AACjD,WAAQ,MAAM,UAAU,UAAU,QAAQ,SAAS;;AAErD,QAAKE,iBAAkB;AAEvB,QAAKJ,KAAM,QAAQ;AACnB,QAAKG,SAAU,YAAY"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Range, TextDocument } from "./textDocument.js";
|
|
2
|
+
|
|
3
|
+
//#region src/editor/searchPanel.d.ts
|
|
4
|
+
type SearchKind = 'findNext' | 'findPrevious' | 'findAll' | 'replace' | 'replaceAll';
|
|
5
|
+
interface SearchParams {
|
|
6
|
+
text: string;
|
|
7
|
+
replaceText: string;
|
|
8
|
+
caseSensitive: boolean;
|
|
9
|
+
wholeWord: boolean;
|
|
10
|
+
regex: boolean;
|
|
11
|
+
}
|
|
12
|
+
interface SearchPanelOptions {
|
|
13
|
+
textDocument: TextDocument<unknown>;
|
|
14
|
+
containerElement: HTMLElement;
|
|
15
|
+
defaultQuery: string;
|
|
16
|
+
initialMatch?: [number, number];
|
|
17
|
+
postSearch: (kind: SearchKind, match: [number, number], retainFocus?: boolean) => void;
|
|
18
|
+
getCurrentSearchRange: () => Range | undefined;
|
|
19
|
+
onClose: () => void;
|
|
20
|
+
}
|
|
21
|
+
declare class SearchPanelWidget {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(options: SearchPanelOptions);
|
|
24
|
+
updateMatches(currentMatch?: [number, number]): void;
|
|
25
|
+
focus(): void;
|
|
26
|
+
cleanup(): void;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { SearchKind, SearchPanelOptions, SearchPanelWidget, SearchParams };
|
|
30
|
+
//# sourceMappingURL=searchPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchPanel.d.ts","names":["Range","TextDocument","SearchKind","SearchParams","SearchPanelOptions","HTMLElement","SearchPanelWidget"],"sources":["../../src/editor/searchPanel.d.ts"],"sourcesContent":["import type { Range, TextDocument } from './textDocument';\nexport type SearchKind = 'findNext' | 'findPrevious' | 'findAll' | 'replace' | 'replaceAll';\nexport interface SearchParams {\n text: string;\n replaceText: string;\n caseSensitive: boolean;\n wholeWord: boolean;\n regex: boolean;\n}\nexport interface SearchPanelOptions {\n textDocument: TextDocument<unknown>;\n containerElement: HTMLElement;\n defaultQuery: string;\n initialMatch?: [number, number];\n postSearch: (kind: SearchKind, match: [number, number], retainFocus?: boolean) => void;\n getCurrentSearchRange: () => Range | undefined;\n onClose: () => void;\n}\nexport declare class SearchPanelWidget {\n #private;\n constructor(options: SearchPanelOptions);\n updateMatches(currentMatch?: [number, number]): void;\n focus(): void;\n cleanup(): void;\n}\n//# sourceMappingURL=searchPanel.d.ts.map"],"mappings":";;;KACYE,UAAAA;UACKC,YAAAA;EADLD,IAAAA,EAAAA,MAAAA;EACKC,WAAAA,EAAAA,MAAY;EAOZC,aAAAA,EAAAA,OAAkB;EACjBH,SAAAA,EAAAA,OAAAA;EACII,KAAAA,EAAAA,OAAAA;;AAIWL,UANhBI,kBAAAA,CAMgBJ;EAAK,YAAA,EALpBC,YAKoB,CAAA,OAAA,CAAA;EAGjBK,gBAAAA,EAPCD,WAOgB;;;qBAJfH;+BACUF;;;cAGZM,iBAAAA;;uBAEIF"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { isPrimaryModifier } from "./platform.js";
|
|
2
|
+
import { h } from "./utils.js";
|
|
3
|
+
|
|
4
|
+
//#region src/editor/searchPanel.ts
|
|
5
|
+
var SearchPanelWidget = class {
|
|
6
|
+
#textDocument;
|
|
7
|
+
#container;
|
|
8
|
+
#inputElement;
|
|
9
|
+
#matchesElement;
|
|
10
|
+
#searchParams = {
|
|
11
|
+
text: "",
|
|
12
|
+
replaceText: "",
|
|
13
|
+
caseSensitive: false,
|
|
14
|
+
wholeWord: false,
|
|
15
|
+
regex: false
|
|
16
|
+
};
|
|
17
|
+
#allMatches = [];
|
|
18
|
+
constructor(options) {
|
|
19
|
+
const { textDocument, containerElement, defaultQuery, initialMatch, postSearch, getCurrentSearchRange, onClose } = options;
|
|
20
|
+
const close = () => {
|
|
21
|
+
this.cleanup();
|
|
22
|
+
onClose();
|
|
23
|
+
};
|
|
24
|
+
const updateSearchParam = (key, value) => {
|
|
25
|
+
this.#searchParams[key] = value;
|
|
26
|
+
updateAllMatches();
|
|
27
|
+
this.updateMatches();
|
|
28
|
+
};
|
|
29
|
+
const updateAllMatches = () => {
|
|
30
|
+
this.#allMatches = this.#searchParams.text !== "" ? this.#textDocument.search("findAll", this.#searchParams) : [];
|
|
31
|
+
this.#container.querySelectorAll("[data-disabled]").forEach((element) => {
|
|
32
|
+
element.dataset.disabled = String(this.#allMatches.length === 0);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const search = (kind, retainFocus) => {
|
|
36
|
+
const matches = this.#textDocument.search(kind, this.#searchParams, getCurrentSearchRange());
|
|
37
|
+
if (matches.length === 0) return;
|
|
38
|
+
const firstMatch = matches[0];
|
|
39
|
+
this.updateMatches(firstMatch);
|
|
40
|
+
postSearch(kind, firstMatch, retainFocus);
|
|
41
|
+
};
|
|
42
|
+
const settingsSwitch = h("div", {
|
|
43
|
+
dataset: { icon: "settings" },
|
|
44
|
+
title: "Settings",
|
|
45
|
+
innerHTML: `<svg width="16" height="16" viewBox="0 0 20 20">
|
|
46
|
+
<line x1="3" y1="6" x2="10" y2="6" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
|
|
47
|
+
<circle cx="12.5" cy="6" r="2.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></circle>
|
|
48
|
+
<line x1="15" y1="6" x2="17" y2="6" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
|
|
49
|
+
<line x1="17" y1="14" x2="10" y2="14" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
|
|
50
|
+
<circle cx="7.5" cy="14" r="2.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></circle>
|
|
51
|
+
<line x1="5" y1="14" x2="3" y2="14" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
|
|
52
|
+
</svg>
|
|
53
|
+
`,
|
|
54
|
+
onclick: () => {
|
|
55
|
+
settingsSwitch.replaceWith(settingsPanel);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const settingsPanel = h("div", {
|
|
59
|
+
dataset: "settings",
|
|
60
|
+
children: [
|
|
61
|
+
h("label", {
|
|
62
|
+
dataset: "checkbox",
|
|
63
|
+
children: [h("input", {
|
|
64
|
+
type: "checkbox",
|
|
65
|
+
checked: this.#searchParams.caseSensitive,
|
|
66
|
+
onchange: (e) => {
|
|
67
|
+
updateSearchParam("caseSensitive", e.target.checked);
|
|
68
|
+
}
|
|
69
|
+
}), "Match Case"]
|
|
70
|
+
}),
|
|
71
|
+
h("label", {
|
|
72
|
+
dataset: "checkbox",
|
|
73
|
+
children: [h("input", {
|
|
74
|
+
type: "checkbox",
|
|
75
|
+
checked: this.#searchParams.wholeWord,
|
|
76
|
+
onchange: (e) => {
|
|
77
|
+
updateSearchParam("wholeWord", e.target.checked);
|
|
78
|
+
}
|
|
79
|
+
}), "Whole Word"]
|
|
80
|
+
}),
|
|
81
|
+
h("label", {
|
|
82
|
+
dataset: "checkbox",
|
|
83
|
+
children: [h("input", {
|
|
84
|
+
type: "checkbox",
|
|
85
|
+
checked: this.#searchParams.regex,
|
|
86
|
+
onchange: (e) => {
|
|
87
|
+
updateSearchParam("regex", e.target.checked);
|
|
88
|
+
}
|
|
89
|
+
}), "Regexp"]
|
|
90
|
+
})
|
|
91
|
+
],
|
|
92
|
+
onmouseleave: () => {
|
|
93
|
+
closeSettingsPanelTimeout = setTimeout(() => {
|
|
94
|
+
settingsPanel.replaceWith(settingsSwitch);
|
|
95
|
+
}, 500);
|
|
96
|
+
},
|
|
97
|
+
onmouseenter: () => {
|
|
98
|
+
clearTimeout(closeSettingsPanelTimeout);
|
|
99
|
+
closeSettingsPanelTimeout = void 0;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
let closeSettingsPanelTimeout;
|
|
103
|
+
this.#textDocument = textDocument;
|
|
104
|
+
this.#searchParams.text = defaultQuery;
|
|
105
|
+
this.#inputElement = h("input", {
|
|
106
|
+
type: "text",
|
|
107
|
+
placeholder: "Search",
|
|
108
|
+
dataset: "search",
|
|
109
|
+
value: defaultQuery,
|
|
110
|
+
oninput: (e) => {
|
|
111
|
+
this.#searchParams.text = e.target.value;
|
|
112
|
+
updateAllMatches();
|
|
113
|
+
this.updateMatches();
|
|
114
|
+
},
|
|
115
|
+
onkeydown: (e) => {
|
|
116
|
+
if (e.key === "Escape") {
|
|
117
|
+
e.preventDefault();
|
|
118
|
+
close();
|
|
119
|
+
} else if (e.key === "Enter") {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
search("findNext", true);
|
|
122
|
+
} else if (e.key === "f" && isPrimaryModifier(e)) e.preventDefault();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
this.#matchesElement = h("div", { dataset: "matches" });
|
|
126
|
+
this.#container = h("div", {
|
|
127
|
+
dataset: "searchPanel",
|
|
128
|
+
children: [h("div", {
|
|
129
|
+
dataset: "searchPanelRow",
|
|
130
|
+
children: [
|
|
131
|
+
h("div", {
|
|
132
|
+
dataset: { icon: "search" },
|
|
133
|
+
innerHTML: `<svg width="16" height="16" viewBox="0 0 20 20">
|
|
134
|
+
<line x1="16.5" y1="16.5" x2="12.0355" y2="12.0355" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
|
|
135
|
+
<circle cx="8.5" cy="8.5" r="5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></circle>
|
|
136
|
+
</svg>
|
|
137
|
+
`
|
|
138
|
+
}),
|
|
139
|
+
this.#inputElement,
|
|
140
|
+
this.#matchesElement,
|
|
141
|
+
h("div", {
|
|
142
|
+
dataset: {
|
|
143
|
+
icon: "arrow-up",
|
|
144
|
+
disabled: "true"
|
|
145
|
+
},
|
|
146
|
+
title: "Previous",
|
|
147
|
+
innerHTML: `<svg width="14" height="14" viewBox="0 0 20 20">
|
|
148
|
+
<polyline points="12.5 3.5 6 10 12.5 16.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline>
|
|
149
|
+
</svg>
|
|
150
|
+
`,
|
|
151
|
+
onclick: () => {
|
|
152
|
+
search("findPrevious");
|
|
153
|
+
}
|
|
154
|
+
}),
|
|
155
|
+
h("div", {
|
|
156
|
+
dataset: {
|
|
157
|
+
icon: "arrow-down",
|
|
158
|
+
disabled: "true"
|
|
159
|
+
},
|
|
160
|
+
title: "Next",
|
|
161
|
+
innerHTML: `<svg width="14" height="14" viewBox="0 0 20 20">
|
|
162
|
+
<polyline points="7.5 16.5 14 10 7.5 3.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline>
|
|
163
|
+
</svg>
|
|
164
|
+
`,
|
|
165
|
+
onclick: () => {
|
|
166
|
+
search("findNext");
|
|
167
|
+
}
|
|
168
|
+
}),
|
|
169
|
+
h("div", { dataset: "spacer" }),
|
|
170
|
+
settingsSwitch,
|
|
171
|
+
h("div", {
|
|
172
|
+
dataset: { icon: "close" },
|
|
173
|
+
title: "Close",
|
|
174
|
+
innerHTML: `<svg width="16" height="16" viewBox="0 0 20 20">
|
|
175
|
+
<line x1="5" y1="5" x2="15" y2="15" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
|
|
176
|
+
<line x1="5" y1="15" x2="15" y2="5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
|
|
177
|
+
</svg>
|
|
178
|
+
`,
|
|
179
|
+
onclick: close
|
|
180
|
+
})
|
|
181
|
+
]
|
|
182
|
+
})]
|
|
183
|
+
});
|
|
184
|
+
containerElement.before(this.#container);
|
|
185
|
+
requestAnimationFrame(() => {
|
|
186
|
+
if (initialMatch !== void 0) {
|
|
187
|
+
updateAllMatches();
|
|
188
|
+
this.updateMatches(initialMatch);
|
|
189
|
+
}
|
|
190
|
+
this.#inputElement.select();
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
updateMatches(currentMatch = this.#allMatches[0]) {
|
|
194
|
+
const allMatches = this.#allMatches;
|
|
195
|
+
if (this.#searchParams.text === "") {
|
|
196
|
+
this.#matchesElement.textContent = "";
|
|
197
|
+
delete this.#matchesElement.dataset.noMatches;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (allMatches.length === 0) {
|
|
201
|
+
this.#matchesElement.textContent = "No results";
|
|
202
|
+
this.#matchesElement.dataset.noMatches = "";
|
|
203
|
+
} else {
|
|
204
|
+
delete this.#matchesElement.dataset.noMatches;
|
|
205
|
+
const index = allMatches.findIndex((m) => m[0] === currentMatch[0] && m[1] === currentMatch[1]);
|
|
206
|
+
this.#matchesElement.textContent = index !== -1 ? `${index + 1} of ${allMatches.length}` : "No results";
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
focus() {
|
|
210
|
+
this.#inputElement.select();
|
|
211
|
+
}
|
|
212
|
+
cleanup() {
|
|
213
|
+
this.#container.remove();
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
//#endregion
|
|
218
|
+
export { SearchPanelWidget };
|
|
219
|
+
//# sourceMappingURL=searchPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchPanel.js","names":["#searchParams","#allMatches","#textDocument","#container","closeSettingsPanelTimeout: ReturnType<typeof setTimeout> | undefined","#inputElement","#matchesElement"],"sources":["../../src/editor/searchPanel.ts"],"sourcesContent":["import { isPrimaryModifier } from './platform';\nimport type { Range, TextDocument } from './textDocument';\nimport { h } from './utils';\n\nexport type SearchKind =\n | 'findNext'\n | 'findPrevious'\n | 'findAll'\n | 'replace'\n | 'replaceAll';\n\nexport interface SearchParams {\n text: string;\n replaceText: string;\n caseSensitive: boolean;\n wholeWord: boolean;\n regex: boolean;\n}\n\nexport interface SearchPanelOptions {\n textDocument: TextDocument<unknown>;\n containerElement: HTMLElement;\n defaultQuery: string;\n initialMatch?: [number, number];\n postSearch: (\n kind: SearchKind,\n match: [number, number],\n retainFocus?: boolean\n ) => void;\n getCurrentSearchRange: () => Range | undefined;\n onClose: () => void;\n}\n\nexport class SearchPanelWidget {\n #textDocument: TextDocument<unknown>;\n #container: HTMLDivElement;\n #inputElement: HTMLInputElement;\n #matchesElement: HTMLDivElement;\n #searchParams: SearchParams = {\n text: '',\n replaceText: '',\n caseSensitive: false,\n wholeWord: false,\n regex: false,\n };\n #allMatches: [number, number][] = [];\n\n constructor(options: SearchPanelOptions) {\n const {\n textDocument,\n containerElement,\n defaultQuery,\n initialMatch,\n postSearch,\n getCurrentSearchRange,\n onClose,\n } = options;\n\n const close = () => {\n this.cleanup();\n onClose();\n };\n\n const updateSearchParam = <K extends keyof SearchParams>(\n key: K,\n value: SearchParams[K]\n ) => {\n this.#searchParams[key] = value;\n updateAllMatches();\n this.updateMatches();\n };\n\n const updateAllMatches = () => {\n this.#allMatches =\n this.#searchParams.text !== ''\n ? this.#textDocument.search('findAll', this.#searchParams)\n : [];\n this.#container\n .querySelectorAll<HTMLElement>('[data-disabled]')\n .forEach((element) => {\n element.dataset.disabled = String(this.#allMatches.length === 0);\n });\n };\n\n const search = (kind: SearchKind, retainFocus?: boolean) => {\n const matches = this.#textDocument.search(\n kind,\n this.#searchParams,\n getCurrentSearchRange()\n );\n if (matches.length === 0) {\n return;\n }\n const firstMatch = matches[0];\n this.updateMatches(firstMatch);\n postSearch(kind, firstMatch, retainFocus);\n };\n\n const settingsSwitch = h('div', {\n dataset: { icon: 'settings' },\n title: 'Settings',\n innerHTML: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\">\n <line x1=\"3\" y1=\"6\" x2=\"10\" y2=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <circle cx=\"12.5\" cy=\"6\" r=\"2.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></circle>\n <line x1=\"15\" y1=\"6\" x2=\"17\" y2=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <line x1=\"17\" y1=\"14\" x2=\"10\" y2=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <circle cx=\"7.5\" cy=\"14\" r=\"2.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></circle>\n <line x1=\"5\" y1=\"14\" x2=\"3\" y2=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n </svg>\n `,\n onclick: () => {\n settingsSwitch.replaceWith(settingsPanel);\n },\n });\n const settingsPanel = h('div', {\n dataset: 'settings',\n children: [\n h('label', {\n dataset: 'checkbox',\n children: [\n h('input', {\n type: 'checkbox',\n checked: this.#searchParams.caseSensitive,\n onchange: (e: Event) => {\n updateSearchParam(\n 'caseSensitive',\n (e.target as HTMLInputElement).checked\n );\n },\n }),\n 'Match Case',\n ],\n }),\n h('label', {\n dataset: 'checkbox',\n children: [\n h('input', {\n type: 'checkbox',\n checked: this.#searchParams.wholeWord,\n onchange: (e: Event) => {\n updateSearchParam(\n 'wholeWord',\n (e.target as HTMLInputElement).checked\n );\n },\n }),\n 'Whole Word',\n ],\n }),\n h('label', {\n dataset: 'checkbox',\n children: [\n h('input', {\n type: 'checkbox',\n checked: this.#searchParams.regex,\n onchange: (e: Event) => {\n updateSearchParam(\n 'regex',\n (e.target as HTMLInputElement).checked\n );\n },\n }),\n 'Regexp',\n ],\n }),\n ],\n onmouseleave: () => {\n closeSettingsPanelTimeout = setTimeout(() => {\n settingsPanel.replaceWith(settingsSwitch);\n }, 500);\n },\n onmouseenter: () => {\n clearTimeout(closeSettingsPanelTimeout);\n closeSettingsPanelTimeout = undefined;\n },\n });\n\n let closeSettingsPanelTimeout: ReturnType<typeof setTimeout> | undefined;\n\n this.#textDocument = textDocument;\n this.#searchParams.text = defaultQuery;\n\n this.#inputElement = h('input', {\n type: 'text',\n placeholder: 'Search',\n dataset: 'search',\n value: defaultQuery,\n oninput: (e: Event) => {\n this.#searchParams.text = (e.target as HTMLInputElement).value;\n updateAllMatches();\n this.updateMatches();\n },\n onkeydown: (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n close();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n search('findNext', true);\n } else if (e.key === 'f' && isPrimaryModifier(e)) {\n // prevent the default browser search panel open behavior\n e.preventDefault();\n }\n },\n });\n this.#matchesElement = h('div', { dataset: 'matches' });\n this.#container = h('div', {\n dataset: 'searchPanel',\n children: [\n h('div', {\n dataset: 'searchPanelRow',\n children: [\n h('div', {\n dataset: { icon: 'search' },\n innerHTML: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\">\n <line x1=\"16.5\" y1=\"16.5\" x2=\"12.0355\" y2=\"12.0355\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <circle cx=\"8.5\" cy=\"8.5\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></circle>\n </svg>\n `,\n }),\n this.#inputElement,\n this.#matchesElement,\n h('div', {\n dataset: { icon: 'arrow-up', disabled: 'true' },\n title: 'Previous',\n innerHTML: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\">\n <polyline points=\"12.5 3.5 6 10 12.5 16.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></polyline>\n </svg>\n `,\n onclick: () => {\n search('findPrevious');\n },\n }),\n h('div', {\n dataset: { icon: 'arrow-down', disabled: 'true' },\n title: 'Next',\n innerHTML: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\">\n <polyline points=\"7.5 16.5 14 10 7.5 3.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></polyline>\n </svg>\n `,\n onclick: () => {\n search('findNext');\n },\n }),\n h('div', { dataset: 'spacer' }),\n settingsSwitch,\n h('div', {\n dataset: { icon: 'close' },\n title: 'Close',\n innerHTML: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\">\n <line x1=\"5\" y1=\"5\" x2=\"15\" y2=\"15\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <line x1=\"5\" y1=\"15\" x2=\"15\" y2=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n </svg>\n `,\n onclick: close,\n }),\n ],\n }),\n ],\n });\n containerElement.before(this.#container);\n\n requestAnimationFrame(() => {\n if (initialMatch !== undefined) {\n updateAllMatches();\n this.updateMatches(initialMatch);\n }\n this.#inputElement.select();\n });\n }\n\n updateMatches(currentMatch: [number, number] = this.#allMatches[0]): void {\n const allMatches = this.#allMatches;\n const searchText = this.#searchParams.text;\n\n if (searchText === '') {\n this.#matchesElement.textContent = '';\n delete this.#matchesElement.dataset.noMatches;\n return;\n }\n\n if (allMatches.length === 0) {\n this.#matchesElement.textContent = 'No results';\n this.#matchesElement.dataset.noMatches = '';\n } else {\n delete this.#matchesElement.dataset.noMatches;\n const index = allMatches.findIndex(\n (m) => m[0] === currentMatch[0] && m[1] === currentMatch[1]\n );\n this.#matchesElement.textContent =\n index !== -1 ? `${index + 1} of ${allMatches.length}` : 'No results';\n }\n }\n\n focus(): void {\n this.#inputElement.select();\n }\n\n cleanup(): void {\n this.#container.remove();\n }\n}\n"],"mappings":"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"}
|