Skip to content
Draft
Show file tree
Hide file tree
Changes from 107 commits
Commits
Show all changes
214 commits
Select commit Hold shift + click to select a range
434ea2a
First implement
ije Apr 23, 2026
364e3b2
Fix paste
ije Apr 23, 2026
b915a8c
Fix character X
ije Apr 23, 2026
f05e492
Add 'indent' and 'outdent' commands
ije Apr 23, 2026
b1edaee
Add typing buffer
ije Apr 23, 2026
3779a55
Type alias migration from `ISelection`/`IEditorSelection` to `EditorS…
ije Apr 23, 2026
fefbac3
Fix indent command for multiline selection
ije Apr 23, 2026
1d081f5
Refactor
ije Apr 24, 2026
73623fb
Improve shiki theme/garmmar loading
ije Apr 25, 2026
fc88eb8
Add `minNumberColumnWidth` option
ije Apr 25, 2026
0113543
Refactor
ije Apr 25, 2026
79177f5
Remove history coalesce
ije Apr 25, 2026
4cb7b41
Fix selction/crate not updated when do "redo" command
ije Apr 25, 2026
57cfbe6
Remove visualColumns.ts
ije Apr 25, 2026
78ec876
Move editor ts files
ije Apr 25, 2026
a0934f8
Refactor textarea buffer
ije Apr 25, 2026
84d5df6
Rename `EditSnippet` type to `TextareaSnapshot`
ije Apr 25, 2026
996db61
Remove `Editor` component, introduce the `Editor` class for `File` co…
ije Apr 27, 2026
f95df57
Update demo
ije Apr 27, 2026
18f5422
Update editor constants to set text and background color to transparent
ije Apr 27, 2026
0194e41
Rewrite rerender logic
ije Apr 27, 2026
ef525f1
Format
ije Apr 27, 2026
dd85b08
Remove dead code
ije Apr 27, 2026
1ae5008
Fix caret postion on empty line
ije Apr 28, 2026
a8b41bc
Improve `renderSelectionRange` performance by using cached DOM elements
ije Apr 28, 2026
e647f74
Support range selection in textarea
ije Apr 28, 2026
d08abe3
Improve rerender performance
ije Apr 28, 2026
b9495e7
Use piece table data sturcture for the text document
ije Apr 29, 2026
6ea0708
refactor
ije Apr 29, 2026
e42e502
Add public `setSelection` method for the `Editor` class
ije Apr 29, 2026
9a3eb6a
Add `FileContentsWithLineOffsets` interface and update related compon…
ije Apr 29, 2026
3b4d3b4
Add `updateRenderCacheAt` method to `FileRenderer` and `File` classes…
ije Apr 29, 2026
fc6a47e
Refactor file iteration logic by removing `iterateOverFile` utility a…
ije Apr 29, 2026
a6ec728
Remove EOF field
ije Apr 30, 2026
44d631f
Remove text length fields from HistoryEntry and related test cases in…
ije Apr 30, 2026
59f379e
Rename class `EditHistory` to `EditStack`
ije Apr 30, 2026
0eceba2
Refactor EditStack and PieceTable to use a unified text slice interface.
ije Apr 30, 2026
43247d8
Refactor PieceTable and TextDocument to improve line offset handling …
ije May 1, 2026
1b90426
Refactor `Editor` to utilize new dirty line resolution logic, enhanci…
ije May 1, 2026
ec78938
Fix multi-cursor textarea sync
ije May 1, 2026
c56c600
Refactor Editor rendering logic for improved performance and reduce d…
ije May 1, 2026
2a74aaf
Add grammer cache
ije May 1, 2026
d456fa9
Enhance line position caching in Editor for improved performance and …
ije May 1, 2026
c446ad9
Refactor indentation handling in Editor and remove unused utility fun…
ije May 1, 2026
3e14a92
Fix testing types
ije May 1, 2026
d656e4a
Improve performance of the `getCharacterX` method
ije May 1, 2026
a8961f4
Improve caching mechanism for enhanced performance.
ije May 1, 2026
738e2b7
Add maxEntries feature to EditStack for managing undo history size
ije May 1, 2026
aaedff4
Refactor
ije May 1, 2026
fe150a0
Enhance PieceTable and TextDocument to trim line endings in getLineTe…
ije May 3, 2026
45b71a1
Refactor
ije May 3, 2026
a685b75
Add `BackgroundTokenzier` class
ije May 3, 2026
acbde05
Improve performance
ije May 4, 2026
209999f
Fix hightlight bug
ije May 4, 2026
2b8cb09
Add `--diffs-bg-caret` css property
ije May 4, 2026
6f3659a
Fix input
ije May 4, 2026
0686fac
Fix selection range rendering
ije May 4, 2026
cefee50
Fix prebuildStateStackCache funciton
ije May 4, 2026
af0e508
Update `TOKENIZE_MAX_LINE_LENGTH` to 10,000
ije May 4, 2026
d9da211
Add `DiffsEditor` interface
ije May 4, 2026
092486e
Fix `lineAnnotations` argument on `triggerEdit` invoke
ije May 4, 2026
4dcc108
Refactor editor edit method to accept onChange callback directly and …
ije May 4, 2026
a2cf5cc
Clean up
ije May 4, 2026
dbbc2b1
typo
ije May 4, 2026
a187ff8
Refactor BackgroundTokenizer to use message-based scheduling.
ije May 5, 2026
d69e59b
Refactor editor focus handling by removing redundant event listeners …
ije May 5, 2026
24f899a
Refactor
ije May 5, 2026
4634c3d
Fix `toTextareaSelectionDirection` function
ije May 5, 2026
229e21e
Refactor
ije May 5, 2026
febadf7
Update `DiffsEditor` types
ije May 5, 2026
1002da8
Add line annotation handling
ije May 5, 2026
a9b7106
Add documentation for `hasVisibleLineAnnotation` function.
ije May 5, 2026
264a4ed
Get rid of enum
ije May 6, 2026
5521967
Clean up
ije May 6, 2026
d83eaa6
Refactor
ije May 6, 2026
c69028b
Update editor CSS
ije May 6, 2026
4b26cba
Support text wrap
ije May 7, 2026
7fc5f61
Clean up
ije May 7, 2026
c3a1fa8
Fix line y/wrap cache
ije May 7, 2026
e567b0b
Fix line cache
ije May 7, 2026
dd12a8a
Copies leading indentation onto the new line after Enter
ije May 7, 2026
415b6df
Focus textare after undo/redo
ije May 7, 2026
c5ad096
Move multi-selection functions to editorSelection module
ije May 8, 2026
8a387b3
Add support for handling leading indentation deletion in applyTextCha…
ije May 8, 2026
47e57d4
Fix selection glitch bug
ije May 8, 2026
2609f22
Add extendSelection command
ije May 8, 2026
23dc842
Fix `focusTextare` function
ije May 8, 2026
18487ed
Fix `resolveTextareaChange` function
ije May 8, 2026
754958f
Remove unnecessary target check in mouseup event listener in Editor c…
ije May 8, 2026
fc26f73
Fix textarea selction direction
ije May 8, 2026
f16e618
Fix selection bg color for safair
ije May 8, 2026
779a50a
Clean up
ije May 8, 2026
d9651ff
Fix shift select
ije May 8, 2026
262f8f9
Refactor
ije May 8, 2026
2bb2e4b
Refactor
ije May 9, 2026
f114396
Fix shift select delay
ije May 9, 2026
f847f63
Coalesce edit stack entries for simple typing or backspace operations.
ije May 9, 2026
2967161
Add Support forward-delete coalescing for edit history
ije May 9, 2026
f63f2fd
docs: add docs for editStack module
ije May 9, 2026
d4d8dec
Refctor
ije May 9, 2026
fe5ab6d
Fix 'documentStart' and 'documentEnd' commands
ije May 9, 2026
5ff2b42
Rewrite selection handle logic
ije May 9, 2026
76a2fb4
Fix shouldCoalesceEditStackEntry function
ije May 9, 2026
b23ad56
Update demo
ije May 9, 2026
1e76276
Add `removeEditor` for File component
ije May 9, 2026
3bb44ee
Add react api
ije May 9, 2026
ff1d452
Clean up
ije May 9, 2026
0ff08c9
Update demo app
ije May 9, 2026
3b40cf8
Refactor useFileInstance to remove redundant editor cleanup logic
ije May 9, 2026
d3289c7
Fix `computeLineOffsets` function
ije May 10, 2026
2346eef
typo
ije May 10, 2026
1a7797c
Update editor style
ije May 10, 2026
99720ae
Fix `getOrCreateLineOffSets` method
ije May 10, 2026
1abf83a
Refactor line count and annotation handling in File component; remove…
ije May 10, 2026
e174585
Fix lines deletion crocss virtul viewport
ije May 10, 2026
9083774
Remove `normalizeSelectionsForDocument` function
ije May 10, 2026
2e6580e
Fix `edit` function
ije May 10, 2026
3951793
Add editor sub-module
ije May 10, 2026
3219737
Use `contenteditable` model
ije May 11, 2026
3fbcba6
Fix line wrap
ije May 11, 2026
7c979b1
Fix wrap line
ije May 11, 2026
60a98b6
Fix selection on mobile
ije May 11, 2026
583adb3
Update editor style
ije May 11, 2026
942cba9
Fix resize handling
ije May 11, 2026
2095c1d
Add editor overlay layer
ije May 12, 2026
3ce394a
Cleanup
ije May 12, 2026
a8b674d
Add `DiffsEditableComponent` types
ije May 12, 2026
1f3a448
Fix `VirtualizedFile` component
ije May 12, 2026
c18a373
Update `DiffsEditableComponent` type
ije May 12, 2026
0d9ea91
Add editor demo
ije May 12, 2026
c76b51b
Merge branch 'main' into editor
ije May 12, 2026
b1c50ef
Fix slection rendering
ije May 12, 2026
c9ef7e8
Update editor demo app
ije May 12, 2026
6dea24a
Fix VirualizedFile component
ije May 12, 2026
8140e15
Update editor demo app
ije May 12, 2026
b273533
Fix some selection bugs
ije May 13, 2026
6892b6c
Update demo app
ije May 13, 2026
50fe728
Refactor findNextNonOverlappingSubstring method into PieceTable and T…
ije May 13, 2026
672dae3
Refactor
ije May 13, 2026
f455639
feat: Implement line jump
ije May 14, 2026
d1a5aad
Fix selection rendering when scrolling
ije May 14, 2026
02883aa
Improve tokenzier performance
ije May 14, 2026
7311b69
feat: simple search pannel
ije May 14, 2026
59af9aa
Update editor demo app
ije May 15, 2026
96d3e51
Fix jump
ije May 15, 2026
99caccd
Update search UI
ije May 15, 2026
5c5a535
Add lag radar
ije May 15, 2026
40262dd
Fix virtualizer
ije May 15, 2026
d8ea490
Fix render range after typing
ije May 15, 2026
d4dbb1e
Fix editor tokenzier cache
ije May 15, 2026
81b8668
Fix search input focus
ije May 15, 2026
e53e7e2
Update log rader position
ije May 15, 2026
cc8a1d8
Improve piece table performance
ije May 15, 2026
25543a0
Refactor
ije May 15, 2026
777ca44
Add lag radar
ije May 15, 2026
dcc5233
Fix line count for empty documents
ije May 15, 2026
37feda5
Fix offscreen lines flush
ije May 15, 2026
ae70e25
Introduce gutter width tracking
ije May 15, 2026
13881f8
refactor
ije May 17, 2026
a6e714b
Refactor
ije May 18, 2026
79bdaf3
fix import
ije May 18, 2026
1791756
Add 'expandSelectionDocStart' and 'expandSelectionDocEnd' commands
ije May 18, 2026
9e1d025
Fix buffer height
ije May 18, 2026
84a0305
Add matches text for the search pancel
ije May 18, 2026
e01ac32
Disable preious/next icon when no matches
ije May 18, 2026
4327a3e
Update style.css
ije May 18, 2026
980f10d
feat: Support `quiteEdit` action
ije May 18, 2026
08b1da1
Update edtior demo app
ije May 18, 2026
290e3e9
Refactor
ije May 18, 2026
0037756
Update demo app
ije May 18, 2026
aae9c6b
Update demo app
ije May 19, 2026
c19cbf2
Fix girdRow when render quick edit UI
ije May 19, 2026
04205aa
Move testing files
ije May 19, 2026
952f671
Clean up
ije May 19, 2026
942d3f0
Add searchPanel.ts
ije May 19, 2026
f8f2ae7
Fix expandCollapsedSelectionToWord to match when the cursor is immedi…
ije May 19, 2026
3a39eef
clean up
ije May 19, 2026
eae60e6
Potential fix for pull request finding
ije May 19, 2026
da96eac
Fix typo
ije May 19, 2026
98e4182
Merge branch 'editor' of https://github.com/ije/pierre into editor
ije May 19, 2026
d717cbc
Merge branch 'pierrecomputer:main' into editor
ije May 19, 2026
d911015
Clean up searchPanel and quickEdit when swith file
ije May 19, 2026
0fd8945
Rebase to beta-1.2
ije May 20, 2026
e01c258
Fix selection after clean up quick edit widget
ije May 20, 2026
b643f6a
Fix virtual buffer
ije May 20, 2026
c66a6fd
Fix `updateWindowSelection` method of Editor class
ije May 20, 2026
e478623
Fix render range when typing new line at the end of the file
ije May 20, 2026
d70a613
Fix buffer when adding large lines
ije May 20, 2026
79a6150
[editor] Support 'deleteHardLineForward' input
ije May 20, 2026
8f13c91
Add `insertTranspose` input
ije May 20, 2026
b66f559
Move `change` handler to options
ije May 20, 2026
3c990dd
Update css
ije May 20, 2026
7b1c844
Merge beta-1.2 changes
ije May 20, 2026
1fdc87a
Fix emply line rendering
ije May 21, 2026
458213a
Add search settings UI
ije May 21, 2026
82b364e
Merge branch 'main' into editor
ije May 21, 2026
bc4c288
Merge branch 'main' into editor
ije May 21, 2026
416674c
Support FileDiff component
ije May 21, 2026
af87f6f
Update `DiffsEditableComponent` interface
ije May 21, 2026
225f0f0
Fix `getSelectionAnchor` function
ije May 21, 2026
c8ed844
Fix text measurement for emoji
ije May 21, 2026
df5d640
Increase delay for diff rendering in FileDiff component
ije May 22, 2026
acd1471
Update types
ije May 22, 2026
75035a3
Add unit testings for text measue functions
ije May 22, 2026
1a50cad
Clean up dirty render cache
ije May 22, 2026
f16ca64
Fix `lineAnnotations` re-rendering
ije May 22, 2026
fec9d4c
Disable gutter utility when editing
ije May 22, 2026
cd8cd09
Add global css
ije May 22, 2026
030136e
Fix scrollToLine method
ije May 22, 2026
4746c4d
Refactor selection handling in Editor class to initialize selections …
ije May 22, 2026
519ebae
Merge branch 'main' into editor
ije May 22, 2026
deb3d64
Fix diffs components
ije May 22, 2026
ca75a7d
Allow to create selection from gutter interaction
ije May 22, 2026
953be5d
Fix focus
ije May 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 35 additions & 5 deletions apps/demo/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
DEFAULT_THEMES,
DIFFS_TAG_NAME,
type DiffsThemeNames,
Editor,
File,
type FileContents,
FileDiff,
Expand Down Expand Up @@ -47,7 +48,7 @@ import {
const DEMO_THEME: DiffsThemeNames | ThemesType = DEFAULT_THEMES;
const WORKER_POOL = true;
const VIRTUALIZE = true;
const CRAZY_FILE = false;
const CRAZY_FILE = true;
Comment thread
ije marked this conversation as resolved.
Outdated
const LARGE_CONFLICT_FILE = false;

const FileStreamCodeConfigs: FileStreamCodeConfigsItem[] = [
Expand Down Expand Up @@ -206,7 +207,8 @@ function renderDiff(parsedPatches: ParsedPatch[], manager?: WorkerPoolManager) {
overflow: wrap ? 'wrap' : 'scroll',
renderAnnotation: renderDiffAnnotation,
renderHeaderMetadata() {
return createCollapsedToggle(
return createToggle(
'Collapse',
instance?.options.collapsed ?? false,
(checked) => {
instance?.setOptions({
Expand Down Expand Up @@ -673,6 +675,7 @@ if (renderFileButton != null) {

virtualizer?.setup(globalThis.document);
const wrap = getWrapped();
const editor = new Editor();
const fileContainer = document.createElement(DIFFS_TAG_NAME);
wrapper.appendChild(fileContainer);
let instance:
Expand All @@ -684,7 +687,8 @@ if (renderFileButton != null) {
themeType: getThemeType(),
renderAnnotation,
renderCustomMetadata() {
return createCollapsedToggle(
const collapsedToggle = createToggle(
'Collapse',
instance?.options.collapsed ?? false,
(checked) => {
instance?.setOptions({
Expand All @@ -696,6 +700,31 @@ if (renderFileButton != null) {
}
}
);
const editableToggle = createToggle('Editable', false, (checked) => {
if (checked) {
editor.edit(instance);
editor.setSelections([
{
start: {
line: 0,
character: 0,
},
end: {
line: 0,
character: 0,
},
direction: 0,
},
]);
} else {
editor.cleanUp();
}
});
const div = document.createElement('div');
div.style.display = 'flex';
div.style.gap = '8px';
div.append(collapsedToggle, editableToggle);
return div;
},

// Line selection stuff
Expand Down Expand Up @@ -883,7 +912,8 @@ cleanButton?.addEventListener('click', () => {
cleanupInstances(container);
});

function createCollapsedToggle(
function createToggle(
labelText: string,
checked: boolean,
onChange: (checked: boolean) => void
): HTMLElement {
Expand All @@ -896,7 +926,7 @@ function createCollapsedToggle(
});
label.dataset.collapser = '';
label.appendChild(input);
label.append(' Collapse');
label.append(labelText);
Comment thread
ije marked this conversation as resolved.
Outdated
return label;
}

Expand Down
107 changes: 100 additions & 7 deletions packages/diffs/src/components/File.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import { SVGSpriteSheet } from '../sprite';
import type {
AppliedThemeStyleCache,
BaseCodeOptions,
DiffsEditor,
FileContents,
HighlightedToken,
LineAnnotation,
PrePropertiesConfig,
RenderFileMetadata,
Expand All @@ -41,14 +43,13 @@ import { createUnsafeCSSStyleNode } from '../utils/createUnsafeCSSStyleNode';
import { wrapThemeCSS, wrapUnsafeCSS } from '../utils/cssWrappers';
import { getLineAnnotationName } from '../utils/getLineAnnotationName';
import { getOrCreateCodeNode } from '../utils/getOrCreateCodeNode';
import { hasVisibleLineAnnotation } from '../utils/hasVisibleLineAnnotation';
import { upsertHostThemeStyle } from '../utils/hostTheme';
import { prerenderHTMLIfNecessary } from '../utils/prerenderHTMLIfNecessary';
import { setPreNodeProperties } from '../utils/setWrapperNodeProps';
import type { WorkerPoolManager } from '../worker';
import { DiffsContainerLoaded } from './web-components';

const EMPTY_STRINGS: string[] = [];

export interface FileRenderProps<LAnnotation> {
file: FileContents;
fileContainer?: HTMLElement;
Expand Down Expand Up @@ -154,6 +155,8 @@ export class File<LAnnotation = undefined> {
protected file: FileContents | undefined;
protected renderRange: RenderRange | undefined;

protected editor: DiffsEditor<LAnnotation> | undefined;

constructor(
public options: FileOptions<LAnnotation> = { theme: DEFAULT_THEMES },
private workerManager?: WorkerPoolManager | undefined,
Expand All @@ -172,6 +175,23 @@ export class File<LAnnotation = undefined> {
this.workerManager?.subscribeToThemeChanges(this);
}

public setEditor(editor: DiffsEditor<LAnnotation>): void {
this.editor?.cleanUp();
if (this.fileContainer != null && this.file != null) {
editor.syncFile(
this.fileContainer,
this.file,
this.lineAnnotations,
this.renderRange
);
}
this.editor = editor;
}

public removeEditor(): void {
this.editor = undefined;
}

private handleHighlightRender = (): void => {
this.rerender();
};
Expand Down Expand Up @@ -264,6 +284,10 @@ export class File<LAnnotation = undefined> {
this.unsafeCSSStyle = undefined;
this.appliedUnsafeCSS = undefined;
this.placeHolder = undefined;

// Clean up the editor
this.editor?.cleanUp();
this.editor = undefined;
}

public hydrate(props: FileHydrateProps<LAnnotation>): void {
Expand Down Expand Up @@ -362,12 +386,75 @@ export class File<LAnnotation = undefined> {
this.resizeManager.setup(this.pre, overflow === 'wrap');
}

public getOrCreateLineCache(
public getOrCreateLineOffSets(
file: FileContents | undefined = this.file
): string[] {
return file != null
? this.fileRenderer.getOrCreateLineCache(file)
: EMPTY_STRINGS;
): number[] {
return file != null ? this.fileRenderer.getOrCreateLineOffsets(file) : [];
}
Comment thread
ije marked this conversation as resolved.
Outdated

public getLineCount(file: FileContents | undefined = this.file): number {
return file != null ? this.fileRenderer.getLineCount(file) : 0;
}

public emitDirtyLines(lines: Map<number, Array<HighlightedToken>>): void {
this.fileRenderer.emitDirtyLines(lines);
}

public emitLineCountChange(lineCount: number): void {
const result = this.fileRenderer.emitLineCountChange(
lineCount,
this.renderRange
);
if (result != null && this.code != null) {
const { gutterAST, rowCount } = result;
const columns = this.getColumns(this.code);
if (columns != null) {
columns.gutter.innerHTML =
this.fileRenderer.renderPartialHTML(gutterAST);
columns.content.style.gridRow = `span ${rowCount}`;
columns.gutter.style.gridRow = `span ${rowCount}`;
}
}
}

public emitLineAnnotationsChange(
newLineAnnotations: LineAnnotation<LAnnotation>[]
): void {
const previousLineAnnotations = this.lineAnnotations;
const renderRange = this.renderRange;
const result = this.fileRenderer.emitLineAnnotationsChange(
newLineAnnotations,
this.renderRange
);
for (const { element } of this.annotationCache.values()) {
element.remove();
}
this.annotationCache.clear();
this.lineAnnotations = newLineAnnotations;
const hasVisibleAnnotationChange =
hasVisibleLineAnnotation(previousLineAnnotations, renderRange) ||
hasVisibleLineAnnotation(newLineAnnotations, renderRange);
if (result != null && this.code != null && hasVisibleAnnotationChange) {
const { gutterAST, contentAST, rowCount } = result;
const columns = this.getColumns(this.code);
if (columns != null) {
columns.content.innerHTML =
this.fileRenderer.renderPartialHTML(contentAST);
columns.gutter.innerHTML =
this.fileRenderer.renderPartialHTML(gutterAST);
columns.content.style.gridRow = `span ${rowCount}`;
columns.gutter.style.gridRow = `span ${rowCount}`;
this.renderAnnotations();
if (this.fileContainer != null && this.file != null) {
this.editor?.syncFile(
this.fileContainer,
this.file,
this.lineAnnotations,
this.renderRange
);
}
}
}
}

public render({
Expand Down Expand Up @@ -501,6 +588,12 @@ export class File<LAnnotation = undefined> {
this.resizeManager.setup(pre, overflow === 'wrap');
this.renderAnnotations();
this.renderGutterUtility();
this.editor?.syncFile(
fileContainer,
file,
this.lineAnnotations,
nextRenderRange
);
} catch (error: unknown) {
if (disableErrorHandling) {
throw error;
Expand Down
Loading
Loading