@unovis/mcp 1.7.0-mcp.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +193 -0
- package/README.md +154 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +109 -0
- package/dist/cli.js.map +1 -0
- package/dist/codegen/index.d.ts +14 -0
- package/dist/codegen/index.js +346 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/env/bbox.d.ts +13 -0
- package/dist/env/bbox.js +335 -0
- package/dist/env/bbox.js.map +1 -0
- package/dist/env/canvas.d.ts +9 -0
- package/dist/env/canvas.js +55 -0
- package/dist/env/canvas.js.map +1 -0
- package/dist/env/computed-style.d.ts +38 -0
- package/dist/env/computed-style.js +186 -0
- package/dist/env/computed-style.js.map +1 -0
- package/dist/env/fonts.d.ts +3 -0
- package/dist/env/fonts.js +103 -0
- package/dist/env/fonts.js.map +1 -0
- package/dist/env/index.d.ts +13 -0
- package/dist/env/index.js +121 -0
- package/dist/env/index.js.map +1 -0
- package/dist/env/raf-queue.d.ts +23 -0
- package/dist/env/raf-queue.js +51 -0
- package/dist/env/raf-queue.js.map +1 -0
- package/dist/env/size.d.ts +9 -0
- package/dist/env/size.js +30 -0
- package/dist/env/size.js.map +1 -0
- package/dist/html/document.d.ts +16 -0
- package/dist/html/document.js +95 -0
- package/dist/html/document.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/recipes/area.d.ts +66 -0
- package/dist/recipes/area.js +76 -0
- package/dist/recipes/area.js.map +1 -0
- package/dist/recipes/bar.d.ts +67 -0
- package/dist/recipes/bar.js +69 -0
- package/dist/recipes/bar.js.map +1 -0
- package/dist/recipes/boxplot.d.ts +64 -0
- package/dist/recipes/boxplot.js +89 -0
- package/dist/recipes/boxplot.js.map +1 -0
- package/dist/recipes/chord.d.ts +41 -0
- package/dist/recipes/chord.js +72 -0
- package/dist/recipes/chord.js.map +1 -0
- package/dist/recipes/choropleth-regions.d.ts +49 -0
- package/dist/recipes/choropleth-regions.js +521 -0
- package/dist/recipes/choropleth-regions.js.map +1 -0
- package/dist/recipes/choropleth.d.ts +27 -0
- package/dist/recipes/choropleth.js +86 -0
- package/dist/recipes/choropleth.js.map +1 -0
- package/dist/recipes/donut.d.ts +25 -0
- package/dist/recipes/donut.js +51 -0
- package/dist/recipes/donut.js.map +1 -0
- package/dist/recipes/graph.d.ts +55 -0
- package/dist/recipes/graph.js +132 -0
- package/dist/recipes/graph.js.map +1 -0
- package/dist/recipes/heatmap.d.ts +21 -0
- package/dist/recipes/heatmap.js +79 -0
- package/dist/recipes/heatmap.js.map +1 -0
- package/dist/recipes/index.d.ts +5 -0
- package/dist/recipes/index.js +35 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/line.d.ts +69 -0
- package/dist/recipes/line.js +64 -0
- package/dist/recipes/line.js.map +1 -0
- package/dist/recipes/nested-donut.d.ts +22 -0
- package/dist/recipes/nested-donut.js +47 -0
- package/dist/recipes/nested-donut.js.map +1 -0
- package/dist/recipes/radial-bar.d.ts +25 -0
- package/dist/recipes/radial-bar.js +53 -0
- package/dist/recipes/radial-bar.js.map +1 -0
- package/dist/recipes/sankey.d.ts +41 -0
- package/dist/recipes/sankey.js +61 -0
- package/dist/recipes/sankey.js.map +1 -0
- package/dist/recipes/scatter.d.ts +68 -0
- package/dist/recipes/scatter.js +75 -0
- package/dist/recipes/scatter.js.map +1 -0
- package/dist/recipes/shared.d.ts +144 -0
- package/dist/recipes/shared.js +212 -0
- package/dist/recipes/shared.js.map +1 -0
- package/dist/recipes/timeline.d.ts +31 -0
- package/dist/recipes/timeline.js +123 -0
- package/dist/recipes/timeline.js.map +1 -0
- package/dist/recipes/treemap.d.ts +19 -0
- package/dist/recipes/treemap.js +43 -0
- package/dist/recipes/treemap.js.map +1 -0
- package/dist/recipes/types.d.ts +16 -0
- package/dist/recipes/types.js +2 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/render/headless.d.ts +62 -0
- package/dist/render/headless.js +158 -0
- package/dist/render/headless.js.map +1 -0
- package/dist/render/materialize.d.ts +35 -0
- package/dist/render/materialize.js +160 -0
- package/dist/render/materialize.js.map +1 -0
- package/dist/render/mutex.d.ts +9 -0
- package/dist/render/mutex.js +14 -0
- package/dist/render/mutex.js.map +1 -0
- package/dist/render/rasterize.d.ts +10 -0
- package/dist/render/rasterize.js +29 -0
- package/dist/render/rasterize.js.map +1 -0
- package/dist/render/renderer.d.ts +21 -0
- package/dist/render/renderer.js +66 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/render/spec.d.ts +95 -0
- package/dist/render/spec.js +15 -0
- package/dist/render/spec.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +44 -0
- package/dist/server.js.map +1 -0
- package/dist/svg/collect-css.d.ts +14 -0
- package/dist/svg/collect-css.js +53 -0
- package/dist/svg/collect-css.js.map +1 -0
- package/dist/svg/css-vars.d.ts +17 -0
- package/dist/svg/css-vars.js +64 -0
- package/dist/svg/css-vars.js.map +1 -0
- package/dist/svg/header.d.ts +8 -0
- package/dist/svg/header.js +81 -0
- package/dist/svg/header.js.map +1 -0
- package/dist/svg/ids.d.ts +12 -0
- package/dist/svg/ids.js +94 -0
- package/dist/svg/ids.js.map +1 -0
- package/dist/svg/postprocess.d.ts +41 -0
- package/dist/svg/postprocess.js +135 -0
- package/dist/svg/postprocess.js.map +1 -0
- package/dist/tools/register.d.ts +12 -0
- package/dist/tools/register.js +127 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/widget/bundle.js +1777 -0
- package/dist/widget/bundle.meta.json +3 -0
- package/dist/widget/entry.d.ts +34 -0
- package/dist/widget/entry.js +118 -0
- package/dist/widget/entry.js.map +1 -0
- package/dist/widget/interactions.d.ts +14 -0
- package/dist/widget/interactions.js +151 -0
- package/dist/widget/interactions.js.map +1 -0
- package/dist/widget/unovis-slim.d.ts +33 -0
- package/dist/widget/unovis-slim.js +34 -0
- package/dist/widget/unovis-slim.js.map +1 -0
- package/docs/README.md +56 -0
- package/docs/architecture.md +158 -0
- package/docs/chart-spec.md +148 -0
- package/docs/getting-started.md +175 -0
- package/docs/interactive.md +125 -0
- package/docs/output-types.md +170 -0
- package/docs/programmatic.md +234 -0
- package/docs/tools.md +273 -0
- package/docs/troubleshooting.md +140 -0
- package/fonts/README.md +19 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computed-style.js","sourceRoot":"","sources":["../../src/env/computed-style.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** Inter font provisioning.
|
|
2
|
+
*
|
|
3
|
+
* Unovis defaults to the Inter font stack, and text measurement drives label
|
|
4
|
+
* trimming, wrapping and axis margins — measuring with the same font the
|
|
5
|
+
* viewer renders keeps geometry faithful. Fonts are resolved in order:
|
|
6
|
+
*
|
|
7
|
+
* 1. `UNOVIS_MCP_FONTS_DIR` (explicit directory of font files)
|
|
8
|
+
* 2. the package's own `fonts/` directory (manually added / bundled)
|
|
9
|
+
* 3. a user-level cache, populated once by downloading the official Inter
|
|
10
|
+
* release (pinned version + SHA-256 verified) and extracting four static
|
|
11
|
+
* TTF faces + the OFL license
|
|
12
|
+
*
|
|
13
|
+
* The download is best-effort: offline environments (or
|
|
14
|
+
* `UNOVIS_MCP_NO_DOWNLOAD=1`) fall back to system fonts with a one-line
|
|
15
|
+
* stderr note — rendering never fails because of fonts.
|
|
16
|
+
*/
|
|
17
|
+
import { createHash } from 'node:crypto';
|
|
18
|
+
import { mkdirSync, readdirSync, writeFileSync, renameSync, rmSync } from 'node:fs';
|
|
19
|
+
import { tmpdir, homedir } from 'node:os';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
import { fileURLToPath } from 'node:url';
|
|
22
|
+
import { unzipSync } from 'fflate';
|
|
23
|
+
const INTER_VERSION = '4.1';
|
|
24
|
+
const INTER_URL = `https://github.com/rsms/inter/releases/download/v${INTER_VERSION}/Inter-${INTER_VERSION}.zip`;
|
|
25
|
+
const INTER_SHA256 = '9883fdd4a49d4fb66bd8177ba6625ef9a64aa45899767dde3d36aa425756b11e';
|
|
26
|
+
const DOWNLOAD_TIMEOUT_MS = 60_000;
|
|
27
|
+
/** Faces used by chart text: Regular (labels), Medium (ticks, weight 500),
|
|
28
|
+
* SemiBold (titles), Bold */
|
|
29
|
+
const FACES = ['Inter-Regular.ttf', 'Inter-Medium.ttf', 'Inter-SemiBold.ttf', 'Inter-Bold.ttf'];
|
|
30
|
+
const LICENSE_ENTRY = 'LICENSE.txt';
|
|
31
|
+
const hasFontFiles = (dir) => {
|
|
32
|
+
try {
|
|
33
|
+
return readdirSync(dir).some(f => /\.(ttf|otf|woff2?)$/i.test(f));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
function cacheDir() {
|
|
40
|
+
const base = process.env.XDG_CACHE_HOME || join(homedir(), '.cache');
|
|
41
|
+
return join(base, 'unovis-mcp', 'fonts', `inter-${INTER_VERSION}`);
|
|
42
|
+
}
|
|
43
|
+
async function downloadInter(targetDir) {
|
|
44
|
+
const response = await fetch(INTER_URL, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS), redirect: 'follow' });
|
|
45
|
+
if (!response.ok)
|
|
46
|
+
throw new Error(`HTTP ${response.status} for ${INTER_URL}`);
|
|
47
|
+
const zip = new Uint8Array(await response.arrayBuffer());
|
|
48
|
+
const digest = createHash('sha256').update(zip).digest('hex');
|
|
49
|
+
if (digest !== INTER_SHA256)
|
|
50
|
+
throw new Error(`checksum mismatch for ${INTER_URL}: ${digest}`);
|
|
51
|
+
const wanted = new Set([...FACES.map(f => `extras/ttf/${f}`), LICENSE_ENTRY]);
|
|
52
|
+
const entries = unzipSync(zip, { filter: file => wanted.has(file.name) });
|
|
53
|
+
const missing = [...wanted].filter(name => !entries[name]);
|
|
54
|
+
if (missing.length)
|
|
55
|
+
throw new Error(`entries missing from Inter archive: ${missing.join(', ')}`);
|
|
56
|
+
// Extract to a temp dir and move into place so a killed process can't
|
|
57
|
+
// leave a half-populated cache behind
|
|
58
|
+
const staging = join(tmpdir(), `unovis-mcp-fonts-${process.pid}`);
|
|
59
|
+
rmSync(staging, { recursive: true, force: true });
|
|
60
|
+
mkdirSync(staging, { recursive: true });
|
|
61
|
+
for (const [name, data] of Object.entries(entries)) {
|
|
62
|
+
writeFileSync(join(staging, name.split('/').pop()), data);
|
|
63
|
+
}
|
|
64
|
+
mkdirSync(join(targetDir, '..'), { recursive: true });
|
|
65
|
+
rmSync(targetDir, { recursive: true, force: true });
|
|
66
|
+
renameSync(staging, targetDir);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
let ensurePromise;
|
|
70
|
+
/** Resolve a directory containing font files for text measurement, or
|
|
71
|
+
* undefined when none is available (system-font fallback). */
|
|
72
|
+
export function ensureFontsDir() {
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
74
|
+
if (!ensurePromise)
|
|
75
|
+
ensurePromise = resolveFontsDir();
|
|
76
|
+
return ensurePromise;
|
|
77
|
+
}
|
|
78
|
+
async function resolveFontsDir() {
|
|
79
|
+
const explicit = process.env.UNOVIS_MCP_FONTS_DIR;
|
|
80
|
+
if (explicit) {
|
|
81
|
+
if (hasFontFiles(explicit))
|
|
82
|
+
return explicit;
|
|
83
|
+
console.error(`unovis-mcp: UNOVIS_MCP_FONTS_DIR has no font files: ${explicit}`);
|
|
84
|
+
}
|
|
85
|
+
const packageFonts = fileURLToPath(new URL('../../fonts', import.meta.url));
|
|
86
|
+
if (hasFontFiles(packageFonts))
|
|
87
|
+
return packageFonts;
|
|
88
|
+
const cache = cacheDir();
|
|
89
|
+
if (hasFontFiles(cache))
|
|
90
|
+
return cache;
|
|
91
|
+
if (process.env.UNOVIS_MCP_NO_DOWNLOAD)
|
|
92
|
+
return undefined;
|
|
93
|
+
try {
|
|
94
|
+
await downloadInter(cache);
|
|
95
|
+
console.error(`unovis-mcp: downloaded Inter ${INTER_VERSION} (SIL OFL 1.1) to ${cache}`);
|
|
96
|
+
return cache;
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
console.error(`unovis-mcp: Inter download skipped (${e instanceof Error ? e.message : e}) — using system fonts for text measurement`);
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/env/fonts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DOMWindow } from 'jsdom';
|
|
2
|
+
import { RafQueue } from './raf-queue.js';
|
|
3
|
+
import type { VarMaps } from './computed-style.js';
|
|
4
|
+
export { defineElementSize } from './size.js';
|
|
5
|
+
export type UnovisLib = typeof import('@unovis/ts');
|
|
6
|
+
export interface RenderEnv {
|
|
7
|
+
window: DOMWindow;
|
|
8
|
+
document: Document;
|
|
9
|
+
lib: UnovisLib;
|
|
10
|
+
raf: RafQueue;
|
|
11
|
+
varMaps: VarMaps;
|
|
12
|
+
}
|
|
13
|
+
export declare function getRenderEnv(): Promise<RenderEnv>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/** Headless rendering environment for @unovis/ts.
|
|
2
|
+
*
|
|
3
|
+
* Creates a single shared jsdom window, installs every browser API the
|
|
4
|
+
* library needs (in the right order — some are captured at module load),
|
|
5
|
+
* and only then dynamically imports '@unovis/ts'. Import order matters:
|
|
6
|
+
*
|
|
7
|
+
* - emotion inserts real <style> tags only if `document` exists at import
|
|
8
|
+
* - utils/text-measure snapshots a canvas 2D context at module scope
|
|
9
|
+
* - d3-timer binds `window.requestAnimationFrame` at module load
|
|
10
|
+
*/
|
|
11
|
+
import { JSDOM } from 'jsdom';
|
|
12
|
+
import { RafQueue } from './raf-queue.js';
|
|
13
|
+
import { installCanvasHook, registerFontsFromDir } from './canvas.js';
|
|
14
|
+
import { ensureFontsDir } from './fonts.js';
|
|
15
|
+
import { installBBoxPolyfills } from './bbox.js';
|
|
16
|
+
import { installComputedStyle, setVarMaps, setFontRules } from './computed-style.js';
|
|
17
|
+
import { collectCssRules } from '../svg/collect-css.js';
|
|
18
|
+
export { defineElementSize } from './size.js';
|
|
19
|
+
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
20
|
+
class NoopResizeObserver {
|
|
21
|
+
observe() { }
|
|
22
|
+
unobserve() { }
|
|
23
|
+
disconnect() { }
|
|
24
|
+
}
|
|
25
|
+
/* eslint-enable @typescript-eslint/no-empty-function */
|
|
26
|
+
function exposeGlobals(window, raf) {
|
|
27
|
+
const globalNames = [
|
|
28
|
+
'document', 'location', 'navigator',
|
|
29
|
+
'Element', 'HTMLElement', 'SVGElement', 'SVGGraphicsElement', 'HTMLCanvasElement',
|
|
30
|
+
'Node', 'Text', 'DOMParser', 'XMLSerializer', 'MutationObserver',
|
|
31
|
+
'CSS', 'DOMPoint', 'DOMRect', 'getComputedStyle',
|
|
32
|
+
];
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
const g = globalThis;
|
|
35
|
+
g.window = window;
|
|
36
|
+
for (const name of globalNames) {
|
|
37
|
+
if (!(name in window))
|
|
38
|
+
continue;
|
|
39
|
+
try {
|
|
40
|
+
Object.defineProperty(g, name, { configurable: true, get: () => window[name] });
|
|
41
|
+
}
|
|
42
|
+
catch { /* some globals (e.g. navigator on newer Node) may resist redefinition */ }
|
|
43
|
+
}
|
|
44
|
+
g.requestAnimationFrame = raf.request;
|
|
45
|
+
g.cancelAnimationFrame = raf.cancel;
|
|
46
|
+
g.ResizeObserver = NoopResizeObserver;
|
|
47
|
+
}
|
|
48
|
+
/** Parse all emotion-injected CSS custom properties into light/dark maps */
|
|
49
|
+
function buildVarMapsFromRules(rules) {
|
|
50
|
+
const light = new Map();
|
|
51
|
+
const dark = new Map();
|
|
52
|
+
const darkSelector = /dark-theme|theme-dark|\[data-theme="?dark"?\]/;
|
|
53
|
+
for (const rule of rules) {
|
|
54
|
+
const isDark = darkSelector.test(rule.selector);
|
|
55
|
+
// Only :root-scoped declarations are global defaults. Class-scoped
|
|
56
|
+
// custom-property overrides (e.g. styleLargeSize from styles/sizes.ts)
|
|
57
|
+
// must not leak into the global maps.
|
|
58
|
+
if (!isDark && !rule.selector.includes(':root'))
|
|
59
|
+
continue;
|
|
60
|
+
for (const match of rule.block.matchAll(/(--[\w-]+)\s*:\s*([^;}]+)/g)) {
|
|
61
|
+
const [, name, value] = match;
|
|
62
|
+
(isDark ? dark : light).set(name, value.trim());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// The dark palette remap (--vis-colorN → --vis-dark-colorN) is declared
|
|
66
|
+
// under selectors jsdom can't apply; reproduce it here.
|
|
67
|
+
for (const [name, value] of light) {
|
|
68
|
+
const darkEquivalent = name.replace(/^--vis-color(\d+)$/, '--vis-dark-color$1');
|
|
69
|
+
if (darkEquivalent !== name && light.has(darkEquivalent)) {
|
|
70
|
+
if (!dark.has(name))
|
|
71
|
+
dark.set(name, light.get(darkEquivalent));
|
|
72
|
+
}
|
|
73
|
+
if (/^--vis-dark-/.test(name)) {
|
|
74
|
+
const lightName = name.replace('--vis-dark-', '--vis-');
|
|
75
|
+
if (!dark.has(lightName))
|
|
76
|
+
dark.set(lightName, value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { light, dark };
|
|
80
|
+
}
|
|
81
|
+
let envPromise;
|
|
82
|
+
export function getRenderEnv() {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
84
|
+
if (!envPromise)
|
|
85
|
+
envPromise = createEnv();
|
|
86
|
+
return envPromise;
|
|
87
|
+
}
|
|
88
|
+
async function createEnv() {
|
|
89
|
+
// Provision measurement fonts before anything can measure text
|
|
90
|
+
// (best-effort: falls back to system fonts offline)
|
|
91
|
+
const fontsDir = await ensureFontsDir();
|
|
92
|
+
if (fontsDir)
|
|
93
|
+
registerFontsFromDir(fontsDir);
|
|
94
|
+
const dom = new JSDOM('<!doctype html><html><body></body></html>', {
|
|
95
|
+
url: 'http://localhost/',
|
|
96
|
+
pretendToBeVisual: false,
|
|
97
|
+
});
|
|
98
|
+
const window = dom.window;
|
|
99
|
+
const raf = new RafQueue();
|
|
100
|
+
// Install shims before the library import — several APIs are captured
|
|
101
|
+
// at module scope inside @unovis/ts and its dependencies.
|
|
102
|
+
window.requestAnimationFrame = raf.request;
|
|
103
|
+
window.cancelAnimationFrame = raf.cancel;
|
|
104
|
+
window.ResizeObserver = NoopResizeObserver;
|
|
105
|
+
installCanvasHook(window);
|
|
106
|
+
installBBoxPolyfills(window);
|
|
107
|
+
installComputedStyle(window);
|
|
108
|
+
exposeGlobals(window, raf);
|
|
109
|
+
const lib = await import('@unovis/ts');
|
|
110
|
+
const cssRules = collectCssRules(window.document);
|
|
111
|
+
const varMaps = buildVarMapsFromRules(cssRules);
|
|
112
|
+
// Unovis estimates text width as chars × fontSize × ratio (default 0.5) when
|
|
113
|
+
// reserving label space, but trims against real canvas metrics — Inter runs
|
|
114
|
+
// wider (~0.55), so marginal labels would get clipped. A slightly generous
|
|
115
|
+
// ratio makes reservations always cover measured text.
|
|
116
|
+
varMaps.light.set('--vis-font-wh-ratio', '0.58');
|
|
117
|
+
setVarMaps(varMaps);
|
|
118
|
+
setFontRules(cssRules);
|
|
119
|
+
return { window, document: window.document, lib, raf, varMaps };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/env/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Flushable requestAnimationFrame queue.
|
|
2
|
+
*
|
|
3
|
+
* Unovis defers rendering to the next animation frame (`ContainerCore.render`),
|
|
4
|
+
* and several components schedule follow-up frames (axis, scatter, heatmap,
|
|
5
|
+
* sankey, annotations, text-overlap). Instead of waiting on real timers we
|
|
6
|
+
* queue callbacks and drain the queue synchronously until no new frames are
|
|
7
|
+
* scheduled.
|
|
8
|
+
*/
|
|
9
|
+
type FrameCallback = (time: number) => void;
|
|
10
|
+
export declare class RafQueue {
|
|
11
|
+
private queue;
|
|
12
|
+
private nextId;
|
|
13
|
+
/** Errors thrown by frame callbacks (collected so one bad frame can't kill a render) */
|
|
14
|
+
errors: unknown[];
|
|
15
|
+
request: (cb: FrameCallback) => number;
|
|
16
|
+
cancel: (id: number) => void;
|
|
17
|
+
get size(): number;
|
|
18
|
+
/** Drain the queue, letting callbacks schedule follow-up frames, until it
|
|
19
|
+
* stays empty or the iteration cap is reached. Returns rounds executed. */
|
|
20
|
+
flushAll(cap?: number): number;
|
|
21
|
+
clear(): void;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Flushable requestAnimationFrame queue.
|
|
2
|
+
*
|
|
3
|
+
* Unovis defers rendering to the next animation frame (`ContainerCore.render`),
|
|
4
|
+
* and several components schedule follow-up frames (axis, scatter, heatmap,
|
|
5
|
+
* sankey, annotations, text-overlap). Instead of waiting on real timers we
|
|
6
|
+
* queue callbacks and drain the queue synchronously until no new frames are
|
|
7
|
+
* scheduled.
|
|
8
|
+
*/
|
|
9
|
+
export class RafQueue {
|
|
10
|
+
queue = [];
|
|
11
|
+
nextId = 1;
|
|
12
|
+
/** Errors thrown by frame callbacks (collected so one bad frame can't kill a render) */
|
|
13
|
+
errors = [];
|
|
14
|
+
request = (cb) => {
|
|
15
|
+
const id = this.nextId++;
|
|
16
|
+
this.queue.push({ id, cb });
|
|
17
|
+
return id;
|
|
18
|
+
};
|
|
19
|
+
cancel = (id) => {
|
|
20
|
+
const index = this.queue.findIndex(entry => entry.id === id);
|
|
21
|
+
if (index >= 0)
|
|
22
|
+
this.queue.splice(index, 1);
|
|
23
|
+
};
|
|
24
|
+
get size() {
|
|
25
|
+
return this.queue.length;
|
|
26
|
+
}
|
|
27
|
+
/** Drain the queue, letting callbacks schedule follow-up frames, until it
|
|
28
|
+
* stays empty or the iteration cap is reached. Returns rounds executed. */
|
|
29
|
+
flushAll(cap = 32) {
|
|
30
|
+
let rounds = 0;
|
|
31
|
+
while (this.queue.length && rounds < cap) {
|
|
32
|
+
rounds += 1;
|
|
33
|
+
const batch = this.queue.splice(0, this.queue.length);
|
|
34
|
+
const time = performance.now();
|
|
35
|
+
for (const { cb } of batch) {
|
|
36
|
+
try {
|
|
37
|
+
cb(time);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
this.errors.push(e);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return rounds;
|
|
45
|
+
}
|
|
46
|
+
clear() {
|
|
47
|
+
this.queue.length = 0;
|
|
48
|
+
this.errors.length = 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=raf-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raf-queue.js","sourceRoot":"","sources":["../../src/env/raf-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,OAAO,QAAQ;IACX,KAAK,GAAwC,EAAE,CAAA;IAC/C,MAAM,GAAG,CAAC,CAAA;IAClB,wFAAwF;IACjF,MAAM,GAAc,EAAE,CAAA;IAE7B,OAAO,GAAG,CAAC,EAAiB,EAAU,EAAE;QACtC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;QACxB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAC3B,OAAO,EAAE,CAAA;IACX,CAAC,CAAA;IAED,MAAM,GAAG,CAAC,EAAU,EAAQ,EAAE;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QAC5D,IAAI,KAAK,IAAI,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC7C,CAAC,CAAA;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAA;IAC1B,CAAC;IAED;+EAC2E;IAC3E,QAAQ,CAAE,GAAG,GAAG,EAAE;QAChB,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;YACzC,MAAM,IAAI,CAAC,CAAA;YACX,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACrD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;YAC9B,KAAK,MAAM,EAAE,EAAE,EAAE,IAAI,KAAK,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACH,EAAE,CAAC,IAAI,CAAC,CAAA;gBACV,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;QACrB,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Element size shims.
|
|
2
|
+
*
|
|
3
|
+
* jsdom performs no layout: `clientWidth`/`clientHeight` are always 0 and
|
|
4
|
+
* `getBoundingClientRect()` returns a zero rect. Unovis containers read both
|
|
5
|
+
* to size charts (`ContainerCore.containerWidth/Height` — including
|
|
6
|
+
* `this.element.clientWidth` on the SVG element when explicit width/height
|
|
7
|
+
* are set in the config), so we define real values per element.
|
|
8
|
+
*/
|
|
9
|
+
export declare function defineElementSize(element: Element, width: number, height: number): void;
|
package/dist/env/size.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Element size shims.
|
|
2
|
+
*
|
|
3
|
+
* jsdom performs no layout: `clientWidth`/`clientHeight` are always 0 and
|
|
4
|
+
* `getBoundingClientRect()` returns a zero rect. Unovis containers read both
|
|
5
|
+
* to size charts (`ContainerCore.containerWidth/Height` — including
|
|
6
|
+
* `this.element.clientWidth` on the SVG element when explicit width/height
|
|
7
|
+
* are set in the config), so we define real values per element.
|
|
8
|
+
*/
|
|
9
|
+
export function defineElementSize(element, width, height) {
|
|
10
|
+
Object.defineProperties(element, {
|
|
11
|
+
clientWidth: { configurable: true, get: () => width },
|
|
12
|
+
clientHeight: { configurable: true, get: () => height },
|
|
13
|
+
});
|
|
14
|
+
const rect = {
|
|
15
|
+
x: 0,
|
|
16
|
+
y: 0,
|
|
17
|
+
top: 0,
|
|
18
|
+
left: 0,
|
|
19
|
+
right: width,
|
|
20
|
+
bottom: height,
|
|
21
|
+
width,
|
|
22
|
+
height,
|
|
23
|
+
toJSON: () => ({ width, height }),
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(element, 'getBoundingClientRect', {
|
|
26
|
+
configurable: true,
|
|
27
|
+
value: () => rect,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=size.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"size.js","sourceRoot":"","sources":["../../src/env/size.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,UAAU,iBAAiB,CAAE,OAAgB,EAAE,KAAa,EAAE,MAAc;IAChF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE;QAC/B,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE;QACrD,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;KACxD,CAAC,CAAA;IAEF,MAAM,IAAI,GAAG;QACX,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;QACd,KAAK;QACL,MAAM;QACN,MAAM,EAAE,GAAY,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;KAC3C,CAAA;IACD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,uBAAuB,EAAE;QACtD,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI;KAClB,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ChartSpec } from '../render/spec.js';
|
|
2
|
+
/** The compiled widget bundle (built by scripts/build-widget.mjs) */
|
|
3
|
+
export declare function widgetBundle(): string;
|
|
4
|
+
export interface ChartDocumentOptions {
|
|
5
|
+
/** Document <title>; defaults to the spec title */
|
|
6
|
+
documentTitle?: string;
|
|
7
|
+
/** Animation duration in ms. 0 renders immediately (deterministic tests,
|
|
8
|
+
* and useful when the chart is screenshotted right after load) */
|
|
9
|
+
duration?: number;
|
|
10
|
+
}
|
|
11
|
+
/** A standalone page that renders `spec` on load */
|
|
12
|
+
export declare function buildChartDocument(spec: ChartSpec, options?: ChartDocumentOptions): string;
|
|
13
|
+
/** A page that renders whatever spec it is sent over postMessage.
|
|
14
|
+
* Protocol: iframe posts `unovis:ready`, host posts `unovis:render` with a
|
|
15
|
+
* spec, iframe posts `unovis:size` after each render. */
|
|
16
|
+
export declare function buildEmbedDocument(): string;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** Self-contained interactive chart documents.
|
|
2
|
+
*
|
|
3
|
+
* Emits one HTML file with the spec, the widget bundle and all styles inlined
|
|
4
|
+
* — no network, no build step, opens anywhere. Two shapes:
|
|
5
|
+
*
|
|
6
|
+
* - `buildChartDocument(spec)`: renders the spec on load (file deliverable)
|
|
7
|
+
* - `buildEmbedDocument()`: waits for a spec over postMessage (iframe/widget
|
|
8
|
+
* host, used for the ui:// resource and third-party embedding)
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
let cachedBundle;
|
|
13
|
+
/** The compiled widget bundle (built by scripts/build-widget.mjs) */
|
|
14
|
+
export function widgetBundle() {
|
|
15
|
+
if (cachedBundle)
|
|
16
|
+
return cachedBundle;
|
|
17
|
+
// Resolve relative to this module so it works from dist/ and from src/
|
|
18
|
+
const candidates = [
|
|
19
|
+
new URL('../widget/bundle.js', import.meta.url),
|
|
20
|
+
new URL('../../dist/widget/bundle.js', import.meta.url),
|
|
21
|
+
];
|
|
22
|
+
for (const candidate of candidates) {
|
|
23
|
+
try {
|
|
24
|
+
cachedBundle = readFileSync(fileURLToPath(candidate), 'utf8');
|
|
25
|
+
return cachedBundle;
|
|
26
|
+
}
|
|
27
|
+
catch { /* try the next candidate */ }
|
|
28
|
+
}
|
|
29
|
+
throw new Error('Widget bundle not found — run `pnpm build:widget`');
|
|
30
|
+
}
|
|
31
|
+
/** `</script` inside embedded JSON would close the host script element */
|
|
32
|
+
const escapeForScript = (json) => json.replace(/</g, '\\u003c');
|
|
33
|
+
const FONT_STACK = 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif';
|
|
34
|
+
function styles(spec) {
|
|
35
|
+
const aspect = spec ? `${spec.width} / ${spec.height}` : '16 / 9';
|
|
36
|
+
return `
|
|
37
|
+
:root { --uv-bg: #ffffff; --uv-fg: #1f2937; --uv-muted: #6b7280; --uv-border: #e5e7eb; }
|
|
38
|
+
:root[data-theme="dark"] { --uv-bg: #292b34; --uv-fg: #f2f4f9; --uv-muted: #aab2c0; --uv-border: #3a3d47; }
|
|
39
|
+
html, body { margin: 0; padding: 0; background: var(--uv-bg); color: var(--uv-fg); font-family: ${FONT_STACK}; }
|
|
40
|
+
body { padding: 16px; box-sizing: border-box; }
|
|
41
|
+
.uv-root { display: flex; flex-direction: column; gap: 8px; max-width: 100%; }
|
|
42
|
+
.uv-title { font-size: 16px; font-weight: 600; }
|
|
43
|
+
.uv-legend { display: flex; flex-wrap: wrap; }
|
|
44
|
+
.uv-chart { width: 100%; aspect-ratio: ${aspect}; min-height: 240px; }
|
|
45
|
+
.uv-error { padding: 16px; border: 1px solid #e35a68; border-radius: 8px; color: #e35a68; font-family: ui-monospace, monospace; font-size: 13px; }
|
|
46
|
+
/* Tooltip / crosshair content (Unovis provides the container chrome) */
|
|
47
|
+
.uv-tt-title { font-weight: 600; margin-bottom: 4px; }
|
|
48
|
+
.uv-tt-row { display: flex; gap: 12px; justify-content: space-between; font-size: 12px; line-height: 1.6; }
|
|
49
|
+
.uv-tt-key { color: var(--uv-muted); }
|
|
50
|
+
.uv-tt-val { font-variant-numeric: tabular-nums; font-weight: 500; }
|
|
51
|
+
@media (max-width: 560px) { .uv-chart { aspect-ratio: 4 / 3; } }`;
|
|
52
|
+
}
|
|
53
|
+
/** A standalone page that renders `spec` on load */
|
|
54
|
+
export function buildChartDocument(spec, options = {}) {
|
|
55
|
+
const title = options.documentTitle ?? spec.title ?? 'Unovis chart';
|
|
56
|
+
return `<!doctype html>
|
|
57
|
+
<html lang="en"${spec.theme === 'dark' ? ' data-theme="dark"' : ''}>
|
|
58
|
+
<head>
|
|
59
|
+
<meta charset="utf-8">
|
|
60
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
61
|
+
<title>${title.replace(/</g, '<')}</title>
|
|
62
|
+
<style>${styles(spec)}</style>
|
|
63
|
+
</head>
|
|
64
|
+
<body>
|
|
65
|
+
<div id="uv-root"></div>
|
|
66
|
+
<script type="application/json" id="uv-spec">${escapeForScript(JSON.stringify(spec))}</script>
|
|
67
|
+
<script type="application/json" id="uv-options">${escapeForScript(JSON.stringify({ duration: options.duration ?? 400 }))}</script>
|
|
68
|
+
<script>${widgetBundle()}</script>
|
|
69
|
+
</body>
|
|
70
|
+
</html>
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
/** A page that renders whatever spec it is sent over postMessage.
|
|
74
|
+
* Protocol: iframe posts `unovis:ready`, host posts `unovis:render` with a
|
|
75
|
+
* spec, iframe posts `unovis:size` after each render. */
|
|
76
|
+
export function buildEmbedDocument() {
|
|
77
|
+
return `<!doctype html>
|
|
78
|
+
<html lang="en">
|
|
79
|
+
<head>
|
|
80
|
+
<meta charset="utf-8">
|
|
81
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
82
|
+
<title>Unovis chart</title>
|
|
83
|
+
<style>${styles()}
|
|
84
|
+
body { padding: 8px; }
|
|
85
|
+
</style>
|
|
86
|
+
</head>
|
|
87
|
+
<body>
|
|
88
|
+
<div id="uv-embed-root"></div>
|
|
89
|
+
<script>${widgetBundle()}</script>
|
|
90
|
+
<script>window.UnovisChart.startEmbed()</script>
|
|
91
|
+
</body>
|
|
92
|
+
</html>
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/html/document.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAIxC,IAAI,YAAgC,CAAA;AAEpC,qEAAqE;AACrE,MAAM,UAAU,YAAY;IAC1B,IAAI,YAAY;QAAE,OAAO,YAAY,CAAA;IACrC,uEAAuE;IACvE,MAAM,UAAU,GAAG;QACjB,IAAI,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QAC/C,IAAI,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;KACxD,CAAA;IACD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,YAAY,GAAG,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAA;YAC7D,OAAO,YAAY,CAAA;QACrB,CAAC;QAAC,MAAM,CAAC,CAAC,4BAA4B,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;AACtE,CAAC;AAED,0EAA0E;AAC1E,MAAM,eAAe,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;AAE/E,MAAM,UAAU,GAAG,6EAA6E,CAAA;AAEhG,SAAS,MAAM,CAAE,IAAgB;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;IACjE,OAAO;;;oGAG2F,UAAU;;;;;2CAKnE,MAAM;;;;;;;mEAOkB,CAAA;AACnE,CAAC;AAUD,oDAAoD;AACpD,MAAM,UAAU,kBAAkB,CAAE,IAAe,EAAE,UAAgC,EAAE;IACrF,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,KAAK,IAAI,cAAc,CAAA;IACnE,OAAO;iBACQ,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE;;;;SAIzD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SAC3B,MAAM,CAAC,IAAI,CAAC;;;;+CAI0B,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;kDAClC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,GAAG,EAAE,CAAC,CAAC;UAC9G,YAAY,EAAE;;;CAGvB,CAAA;AACD,CAAC;AAED;;yDAEyD;AACzD,MAAM,UAAU,kBAAkB;IAChC,OAAO;;;;;;SAMA,MAAM,EAAE;;;;;;UAMP,YAAY,EAAE;;;;CAIvB,CAAA;AACD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** @unovis/mcp — programmatic API.
|
|
2
|
+
*
|
|
3
|
+
* The package is primarily a CLI (`unovis-mcp`), but the renderer and server
|
|
4
|
+
* builder are exported for embedding:
|
|
5
|
+
*
|
|
6
|
+
* import { renderChart, buildServer, recipes } from '@unovis/mcp'
|
|
7
|
+
*/
|
|
8
|
+
export { renderChart, ChartInputError } from './render/renderer.js';
|
|
9
|
+
export type { RenderOptions } from './render/renderer.js';
|
|
10
|
+
export { renderToSvg } from './render/headless.js';
|
|
11
|
+
export type { HeadlessRenderOptions, BuildContext, RenderedChart, RenderResult } from './render/headless.js';
|
|
12
|
+
export { buildChartDocument, buildEmbedDocument } from './html/document.js';
|
|
13
|
+
export type { ChartDocumentOptions } from './html/document.js';
|
|
14
|
+
export { svgToPng, themeBackground } from './render/rasterize.js';
|
|
15
|
+
export type { RasterizeOptions } from './render/rasterize.js';
|
|
16
|
+
export type { ChartSpec, ComponentSpec, AxisSpec, AccessorRef, LegendItemSpec } from './render/spec.js';
|
|
17
|
+
export { recipes, recipeByName } from './recipes/index.js';
|
|
18
|
+
export type { Recipe, AnyRecipe } from './recipes/index.js';
|
|
19
|
+
export { buildServer } from './server.js';
|
|
20
|
+
export { registerTools, activeRecipes } from './tools/register.js';
|
|
21
|
+
export type { ToolFilterOptions } from './tools/register.js';
|
|
22
|
+
export { getRenderEnv } from './env/index.js';
|
|
23
|
+
export type { RenderEnv, UnovisLib } from './env/index.js';
|
|
24
|
+
export { generateCode, formatGeneratedFiles, FRAMEWORKS } from './codegen/index.js';
|
|
25
|
+
export type { Framework, GeneratedFile } from './codegen/index.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** @unovis/mcp — programmatic API.
|
|
2
|
+
*
|
|
3
|
+
* The package is primarily a CLI (`unovis-mcp`), but the renderer and server
|
|
4
|
+
* builder are exported for embedding:
|
|
5
|
+
*
|
|
6
|
+
* import { renderChart, buildServer, recipes } from '@unovis/mcp'
|
|
7
|
+
*/
|
|
8
|
+
export { renderChart, ChartInputError } from './render/renderer.js';
|
|
9
|
+
// The headless primitive: render any Unovis chart to standalone SVG in Node
|
|
10
|
+
export { renderToSvg } from './render/headless.js';
|
|
11
|
+
export { buildChartDocument, buildEmbedDocument } from './html/document.js';
|
|
12
|
+
export { svgToPng, themeBackground } from './render/rasterize.js';
|
|
13
|
+
export { recipes, recipeByName } from './recipes/index.js';
|
|
14
|
+
export { buildServer } from './server.js';
|
|
15
|
+
export { registerTools, activeRecipes } from './tools/register.js';
|
|
16
|
+
export { getRenderEnv } from './env/index.js';
|
|
17
|
+
export { generateCode, formatGeneratedFiles, FRAMEWORKS } from './codegen/index.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEnE,4EAA4E;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE3E,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAGjE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE7C,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Recipe } from './types.js';
|
|
3
|
+
export declare const areaInputShape: {
|
|
4
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
theme: z.ZodDefault<z.ZodEnum<["light", "dark"]>>;
|
|
7
|
+
title: z.ZodOptional<z.ZodString>;
|
|
8
|
+
colors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
9
|
+
framework: z.ZodDefault<z.ZodEnum<["ts", "react", "svelte", "vue", "angular", "solid"]>>;
|
|
10
|
+
outputType: z.ZodDefault<z.ZodEnum<["svg", "png", "html", "interactive", "config", "code"]>>;
|
|
11
|
+
outputPath: z.ZodOptional<z.ZodString>;
|
|
12
|
+
scale: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
xAxisLabel: z.ZodOptional<z.ZodString>;
|
|
14
|
+
yAxisLabel: z.ZodOptional<z.ZodString>;
|
|
15
|
+
showGridLines: z.ZodDefault<z.ZodBoolean>;
|
|
16
|
+
legend: z.ZodDefault<z.ZodBoolean>;
|
|
17
|
+
referenceLines: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
18
|
+
axis: z.ZodDefault<z.ZodEnum<["x", "y"]>>;
|
|
19
|
+
value: z.ZodNumber;
|
|
20
|
+
label: z.ZodOptional<z.ZodString>;
|
|
21
|
+
color: z.ZodOptional<z.ZodString>;
|
|
22
|
+
lineWidth: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
style: z.ZodDefault<z.ZodEnum<["dashed", "solid", "dotted"]>>;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
value: number;
|
|
26
|
+
style: "solid" | "dashed" | "dotted";
|
|
27
|
+
axis: "x" | "y";
|
|
28
|
+
lineWidth: number;
|
|
29
|
+
label?: string | undefined;
|
|
30
|
+
color?: string | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
value: number;
|
|
33
|
+
label?: string | undefined;
|
|
34
|
+
color?: string | undefined;
|
|
35
|
+
style?: "solid" | "dashed" | "dotted" | undefined;
|
|
36
|
+
axis?: "x" | "y" | undefined;
|
|
37
|
+
lineWidth?: number | undefined;
|
|
38
|
+
}>, "many">>;
|
|
39
|
+
referenceBands: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
40
|
+
axis: z.ZodDefault<z.ZodEnum<["x", "y"]>>;
|
|
41
|
+
from: z.ZodNumber;
|
|
42
|
+
to: z.ZodNumber;
|
|
43
|
+
label: z.ZodOptional<z.ZodString>;
|
|
44
|
+
color: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
axis: "x" | "y";
|
|
47
|
+
from: number;
|
|
48
|
+
to: number;
|
|
49
|
+
label?: string | undefined;
|
|
50
|
+
color?: string | undefined;
|
|
51
|
+
}, {
|
|
52
|
+
from: number;
|
|
53
|
+
to: number;
|
|
54
|
+
label?: string | undefined;
|
|
55
|
+
color?: string | undefined;
|
|
56
|
+
axis?: "x" | "y" | undefined;
|
|
57
|
+
}>, "many">>;
|
|
58
|
+
data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>, "many">;
|
|
59
|
+
x: z.ZodString;
|
|
60
|
+
y: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
|
|
61
|
+
stacked: z.ZodDefault<z.ZodBoolean>;
|
|
62
|
+
curve: z.ZodDefault<z.ZodEnum<["linear", "monotoneX", "basis", "natural", "step", "stepAfter", "stepBefore"]>>;
|
|
63
|
+
xIsTime: z.ZodDefault<z.ZodBoolean>;
|
|
64
|
+
seriesLabels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
65
|
+
};
|
|
66
|
+
export declare const areaRecipe: Recipe<typeof areaInputShape>;
|