pdf_signature/tool/gen_view_wireframe_md.dart

116 lines
3.6 KiB
Dart

// The script will
// 1. Copy `docs/wireframe.md` to `docs/.wireframe.md`.
// 2. In `docs/.wireframe.md`, replace all `*.excalidraw` paths (excluding `*.excalidraw.svg`)
// to use the `.svg` extension.
// 3. Export `*.excalidraw` files to svg `*.svg` by
// `npx --no-install excalidraw-to-svg {file_path}.excalidraw`.
import 'dart:io';
void main(List<String> args) async {
final cwd = Directory.current;
final docsDir = Directory('${cwd.path}/docs');
final sourceMd = File('${docsDir.path}/wireframe.md');
final targetMd = File('${docsDir.path}/.wireframe.md');
if (!await docsDir.exists()) {
stderr.writeln('docs directory not found at: ${docsDir.path}');
exitCode = 1;
return;
}
if (!await sourceMd.exists()) {
stderr.writeln('Source markdown not found: ${sourceMd.path}');
exitCode = 1;
return;
}
// 1) Copy wireframe.md to .wireframe.md (overwrite to keep it up-to-date)
stdout.writeln('Copying ${sourceMd.path} -> ${targetMd.path}');
await targetMd.writeAsBytes(await sourceMd.readAsBytes(), flush: true);
// 2) Replace *.excalidraw (not already followed by .svg) with *.svg in the copied markdown
final content = await targetMd.readAsString();
final replaced = content.replaceAll(RegExp(r"\.excalidraw(?!\.svg)"), '.svg');
if (replaced != content) {
stdout.writeln('Updating links in ${targetMd.path} to use .svg');
await targetMd.writeAsString(replaced);
} else {
stdout.writeln('No link updates needed in ${targetMd.path}');
}
// 3) Find all *.excalidraw files under docs and export to *.svg using excalidraw-to-svg
stdout.writeln('Scanning for .excalidraw assets under ${docsDir.path}');
final excalidrawFiles = <File>[];
await for (final entity in docsDir.list(
recursive: true,
followLinks: false,
)) {
if (entity is File && entity.path.endsWith('.excalidraw')) {
excalidrawFiles.add(entity);
}
}
if (excalidrawFiles.isEmpty) {
stdout.writeln('No .excalidraw files found. Done.');
return;
}
// Verify npx availability; if missing, skip export with a clear message.
bool hasNpx = false;
try {
final npxCheck = await Process.run(
'npx',
['--version'],
runInShell: true,
workingDirectory: cwd.path,
);
hasNpx = npxCheck.exitCode == 0;
} catch (_) {
hasNpx = false;
}
if (!hasNpx) {
stderr.writeln(
'npx not found. Skipping SVG export. Install Node.js (npx) and ensure excalidraw-to-svg is available locally.',
);
return;
}
int exported = 0;
for (final src in excalidrawFiles) {
final destPath = src.path.replaceFirst(RegExp(r'\.excalidraw$'), '.svg');
final dest = File(destPath);
// Skip if up-to-date
if (await dest.exists()) {
try {
final srcStat = await src.stat();
final destStat = await dest.stat();
if (!srcStat.modified.isAfter(destStat.modified)) {
stdout.writeln('Skip (up-to-date): ${dest.path}');
continue;
}
} catch (_) {
// If stats fail, proceed to export
}
}
stdout.writeln('Exporting to SVG via excalidraw-to-svg: ${src.path}');
final result = await Process.run(
'npx',
['--no-install', 'excalidraw-to-svg', src.path],
runInShell: true,
workingDirectory: cwd.path,
);
if (result.exitCode == 0) {
stdout.writeln('Exported: ${dest.path}');
exported++;
} else {
stderr.writeln(
'Failed to export ${src.path} -> ${dest.path}\n${result.stderr}\n${result.stdout}',
);
}
}
stdout.writeln('Completed. ${exported} file(s) exported.');
}