Skip to content

Commit 815f159

Browse files
authored
Adds table converter code action (#9)
1 parent 9f3b1de commit 815f159

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

server/plugins/codeaction.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as LSP from "vscode-languageserver/node";
2+
import * as Markdoc from "@markdoc/markdoc";
3+
4+
import type { Config, ServiceInstances } from "../types";
5+
6+
export default class CodeActionProvider {
7+
constructor(
8+
protected config: Config,
9+
protected connection: LSP.Connection,
10+
protected services: ServiceInstances
11+
) {
12+
connection.onCodeAction(this.onCodeAction.bind(this));
13+
}
14+
15+
register(registration: LSP.BulkRegistration) {
16+
registration.add(LSP.CodeActionRequest.type, {documentSelector: null});
17+
}
18+
19+
findTables(ast: Markdoc.Node, params: LSP.CodeActionParams): LSP.Command[] {
20+
const output: LSP.Command[] = [];
21+
const {line} = params.range.start;
22+
const {uri} = params.textDocument;
23+
24+
for (const node of ast.walk())
25+
if (node.type === 'table' && node.lines.includes(line))
26+
output.push({
27+
command: 'markdoc.convertTable',
28+
title: 'Convert to Markdoc Table',
29+
arguments: [uri, line]
30+
});
31+
32+
return output;
33+
}
34+
35+
onCodeAction(params: LSP.CodeActionParams): (LSP.CodeAction | LSP.Command)[] {
36+
const ast = this.services.Documents.ast(params.textDocument.uri);
37+
return ast ? this.findTables(ast, params) : [];
38+
}
39+
}

server/plugins/formatting.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ function mockDoc(content: string) {
3131

3232
test("formatting provider", async (t) => {
3333
// @ts-expect-error
34-
const provider = new FormattingProvider({}, mockConnection, {});
34+
const provider = new FormattingProvider({}, mockConnection, {Commands: {add(...args: any) {}}});
3535

3636
await t.test("simple full-text formatting", () => {
3737
const doc = mockDoc(example1);
38-
// @ts-expect-error
3938
const [output] = provider.formatRange(doc);
4039
assert.strictEqual(output.newText.trim(), example1Formatted.trim());
4140
});

server/plugins/formatting.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default class FormattingProvider {
1515
this.tokenizer = new Markdoc.Tokenizer(config.markdoc ?? {});
1616
connection.onDocumentFormatting(this.onDocumentFormatting.bind(this));
1717
connection.onDocumentRangeFormatting(this.onRangeFormatting.bind(this));
18+
services.Commands.add('markdoc.convertTable', this.convertTable.bind(this));
1819
}
1920

2021
register(registration: LSP.BulkRegistration) {
@@ -26,8 +27,26 @@ export default class FormattingProvider {
2627
documentSelector: null,
2728
});
2829
}
30+
31+
convertTable(uri: string, line: number) {
32+
const ast = this.services.Documents.ast(uri);
33+
if (!ast) return;
2934

30-
protected formatRange(doc: TextDocument, range?: LSP.Range) {
35+
for (const node of ast.walk())
36+
if (node.type === 'table' && node.lines.includes(line)) {
37+
const content = new Markdoc.Ast.Node('tag', {}, [node], 'table');
38+
const newText = Markdoc.format(content);
39+
const [start, end] = node.lines;
40+
const range = LSP.Range.create(start, 0, end + 1, 0);
41+
42+
const wschange = new LSP.WorkspaceChange();
43+
const edit = wschange.getTextEditChange(uri);
44+
edit.replace(range, newText);
45+
this.connection.workspace.applyEdit(wschange.edit);
46+
}
47+
}
48+
49+
formatRange(doc: TextDocument, range?: LSP.Range) {
3150
const actualRange = range
3251
? LSP.Range.create(range.start.line, 0, range.end.line + 1, 0)
3352
: LSP.Range.create(0, 0, doc.lineCount, 0);

server/plugins/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import CodeActionProvider from "./codeaction";
12
import CompletionProvider from "./completion";
23
import DefinitionProvider from "./definition";
34
import DependenciesProvider from "./dependencies";
@@ -10,6 +11,7 @@ import ValidationProvider from "./validation";
1011
import Watch from "./watch";
1112

1213
export {
14+
CodeActionProvider,
1315
CompletionProvider,
1416
DefinitionProvider,
1517
DependenciesProvider,

0 commit comments

Comments
 (0)