Skip to content

Commit 71d1aba

Browse files
committed
refactor: decorationManager
1 parent b8919f1 commit 71d1aba

File tree

5 files changed

+244
-222
lines changed

5 files changed

+244
-222
lines changed

src/decoration-manager.ts

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import * as vscode from "vscode";
2+
import { genMarkdownString, getColorTokenValue } from "./utils";
3+
4+
export default class DecorationManager {
5+
private activeEditor: vscode.TextEditor | undefined;
6+
private fullToken: any;
7+
private fileDecorationMap: Map<
8+
string,
9+
Map<number, vscode.TextEditorDecorationType[]>
10+
>;
11+
private timeout: NodeJS.Timer | undefined = undefined;
12+
private fileName: string = "";
13+
private fileLineCount: number = 0;
14+
15+
constructor($activeEditor: vscode.TextEditor | undefined, $fullToken: any) {
16+
this.activeEditor = $activeEditor;
17+
this.fullToken = $fullToken;
18+
this.fileDecorationMap = new Map();
19+
}
20+
21+
setActiveEditor(editor: vscode.TextEditor) {
22+
this.activeEditor = editor;
23+
this.fileName = editor.document.fileName;
24+
this.fileLineCount = editor.document.lineCount;
25+
}
26+
27+
triggerUpdateDecorations(
28+
throttle: boolean = false,
29+
isEdit: boolean = false,
30+
startLine?: number,
31+
endLine?: number
32+
) {
33+
console.log("fileName", this.fileName);
34+
if (!isEdit) {
35+
if (this.fileDecorationMap.has(this.fileName)) {
36+
this.clearCurrentFileDecoration();
37+
this.fileDecorationMap.set(this.fileName, new Map());
38+
}
39+
}
40+
41+
if (this.timeout) {
42+
clearTimeout(this.timeout);
43+
this.timeout = undefined;
44+
}
45+
46+
if (throttle) {
47+
this.timeout = setTimeout(() => {
48+
this.setupDecorations(startLine, endLine);
49+
}, 500);
50+
} else {
51+
this.setupDecorations(startLine, endLine);
52+
}
53+
}
54+
55+
setupDecorations(startLine?: number, endLine?: number) {
56+
if (startLine && endLine) {
57+
console.log("editing", startLine, endLine);
58+
const currentLineCount = this.activeEditor!.document.lineCount;
59+
const diffLine = currentLineCount - this.fileLineCount;
60+
console.log("diffLine", diffLine);
61+
62+
if (diffLine < 0) {
63+
const lines = this.getLines(startLine, endLine);
64+
return this.clearCurrentFileDecoration(lines);
65+
}
66+
67+
if (diffLine === 0) {
68+
this.clearCurrentFileDecoration([startLine]);
69+
}
70+
}
71+
72+
this.setDecorations();
73+
}
74+
75+
setDecorations() {
76+
console.log("!!!!!!updating!!!!!");
77+
const text = this.activeEditor!.document.getText();
78+
const fullTokenKeys = Object.keys(this.fullToken);
79+
const lineDecorationMap = new Map<
80+
number,
81+
vscode.TextEditorDecorationType[]
82+
>();
83+
84+
if (!this.fileDecorationMap.has(this.fileName)) {
85+
this.fileDecorationMap.set(this.fileName, new Map());
86+
}
87+
88+
fullTokenKeys.forEach((key: string) => {
89+
const regEx = new RegExp(`\\b(${key})\\b(?!-)`, "g");
90+
let match;
91+
92+
while ((match = regEx.exec(text))) {
93+
const currentLine = this.activeEditor!.document.positionAt(
94+
match.index
95+
).line;
96+
97+
this.setDecoration(match, key, lineDecorationMap);
98+
}
99+
});
100+
101+
this.fileDecorationMap.set(this.fileName, lineDecorationMap);
102+
console.log(this.fileDecorationMap);
103+
}
104+
105+
clearCurrentFileDecoration(lines?: number[]) {
106+
const lineDecorationMapItem = this.fileDecorationMap.get(this.fileName);
107+
108+
if (lineDecorationMapItem) {
109+
if (lines) {
110+
lines.forEach((line) => {
111+
console.log("dispose line", line);
112+
lineDecorationMapItem.get(line)?.forEach(this.dispose);
113+
});
114+
} else {
115+
lineDecorationMapItem.forEach((value) => {
116+
value.forEach(this.dispose);
117+
});
118+
}
119+
}
120+
}
121+
122+
dispose(disposable: vscode.TextEditorDecorationType) {
123+
disposable.dispose();
124+
}
125+
126+
getLines(start: number, end: number): number[] {
127+
const result: number[] = [];
128+
129+
if (start > end) {
130+
return [];
131+
}
132+
133+
for (let i = start; i <= end; i++) {
134+
result.push(i);
135+
}
136+
137+
return result;
138+
}
139+
140+
setDecoration(
141+
match: RegExpExecArray,
142+
key: string,
143+
lineDecorationMap: Map<number, vscode.TextEditorDecorationType[]>
144+
) {
145+
const valueDecorations: vscode.DecorationOptions[] = [];
146+
const startPos = this.activeEditor!.document.positionAt(match.index);
147+
const endPos = this.activeEditor!.document.positionAt(
148+
match.index + match[0].length
149+
);
150+
const currentLine = startPos.line;
151+
const value = String(this.fullToken[key]);
152+
const colorSpan = genMarkdownString(value);
153+
const markDownString = new vscode.MarkdownString(
154+
`<h3>antd design token: ${match[0]}</h3>${colorSpan}<code>${value}</code><br></br>`
155+
);
156+
markDownString.supportHtml = true;
157+
markDownString.isTrusted = true;
158+
159+
const decoration = {
160+
range: new vscode.Range(startPos, endPos),
161+
hoverMessage: markDownString,
162+
};
163+
164+
const colorValue = getColorTokenValue(this.fullToken[key]);
165+
valueDecorations.push(decoration);
166+
167+
const decorationType = vscode.window.createTextEditorDecorationType({
168+
after: {
169+
contentText: colorValue ? `**` : `${String(this.fullToken[key])}`,
170+
backgroundColor: colorValue || "",
171+
margin: "0 0 0 5px;",
172+
color: colorValue || "#b37feb",
173+
fontWeight: "bolder",
174+
},
175+
});
176+
177+
const lineValue = lineDecorationMap.get(currentLine);
178+
lineDecorationMap.set(
179+
currentLine,
180+
lineValue ? lineValue.concat([decorationType]) : [decorationType]
181+
);
182+
// console.log("setDecorations", currentLine);
183+
this.activeEditor!.setDecorations(decorationType, valueDecorations);
184+
}
185+
}

0 commit comments

Comments
 (0)