@ingcreators/annot-core 0.3.1 → 0.4.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/CHANGELOG.md +20 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/svg-format.d.ts +28 -0
- package/dist/element-tree/attr-whitelist.d.ts +29 -0
- package/dist/element-tree/index.d.ts +1 -0
- package/dist/{element-tree-Bp-_IB-7.js → element-tree-C0Vl00o2.js} +261 -239
- package/dist/element-tree.js +2 -2
- package/dist/index.js +1 -1
- package/dist/storage/types.d.ts +10 -0
- package/dist/utils/filename.d.ts +19 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/xmp/xmp-browser.d.ts +3 -18
- package/dist/xmp/xmp-bytes.d.ts +42 -2
- package/dist/xmp-bytes.js +103 -91
- package/package.json +3 -4
package/dist/element-tree.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, c as t,
|
|
2
|
-
export {
|
|
1
|
+
import { a as e, c as t, d as n, i as r, l as i, n as a, o, r as s, s as c, t as l, u } from "./element-tree-C0Vl00o2.js";
|
|
2
|
+
export { n as ELEMENT_TREE_ATTR_WHITELIST, s as findByMatch, r as findByRef, e as flattenTree, u as isElementTreeShape, c as parseElementTreeFromJson, l as parseElementTreeFromYaml, t as serializeElementTreeToJson, a as serializeElementTreeToYaml, i as validateElementTree, o as walkTree };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c, u as l } from "./element-tree-
|
|
1
|
+
import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c, u as l } from "./element-tree-C0Vl00o2.js";
|
|
2
2
|
import { buildPngChunk as u, concat as d, readU32be as f, startsWith as p } from "./xmp-bytes.js";
|
|
3
3
|
import { deflate as m, inflate as h } from "pako";
|
|
4
4
|
//#region src/editor/font-registry.ts
|
package/dist/storage/types.d.ts
CHANGED
|
@@ -13,6 +13,16 @@ export interface ImageRecord {
|
|
|
13
13
|
tags: Record<string, string>;
|
|
14
14
|
createdAt: string;
|
|
15
15
|
updatedAt: string;
|
|
16
|
+
/** What created the image: `extension` / `desktop` / `web` /
|
|
17
|
+
* `vscode` / `annotator` / `mcp` / `playwright` / …. Persisted
|
|
18
|
+
* as `annot:producer` in the XMP packet (schema 2.0). Empty /
|
|
19
|
+
* undefined for records that predate 2.0. */
|
|
20
|
+
producer?: string;
|
|
21
|
+
/** `devicePixelRatio` (or display scale factor) at capture time.
|
|
22
|
+
* Persisted as `annot:dpr` (schema 2.0). Maps device-px image
|
|
23
|
+
* dimensions back to CSS px for sources without an ElementTree.
|
|
24
|
+
* 0 / undefined when unknown. */
|
|
25
|
+
dpr?: number;
|
|
16
26
|
/** Canonical screen-capture tree captured alongside the
|
|
17
27
|
* screenshot. Source-agnostic: produced by the browser extension's
|
|
18
28
|
* MAIN-world walker, by Playwright's adapter, or by any future
|
package/dist/utils/filename.d.ts
CHANGED
|
@@ -46,3 +46,22 @@ export declare function defaultAnnotFilenameStem(date?: Date): string;
|
|
|
46
46
|
* and stray callers — and PNG (lossless) is the safer guess.
|
|
47
47
|
*/
|
|
48
48
|
export declare function defaultAnnotImageFilename(originalDataUrl: string, date?: Date): string;
|
|
49
|
+
/**
|
|
50
|
+
* Normalize a caller-supplied image filename to the `.annot.<ext>`
|
|
51
|
+
* double extension — the single identity rule for Annot-managed
|
|
52
|
+
* files (`docs/plans/metadata-unification.md` Phase 4): a file the
|
|
53
|
+
* gallery manages carries BOTH the `.annot.` infix AND the XMP
|
|
54
|
+
* packet, so every host (including the vscode custom editor, which
|
|
55
|
+
* claims `*.annot.{svg,png,jpeg,jpg}` only) recognizes it.
|
|
56
|
+
*
|
|
57
|
+
* `uploaded.png` → `uploaded.annot.png`; already-normalized names
|
|
58
|
+
* pass through unchanged; the extension is lowercased. A name with
|
|
59
|
+
* no recognizable raster/svg extension gets `.annot.png` appended
|
|
60
|
+
* (production callers always pass one — this is the safe fallback).
|
|
61
|
+
*
|
|
62
|
+
* Persistent stores apply this in `saveImage`; the extension's
|
|
63
|
+
* transient IDB staging deliberately does not (see
|
|
64
|
+
* {@link defaultAnnotImageFilename}'s note — pre-annotation
|
|
65
|
+
* captures aren't annot-native yet).
|
|
66
|
+
*/
|
|
67
|
+
export declare function normalizeAnnotImageFilename(filename: string): string;
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { assertNonNull } from './assert.js';
|
|
2
2
|
export { DEFAULT_FILL_COLOR, DEFAULT_FONT_SIZE, DEFAULT_STROKE_COLOR, DEFAULT_STROKE_WIDTH, JPEG_QUALITY, MOSAIC_BLOCK_SIZE, REDACT_BLUR_RADIUS, REDACT_SOLID_COLOR, } from './constants.js';
|
|
3
3
|
export { computeDasharray, detectDashKey } from './dash-utils.js';
|
|
4
|
-
export { ANNOT_FILENAME_PREFIX, defaultAnnotFilenameStem, defaultAnnotImageFilename, formatLocalTimestamp, } from './filename.js';
|
|
4
|
+
export { ANNOT_FILENAME_PREFIX, defaultAnnotFilenameStem, defaultAnnotImageFilename, formatLocalTimestamp, normalizeAnnotImageFilename, } from './filename.js';
|
|
5
5
|
export { newIdB58 } from './id.js';
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Wraps the Tier-A `xmp-bytes` primitives with Blob input / Blob output
|
|
5
|
-
* and adds the JPEG output path, which needs an Image + <canvas> pipeline
|
|
6
|
-
* to transcode the rendered PNG to JPEG.
|
|
7
|
-
*
|
|
8
|
-
* For Node / non-browser callers, import the Tier-A primitives
|
|
9
|
-
* directly:
|
|
10
|
-
*
|
|
11
|
-
* import { createEditablePngBytes, readEditableImage }
|
|
12
|
-
* from "@ingcreators/annot-core/xmp-bytes";
|
|
13
|
-
*
|
|
14
|
-
* Re-exports of Tier-A symbols below keep existing
|
|
15
|
-
* `@ingcreators/annot-core/xmp` consumers working unchanged.
|
|
16
|
-
*/
|
|
17
|
-
export { type AnnotMetadata, type CreateEditablePngBytesOptions, createEditablePngBytes, dataUrlToUint8Array, readEditableImage, readEditablePngBytes, WELL_KNOWN_TAG_KEYS, writePngWithTagsOnly, } from './xmp-bytes.js';
|
|
18
|
-
export interface EditableImageOptions {
|
|
1
|
+
import { XmpProvenance } from './xmp-bytes.js';
|
|
2
|
+
export { ANNOT_XMP_VERSION, type AnnotMetadata, type BuildXmpOptions, type CreateEditablePngBytesOptions, createEditablePngBytes, dataUrlToUint8Array, readEditableImage, readEditablePngBytes, WELL_KNOWN_TAG_KEYS, writePngWithTagsOnly, type XmpProvenance, } from './xmp-bytes.js';
|
|
3
|
+
export interface EditableImageOptions extends XmpProvenance {
|
|
19
4
|
/** Rendered image (screenshot + annotations) as Blob */
|
|
20
5
|
renderedBlob: Blob;
|
|
21
6
|
/** Original capture image data URL (without annotations) */
|
package/dist/xmp/xmp-bytes.d.ts
CHANGED
|
@@ -15,7 +15,38 @@
|
|
|
15
15
|
* JPEG: XMP in APP1 segment, original image in one or more APP2
|
|
16
16
|
* segments (each prefixed with `annot:OriginalImage\0`).
|
|
17
17
|
*/
|
|
18
|
-
|
|
18
|
+
/** Schema version written into `<annot:version>`. History lives in
|
|
19
|
+
* `docs/metadata-format.md`. 2.0 added the first-class provenance
|
|
20
|
+
* fields (`sourceUrl` / `createdAt` / `producer` / `dpr`) per
|
|
21
|
+
* `docs/plans/metadata-unification.md`. */
|
|
22
|
+
export declare const ANNOT_XMP_VERSION = "2.0";
|
|
23
|
+
/**
|
|
24
|
+
* Capture provenance persisted in the XMP packet since schema 2.0.
|
|
25
|
+
* All optional — omitted fields emit no element, and readers
|
|
26
|
+
* default them to `""` / `0`. See `docs/metadata-format.md`.
|
|
27
|
+
*/
|
|
28
|
+
export interface XmpProvenance {
|
|
29
|
+
/** URL of the page the capture came from. Empty / omitted for
|
|
30
|
+
* non-page sources (desktop screen capture, paste, upload). */
|
|
31
|
+
sourceUrl?: string;
|
|
32
|
+
/** ISO timestamp of the capture / import moment. NOT the file
|
|
33
|
+
* mtime — copies and syncs must not rewrite it. */
|
|
34
|
+
createdAt?: string;
|
|
35
|
+
/** What created the file: `extension` / `desktop` / `web` /
|
|
36
|
+
* `vscode` / `annotator` / `mcp` / `playwright` / … */
|
|
37
|
+
producer?: string;
|
|
38
|
+
/** `window.devicePixelRatio` (or display scale factor) at capture
|
|
39
|
+
* time. Maps device-pixel image dimensions back to CSS px for
|
|
40
|
+
* sources that never produce an ElementTree. */
|
|
41
|
+
dpr?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface BuildXmpOptions extends XmpProvenance {
|
|
44
|
+
annotationsSvg: string;
|
|
45
|
+
width: number;
|
|
46
|
+
height: number;
|
|
47
|
+
tags?: Record<string, string>;
|
|
48
|
+
}
|
|
49
|
+
export declare function buildXmp(opts: BuildXmpOptions): string;
|
|
19
50
|
export declare function u32be(n: number): Uint8Array;
|
|
20
51
|
export declare function readU32be(data: Uint8Array, offset: number): number;
|
|
21
52
|
export declare function concat(...arrays: Uint8Array[]): Uint8Array;
|
|
@@ -84,7 +115,7 @@ export declare function writePngWithTagsOnly(pngData: Uint8Array, tags: Record<s
|
|
|
84
115
|
* - `commit` — git SHA when applicable.
|
|
85
116
|
*/
|
|
86
117
|
export declare const WELL_KNOWN_TAG_KEYS: readonly ["source", "screen", "capturedAt", "commit"];
|
|
87
|
-
export interface CreateEditablePngBytesOptions {
|
|
118
|
+
export interface CreateEditablePngBytesOptions extends XmpProvenance {
|
|
88
119
|
/** Rasterised PNG bytes — the visible image, with annotations already
|
|
89
120
|
* baked into the pixels. */
|
|
90
121
|
renderedPng: Uint8Array;
|
|
@@ -128,6 +159,15 @@ export interface AnnotMetadata {
|
|
|
128
159
|
/** Opaque kv tags. Empty object when the XMP carried no `<annot:tags>`
|
|
129
160
|
* element or the embedded JSON was malformed. */
|
|
130
161
|
tags: Record<string, string>;
|
|
162
|
+
/** Schema version the packet was written with (`<annot:version>`).
|
|
163
|
+
* Empty string for packets that predate version emission. */
|
|
164
|
+
version: string;
|
|
165
|
+
/** Capture provenance (schema 2.0). Empty string / 0 when the
|
|
166
|
+
* packet doesn't carry the field. */
|
|
167
|
+
sourceUrl: string;
|
|
168
|
+
createdAt: string;
|
|
169
|
+
producer: string;
|
|
170
|
+
dpr: number;
|
|
131
171
|
}
|
|
132
172
|
/**
|
|
133
173
|
* Read XMP metadata from a re-editable PNG.
|
package/dist/xmp-bytes.js
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
//#region src/xmp/xmp-bytes.ts
|
|
2
|
-
var e = "annot", t = "https://ingcreators.com/annot/ns/1.0/", n = new TextEncoder().encode("http://ns.adobe.com/xap/1.0/\0"), r = new TextEncoder().encode("annot:OriginalImage\0"), i = new TextEncoder().encode("XML:com.adobe.xmp");
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
var e = "annot", t = "https://ingcreators.com/annot/ns/1.0/", n = new TextEncoder().encode("http://ns.adobe.com/xap/1.0/\0"), r = new TextEncoder().encode("annot:OriginalImage\0"), i = new TextEncoder().encode("XML:com.adobe.xmp"), a = "2.0";
|
|
3
|
+
function o(e) {
|
|
4
|
+
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
5
|
+
}
|
|
6
|
+
function s(e) {
|
|
7
|
+
return e.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
8
|
+
}
|
|
9
|
+
function c(n) {
|
|
10
|
+
let r = [], i = (t, n) => r.push(`\n <${e}:${t}>${n}</${e}:${t}>`), a = n.tags && Object.keys(n.tags).length > 0 ? JSON.stringify(n.tags) : "";
|
|
11
|
+
return a && i("tags", o(a)), n.sourceUrl && i("sourceUrl", o(n.sourceUrl)), n.createdAt && i("createdAt", o(n.createdAt)), n.producer && i("producer", o(n.producer)), n.dpr && n.dpr > 0 && i("dpr", String(n.dpr)), `<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
|
6
12
|
<x:xmpmeta xmlns:x="adobe:ns:meta/">
|
|
7
13
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
|
8
14
|
<rdf:Description rdf:about=""
|
|
9
15
|
xmlns:${e}="${t}">
|
|
10
|
-
<${e}:annotations><![CDATA[${n}]]></${e}:annotations>
|
|
11
|
-
<${e}:width>${
|
|
12
|
-
<${e}:height>${
|
|
13
|
-
<${e}:version>
|
|
16
|
+
<${e}:annotations><![CDATA[${n.annotationsSvg}]]></${e}:annotations>
|
|
17
|
+
<${e}:width>${n.width}</${e}:width>
|
|
18
|
+
<${e}:height>${n.height}</${e}:height>
|
|
19
|
+
<${e}:version>2.0</${e}:version>${r.join("")}
|
|
14
20
|
</rdf:Description>
|
|
15
21
|
</rdf:RDF>
|
|
16
22
|
</x:xmpmeta>
|
|
17
23
|
<?xpacket end="w"?>`;
|
|
18
24
|
}
|
|
19
|
-
function
|
|
25
|
+
function l(e) {
|
|
20
26
|
return new Uint8Array([e >> 8 & 255, e & 255]);
|
|
21
27
|
}
|
|
22
|
-
function
|
|
28
|
+
function u(e) {
|
|
23
29
|
return new Uint8Array([
|
|
24
30
|
e >> 24 & 255,
|
|
25
31
|
e >> 16 & 255,
|
|
@@ -27,58 +33,58 @@ function s(e) {
|
|
|
27
33
|
e & 255
|
|
28
34
|
]);
|
|
29
35
|
}
|
|
30
|
-
function
|
|
36
|
+
function d(e, t) {
|
|
31
37
|
return e[t] << 8 | e[t + 1];
|
|
32
38
|
}
|
|
33
|
-
function
|
|
39
|
+
function f(e, t) {
|
|
34
40
|
return (e[t] << 24 | e[t + 1] << 16 | e[t + 2] << 8 | e[t + 3]) >>> 0;
|
|
35
41
|
}
|
|
36
|
-
function
|
|
42
|
+
function p(...e) {
|
|
37
43
|
let t = 0;
|
|
38
44
|
for (let n of e) t += n.length;
|
|
39
45
|
let n = new Uint8Array(t), r = 0;
|
|
40
46
|
for (let t of e) n.set(t, r), r += t.length;
|
|
41
47
|
return n;
|
|
42
48
|
}
|
|
43
|
-
function
|
|
49
|
+
function m(e, t, n) {
|
|
44
50
|
if (t + n.length > e.length) return !1;
|
|
45
51
|
for (let r = 0; r < n.length; r++) if (e[t + r] !== n[r]) return !1;
|
|
46
52
|
return !0;
|
|
47
53
|
}
|
|
48
|
-
function
|
|
54
|
+
function h(e) {
|
|
49
55
|
let t = e.split(",")[1] || "", n = atob(t), r = new Uint8Array(n.length);
|
|
50
56
|
for (let e = 0; e < n.length; e++) r[e] = n.charCodeAt(e);
|
|
51
57
|
return r;
|
|
52
58
|
}
|
|
53
|
-
function
|
|
59
|
+
function g(e, t) {
|
|
54
60
|
let n = t.length + 2;
|
|
55
|
-
return
|
|
61
|
+
return p(new Uint8Array([255, e]), l(n), t);
|
|
56
62
|
}
|
|
57
|
-
function
|
|
63
|
+
function _(e) {
|
|
58
64
|
let t = 65533 - r.length - 4, n = Math.ceil(e.length / t), i = [];
|
|
59
65
|
for (let a = 0; a < n; a++) {
|
|
60
|
-
let
|
|
61
|
-
i.push(
|
|
66
|
+
let o = a * t, s = Math.min(o + t, e.length), c = e.slice(o, s), u = p(r, l(a), l(n), c);
|
|
67
|
+
i.push(g(226, u));
|
|
62
68
|
}
|
|
63
|
-
return
|
|
69
|
+
return p(...i);
|
|
64
70
|
}
|
|
65
|
-
function
|
|
71
|
+
function v(e) {
|
|
66
72
|
let t = [e.slice(0, 2)], i = 2;
|
|
67
73
|
for (; i + 4 <= e.length && e[i] === 255;) {
|
|
68
74
|
let a = e[i + 1];
|
|
69
|
-
if (a === 217 || a === 218) return t.push(e.slice(i)),
|
|
70
|
-
let o =
|
|
75
|
+
if (a === 217 || a === 218) return t.push(e.slice(i)), p(...t);
|
|
76
|
+
let o = d(e, i + 2), s = i + 2 + o;
|
|
71
77
|
if (s > e.length) break;
|
|
72
|
-
let
|
|
73
|
-
!
|
|
78
|
+
let c = a === 225 && m(e, i + 4, n), l = a === 226 && m(e, i + 4, r);
|
|
79
|
+
!c && !l && t.push(e.slice(i, s)), i = s;
|
|
74
80
|
}
|
|
75
|
-
return i < e.length && t.push(e.slice(i)),
|
|
81
|
+
return i < e.length && t.push(e.slice(i)), p(...t);
|
|
76
82
|
}
|
|
77
|
-
function
|
|
78
|
-
let i =
|
|
79
|
-
return
|
|
83
|
+
function y(e, t, r) {
|
|
84
|
+
let i = g(225, p(n, t)), a = _(r), o = v(e);
|
|
85
|
+
return p(o.slice(0, 2), i, a, o.slice(2));
|
|
80
86
|
}
|
|
81
|
-
var
|
|
87
|
+
var b = (() => {
|
|
82
88
|
let e = /* @__PURE__ */ new Uint32Array(256);
|
|
83
89
|
for (let t = 0; t < 256; t++) {
|
|
84
90
|
let n = t;
|
|
@@ -87,117 +93,123 @@ var _ = (() => {
|
|
|
87
93
|
}
|
|
88
94
|
return e;
|
|
89
95
|
})();
|
|
90
|
-
function
|
|
96
|
+
function x(e) {
|
|
91
97
|
let t = 4294967295;
|
|
92
|
-
for (let n = 0; n < e.length; n++) t =
|
|
98
|
+
for (let n = 0; n < e.length; n++) t = b[(t ^ e[n]) & 255] ^ t >>> 8;
|
|
93
99
|
return (t ^ 4294967295) >>> 0;
|
|
94
100
|
}
|
|
95
|
-
function
|
|
96
|
-
let n =
|
|
97
|
-
return u(
|
|
101
|
+
function S(e, t) {
|
|
102
|
+
let n = p(e, t), r = x(n);
|
|
103
|
+
return p(u(t.length), n, u(r));
|
|
98
104
|
}
|
|
99
|
-
function
|
|
100
|
-
let t =
|
|
105
|
+
function C(e) {
|
|
106
|
+
let t = p(i, new Uint8Array([
|
|
101
107
|
0,
|
|
102
108
|
0,
|
|
103
109
|
0,
|
|
104
110
|
0,
|
|
105
111
|
0
|
|
106
112
|
]), e);
|
|
107
|
-
return
|
|
113
|
+
return S(new TextEncoder().encode("iTXt"), t);
|
|
108
114
|
}
|
|
109
|
-
function
|
|
115
|
+
function w(e) {
|
|
110
116
|
let t = [e.slice(0, 8)], n = 8;
|
|
111
117
|
for (; n + 12 <= e.length;) {
|
|
112
|
-
let r =
|
|
118
|
+
let r = f(e, n), a = e.slice(n + 4, n + 8), o = n + 8, s = o + r + 4;
|
|
113
119
|
if (s > e.length) break;
|
|
114
120
|
let c = String.fromCharCode(...a);
|
|
115
|
-
!(c === "iTXt" &&
|
|
121
|
+
!(c === "iTXt" && m(e, o, i)) && c !== "svGo" && t.push(e.slice(n, s)), n = s;
|
|
116
122
|
}
|
|
117
|
-
return
|
|
123
|
+
return p(...t);
|
|
118
124
|
}
|
|
119
|
-
function
|
|
120
|
-
let r =
|
|
121
|
-
return
|
|
125
|
+
function T(e, t, n) {
|
|
126
|
+
let r = C(t), i = S(new TextEncoder().encode("svGo"), n), a = w(e), o = a.length - 12;
|
|
127
|
+
return p(a.slice(0, o), r, i, a.slice(o));
|
|
122
128
|
}
|
|
123
|
-
function
|
|
129
|
+
function E(n) {
|
|
124
130
|
return `<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
|
125
131
|
<x:xmpmeta xmlns:x="adobe:ns:meta/">
|
|
126
132
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
|
127
133
|
<rdf:Description rdf:about=""
|
|
128
134
|
xmlns:${e}="${t}">
|
|
129
|
-
<${e}:tags>${JSON.stringify(n)}</${e}:tags>
|
|
135
|
+
<${e}:tags>${o(JSON.stringify(n))}</${e}:tags>
|
|
130
136
|
</rdf:Description>
|
|
131
137
|
</rdf:RDF>
|
|
132
138
|
</x:xmpmeta>
|
|
133
139
|
<?xpacket end="w"?>`;
|
|
134
140
|
}
|
|
135
|
-
function
|
|
141
|
+
function D(e, t) {
|
|
136
142
|
if (!t || Object.keys(t).length === 0) return e;
|
|
137
|
-
let n =
|
|
138
|
-
return
|
|
143
|
+
let n = C(new TextEncoder().encode(E(t))), r = w(e), i = r.length - 12;
|
|
144
|
+
return p(r.slice(0, i), n, r.slice(i));
|
|
139
145
|
}
|
|
140
|
-
var
|
|
146
|
+
var O = [
|
|
141
147
|
"source",
|
|
142
148
|
"screen",
|
|
143
149
|
"capturedAt",
|
|
144
150
|
"commit"
|
|
145
151
|
];
|
|
146
|
-
function
|
|
147
|
-
let t =
|
|
148
|
-
return
|
|
152
|
+
function k(e) {
|
|
153
|
+
let t = c(e), n = new TextEncoder().encode(t), r = typeof e.originalImage == "string" ? h(e.originalImage) : e.originalImage;
|
|
154
|
+
return T(e.renderedPng, n, r);
|
|
149
155
|
}
|
|
150
|
-
function
|
|
151
|
-
return
|
|
156
|
+
function A(e) {
|
|
157
|
+
return N(e) ? F(e) : null;
|
|
152
158
|
}
|
|
153
|
-
function
|
|
154
|
-
return
|
|
159
|
+
function j(e) {
|
|
160
|
+
return M(e) ? P(e) : N(e) ? F(e) : null;
|
|
155
161
|
}
|
|
156
|
-
function
|
|
162
|
+
function M(e) {
|
|
157
163
|
return e[0] === 255 && e[1] === 216;
|
|
158
164
|
}
|
|
159
|
-
function
|
|
165
|
+
function N(e) {
|
|
160
166
|
return e[0] === 137 && e[1] === 80 && e[2] === 78 && e[3] === 71;
|
|
161
167
|
}
|
|
162
|
-
function
|
|
163
|
-
let t =
|
|
164
|
-
return t ?
|
|
168
|
+
function P(e) {
|
|
169
|
+
let t = R(e), n = z(e);
|
|
170
|
+
return t ? I(t, n) : null;
|
|
165
171
|
}
|
|
166
|
-
function
|
|
167
|
-
let t =
|
|
168
|
-
return t ?
|
|
172
|
+
function F(e) {
|
|
173
|
+
let t = B(e), n = V(e);
|
|
174
|
+
return t ? I(t, n) : null;
|
|
169
175
|
}
|
|
170
|
-
function
|
|
171
|
-
let n =
|
|
176
|
+
function I(e, t) {
|
|
177
|
+
let n = L(e, "annotations");
|
|
172
178
|
if (!n) return null;
|
|
173
|
-
let r = n.replace(/^<!\[CDATA\[/, "").replace(/\]\]>$/, ""), i = Number.parseInt(
|
|
174
|
-
t && t.length > 0 && (o = `data:${t[0] === 137 && t[1] === 80 ? "image/png" : "image/jpeg"};base64,${
|
|
175
|
-
let
|
|
176
|
-
if (
|
|
177
|
-
|
|
179
|
+
let r = n.replace(/^<!\[CDATA\[/, "").replace(/\]\]>$/, ""), i = Number.parseInt(L(e, "width") || "0", 10), a = Number.parseInt(L(e, "height") || "0", 10), o = "";
|
|
180
|
+
t && t.length > 0 && (o = `data:${t[0] === 137 && t[1] === 80 ? "image/png" : "image/jpeg"};base64,${H(t)}`);
|
|
181
|
+
let c = {}, l = L(e, "tags");
|
|
182
|
+
if (l) try {
|
|
183
|
+
c = JSON.parse(s(l));
|
|
178
184
|
} catch {}
|
|
185
|
+
let u = L(e, "version") || "", d = s(L(e, "sourceUrl") || ""), f = s(L(e, "createdAt") || ""), p = s(L(e, "producer") || ""), m = Number.parseFloat(L(e, "dpr") || "0") || 0;
|
|
179
186
|
return {
|
|
180
187
|
originalImageDataUrl: o,
|
|
181
188
|
annotationsSvg: r,
|
|
182
189
|
width: i,
|
|
183
190
|
height: a,
|
|
184
|
-
tags:
|
|
191
|
+
tags: c,
|
|
192
|
+
version: u,
|
|
193
|
+
sourceUrl: d,
|
|
194
|
+
createdAt: f,
|
|
195
|
+
producer: p,
|
|
196
|
+
dpr: m
|
|
185
197
|
};
|
|
186
198
|
}
|
|
187
|
-
function
|
|
199
|
+
function L(t, n) {
|
|
188
200
|
let r = `<${e}:${n}>`, i = `</${e}:${n}>`, a = t.indexOf(r);
|
|
189
201
|
if (a < 0) return null;
|
|
190
202
|
let o = t.indexOf(i, a);
|
|
191
203
|
return o < 0 ? null : t.substring(a + r.length, o);
|
|
192
204
|
}
|
|
193
|
-
function
|
|
205
|
+
function R(e) {
|
|
194
206
|
let t = 2;
|
|
195
207
|
for (; t + 4 <= e.length && e[t] === 255;) {
|
|
196
208
|
let r = e[t + 1];
|
|
197
209
|
if (r === 217 || r === 218) break;
|
|
198
|
-
let i =
|
|
210
|
+
let i = d(e, t + 2), a = t + 2 + i;
|
|
199
211
|
if (a > e.length) break;
|
|
200
|
-
if (r === 225 &&
|
|
212
|
+
if (r === 225 && m(e, t + 4, n)) {
|
|
201
213
|
let r = t + 4 + n.length;
|
|
202
214
|
return new TextDecoder().decode(e.slice(r, a));
|
|
203
215
|
}
|
|
@@ -205,17 +217,17 @@ function F(e) {
|
|
|
205
217
|
}
|
|
206
218
|
return null;
|
|
207
219
|
}
|
|
208
|
-
function
|
|
220
|
+
function z(e) {
|
|
209
221
|
let t = r.length, n = [], i = 2;
|
|
210
222
|
for (; i + 4 <= e.length && e[i] === 255;) {
|
|
211
223
|
let a = e[i + 1];
|
|
212
224
|
if (a === 217 || a === 218) break;
|
|
213
|
-
let o =
|
|
225
|
+
let o = d(e, i + 2), s = i + 2 + o;
|
|
214
226
|
if (s > e.length) break;
|
|
215
|
-
if (a === 226 &&
|
|
227
|
+
if (a === 226 && m(e, i + 4, r)) {
|
|
216
228
|
let r = i + 4 + t;
|
|
217
229
|
if (r + 4 <= s) {
|
|
218
|
-
let t =
|
|
230
|
+
let t = d(e, r), i = e.slice(r + 4, s);
|
|
219
231
|
n.push({
|
|
220
232
|
seq: t,
|
|
221
233
|
data: i
|
|
@@ -224,14 +236,14 @@ function I(e) {
|
|
|
224
236
|
}
|
|
225
237
|
i = s;
|
|
226
238
|
}
|
|
227
|
-
return n.length === 0 ? null : (n.sort((e, t) => e.seq - t.seq),
|
|
239
|
+
return n.length === 0 ? null : (n.sort((e, t) => e.seq - t.seq), p(...n.map((e) => e.data)));
|
|
228
240
|
}
|
|
229
|
-
function
|
|
241
|
+
function B(e) {
|
|
230
242
|
let t = 8;
|
|
231
243
|
for (; t + 12 <= e.length;) {
|
|
232
|
-
let n =
|
|
244
|
+
let n = f(e, t), r = String.fromCharCode(e[t + 4], e[t + 5], e[t + 6], e[t + 7]), a = t + 8, o = a + n + 4;
|
|
233
245
|
if (o > e.length) break;
|
|
234
|
-
if (r === "iTXt" &&
|
|
246
|
+
if (r === "iTXt" && m(e, a, i)) {
|
|
235
247
|
let t = a + i.length, r = 0, o = t;
|
|
236
248
|
for (let i = t; i < a + n; i++) if (e[i] === 0 && r++, r >= 4) {
|
|
237
249
|
o = i + 1;
|
|
@@ -243,17 +255,17 @@ function L(e) {
|
|
|
243
255
|
}
|
|
244
256
|
return null;
|
|
245
257
|
}
|
|
246
|
-
function
|
|
258
|
+
function V(e) {
|
|
247
259
|
let t = 8;
|
|
248
260
|
for (; t + 12 <= e.length;) {
|
|
249
|
-
let n =
|
|
261
|
+
let n = f(e, t), r = String.fromCharCode(e[t + 4], e[t + 5], e[t + 6], e[t + 7]), i = t + 8, a = i + n + 4;
|
|
250
262
|
if (a > e.length) break;
|
|
251
263
|
if (r === "svGo") return e.slice(i, i + n);
|
|
252
264
|
t = a;
|
|
253
265
|
}
|
|
254
266
|
return null;
|
|
255
267
|
}
|
|
256
|
-
function
|
|
268
|
+
function H(e) {
|
|
257
269
|
let t = 32768, n = "";
|
|
258
270
|
for (let r = 0; r < e.length; r += t) {
|
|
259
271
|
let i = e.subarray(r, Math.min(r + t, e.length));
|
|
@@ -262,4 +274,4 @@ function z(e) {
|
|
|
262
274
|
return btoa(n);
|
|
263
275
|
}
|
|
264
276
|
//#endregion
|
|
265
|
-
export {
|
|
277
|
+
export { a as ANNOT_XMP_VERSION, O as WELL_KNOWN_TAG_KEYS, S as buildPngChunk, c as buildXmp, E as buildXmpTagsOnly, p as concat, x as crc32, k as createEditablePngBytes, h as dataUrlToUint8Array, j as readEditableImage, A as readEditablePngBytes, f as readU32be, m as startsWith, w as stripPngEditableLayer, u as u32be, y as writeJpegWithMetadata, T as writePngWithMetadata, D as writePngWithTagsOnly };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ingcreators/annot-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Annot SDK — SVG-first screenshot annotation format, storage abstractions, and editor primitives. The foundation shared by the PWA, Chrome extension, Electron desktop, VSCode extension, and the headless annotator.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "ingcreators",
|
|
@@ -51,14 +51,13 @@
|
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/js-yaml": "^4.0.9",
|
|
54
|
-
"@types/pako": "^2.0.4",
|
|
55
54
|
"typescript": "^6.0.3",
|
|
56
|
-
"vite": "^8.
|
|
55
|
+
"vite": "^8.1.3",
|
|
57
56
|
"vite-plugin-dts": "^5.0.3"
|
|
58
57
|
},
|
|
59
58
|
"dependencies": {
|
|
60
59
|
"js-yaml": "^4.2.0",
|
|
61
|
-
"pako": "^
|
|
60
|
+
"pako": "^3.0.1"
|
|
62
61
|
},
|
|
63
62
|
"scripts": {
|
|
64
63
|
"build": "vite build",
|