Skip to content

Commit 31a8360

Browse files
committed
refactor renderer dom typing and line-height handling
1 parent b6a70cf commit 31a8360

14 files changed

Lines changed: 328 additions & 259 deletions

anycode-base/src/cursor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { AnycodeLine, isDiagnosticElement } from './utils';
1+
import { AnycodeLine } from './types';
2+
import { isDiagnosticElement } from './utils';
23

34
export function removeCursor() {
45
const sel = window.getSelection();

anycode-base/src/editor.ts

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
generateCssClasses, addCssToDocument,
1919
findPrevWord, findNextWord,
2020
getCompletionRange, scoreMatches,
21-
isInsideDiagnostic
21+
isFoldElement, isInsideDiagnostic
2222
} from './utils';
2323

2424
import './styles.css';
@@ -57,6 +57,7 @@ export interface EditorState {
5757
codeFoldingEnabled: boolean;
5858
wordHighlightEnabled: boolean;
5959
wordHighlight: WordHighlight | null;
60+
search: Search;
6061
}
6162

6263
export class AnycodeEditor {
@@ -145,6 +146,7 @@ export class AnycodeEditor {
145146
private createDomElements() {
146147
this.container = document.createElement('div');
147148
this.container.className = 'anyeditor';
149+
this.container.style.setProperty('--anycode-line-height', `${this.settings.lineHeight}px`);
148150

149151
this.buttonsColumn = document.createElement('div');
150152
this.buttonsColumn.className = 'buttons';
@@ -157,10 +159,10 @@ export class AnycodeEditor {
157159

158160
this.codeContent = document.createElement('div');
159161
this.codeContent.className = 'code';
160-
this.codeContent.setAttribute("contentEditable", this.readOnly ? "false" : "true");
161-
this.codeContent.setAttribute("spellcheck", "false");
162-
this.codeContent.setAttribute("autocorrect", "off");
163-
this.codeContent.setAttribute("autocapitalize", "off");
162+
this.codeContent.contentEditable = this.readOnly ? "false" : "true";
163+
this.codeContent.spellcheck = false;
164+
(this.codeContent as any).autocorrect = "off";
165+
this.codeContent.autocapitalize = "off";
164166
if (this.readOnly) {
165167
this.container.classList.add('readonly');
166168
}
@@ -248,7 +250,7 @@ export class AnycodeEditor {
248250
this.search.setMatches(matches);
249251
}
250252

251-
this.renderer.renderChanges(this.getEditorState(), this.search);
253+
this.renderer.renderChanges(this.getEditorState());
252254
this.verifyDiffRendering();
253255
}
254256

@@ -529,7 +531,7 @@ export class AnycodeEditor {
529531
requestAnimationFrame(() => {
530532
if (scrollTop !== this.lastScrollTop) {
531533
let state = this.getEditorState();
532-
this.renderer.renderScroll(state, this.search);
534+
this.renderer.renderScroll(state);
533535
this.lastScrollTop = scrollTop;
534536
}
535537
this.needFocus = false
@@ -547,7 +549,7 @@ export class AnycodeEditor {
547549
public onAttach() {
548550
this.restoreScroll();
549551
const state = this.getEditorState();
550-
this.renderer.renderScroll(state, this.search);
552+
this.renderer.renderScroll(state);
551553
this.renderer.renderCursorOrSelection(state);
552554
}
553555

@@ -570,6 +572,7 @@ export class AnycodeEditor {
570572
codeFoldingEnabled: this.codeFoldingEnabled,
571573
wordHighlightEnabled: this.wordHighlightEnabled,
572574
wordHighlight: this.wordHighlight,
575+
search: this.search,
573576
};
574577
}
575578

@@ -582,7 +585,7 @@ export class AnycodeEditor {
582585
}
583586

584587
public render() {
585-
this.renderer.render(this.getEditorState(), this.search);
588+
this.renderer.render(this.getEditorState());
586589
}
587590

588591
public renderCursorOrSelection() {
@@ -618,7 +621,7 @@ export class AnycodeEditor {
618621
gapData.expandDirection,
619622
);
620623
if (expanded) {
621-
this.renderer.render(this.getEditorState(), this.search);
624+
this.renderer.render(this.getEditorState());
622625
this.container.scrollTop = prevScrollTop;
623626
if (!this.readOnly) {
624627
this.codeContent.focus({ preventScroll: true });
@@ -637,19 +640,7 @@ export class AnycodeEditor {
637640
return;
638641
}
639642

640-
const foldToggle = this.codeFoldingEnabled ? (e.target as HTMLElement | null)?.closest('.fold-toggle') as HTMLElement | null : null;
641-
if (foldToggle) {
642-
const line = Number.parseInt(foldToggle.dataset.line ?? '-1', 10);
643-
if (line >= 0) {
644-
e.preventDefault();
645-
e.stopPropagation();
646-
this.toggleFoldAtLine(line);
647-
this.renderer.render(this.getEditorState(), this.search);
648-
if (!this.readOnly) {
649-
this.codeContent.focus({ preventScroll: true });
650-
this.renderer.renderCursorOrSelection(this.getEditorState(), false);
651-
}
652-
}
643+
if (this.handleFoldToggleClick(e)) {
653644
return;
654645
}
655646

@@ -692,6 +683,29 @@ export class AnycodeEditor {
692683
}
693684
}
694685

686+
private handleFoldToggleClick(e: MouseEvent): boolean {
687+
if (!this.codeFoldingEnabled || !(e.target instanceof HTMLElement)) {
688+
return false;
689+
}
690+
691+
const foldToggle = e.target.closest('.fold-toggle');
692+
if (!isFoldElement(foldToggle)) {
693+
return false;
694+
}
695+
696+
e.preventDefault();
697+
e.stopPropagation();
698+
this.toggleFoldAtLine(foldToggle.lineNumber);
699+
this.renderer.render(this.getEditorState());
700+
701+
if (!this.readOnly) {
702+
this.codeContent.focus({ preventScroll: true });
703+
this.renderer.renderCursorOrSelection(this.getEditorState(), false);
704+
}
705+
706+
return true;
707+
}
708+
695709
private async goToDefinition(row: number, col: number): Promise<void> {
696710
if (!this.goToDefinitionProvider) {
697711
console.warn('Go to definition provider not set');
@@ -1252,7 +1266,7 @@ export class AnycodeEditor {
12521266
let matches = this.code.search(this.search.getPattern());
12531267
this.search.setMatches(matches);
12541268
}
1255-
this.renderer.renderChanges(state, this.search);
1269+
this.renderer.renderChanges(state);
12561270
let focused = this.renderer.focus(state);
12571271
this.verifyDiffRendering();
12581272
} else if (offsetChanged || selectionChanged) {
@@ -1399,7 +1413,7 @@ export class AnycodeEditor {
13991413

14001414
this.renderer.closeCompletion();
14011415
this.isCompletionOpen = false;
1402-
this.renderer.renderChanges(this.getEditorState(), this.search);
1416+
this.renderer.renderChanges(this.getEditorState());
14031417
}
14041418

14051419
private handleCompletionKey(event: KeyboardEvent): boolean {
@@ -1613,7 +1627,7 @@ export class AnycodeEditor {
16131627

16141628
this.recomputeDiffs();
16151629

1616-
this.renderer.renderChanges(this.getEditorState(), this.search);
1630+
this.renderer.renderChanges(this.getEditorState());
16171631
this.verifyDiffRendering();
16181632
}
16191633

@@ -1626,7 +1640,7 @@ export class AnycodeEditor {
16261640
void this.initOriginalCode(baseline).then((updated) => {
16271641
if (!this.diffEnabled || !updated) return;
16281642
this.recomputeDiffs();
1629-
this.renderer.render(this.getEditorState(), this.search);
1643+
this.renderer.render(this.getEditorState());
16301644
this.verifyDiffRendering();
16311645
});
16321646
}
@@ -1635,9 +1649,9 @@ export class AnycodeEditor {
16351649

16361650
if (!enabled) {
16371651
this.renderer.clearAllDiffs();
1638-
this.renderer.render(this.getEditorState(), this.search);
1652+
this.renderer.render(this.getEditorState());
16391653
} else {
1640-
this.renderer.render(this.getEditorState(), this.search);
1654+
this.renderer.render(this.getEditorState());
16411655
this.verifyDiffRendering();
16421656
}
16431657
}
@@ -1646,7 +1660,7 @@ export class AnycodeEditor {
16461660
this.focusedDiffEnabled = enabled;
16471661
this.focusedDiffContextLines = Math.max(0, contextLines);
16481662
this.renderer.setFocusedDiffMode(this.focusedDiffEnabled, this.focusedDiffContextLines);
1649-
this.renderer.render(this.getEditorState(), this.search);
1663+
this.renderer.render(this.getEditorState());
16501664
if (this.diffEnabled) {
16511665
this.verifyDiffRendering();
16521666
}
@@ -1656,7 +1670,7 @@ export class AnycodeEditor {
16561670
void this.initOriginalCode(content).then((updated) => {
16571671
if (!this.diffEnabled || !updated) return;
16581672
this.recomputeDiffs();
1659-
this.renderer.render(this.getEditorState(), this.search);
1673+
this.renderer.render(this.getEditorState());
16601674
this.verifyDiffRendering();
16611675
});
16621676
}

anycode-base/src/mouse.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { AnycodeLine, Pos, getLineTextLength, isDiagnosticElement, isInsideDiagnostic } from "./utils";
1+
import { AnycodeLine, Pos } from "./types";
2+
import { getLineTextLength, isDiagnosticElement, isInsideDiagnostic, isSideLineElement } from "./utils";
23

34
export function getPosFromMouse(e: MouseEvent): Pos | null {
45

@@ -30,12 +31,8 @@ function resolvePosition(node: Node, nodeOffset: number): Pos | null {
3031
? node.closest(".bt, .ln, .fd")
3132
: node.parentElement?.closest(".bt, .ln, .fd");
3233

33-
if (sideElement && sideElement instanceof HTMLElement) {
34-
const lineStr = sideElement.getAttribute("data-line");
35-
if (lineStr) {
36-
const row = parseInt(lineStr, 10);
37-
return { row, col: 0 };
38-
}
34+
if (isSideLineElement(sideElement)) {
35+
return { row: sideElement.lineNumber, col: 0 };
3936
}
4037

4138
// corner case, whole row selected

anycode-base/src/renderer/CompletionRenderer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Code } from "../code";
2-
import { AnycodeLine, findNodeAndOffset, findPrevWord } from "../utils";
2+
import { AnycodeLine } from "../types";
3+
import { findNodeAndOffset, findPrevWord } from "../utils";
34
import { Completion, completionKindMap } from "../lsp";
45

56
/**

anycode-base/src/renderer/DiagnosticRenderer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { AnycodeLine, minimize } from "../utils";
1+
import { AnycodeLine } from "../types";
2+
import { minimize } from "../utils";
23

34
export class DiagnosticRenderer {
45
private getDiagnosticSpan(line: AnycodeLine): HTMLSpanElement | null {
@@ -46,8 +47,7 @@ export class DiagnosticRenderer {
4647
const span = document.createElement('span');
4748
span.className = 'diagnostic';
4849
span.textContent = "\u200B" + text;
49-
span.setAttribute('data-diagnostic', 'true');
50-
span.setAttribute('contentEditable', 'false');
50+
span.contentEditable = 'false';
5151

5252
const anchor = this.getInsertAnchor(line);
5353
if (anchor) {

0 commit comments

Comments
 (0)