feat: introduce archify skill for generating architecture diagrams
- Added a new Archify skill, enabling users to create polished architecture, workflow, sequence, data-flow, and lifecycle diagrams. - Implemented comprehensive functionality including rendering, validation, and delivery of diagrams in various formats. - Integrated a user-friendly command-line interface for generating and previewing diagrams. - Developed supporting files including package.json, LICENSE, and SKILL.md for documentation and licensing. - Added unit tests to ensure reliability and functionality of the new skill. These changes enhance the application by providing a structured approach to visualizing system architecture and workflows, improving user experience and data representation.
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { extractSvgs, parseXml } from './helpers/xml.mjs';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const skillRoot = path.resolve(__dirname, '..');
|
||||
const repoRoot = path.resolve(skillRoot, '..');
|
||||
const artifactRoots = [
|
||||
'archify/examples',
|
||||
'docs',
|
||||
'examples',
|
||||
'experiments',
|
||||
];
|
||||
|
||||
function trackedHtmlArtifacts() {
|
||||
const tracked = spawnSync('git', ['ls-files', '-z', '--', ...artifactRoots], {
|
||||
cwd: repoRoot,
|
||||
encoding: 'buffer',
|
||||
});
|
||||
assert.equal(tracked.status, 0, tracked.stderr.toString());
|
||||
return tracked.stdout.toString()
|
||||
.split('\0')
|
||||
.filter((entry) => entry.endsWith('.html'))
|
||||
.sort();
|
||||
}
|
||||
|
||||
test('artifact SVG extraction follows HTML quoting and preserves SVG document boundaries', () => {
|
||||
const extracted = extractSvgs(`
|
||||
<script>const ignored = '<svg data-node-label></svg>';</script>
|
||||
<template><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1"/></template>
|
||||
<iframe srcdoc='<svg xmlns="http://www.w3.org/2000/svg"><svg viewBox="0 0 1 1"/></svg>'></iframe>
|
||||
`);
|
||||
assert.equal(extracted.direct.length, 1, 'template SVG is markup while script text is not');
|
||||
assert.equal(extracted.embedded.length, 1, 'srcdoc contributes one top-level SVG document');
|
||||
for (const svg of [...extracted.direct, ...extracted.embedded]) assert.doesNotThrow(() => parseXml(svg));
|
||||
|
||||
const inheritedNamespace = extractSvgs(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg><use xlink:href="#icon"/></svg>
|
||||
</svg>
|
||||
`);
|
||||
assert.equal(inheritedNamespace.direct.length, 1, 'nested SVG remains inside its XML document');
|
||||
assert.doesNotThrow(() => parseXml(inheritedNamespace.direct[0]));
|
||||
});
|
||||
|
||||
test('tracked browsable HTML embeds well-formed XML SVG', () => {
|
||||
const artifacts = trackedHtmlArtifacts();
|
||||
const checkoutArtifact = 'examples/checkout-platform-delta.html';
|
||||
assert.ok(artifacts.includes(checkoutArtifact), 'expected the tracked Checkout compare artifact');
|
||||
let checkoutSvgs;
|
||||
|
||||
for (const relative of artifacts) {
|
||||
const html = fs.readFileSync(path.join(repoRoot, relative), 'utf8');
|
||||
const extracted = extractSvgs(html);
|
||||
if (relative === checkoutArtifact) checkoutSvgs = extracted;
|
||||
const svgs = [...extracted.direct, ...extracted.embedded];
|
||||
if (svgs.length === 0) continue;
|
||||
for (const [index, svg] of svgs.entries()) {
|
||||
assert.doesNotThrow(
|
||||
() => parseXml(svg),
|
||||
`${relative}: SVG ${index + 1} must be well-formed XML`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
assert.equal(checkoutSvgs?.direct.length, 1, 'Checkout must contain one comparison SVG');
|
||||
assert.equal(checkoutSvgs?.embedded.length, 2, 'Checkout must retain its base/head SVG snapshots');
|
||||
});
|
||||
|
||||
test('legacy example URLs redirect to the current canonical artifacts', () => {
|
||||
for (const [legacy, canonical] of [
|
||||
['examples/workflow-agent-tool-call.html', 'workflow-agent-tool-call-rendered.html'],
|
||||
['examples/sequence-cache-miss.html', 'sequence-cache-miss-request.html'],
|
||||
]) {
|
||||
const html = fs.readFileSync(path.join(repoRoot, legacy), 'utf8');
|
||||
assert.match(html, new RegExp(`<link rel="canonical" href="${canonical}">`));
|
||||
assert.match(
|
||||
html,
|
||||
new RegExp(`window\\.location\\.replace\\("${canonical}" \\+ window\\.location\\.search \\+ window\\.location\\.hash\\)`),
|
||||
`${legacy} must preserve query parameters and deep-link fragments`,
|
||||
);
|
||||
assert.equal(fs.existsSync(path.join(repoRoot, 'examples', canonical)), true);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user