diff --git a/README.md b/README.md index 7a0b453..b6c05a7 100644 --- a/README.md +++ b/README.md @@ -265,3 +265,38 @@ Contributions are welcome! Please feel free to submit a Pull Request. ## License MIT License - see the [LICENSE](LICENSE) file for details. + +## VS Code Extension + +### Setup + +1. Clone the repository +2. Install dependencies: + + ```bash + npm install + ``` + +3. Open the repository in VS Code +4. Press `F5` to open a new VS Code window with the extension loaded + +### Usage + +- The extension provides real-time linting during document editing for Markdown files. +- Linting errors are displayed in the VS Code Problems panel. +- You can trigger linting manually via the command palette by running the `Doc Structure Lint: Lint Document` command. + +### Configuration + +- You can configure the template source URI in the VS Code settings. +- The extension supports both `https://` and `file://` schemes for the template source URI. +- If the scheme is omitted, it defaults to `file://`. +- You can specify the template at the document level using frontmatter. + - Required: `template` field specifies the template ID. + - Optional: `template_source` field overrides the global template source. + +### Real-time Linting + +- The extension provides real-time linting during document editing for Markdown files. +- Linting errors are displayed in the VS Code Problems panel as you type. +- The extension uses the `doc-structure-lint` tool to validate the document structure against the specified template. diff --git a/package.json b/package.json index d9032d0..223ded4 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,14 @@ "bin": { "doc-structure-lint": "src/index.js" }, - "main": "src/index.js", + "main": "src/extension.ts", "scripts": { "postinstall": "node src/util/preloadModel.js", "clean": "node src/util/tempDir.js clean", "start": "node src/index.js", "test": "mocha 'src/**/*.test.js'", - "prepare": "husky" + "prepare": "husky", + "build": "tsc -p ./" }, "author": "Manny Silva", "license": "MIT", @@ -25,7 +26,8 @@ "remark-frontmatter": "^5.0.0", "uuid": "^11.0.3", "yaml": "^2.6.1", - "yargs": "^17.7.2" + "yargs": "^17.7.2", + "vscode": "^1.1.37" }, "devDependencies": { "chai": "^5.1.2", diff --git a/src/extension.ts b/src/extension.ts new file mode 100644 index 0000000..afa7f69 --- /dev/null +++ b/src/extension.ts @@ -0,0 +1,59 @@ +import * as vscode from 'vscode'; +import { lintDocument } from './index'; + +export function activate(context: vscode.ExtensionContext) { + const diagnosticCollection = vscode.languages.createDiagnosticCollection('doc-structure-lint'); + + context.subscriptions.push( + vscode.workspace.onDidChangeTextDocument((event) => { + if (event.document.languageId === 'markdown') { + lintAndReport(event.document, diagnosticCollection); + } + }) + ); + + context.subscriptions.push( + vscode.workspace.onDidSaveTextDocument((document) => { + if (document.languageId === 'markdown') { + lintAndReport(document, diagnosticCollection); + } + }) + ); + + context.subscriptions.push( + vscode.commands.registerCommand('doc-structure-lint.lintDocument', () => { + const editor = vscode.window.activeTextEditor; + if (editor && editor.document.languageId === 'markdown') { + lintAndReport(editor.document, diagnosticCollection); + } + }) + ); +} + +async function lintAndReport(document: vscode.TextDocument, diagnosticCollection: vscode.DiagnosticCollection) { + const filePath = document.uri.fsPath; + const templatePath = vscode.workspace.getConfiguration('doc-structure-lint').get('templatePath', './templates.yaml'); + const template = vscode.workspace.getConfiguration('doc-structure-lint').get('template', 'default'); + + try { + const result = await lintDocument({ file: filePath, templatePath, template }); + const diagnostics: vscode.Diagnostic[] = []; + + result.errors.forEach((error) => { + const range = new vscode.Range( + document.positionAt(error.position.start.offset), + document.positionAt(error.position.end.offset) + ); + const diagnostic = new vscode.Diagnostic(range, error.message, vscode.DiagnosticSeverity.Error); + diagnostics.push(diagnostic); + }); + + diagnosticCollection.set(document.uri, diagnostics); + } catch (error) { + vscode.window.showErrorMessage(`Linting failed: ${error.message}`); + } +} + +export function deactivate() { + // Clean up resources if needed +}