@pixerate/editor 0.279.1 → 0.280.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.
@@ -4,6 +4,7 @@ import type { VectorBooleanOperation } from './types.cjs';
4
4
  import { type VectorEffect } from './types.cjs';
5
5
  import { type VectorBlendMode, type VectorFilter, type VectorPaintLayer, type VectorStrokeLayer } from './types.cjs';
6
6
  import { type VectorMaskSummary } from './mask.cjs';
7
+ import { type VectorTracePixels } from './trace.cjs';
7
8
  import { type VectorLens, type VectorSymmetry } from './types.cjs';
8
9
  import { type VectorConnector } from './types.cjs';
9
10
  import { type VectorFrame, type VectorResizing } from './types.cjs';
@@ -14,7 +15,31 @@ export interface VectorCommandOptions {
14
15
  group?: string;
15
16
  /** Command scope. Omit for global commands. */
16
17
  scope?: string;
18
+ /**
19
+ * Loads an image that `vector.traceImage` and the stylise commands (`vector.mosaicImage`, …)
20
+ * are given by reference instead of as a PNG data URL: an http(s) or asset URL, or a host id
21
+ * such as a canvas node's. Agents can name an image but cannot write out its bytes, so without
22
+ * this they can only trace PNGs they produced themselves. Return `null` when there is no such
23
+ * image; throw (or reject) with a sentence when it cannot be loaded. `maxPixels` is the most the
24
+ * commands trace: scale larger images down to fit.
25
+ */
26
+ resolveImage?: VectorImageResolver;
27
+ /**
28
+ * What `resolveImage` accepts, for the `image` argument's description (default "an image
29
+ * URL"), e.g. "the id of an image node on the canvas, or an http(s) URL".
30
+ */
31
+ imageReferences?: string;
17
32
  }
33
+ /** An image a host loaded for a reference: RGBA pixels, or a PNG (data URL or bytes). */
34
+ export type VectorResolvedImage = {
35
+ image: VectorTracePixels;
36
+ } | {
37
+ png: string | Uint8Array;
38
+ };
39
+ /** See `VectorCommandOptions.resolveImage`. */
40
+ export type VectorImageResolver = (ref: string, options: {
41
+ maxPixels: number;
42
+ }) => VectorResolvedImage | null | undefined | Promise<VectorResolvedImage | null | undefined>;
18
43
  /** A node as listed for agents. */
19
44
  export interface VectorNodeListing {
20
45
  id: string;
@@ -4,6 +4,7 @@ import type { VectorBooleanOperation } from './types.js';
4
4
  import { type VectorEffect } from './types.js';
5
5
  import { type VectorBlendMode, type VectorFilter, type VectorPaintLayer, type VectorStrokeLayer } from './types.js';
6
6
  import { type VectorMaskSummary } from './mask.js';
7
+ import { type VectorTracePixels } from './trace.js';
7
8
  import { type VectorLens, type VectorSymmetry } from './types.js';
8
9
  import { type VectorConnector } from './types.js';
9
10
  import { type VectorFrame, type VectorResizing } from './types.js';
@@ -14,7 +15,31 @@ export interface VectorCommandOptions {
14
15
  group?: string;
15
16
  /** Command scope. Omit for global commands. */
16
17
  scope?: string;
18
+ /**
19
+ * Loads an image that `vector.traceImage` and the stylise commands (`vector.mosaicImage`, …)
20
+ * are given by reference instead of as a PNG data URL: an http(s) or asset URL, or a host id
21
+ * such as a canvas node's. Agents can name an image but cannot write out its bytes, so without
22
+ * this they can only trace PNGs they produced themselves. Return `null` when there is no such
23
+ * image; throw (or reject) with a sentence when it cannot be loaded. `maxPixels` is the most the
24
+ * commands trace: scale larger images down to fit.
25
+ */
26
+ resolveImage?: VectorImageResolver;
27
+ /**
28
+ * What `resolveImage` accepts, for the `image` argument's description (default "an image
29
+ * URL"), e.g. "the id of an image node on the canvas, or an http(s) URL".
30
+ */
31
+ imageReferences?: string;
17
32
  }
33
+ /** An image a host loaded for a reference: RGBA pixels, or a PNG (data URL or bytes). */
34
+ export type VectorResolvedImage = {
35
+ image: VectorTracePixels;
36
+ } | {
37
+ png: string | Uint8Array;
38
+ };
39
+ /** See `VectorCommandOptions.resolveImage`. */
40
+ export type VectorImageResolver = (ref: string, options: {
41
+ maxPixels: number;
42
+ }) => VectorResolvedImage | null | undefined | Promise<VectorResolvedImage | null | undefined>;
18
43
  /** A node as listed for agents. */
19
44
  export interface VectorNodeListing {
20
45
  id: string;
@@ -16551,17 +16551,72 @@ function createVectorCommands(controller, options = {}) {
16551
16551
  }
16552
16552
  }
16553
16553
  ];
16554
+ const resolveImage = options.resolveImage;
16555
+ const IMAGE_WHAT = resolveImage ? "an image (a PNG data URL, or a reference the editor loads)" : "a PNG (base64 data URL)";
16556
+ const IMAGE_PARAM = {
16557
+ type: "string",
16558
+ description: resolveImage ? `The image: a data:image/png;base64,\u2026 URL, or ${_nullishCoalesce(options.imageReferences, () => ( "an image URL"))} (up to ${_chunkMNHP3AQTcjs.VECTOR_TRACE_MAX_PIXELS / 1e6} million pixels).` : "The image as a data:image/png;base64,\u2026 URL (up to 4 million pixels)."
16559
+ };
16560
+ const decodePngBytes = (bytes, what) => {
16561
+ if (!_chunkW5M3J7PVcjs.isPng.call(void 0, bytes)) fail(`${what} is not a PNG.`);
16562
+ try {
16563
+ return _chunkW5M3J7PVcjs.decodePng.call(void 0, bytes, { maxPixels: _chunkMNHP3AQTcjs.VECTOR_TRACE_MAX_PIXELS });
16564
+ } catch (e) {
16565
+ return fail(`The PNG could not be read: ${e.message}`);
16566
+ }
16567
+ };
16568
+ const fromResolved = (ref, resolved) => {
16569
+ if (!resolved || typeof resolved !== "object") return fail(`There is no image "${ref}".`);
16570
+ if ("image" in resolved && resolved.image) return resolved.image;
16571
+ if ("png" in resolved && typeof resolved.png === "string") {
16572
+ const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, resolved.png);
16573
+ if (!parsed) fail(`The image "${ref}" was loaded as something other than a PNG data URL.`);
16574
+ return decodePngBytes(parsed.bytes, `The image "${ref}"`);
16575
+ }
16576
+ if ("png" in resolved && resolved.png instanceof Uint8Array) return decodePngBytes(resolved.png, `The image "${ref}"`);
16577
+ return fail(`The image "${ref}" was loaded as nothing usable (expected { image } or { png }).`);
16578
+ };
16579
+ const withImage = (image, use) => {
16580
+ if (typeof image !== "string" || !image.trim()) fail("image is empty.");
16581
+ if (/^data:/i.test(image)) {
16582
+ const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, image);
16583
+ if (!parsed || !_chunkW5M3J7PVcjs.isPng.call(void 0, parsed.bytes)) fail(resolveImage ? "image must be a PNG data URL (data:image/png;base64,\u2026) or a reference to an image." : "image must be a PNG data URL (data:image/png;base64,\u2026).");
16584
+ return use(decodePngBytes(parsed.bytes, "image"));
16585
+ }
16586
+ if (!resolveImage) return fail("image must be a PNG data URL (data:image/png;base64,\u2026).");
16587
+ const ref = image.trim();
16588
+ const load = async () => {
16589
+ let resolved;
16590
+ try {
16591
+ resolved = await resolveImage(ref, { maxPixels: _chunkMNHP3AQTcjs.VECTOR_TRACE_MAX_PIXELS });
16592
+ } catch (e) {
16593
+ return fail(`The image "${ref}" could not be loaded: ${e instanceof Error ? e.message : String(e)}`);
16594
+ }
16595
+ return use(fromResolved(ref, resolved));
16596
+ };
16597
+ return load();
16598
+ };
16599
+ const imageResult = (r) => {
16600
+ check2(r);
16601
+ return {
16602
+ id: r.id,
16603
+ paths: r.ids.map((id) => {
16604
+ const n2 = controller.getNode(id);
16605
+ return { id, name: n2.name, fill: n2.fill, subpaths: n2.subpaths.length };
16606
+ })
16607
+ };
16608
+ };
16554
16609
  const traceCommands = () => [
16555
16610
  {
16556
16611
  ...base,
16557
16612
  id: `${prefix}traceImage`,
16558
16613
  label: "Image Trace\u2026",
16559
16614
  keywords: ["trace", "image trace", "live trace", "vectorize", "bitmap to vector", "png to svg", "autotrace", "posterize"],
16560
- description: "Traces a PNG (base64 data URL) into vector paths and adds them as one group: `threshold` mode makes one even-odd path where the image is dark (or opaque with channel alpha); `color` mode makes a stacked path per colour (median-cut to `colors`, the most common at the bottom). Placed with its top-left at x, y and `width` wide (default one unit per pixel). One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.",
16615
+ description: "Traces " + IMAGE_WHAT + " into vector paths and adds them as one group: `threshold` mode makes one even-odd path where the image is dark (or opaque with channel alpha); `color` mode makes a stacked path per colour (median-cut to `colors`, the most common at the bottom). Placed with its top-left at x, y and `width` wide (default one unit per pixel). One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.",
16561
16616
  params: {
16562
16617
  type: "object",
16563
16618
  properties: {
16564
- image: { type: "string", description: "The image as a data:image/png;base64,\u2026 URL (up to 4 million pixels)." },
16619
+ image: IMAGE_PARAM,
16565
16620
  mode: { type: "string", enum: ["threshold", "color"], description: "threshold (one colour, default) or color (a path per colour)." },
16566
16621
  channel: { type: "string", enum: ["luminance", "alpha"], description: "Threshold mode: trace dark pixels (luminance, default) or opaque ones (alpha)." },
16567
16622
  threshold: { type: "number", minimum: 0, maximum: 1, description: "Threshold mode: inside where darkness (or alpha) reaches this (default 0.5)." },
@@ -16581,61 +16636,28 @@ function createVectorCommands(controller, options = {}) {
16581
16636
  undoable: true,
16582
16637
  run: (_ctx, params) => {
16583
16638
  const { image, ...options2 } = params;
16584
- const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, image);
16585
- if (!parsed || !_chunkW5M3J7PVcjs.isPng.call(void 0, parsed.bytes)) fail("image must be a PNG data URL (data:image/png;base64,\u2026).");
16586
- let decoded2;
16587
- try {
16588
- decoded2 = _chunkW5M3J7PVcjs.decodePng.call(void 0, parsed.bytes, { maxPixels: _chunkMNHP3AQTcjs.VECTOR_TRACE_MAX_PIXELS });
16589
- } catch (e) {
16590
- return fail(`The PNG could not be read: ${e.message}`);
16591
- }
16592
- const r = controller.traceImage(decoded2, options2);
16593
- check2(r);
16594
- return {
16595
- id: r.id,
16596
- paths: r.ids.map((id) => {
16597
- const n2 = controller.getNode(id);
16598
- return { id, name: n2.name, fill: n2.fill, subpaths: n2.subpaths.length };
16599
- })
16600
- };
16639
+ return withImage(image, (pixels) => imageResult(controller.traceImage(pixels, options2)));
16601
16640
  }
16602
16641
  }
16603
16642
  ];
16604
16643
  const IMAGE_PLACE = {
16605
- image: { type: "string", description: "The picture as a data:image/png;base64,\u2026 URL (up to 4 million pixels)." },
16644
+ image: resolveImage ? IMAGE_PARAM : { type: "string", description: "The picture as a data:image/png;base64,\u2026 URL (up to 4 million pixels)." },
16606
16645
  x: { type: "number", description: "Left edge in document units (default 0)." },
16607
16646
  y: { type: "number", description: "Top edge in document units (default 0)." },
16608
16647
  width: { type: "number", exclusiveMinimum: 0, description: "Width in document units (default: the image width in pixels)." },
16609
16648
  name: { type: "string", description: "Group name (default: the style's name)." }
16610
16649
  };
16611
- const decodeImage = (image) => {
16612
- const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, image);
16613
- if (!parsed || !_chunkW5M3J7PVcjs.isPng.call(void 0, parsed.bytes)) fail("image must be a PNG data URL (data:image/png;base64,\u2026).");
16614
- try {
16615
- return _chunkW5M3J7PVcjs.decodePng.call(void 0, parsed.bytes, { maxPixels: _chunkMNHP3AQTcjs.VECTOR_TRACE_MAX_PIXELS });
16616
- } catch (e) {
16617
- return fail(`The PNG could not be read: ${e.message}`);
16618
- }
16619
- };
16620
16650
  const stylize = (style, label2, keywords, description, props) => ({
16621
16651
  ...base,
16622
16652
  id: `${prefix}${style}Image`,
16623
16653
  label: label2,
16624
16654
  keywords: ["stylize", "stylise", "bitmap to vector", "artistic", "png to svg", ...keywords],
16625
- description: `${description} Added as one group placed with its top-left at x, y and width wide; colours of one kind share a compound path. One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.`,
16655
+ description: `${resolveImage ? description.replace("a PNG", IMAGE_WHAT) : description} Added as one group placed with its top-left at x, y and width wide; colours of one kind share a compound path. One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.`,
16626
16656
  params: { type: "object", properties: { ...IMAGE_PLACE, ...props }, required: ["image"], additionalProperties: false },
16627
16657
  undoable: true,
16628
16658
  run: (_ctx, params) => {
16629
16659
  const { image, ...options2 } = params;
16630
- const r = controller.stylizeImage(decodeImage(image), style, options2);
16631
- check2(r);
16632
- return {
16633
- id: r.id,
16634
- paths: r.ids.map((id) => {
16635
- const n2 = controller.getNode(id);
16636
- return { id, name: n2.name, fill: n2.fill, subpaths: n2.subpaths.length };
16637
- })
16638
- };
16660
+ return withImage(image, (pixels) => imageResult(controller.stylizeImage(pixels, style, options2)));
16639
16661
  }
16640
16662
  });
16641
16663
  const CELL = (dflt, what) => ({ type: "number", minimum: 1, description: `${what} in image pixels (default ${dflt}); larger draws fewer, bigger shapes.` });
@@ -16551,17 +16551,72 @@ function createVectorCommands(controller, options = {}) {
16551
16551
  }
16552
16552
  }
16553
16553
  ];
16554
+ const resolveImage = options.resolveImage;
16555
+ const IMAGE_WHAT = resolveImage ? "an image (a PNG data URL, or a reference the editor loads)" : "a PNG (base64 data URL)";
16556
+ const IMAGE_PARAM = {
16557
+ type: "string",
16558
+ description: resolveImage ? `The image: a data:image/png;base64,\u2026 URL, or ${options.imageReferences ?? "an image URL"} (up to ${VECTOR_TRACE_MAX_PIXELS / 1e6} million pixels).` : "The image as a data:image/png;base64,\u2026 URL (up to 4 million pixels)."
16559
+ };
16560
+ const decodePngBytes = (bytes, what) => {
16561
+ if (!isPng(bytes)) fail(`${what} is not a PNG.`);
16562
+ try {
16563
+ return decodePng(bytes, { maxPixels: VECTOR_TRACE_MAX_PIXELS });
16564
+ } catch (e) {
16565
+ return fail(`The PNG could not be read: ${e.message}`);
16566
+ }
16567
+ };
16568
+ const fromResolved = (ref, resolved) => {
16569
+ if (!resolved || typeof resolved !== "object") return fail(`There is no image "${ref}".`);
16570
+ if ("image" in resolved && resolved.image) return resolved.image;
16571
+ if ("png" in resolved && typeof resolved.png === "string") {
16572
+ const parsed = parseDataUrl(resolved.png);
16573
+ if (!parsed) fail(`The image "${ref}" was loaded as something other than a PNG data URL.`);
16574
+ return decodePngBytes(parsed.bytes, `The image "${ref}"`);
16575
+ }
16576
+ if ("png" in resolved && resolved.png instanceof Uint8Array) return decodePngBytes(resolved.png, `The image "${ref}"`);
16577
+ return fail(`The image "${ref}" was loaded as nothing usable (expected { image } or { png }).`);
16578
+ };
16579
+ const withImage = (image, use) => {
16580
+ if (typeof image !== "string" || !image.trim()) fail("image is empty.");
16581
+ if (/^data:/i.test(image)) {
16582
+ const parsed = parseDataUrl(image);
16583
+ if (!parsed || !isPng(parsed.bytes)) fail(resolveImage ? "image must be a PNG data URL (data:image/png;base64,\u2026) or a reference to an image." : "image must be a PNG data URL (data:image/png;base64,\u2026).");
16584
+ return use(decodePngBytes(parsed.bytes, "image"));
16585
+ }
16586
+ if (!resolveImage) return fail("image must be a PNG data URL (data:image/png;base64,\u2026).");
16587
+ const ref = image.trim();
16588
+ const load = async () => {
16589
+ let resolved;
16590
+ try {
16591
+ resolved = await resolveImage(ref, { maxPixels: VECTOR_TRACE_MAX_PIXELS });
16592
+ } catch (e) {
16593
+ return fail(`The image "${ref}" could not be loaded: ${e instanceof Error ? e.message : String(e)}`);
16594
+ }
16595
+ return use(fromResolved(ref, resolved));
16596
+ };
16597
+ return load();
16598
+ };
16599
+ const imageResult = (r) => {
16600
+ check2(r);
16601
+ return {
16602
+ id: r.id,
16603
+ paths: r.ids.map((id) => {
16604
+ const n2 = controller.getNode(id);
16605
+ return { id, name: n2.name, fill: n2.fill, subpaths: n2.subpaths.length };
16606
+ })
16607
+ };
16608
+ };
16554
16609
  const traceCommands = () => [
16555
16610
  {
16556
16611
  ...base,
16557
16612
  id: `${prefix}traceImage`,
16558
16613
  label: "Image Trace\u2026",
16559
16614
  keywords: ["trace", "image trace", "live trace", "vectorize", "bitmap to vector", "png to svg", "autotrace", "posterize"],
16560
- description: "Traces a PNG (base64 data URL) into vector paths and adds them as one group: `threshold` mode makes one even-odd path where the image is dark (or opaque with channel alpha); `color` mode makes a stacked path per colour (median-cut to `colors`, the most common at the bottom). Placed with its top-left at x, y and `width` wide (default one unit per pixel). One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.",
16615
+ description: "Traces " + IMAGE_WHAT + " into vector paths and adds them as one group: `threshold` mode makes one even-odd path where the image is dark (or opaque with channel alpha); `color` mode makes a stacked path per colour (median-cut to `colors`, the most common at the bottom). Placed with its top-left at x, y and `width` wide (default one unit per pixel). One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.",
16561
16616
  params: {
16562
16617
  type: "object",
16563
16618
  properties: {
16564
- image: { type: "string", description: "The image as a data:image/png;base64,\u2026 URL (up to 4 million pixels)." },
16619
+ image: IMAGE_PARAM,
16565
16620
  mode: { type: "string", enum: ["threshold", "color"], description: "threshold (one colour, default) or color (a path per colour)." },
16566
16621
  channel: { type: "string", enum: ["luminance", "alpha"], description: "Threshold mode: trace dark pixels (luminance, default) or opaque ones (alpha)." },
16567
16622
  threshold: { type: "number", minimum: 0, maximum: 1, description: "Threshold mode: inside where darkness (or alpha) reaches this (default 0.5)." },
@@ -16581,61 +16636,28 @@ function createVectorCommands(controller, options = {}) {
16581
16636
  undoable: true,
16582
16637
  run: (_ctx, params) => {
16583
16638
  const { image, ...options2 } = params;
16584
- const parsed = parseDataUrl(image);
16585
- if (!parsed || !isPng(parsed.bytes)) fail("image must be a PNG data URL (data:image/png;base64,\u2026).");
16586
- let decoded2;
16587
- try {
16588
- decoded2 = decodePng(parsed.bytes, { maxPixels: VECTOR_TRACE_MAX_PIXELS });
16589
- } catch (e) {
16590
- return fail(`The PNG could not be read: ${e.message}`);
16591
- }
16592
- const r = controller.traceImage(decoded2, options2);
16593
- check2(r);
16594
- return {
16595
- id: r.id,
16596
- paths: r.ids.map((id) => {
16597
- const n2 = controller.getNode(id);
16598
- return { id, name: n2.name, fill: n2.fill, subpaths: n2.subpaths.length };
16599
- })
16600
- };
16639
+ return withImage(image, (pixels) => imageResult(controller.traceImage(pixels, options2)));
16601
16640
  }
16602
16641
  }
16603
16642
  ];
16604
16643
  const IMAGE_PLACE = {
16605
- image: { type: "string", description: "The picture as a data:image/png;base64,\u2026 URL (up to 4 million pixels)." },
16644
+ image: resolveImage ? IMAGE_PARAM : { type: "string", description: "The picture as a data:image/png;base64,\u2026 URL (up to 4 million pixels)." },
16606
16645
  x: { type: "number", description: "Left edge in document units (default 0)." },
16607
16646
  y: { type: "number", description: "Top edge in document units (default 0)." },
16608
16647
  width: { type: "number", exclusiveMinimum: 0, description: "Width in document units (default: the image width in pixels)." },
16609
16648
  name: { type: "string", description: "Group name (default: the style's name)." }
16610
16649
  };
16611
- const decodeImage = (image) => {
16612
- const parsed = parseDataUrl(image);
16613
- if (!parsed || !isPng(parsed.bytes)) fail("image must be a PNG data URL (data:image/png;base64,\u2026).");
16614
- try {
16615
- return decodePng(parsed.bytes, { maxPixels: VECTOR_TRACE_MAX_PIXELS });
16616
- } catch (e) {
16617
- return fail(`The PNG could not be read: ${e.message}`);
16618
- }
16619
- };
16620
16650
  const stylize = (style, label2, keywords, description, props) => ({
16621
16651
  ...base,
16622
16652
  id: `${prefix}${style}Image`,
16623
16653
  label: label2,
16624
16654
  keywords: ["stylize", "stylise", "bitmap to vector", "artistic", "png to svg", ...keywords],
16625
- description: `${description} Added as one group placed with its top-left at x, y and width wide; colours of one kind share a compound path. One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.`,
16655
+ description: `${resolveImage ? description.replace("a PNG", IMAGE_WHAT) : description} Added as one group placed with its top-left at x, y and width wide; colours of one kind share a compound path. One undo step. Returns { id, paths: [{ id, name, fill, subpaths }] }.`,
16626
16656
  params: { type: "object", properties: { ...IMAGE_PLACE, ...props }, required: ["image"], additionalProperties: false },
16627
16657
  undoable: true,
16628
16658
  run: (_ctx, params) => {
16629
16659
  const { image, ...options2 } = params;
16630
- const r = controller.stylizeImage(decodeImage(image), style, options2);
16631
- check2(r);
16632
- return {
16633
- id: r.id,
16634
- paths: r.ids.map((id) => {
16635
- const n2 = controller.getNode(id);
16636
- return { id, name: n2.name, fill: n2.fill, subpaths: n2.subpaths.length };
16637
- })
16638
- };
16660
+ return withImage(image, (pixels) => imageResult(controller.stylizeImage(pixels, style, options2)));
16639
16661
  }
16640
16662
  });
16641
16663
  const CELL = (dflt, what) => ({ type: "number", minimum: 1, description: `${what} in image pixels (default ${dflt}); larger draws fewer, bigger shapes.` });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.279.1",
3
+ "version": "0.280.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -494,7 +494,7 @@
494
494
  ],
495
495
  "sideEffects": false,
496
496
  "devDependencies": {
497
- "@anthropic-ai/sdk": "1.1.0",
497
+ "@anthropic-ai/sdk": "1.6.0",
498
498
  "@dagrejs/dagre": "^1.1.8",
499
499
  "@tiptap/core": "^2.27.3",
500
500
  "@tiptap/extension-character-count": "^2.27.3",
@@ -521,17 +521,17 @@
521
521
  "@tiptap/suggestion": "^2.27.3",
522
522
  "@types/dagre": "^0.7.54",
523
523
  "@types/markdown-it": "^14.2.0",
524
- "@types/node": "^26.6.5",
524
+ "@types/node": "^26.6.6",
525
525
  "assemblyscript": "0.28.20",
526
526
  "fast-check": "^4.10.2",
527
527
  "markdown-it": "^15.0.3",
528
528
  "markdown-it-task-lists": "^2.1.1",
529
- "mermaid": "12.2.0",
529
+ "mermaid": "12.3.0",
530
530
  "prosemirror-markdown": "^1.13.9",
531
531
  "tiptap-markdown": "^0.8.10",
532
532
  "tsup": "^9.0.0",
533
533
  "typescript": "^5.7.3",
534
- "vitest": "^5.0.5",
534
+ "vitest": "^5.1.0",
535
535
  "@pixerate/markdown-conformance": "0.2.0"
536
536
  },
537
537
  "peerDependencies": {
@@ -131,7 +131,7 @@ the pitfalls, and uses the commands below.
131
131
 
132
132
  | Command | Use it to |
133
133
  | --- | --- |
134
- | `vector.traceImage` | Turn a PNG (data URL) into vector paths in one group: `threshold` mode for one-colour art (logos, scans, silhouettes; `channel: "alpha"` for cut-outs), `color` mode for a stacked path per colour (`colors` 2–32). Raise `tolerance` for fewer anchors, `cornerRoundness` 0 for sharp polygons. Place it with `x`, `y`, `width`. Returns `{ id, paths }`; check `subpaths` counts and simplify or delete specks after. |
134
+ | `vector.traceImage` | Turn a PNG (data URL) into vector paths in one group, or an image the host loads by reference (its `image` description says which: a canvas image node's id, a URL); pass the reference instead of writing the image out: `threshold` mode for one-colour art (logos, scans, silhouettes; `channel: "alpha"` for cut-outs), `color` mode for a stacked path per colour (`colors` 2–32). Raise `tolerance` for fewer anchors, `cornerRoundness` 0 for sharp polygons. Place it with `x`, `y`, `width`. Returns `{ id, paths }`; check `subpaths` counts and simplify or delete specks after. |
135
135
  | `vector.mosaicImage` | Stylise a PNG as mosaic tiles (`cell` px, `shape` square / circle, `gap`, `colors`): pixel art, tiled murals. Returns `{ id, paths }`, one compound path per colour. |
136
136
  | `vector.halftoneImage` | Stylise a PNG as halftone dots on a turned screen (`cell`, `angle`, ink `color` or null for the picture's colours): comic and pop-art looks, print effects. |
137
137
  | `vector.lowPolyImage` | Stylise a PNG as low-poly triangles (`cell`, `jitter`, `seed`, `colors`): geometric portraits and backdrops. |