Skip to content

Commit

Permalink
Update webview non-content change via messaging instead
Browse files Browse the repository at this point in the history
JennieJi committed Mar 4, 2023
1 parent 88f33c2 commit 76659ec
Showing 4 changed files with 70 additions and 34 deletions.
28 changes: 24 additions & 4 deletions resources/templates/index.html
Original file line number Diff line number Diff line change
@@ -142,7 +142,10 @@
.no-empty .empty {
display: none;
}
{{style}}

.highlight {
background-color: lightyellow;
}
</style>
</header>
<body>
@@ -163,9 +166,6 @@
classList.add(classname);
}
}
window.option = function (value) {
toggleClass(document.getElementById('page'), value);
};
window.onload = function () {
var COLLAPSE_CLASS = 'collapse';
document.getElementById('ast').addEventListener('click', function (e) {
@@ -178,6 +178,26 @@
}
});
};
window.addEventListener('message', ({ data }) => {
if (!Array.isArray(data)) return;
const [action, message] = data;
switch(action) {
case 'SET_OPTION':
document.getElementById('page').className = message.join(' ');
break;
case 'HIGHLIGHT': {
const highlightClassName = 'highlight';
Array.prototype.forEach.call(
document.getElementsByClassName(highlightClassName),
el => el.classList.remove(highlightClassName)
);
message.forEach(line =>
document.getElementsByClassName(`line-${line}`)[0].classList.add(highlightClassName)
);
break;
}
}
});
</script>
</body>
</html>
71 changes: 44 additions & 27 deletions src/astView.ts
Original file line number Diff line number Diff line change
@@ -12,6 +12,11 @@ export type ASTViewOptions = {
sourceType?: ParserOptions['sourceType'];
};

enum ACTION {
SET_OPTIONS = 'SET_OPTIONS',
HIGHLIGHT = 'HIGHLIGHT',
}

class ASTView {
private panel: vscode.WebviewPanel;
private editor: vscode.TextEditor | undefined;
@@ -21,8 +26,12 @@ class ASTView {
sourceType: 'module',
} as ASTViewOptions;

constructor(onDispose?: () => void, options?: ASTViewOptions) {
constructor(onDispose?: () => void, options: ASTViewOptions = {}) {
this.editor = vscode.window.activeTextEditor;
this.options = {
...this.options,
...options
};
this.panel = vscode.window.createWebviewPanel(
'babelAstExplorer',
this.getTitle(),
@@ -31,28 +40,49 @@ class ASTView {
enableScripts: true,
}
);
this.debouncedUpdatePanel = debounce(this.updatePanel, 500);
if (onDispose) {
this.panel.onDidDispose(onDispose);
}
this.update(options);
const textEditorWatcher = vscode.window.onDidChangeTextEditorSelection(() => this.update());
this.debouncedUpdatePanel = debounce(() => this.updatePanel(), 500);
this.updatePanel()
const textEditorWatcher = vscode.window.onDidChangeTextEditorSelection(() => this.highlightSelected());

this.panel.onDidDispose(() => {
textEditorWatcher.dispose();
if (onDispose) {
onDispose();
}
});
}

public update(options?: ASTViewOptions) {
if (options) {
this.options = { ...this.options, ...options };
}
this.debouncedUpdatePanel();
}
public updateOptions(options: ASTViewOptions) {
if (
options.version !== this.options.version ||
options.sourceType !== this.options.sourceType ||
options.plugins?.toString() !== this.options.plugins?.toString()
) {
return this.update(options);
}
if (options.options?.toString() !== this.options.options?.toString()) {
this.options = {
...this.options,
options: options.options
};
this.panel.webview.postMessage([ACTION.SET_OPTIONS, options.options]);
}
}

public updateEditor() {
this.editor = vscode.window.activeTextEditor;
private highlightSelected() {
const lines = new Set<number>();
this.editor?.selections.forEach(selection => {
for (let n = selection.start.line; n <= selection.end.line; n++) {
lines.add(n + 1);
}
});
this.panel.webview.postMessage([ACTION.HIGHLIGHT, Array.from(lines)]);
}

private getTitle() {
@@ -64,23 +94,16 @@ class ASTView {
}
}

private getContent() {
return this.editor?.document.getText() || '';
}

private async updatePanel() {
this.editor = vscode.window.activeTextEditor;
this.panel.title = this.getTitle();
this.panel.webview.html = 'Loading...';
const content = await this.getWebviewContent();
if (content) {
this.panel.webview.html = content;
} else {
this.panel.webview.html = 'Error: empty content';
}
this.panel.webview.html = content ?? 'Error: empty content';
}

private async getWebviewContent() {
const raw = this.getContent();
const raw = this.editor?.document.getText() || '';
const {
version,
sourceType,
@@ -94,16 +117,10 @@ class ASTView {
sourceType,
plugins,
});
const lines = new Set<number>();
this.editor?.selections.forEach(selection => {
for (let n = selection.start.line; n <= selection.end.line; n++) {
lines.add(n + 1);
}
});

return simpleTemplate('index.html', {
ast: await renderAst(ast),
class: options.join(' '),
style: Array.from(lines).map(l => `.line-${l}`).join(',') + '{ background: lightyellow; }'
class: options.join(' ')
});
} catch (e) {
return (e as Error).message;
3 changes: 1 addition & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ export function activate(context: vscode.ExtensionContext) {
});
}
if (astView) {
astView.updateEditor();
astView.update({ plugins });
} else {
astView = new ASTView(
@@ -44,7 +43,7 @@ export function activate(context: vscode.ExtensionContext) {
(options: ASTViewOptions) => {

if (astView) {
astView.update(options);
astView.updateOptions(options);
}
if (optionsView) {
optionsView.update(options);
2 changes: 1 addition & 1 deletion src/renderAst.ts
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ export default async function renderAst(ast: Node): Promise<string> {
type: node?.type || '',
child,
childType,
line: '' + (node?.loc?.start.line || ''),
line: node?.type === 'Program' ? '' : node?.loc?.start.line.toString() ?? '',
colStart: typeof node?.start === 'number' ? '' + node?.start : '',
colEnd: typeof node?.end === 'number' ? '' + node?.end : '',
class: isEmpty ? `empty` : '',

0 comments on commit 76659ec

Please sign in to comment.