Skip to content

Commit 8baf207

Browse files
authored
Adds partial codeactions (#13)
1 parent 97e92a9 commit 8baf207

File tree

5 files changed

+79
-8
lines changed

5 files changed

+79
-8
lines changed

client/extension.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ export default class Extension {
2323
...commands(),
2424
this.status,
2525
this.preview,
26+
VSC.commands.registerCommand(
27+
"markdoc.extractPartial",
28+
this.onExtractPartial.bind(this)
29+
),
2630
VSC.commands.registerCommand(
2731
"markdoc.newFileFromTemplate",
2832
this.onNewFileFromTemplate.bind(this)
@@ -173,6 +177,31 @@ export default class Extension {
173177
VSC.window.showTextDocument(doc);
174178
}
175179

180+
async onExtractPartial() {
181+
const editor = VSC.window.activeTextEditor;
182+
if (!editor) return;
183+
184+
const uri = await VSC.window.showSaveDialog({
185+
saveLabel: 'Create',
186+
title: 'Name the new partial',
187+
filters: {'Markdoc': ['md', 'mdoc', 'markdoc', 'markdoc.md']}
188+
});
189+
190+
if (!uri) return;
191+
192+
const client = this.findClient(uri);
193+
if (!client) return;
194+
195+
const path = uri.fsPath.slice(client.uri.fsPath.length + 1);
196+
const partialTag = `{% partial file="${path}" /%}`;
197+
198+
const edit = new VSC.WorkspaceEdit();
199+
const contents = new TextEncoder().encode(editor.document.getText(editor.selection));
200+
edit.createFile(uri, {overwrite: true, contents});
201+
edit.replace(editor.document.uri, editor.selection, partialTag);
202+
VSC.workspace.applyEdit(edit);
203+
}
204+
176205
async onPreview(previewUri: VSC.Uri) {
177206
const uri = previewUri ?? VSC.window.activeTextEditor?.document.uri;
178207
if (!uri) return;

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "Markdoc Extension",
44
"author": "Ryan Paul",
55
"license": "MIT",
6-
"version": "0.0.10",
6+
"version": "0.0.11",
77
"scripts": {
88
"build": "esbuild index.ts --bundle --outdir=dist --sourcemap=linked --external:vscode --platform=node --format=cjs",
99
"build:server": "esbuild server.ts --bundle --outdir=dist --sourcemap=linked --external:vscode --platform=node --format=cjs"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"author": "Ryan Paul",
88
"publisher": "stripe",
99
"license": "MIT",
10-
"version": "0.0.10",
10+
"version": "0.0.11",
1111
"description": "A Markdoc language server and Visual Studio Code extension",
1212
"repository": {
1313
"type": "git",

server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@markdoc/language-server",
3-
"version": "0.0.10",
3+
"version": "0.0.11",
44
"description": "A Markdoc language server",
55
"main": "dist/index.js",
66
"author": "Ryan Paul",

server/plugins/codeaction.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,75 @@ export default class CodeActionProvider {
3232
}
3333
}
3434

35-
findTables(ast: Markdoc.Node, params: LSP.CodeActionParams): LSP.CodeAction[] {
35+
async inlinePartial(uri: string, line: number, file: string): Promise<LSP.WorkspaceEdit | void> {
36+
const ast = this.services.Documents.ast(uri);
37+
if (!ast) return;
38+
39+
for (const node of ast.walk()) {
40+
if (node.tag === 'partial' && node.lines[0] === line && !node.attributes.variables) {
41+
const fullPath = this.services.Scanner.fullPath(file);
42+
const newText = await this.services.Scanner.read(fullPath);
43+
const [start, end] = node.lines;
44+
const range = LSP.Range.create(start, 0, end, 0);
45+
return {changes: {[uri]: [{range, newText}]}};
46+
}
47+
}
48+
}
49+
50+
findActions(ast: Markdoc.Node, params: LSP.CodeActionParams): LSP.CodeAction[] {
3651
const output: LSP.CodeAction[] = [];
3752
const {line} = params.range.start;
3853
const {uri} = params.textDocument;
54+
55+
if (params.range.end.line - params.range.start.line > 3)
56+
output.push({
57+
title: 'Extract content to new partial',
58+
command: LSP.Command.create('Extract Partial', 'markdoc.extractPartial')
59+
});
3960

40-
for (const node of ast.walk())
41-
if (node.type === 'table' && node.lines.includes(line))
61+
for (const node of ast.walk()) {
62+
if (node.type === 'table' && node.lines.includes(line)) {
4263
output.push({
4364
data: {type: 'convertTable', uri, line},
4465
title: 'Convert to Markdoc Table',
4566
});
4667

68+
continue;
69+
}
70+
71+
if (node.tag === 'partial' && node.lines[0] === line && !node.attributes.variables) {
72+
output.push({
73+
data: {type: 'inlinePartial', uri, line, file: node.attributes.file},
74+
title: 'Inline contents of this partial',
75+
});
76+
77+
continue;
78+
}
79+
}
80+
4781
return output;
4882
}
4983

5084
onCodeAction(params: LSP.CodeActionParams): (LSP.CodeAction | LSP.Command)[] {
5185
const ast = this.services.Documents.ast(params.textDocument.uri);
52-
return ast ? this.findTables(ast, params) : [];
86+
return ast ? this.findActions(ast, params) : [];
5387
}
5488

55-
onCodeActionResolve(action: LSP.CodeAction): LSP.CodeAction {
89+
async onCodeActionResolve(action: LSP.CodeAction): Promise<LSP.CodeAction> {
90+
if (!action.data?.type) return action;
91+
5692
if (action.data.type === 'convertTable') {
5793
const {uri, line} = action.data;
5894
const edit = this.convertTable(uri, line);
5995
if (edit) return {...action, edit};
6096
}
6197

98+
if (action.data.type === 'inlinePartial') {
99+
const {uri, line, file} = action.data;
100+
const edit = await this.inlinePartial(uri, line, file);
101+
if (edit) return {...action, edit};
102+
}
103+
62104
return action;
63105
}
64106
}

0 commit comments

Comments
 (0)