VS Code extension that previews Archify diagrams from their JSON sources (live, as you type) and opens rendered Archify HTML in a viewer tab. Bundles the Archify 3.0.1 renderer and runs it on VS Code's Node runtime. Adds validation diagnostics, JSON schema help, source-link navigation, export saving, render-to-file and open-in-browser commands. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
78 lines
3.2 KiB
TypeScript
78 lines
3.2 KiB
TypeScript
import { execFile } from 'node:child_process';
|
|
import path from 'node:path';
|
|
import * as vscode from 'vscode';
|
|
import { RuntimeOptions } from './renderer';
|
|
import { ViewerTheme } from './webviewHtml';
|
|
|
|
let output: vscode.LogOutputChannel | undefined;
|
|
|
|
export function log(): vscode.LogOutputChannel {
|
|
output ??= vscode.window.createOutputChannel('Archify', { log: true });
|
|
return output;
|
|
}
|
|
|
|
const gitRoots = new Map<string, Promise<string | undefined>>();
|
|
|
|
function gitTopLevel(dir: string): Promise<string | undefined> {
|
|
let pending = gitRoots.get(dir);
|
|
if (!pending) {
|
|
pending = new Promise((resolve) => {
|
|
execFile('git', ['rev-parse', '--show-toplevel'], { cwd: dir, timeout: 10_000 }, (error, stdout) => {
|
|
resolve(error ? undefined : path.resolve(stdout.trim()));
|
|
});
|
|
});
|
|
gitRoots.set(dir, pending);
|
|
}
|
|
return pending;
|
|
}
|
|
|
|
export function clearGitRootCache(): void {
|
|
gitRoots.clear();
|
|
}
|
|
|
|
/** The checkout used to verify source evidence for a file, if any. */
|
|
export async function repoRootFor(uri: vscode.Uri | undefined): Promise<string | undefined> {
|
|
const configured = vscode.workspace.getConfiguration('archify', uri).get<string>('repoRoot', '').trim();
|
|
if (configured) {
|
|
if (path.isAbsolute(configured)) return configured;
|
|
const folder = (uri && vscode.workspace.getWorkspaceFolder(uri)) ?? vscode.workspace.workspaceFolders?.[0];
|
|
return folder ? path.resolve(folder.uri.fsPath, configured) : path.resolve(configured);
|
|
}
|
|
if (!uri || uri.scheme !== 'file') return undefined;
|
|
return gitTopLevel(path.dirname(uri.fsPath));
|
|
}
|
|
|
|
export async function runtimeFor(context: vscode.ExtensionContext, uri: vscode.Uri | undefined): Promise<RuntimeOptions> {
|
|
const config = vscode.workspace.getConfiguration('archify', uri);
|
|
const nodePath = config.get<string>('nodePath', '').trim();
|
|
const quality = config.get<string>('quality', '');
|
|
return {
|
|
cliPath: context.asAbsolutePath(path.join('vendor', 'archify', 'bin', 'archify.mjs')),
|
|
nodePath: nodePath || process.execPath,
|
|
runAsNode: !nodePath,
|
|
workDir: path.join(context.globalStorageUri.fsPath, 'renders'),
|
|
quality: quality || undefined,
|
|
repoRoot: await repoRootFor(uri),
|
|
log: (line) => log().debug(line),
|
|
};
|
|
}
|
|
|
|
export function evidenceMode(uri: vscode.Uri | undefined): 'fallback' | 'strict' {
|
|
return vscode.workspace.getConfiguration('archify', uri).get<'fallback' | 'strict'>('sourceEvidence', 'fallback');
|
|
}
|
|
|
|
export function viewerTheme(): ViewerTheme {
|
|
const setting = vscode.workspace.getConfiguration('archify').get<string>('theme', 'vscode');
|
|
if (setting === 'dark' || setting === 'light') return setting;
|
|
if (setting === 'diagram') return undefined;
|
|
const kind = vscode.window.activeColorTheme.kind;
|
|
return kind === vscode.ColorThemeKind.Light || kind === vscode.ColorThemeKind.HighContrastLight ? 'light' : 'dark';
|
|
}
|
|
|
|
/** Current text of a document: the open editor buffer, else the file on disk. */
|
|
export async function readText(uri: vscode.Uri): Promise<string> {
|
|
const open = vscode.workspace.textDocuments.find((doc) => doc.uri.toString() === uri.toString());
|
|
if (open) return open.getText();
|
|
return new TextDecoder('utf-8').decode(await vscode.workspace.fs.readFile(uri));
|
|
}
|