@aglyn/aglyn 1.0.0-beta.198 → 1.0.0-beta.200
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/package.json +11 -11
- package/src/lib/app-utils/activity-search.d.ts +39 -0
- package/src/lib/app-utils/activity-search.js +85 -0
- package/src/lib/app-utils/activity-search.js.map +1 -0
- package/src/lib/app-utils/admin-audit-index.d.ts +104 -0
- package/src/lib/app-utils/admin-audit-index.js +177 -0
- package/src/lib/app-utils/admin-audit-index.js.map +1 -0
- package/src/lib/app-utils/artifact-list-keys.d.ts +51 -0
- package/src/lib/app-utils/artifact-list-keys.js +144 -0
- package/src/lib/app-utils/artifact-list-keys.js.map +1 -0
- package/src/lib/app-utils/content-query-fields.d.ts +69 -0
- package/src/lib/app-utils/content-query-fields.js +79 -0
- package/src/lib/app-utils/content-query-fields.js.map +1 -0
- package/src/lib/app-utils/crm.d.ts +151 -1
- package/src/lib/app-utils/crm.js +388 -1
- package/src/lib/app-utils/crm.js.map +1 -1
- package/src/lib/app-utils/dataset-models.d.ts +75 -24
- package/src/lib/app-utils/dataset-models.js +107 -40
- package/src/lib/app-utils/dataset-models.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.js +40 -40
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/email-search.d.ts +36 -0
- package/src/lib/app-utils/email-search.js +53 -0
- package/src/lib/app-utils/email-search.js.map +1 -0
- package/src/lib/app-utils/forms.d.ts +83 -3
- package/src/lib/app-utils/forms.js +67 -0
- package/src/lib/app-utils/forms.js.map +1 -1
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +7 -6
- package/src/lib/app-utils/marketplace-listing-visibility.js +12 -10
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +1 -1
- package/src/lib/app-utils/media-embedded-fields.d.ts +471 -0
- package/src/lib/app-utils/media-embedded-fields.js +619 -0
- package/src/lib/app-utils/media-embedded-fields.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/exif.d.ts +160 -0
- package/src/lib/app-utils/media-embedded-metadata/exif.js +1267 -0
- package/src/lib/app-utils/media-embedded-metadata/exif.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/gif.d.ts +44 -0
- package/src/lib/app-utils/media-embedded-metadata/gif.js +134 -0
- package/src/lib/app-utils/media-embedded-metadata/gif.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/heif.d.ts +23 -0
- package/src/lib/app-utils/media-embedded-metadata/heif.js +354 -0
- package/src/lib/app-utils/media-embedded-metadata/heif.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/icc.d.ts +22 -0
- package/src/lib/app-utils/media-embedded-metadata/icc.js +85 -0
- package/src/lib/app-utils/media-embedded-metadata/icc.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/image-blocks.d.ts +145 -0
- package/src/lib/app-utils/media-embedded-metadata/image-blocks.js +200 -0
- package/src/lib/app-utils/media-embedded-metadata/image-blocks.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/index.d.ts +93 -0
- package/src/lib/app-utils/media-embedded-metadata/index.js +744 -0
- package/src/lib/app-utils/media-embedded-metadata/index.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/iptc.d.ts +59 -0
- package/src/lib/app-utils/media-embedded-metadata/iptc.js +529 -0
- package/src/lib/app-utils/media-embedded-metadata/iptc.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/jpeg.d.ts +43 -0
- package/src/lib/app-utils/media-embedded-metadata/jpeg.js +456 -0
- package/src/lib/app-utils/media-embedded-metadata/jpeg.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/mp4.d.ts +37 -0
- package/src/lib/app-utils/media-embedded-metadata/mp4.js +621 -0
- package/src/lib/app-utils/media-embedded-metadata/mp4.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/ooxml.d.ts +131 -0
- package/src/lib/app-utils/media-embedded-metadata/ooxml.js +1058 -0
- package/src/lib/app-utils/media-embedded-metadata/ooxml.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/pdf-objects.d.ts +223 -0
- package/src/lib/app-utils/media-embedded-metadata/pdf-objects.js +936 -0
- package/src/lib/app-utils/media-embedded-metadata/pdf-objects.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/pdf.d.ts +82 -0
- package/src/lib/app-utils/media-embedded-metadata/pdf.js +1167 -0
- package/src/lib/app-utils/media-embedded-metadata/pdf.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/png.d.ts +41 -0
- package/src/lib/app-utils/media-embedded-metadata/png.js +512 -0
- package/src/lib/app-utils/media-embedded-metadata/png.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/svg.d.ts +30 -0
- package/src/lib/app-utils/media-embedded-metadata/svg.js +154 -0
- package/src/lib/app-utils/media-embedded-metadata/svg.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/tiff.d.ts +40 -0
- package/src/lib/app-utils/media-embedded-metadata/tiff.js +158 -0
- package/src/lib/app-utils/media-embedded-metadata/tiff.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/types.d.ts +60 -0
- package/src/lib/app-utils/media-embedded-metadata/types.js +32 -0
- package/src/lib/app-utils/media-embedded-metadata/types.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/webm.d.ts +26 -0
- package/src/lib/app-utils/media-embedded-metadata/webm.js +417 -0
- package/src/lib/app-utils/media-embedded-metadata/webm.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/webp.d.ts +37 -0
- package/src/lib/app-utils/media-embedded-metadata/webp.js +272 -0
- package/src/lib/app-utils/media-embedded-metadata/webp.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/xml.d.ts +231 -0
- package/src/lib/app-utils/media-embedded-metadata/xml.js +598 -0
- package/src/lib/app-utils/media-embedded-metadata/xml.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/xmp.d.ts +100 -0
- package/src/lib/app-utils/media-embedded-metadata/xmp.js +1475 -0
- package/src/lib/app-utils/media-embedded-metadata/xmp.js.map +1 -0
- package/src/lib/app-utils/media-embedded-metadata/zip.d.ts +93 -0
- package/src/lib/app-utils/media-embedded-metadata/zip.js +531 -0
- package/src/lib/app-utils/media-embedded-metadata/zip.js.map +1 -0
- package/src/lib/app-utils/media-metadata.d.ts +79 -0
- package/src/lib/app-utils/media-metadata.js +74 -0
- package/src/lib/app-utils/media-metadata.js.map +1 -1
- package/src/lib/app-utils/message-search.d.ts +40 -0
- package/src/lib/app-utils/message-search.js +168 -0
- package/src/lib/app-utils/message-search.js.map +1 -0
- package/src/lib/app-utils/name-search.d.ts +95 -0
- package/src/lib/app-utils/name-search.js +108 -0
- package/src/lib/app-utils/name-search.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +2 -0
- package/src/lib/app-utils/server.js +2 -0
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +11 -0
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/server.d.ts +1 -0
- package/src/server.js +7 -0
- package/src/server.js.map +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/aglyn/src/lib/app-utils/media-embedded-metadata/xml.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * A minimal, FAITHFUL XML DOM for editing XMP packets in place (AGL-3331).\n *\n * ## Why not a general XML library\n *\n * An XMP packet written by Lightroom or Photoshop carries structures this\n * module does not understand — `xmpMM:History`, `crs:*` tone curves,\n * `mwg-rs` face regions, contact-info structs — and an edit of one caption\n * must leave every one of them exactly as it was. A conventional DOM\n * normalizes on the way in (quote style, attribute whitespace, entity\n * spelling, `<a/>` versus `<a></a>`), so a round trip through it rewrites\n * the whole packet. This one keeps the raw text of everything it parses\n * next to the decoded value, and {@link serializeXml} writes the raw text\n * back, so `serializeXml(parseXml(s)) === s` for any input it accepts and\n * only the nodes an edit touched come out different.\n *\n * ## What it refuses\n *\n * The input is hostile: it arrives inside an uploaded file. There is NO DTD\n * support at all — `<!DOCTYPE`, and with it `<!ENTITY`, external entities\n * and entity expansion (\"billion laughs\"), are unparseable, as is any named\n * entity other than the five XML predefines (XML 1.0 §4.6). Depth, node\n * count and input length are bounded. Everything that is not well-formed\n * returns `null`; nothing here throws on input.\n *\n * It is deliberately lenient in one direction only: content outside the\n * root element (the `<?xpacket?>` wrappers, trailing padding, a BOM) is\n * kept as nodes of the document rather than rejected, because XMP packets\n * live in exactly that space and a fragment handed over from an SVG's\n * `<metadata>` may have several top-level elements.\n */\n\n/** The `xml:` prefix is bound by definition (Namespaces in XML 1.0 §3). */\nexport const XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'\n/** The `xmlns:` prefix is bound by definition (Namespaces in XML 1.0 §3). */\nexport const XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/'\n\n/** Default parse bounds. XMP packets are kilobytes; these are generous. */\nexport const XML_MAX_DEPTH = 64\nexport const XML_MAX_NODES = 50_000\nexport const XML_MAX_LENGTH = 16 * 1024 * 1024\n\nexport interface XmlLimits {\n /** Element nesting depth; the root element is depth 1. */\n maxDepth?: number\n /** Elements, attributes, text, CDATA, comments and PIs together. */\n maxNodes?: number\n /** Input length in UTF-16 code units. */\n maxLength?: number\n}\n\nexport interface XmlDocument {\n type: 'document'\n children: XmlNode[]\n}\n\nexport type XmlNode =\n XmlElement | XmlText | XmlCData | XmlComment | XmlProcessingInstruction\n\nexport type XmlParent = XmlDocument | XmlElement\n\nexport interface XmlElement {\n type: 'element'\n /** The qualified name as written, prefix included. */\n name: string\n /** In source order; order is part of what a round trip preserves. */\n attributes: XmlAttribute[]\n children: XmlNode[]\n parent: XmlParent | null\n /**\n * Written as `<a/>`. Only honored while the element has no children, so\n * appending to a self-closed element serializes it as `<a>…</a>`.\n */\n selfClosing: boolean\n /** Whitespace after the last attribute (or the name), before `>`/`/>`. */\n tagTail: string\n /** Whitespace between the name and `>` of the end tag: `</a >`. */\n endTagTail: string\n}\n\nexport interface XmlAttribute {\n /** The qualified name as written. */\n name: string\n /**\n * The decoded, normalized value (XML 1.0 §3.3.3): entity and character\n * references resolved, literal tabs and newlines turned into spaces.\n */\n value: string\n /** Exactly what was between the quotes. Serialized as-is. */\n raw: string\n quote: '\"' | \"'\"\n /** Whitespace before the name — a space, or a newline and an indent. */\n leading: string\n /** The `=` with whatever whitespace the author put around it. */\n equals: string\n}\n\nexport interface XmlText {\n type: 'text'\n /** Decoded (references resolved, line ends normalized, XML 1.0 §2.11). */\n value: string\n /** Exactly as written. Serialized as-is. */\n raw: string\n}\n\nexport interface XmlCData {\n type: 'cdata'\n value: string\n}\n\nexport interface XmlComment {\n type: 'comment'\n value: string\n}\n\nexport interface XmlProcessingInstruction {\n type: 'pi'\n target: string\n /** Everything after the target up to `?>`, leading whitespace included. */\n data: string\n}\n\n/*\n * XML 1.0 (Fifth Edition) §2.3, NameStartChar and NameChar, exactly. The\n * `u` flag makes the astral range one range of code points rather than a\n * pair of surrogate halves. The combining-mark range leads NameChar so no\n * base character sits right before it in the class.\n */\nconst NAME_START =\n 'A-Za-z_:\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D' +\n '\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF' +\n '\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD\\\\u{10000}-\\\\u{EFFFF}'\nconst NAME_CHAR =\n '\\\\u0300-\\\\u036F' + NAME_START + '\\\\-.0-9\\\\u00B7\\\\u203F-\\\\u2040'\nconst NAME = new RegExp(`[${NAME_START}][${NAME_CHAR}]*`, 'uy')\nconst WHITESPACE = /[ \\t\\r\\n]*/y\nconst EQUALS = /[ \\t\\r\\n]*=[ \\t\\r\\n]*/y\nconst ALL_WHITESPACE = /^[ \\t\\r\\n]*$/\n\n/** Read a Name at `pos` with a sticky regex, or null. */\nfunction matchAt(pattern: RegExp, input: string, pos: number): string | null {\n pattern.lastIndex = pos\n const match = pattern.exec(input)\n return match ? match[0] : null\n}\n\n/**\n * Whether a code point is a legal XML 1.0 `Char` (§2.2). Character\n * references to anything else — `�`, a lone surrogate — are not\n * well-formed.\n */\nfunction isXmlChar(code: number): boolean {\n return (\n code === 0x9 ||\n code === 0xa ||\n code === 0xd ||\n (code >= 0x20 && code <= 0xd7ff) ||\n (code >= 0xe000 && code <= 0xfffd) ||\n (code >= 0x10000 && code <= 0x10ffff)\n )\n}\n\nconst PREDEFINED_ENTITIES: Record<string, string> = {\n lt: '<',\n gt: '>',\n amp: '&',\n quot: '\"',\n apos: \"'\",\n}\n\n/**\n * Decode the raw text of a text node or an attribute value.\n *\n * Applies the normalizations a conforming parser applies, in the order the\n * spec gives them: line ends first (§2.11, CRLF and lone CR become LF),\n * then — for attributes only — each literal whitespace character becomes a\n * space (§3.3.3), then references are replaced. A character produced by a\n * reference is NOT normalized, which is how `
` survives in an\n * attribute. Returns null for an undeclared entity, a bare `&` or a\n * reference to a character XML cannot hold.\n */\nexport function decodeXmlText(raw: string, attribute = false): string | null {\n let text = raw\n if (text.includes('\\r')) text = text.replace(/\\r\\n?/g, '\\n')\n if (attribute && /[\\t\\n]/.test(text)) text = text.replace(/[\\t\\n]/g, ' ')\n if (!text.includes('&')) return text\n let out = ''\n let pos = 0\n for (;;) {\n const amp = text.indexOf('&', pos)\n if (amp === -1) break\n const semi = text.indexOf(';', amp + 1)\n // The longest legal reference is a padded numeric one; 32 is generous.\n if (semi === -1 || semi - amp > 32) return null\n const ref = text.slice(amp + 1, semi)\n let decoded: string | undefined\n if (ref.startsWith('#x')) {\n if (!/^#x[0-9A-Fa-f]+$/.test(ref)) return null\n const code = parseInt(ref.slice(2), 16)\n if (!isXmlChar(code)) return null\n decoded = String.fromCodePoint(code)\n } else if (ref.startsWith('#')) {\n if (!/^#[0-9]+$/.test(ref)) return null\n const code = parseInt(ref.slice(1), 10)\n if (!isXmlChar(code)) return null\n decoded = String.fromCodePoint(code)\n } else {\n decoded = Object.prototype.hasOwnProperty.call(PREDEFINED_ENTITIES, ref)\n ? PREDEFINED_ENTITIES[ref]\n : undefined\n if (decoded === undefined) return null\n }\n out += text.slice(pos, amp) + decoded\n pos = semi + 1\n }\n return out + text.slice(pos)\n}\n\n/**\n * Escape a value for a text node. `>` is escaped too so a value can never\n * spell `]]>`, and CR is written as a reference because a parser would\n * otherwise normalize it away (§2.11).\n */\nexport function escapeXmlText(value: string): string {\n return value.replace(/[&<>\\r]/g, (ch) =>\n ch === '&' ? '&' : ch === '<' ? '<' : ch === '>' ? '>' : '
',\n )\n}\n\n/**\n * Escape a value for an attribute delimited by `quote`. Tab, LF and CR are\n * written as references so attribute-value normalization (§3.3.3) does not\n * turn them into spaces on the next read.\n */\nexport function escapeXmlAttribute(\n value: string,\n quote: '\"' | \"'\" = '\"',\n): string {\n return value.replace(/[&<>\"'\\t\\n\\r]/g, (ch) => {\n switch (ch) {\n case '&':\n return '&'\n case '<':\n return '<'\n case '>':\n return '>'\n case '\"':\n return quote === '\"' ? '"' : ch\n case \"'\":\n return quote === \"'\" ? ''' : ch\n case '\\t':\n return '	'\n case '\\n':\n return '
'\n default:\n return '
'\n }\n })\n}\n\n/**\n * Whether a string holds a character that XML 1.0 cannot represent at all,\n * not even as a reference (§2.2): C0 controls other than tab/LF/CR, U+FFFE,\n * U+FFFF and unpaired surrogates. A writer must refuse such a value rather\n * than emit a packet no reader will parse.\n */\nexport function hasNonXmlCharacters(value: string): boolean {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i)\n if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(i + 1)\n if (next >= 0xdc00 && next <= 0xdfff) {\n i++\n continue\n }\n return true\n }\n if (!isXmlChar(code)) return true\n }\n return false\n}\n\n/**\n * Parse `input` into a faithful DOM, or return null when it is not\n * well-formed, declares a DTD, or exceeds a bound. Never throws.\n *\n * The parser is iterative — an explicit stack, not recursion — so a\n * hostile nesting depth costs a counter check, not the call stack.\n */\nexport function parseXml(\n input: string,\n limits: XmlLimits = {},\n): XmlDocument | null {\n try {\n return parse(input, limits)\n } catch {\n // Defensive only: every path below returns null rather than throwing,\n // and a parser of hostile bytes must not become a 500 if one is missed.\n return null\n }\n}\n\nfunction parse(input: string, limits: XmlLimits): XmlDocument | null {\n if (typeof input !== 'string') return null\n const maxDepth = limits.maxDepth ?? XML_MAX_DEPTH\n const maxNodes = limits.maxNodes ?? XML_MAX_NODES\n const maxLength = limits.maxLength ?? XML_MAX_LENGTH\n if (input.length > maxLength) return null\n\n const doc: XmlDocument = { type: 'document', children: [] }\n const stack: XmlParent[] = [doc]\n let nodes = 0\n let pos = 0\n const length = input.length\n\n const current = (): XmlParent => stack[stack.length - 1] ?? doc\n const add = (node: XmlNode): boolean => {\n if (++nodes > maxNodes) return false\n const parent = current()\n if (node.type === 'element') node.parent = parent\n parent.children.push(node)\n return true\n }\n\n while (pos < length) {\n const lt = input.indexOf('<', pos)\n const textEnd = lt === -1 ? length : lt\n if (textEnd > pos) {\n const raw = input.slice(pos, textEnd)\n const value = decodeXmlText(raw)\n if (value === null) return null\n if (!add({ type: 'text', value, raw })) return null\n pos = textEnd\n continue\n }\n\n // `input[pos]` is '<'.\n if (input.startsWith('<!--', pos)) {\n const end = input.indexOf('-->', pos + 4)\n if (end === -1) return null\n if (!add({ type: 'comment', value: input.slice(pos + 4, end) }))\n return null\n pos = end + 3\n continue\n }\n if (input.startsWith('<![CDATA[', pos)) {\n // CDATA is content (§2.7): it cannot stand outside an element.\n if (stack.length === 1) return null\n const end = input.indexOf(']]>', pos + 9)\n if (end === -1) return null\n if (!add({ type: 'cdata', value: input.slice(pos + 9, end) })) return null\n pos = end + 3\n continue\n }\n if (input.startsWith('<!', pos)) {\n // <!DOCTYPE, <!ENTITY, <!ELEMENT, <!ATTLIST … — no DTD, ever.\n return null\n }\n if (input.startsWith('<?', pos)) {\n const target = matchAt(NAME, input, pos + 2)\n if (!target) return null\n const end = input.indexOf('?>', pos + 2 + target.length)\n if (end === -1) return null\n const data = input.slice(pos + 2 + target.length, end)\n // PI data is separated from its target by whitespace (§2.6).\n if (data && !/^[ \\t\\r\\n]/.test(data)) return null\n if (!add({ type: 'pi', target, data })) return null\n pos = end + 2\n continue\n }\n if (input.startsWith('</', pos)) {\n const name = matchAt(NAME, input, pos + 2)\n if (!name) return null\n let cursor = pos + 2 + name.length\n const tail = matchAt(WHITESPACE, input, cursor) ?? ''\n cursor += tail.length\n if (input[cursor] !== '>') return null\n const open = current()\n if (open.type !== 'element' || open.name !== name) return null\n open.endTagTail = tail\n stack.pop()\n pos = cursor + 1\n continue\n }\n\n // A start tag (§3.1).\n const name = matchAt(NAME, input, pos + 1)\n if (!name) return null\n if (stack.length > maxDepth) return null\n const element: XmlElement = {\n type: 'element',\n name,\n attributes: [],\n children: [],\n parent: null,\n selfClosing: false,\n tagTail: '',\n endTagTail: '',\n }\n if (!add(element)) return null\n let cursor = pos + 1 + name.length\n const seen = new Set<string>()\n for (;;) {\n const space = matchAt(WHITESPACE, input, cursor) ?? ''\n cursor += space.length\n if (input[cursor] === '>') {\n element.tagTail = space\n cursor += 1\n stack.push(element)\n break\n }\n if (input.startsWith('/>', cursor)) {\n element.tagTail = space\n element.selfClosing = true\n cursor += 2\n break\n }\n // Attributes are separated from the name and each other by space.\n if (!space) return null\n const attrName = matchAt(NAME, input, cursor)\n if (!attrName) return null\n cursor += attrName.length\n const equals = matchAt(EQUALS, input, cursor)\n if (!equals) return null\n cursor += equals.length\n const quote = input[cursor]\n if (quote !== '\"' && quote !== \"'\") return null\n const close = input.indexOf(quote, cursor + 1)\n if (close === -1) return null\n const raw = input.slice(cursor + 1, close)\n // `<` may not appear in an attribute value, even escaped-looking.\n if (raw.includes('<')) return null\n const value = decodeXmlText(raw, true)\n if (value === null) return null\n // Unique attribute names (§3.1, WFC: Unique Att Spec).\n if (seen.has(attrName)) return null\n seen.add(attrName)\n if (++nodes > maxNodes) return null\n element.attributes.push({\n name: attrName,\n value,\n raw,\n quote,\n leading: space,\n equals,\n })\n cursor = close + 1\n }\n pos = cursor\n }\n\n // An element still open at the end of input is an unterminated tag.\n if (stack.length !== 1) return null\n return doc\n}\n\n/** Serialize a document or node back to text, raw spellings preserved. */\nexport function serializeXml(node: XmlDocument | XmlNode): string {\n const out: string[] = []\n write(node, out)\n return out.join('')\n}\n\nfunction write(node: XmlDocument | XmlNode, out: string[]): void {\n switch (node.type) {\n case 'document':\n for (const child of node.children) write(child, out)\n return\n case 'text':\n out.push(node.raw)\n return\n case 'cdata':\n out.push('<![CDATA[', node.value, ']]>')\n return\n case 'comment':\n out.push('<!--', node.value, '-->')\n return\n case 'pi':\n out.push('<?', node.target, node.data, '?>')\n return\n case 'element': {\n out.push('<', node.name)\n for (const attr of node.attributes) {\n out.push(\n attr.leading,\n attr.name,\n attr.equals,\n attr.quote,\n attr.raw,\n attr.quote,\n )\n }\n out.push(node.tagTail)\n if (node.selfClosing && !node.children.length) {\n out.push('/>')\n return\n }\n out.push('>')\n for (const child of node.children) write(child, out)\n out.push('</', node.name, node.endTagTail, '>')\n return\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Construction and mutation. Every helper keeps `raw` in step with `value`\n// and `parent` in step with `children`, so a serializer pass never has to\n// guess which of the two is current.\n// ---------------------------------------------------------------------------\n\n/** A text node whose raw spelling is the escaped value. */\nexport function createText(value: string): XmlText {\n return { type: 'text', value, raw: escapeXmlText(value) }\n}\n\n/**\n * A whitespace-only text node written verbatim — indentation copied from\n * the document, where escaping a CR would turn `\\r\\n` into `
\\n`.\n * Anything that is not XML whitespace is dropped.\n */\nexport function createWhitespace(raw: string): XmlText {\n const clean = raw.replace(/[^ \\t\\r\\n]/g, '')\n return { type: 'text', value: clean.replace(/\\r\\n?/g, '\\n'), raw: clean }\n}\n\n/** A new element; attributes are `[name, value]` pairs, space-separated. */\nexport function createElement(\n name: string,\n attributes: ReadonlyArray<readonly [string, string]> = [],\n children: XmlNode[] = [],\n quote: '\"' | \"'\" = '\"',\n): XmlElement {\n const element: XmlElement = {\n type: 'element',\n name,\n attributes: attributes.map(([attrName, value]) => ({\n name: attrName,\n value,\n raw: escapeXmlAttribute(value, quote),\n quote,\n leading: ' ',\n equals: '=',\n })),\n children: [],\n parent: null,\n selfClosing: false,\n tagTail: '',\n endTagTail: '',\n }\n insertChildren(element, 0, children)\n return element\n}\n\n/** Insert nodes at `index`, adopting any elements among them. */\nexport function insertChildren(\n parent: XmlParent,\n index: number,\n nodes: XmlNode[],\n): void {\n for (const node of nodes) {\n if (node.type === 'element') node.parent = parent\n }\n parent.children.splice(index, 0, ...nodes)\n}\n\n/** Replace every child of `parent`. */\nexport function replaceChildren(parent: XmlParent, nodes: XmlNode[]): void {\n parent.children = []\n insertChildren(parent, 0, nodes)\n}\n\n/** Remove one child. Returns false when it was not a child of `parent`. */\nexport function removeChild(parent: XmlParent, node: XmlNode): boolean {\n const index = parent.children.indexOf(node)\n if (index === -1) return false\n parent.children.splice(index, 1)\n if (node.type === 'element') node.parent = null\n return true\n}\n\nexport function getAttribute(\n element: XmlElement,\n name: string,\n): XmlAttribute | undefined {\n return element.attributes.find((attr) => attr.name === name)\n}\n\n/**\n * Set an attribute's value. An existing attribute keeps its position,\n * quote style and surrounding whitespace; a new one is appended with\n * `leading` before it.\n */\nexport function setAttribute(\n element: XmlElement,\n name: string,\n value: string,\n options: { leading?: string; quote?: '\"' | \"'\"; index?: number } = {},\n): XmlAttribute {\n const existing = getAttribute(element, name)\n if (existing) {\n existing.value = value\n existing.raw = escapeXmlAttribute(value, existing.quote)\n return existing\n }\n const quote = options.quote ?? '\"'\n const attr: XmlAttribute = {\n name,\n value,\n raw: escapeXmlAttribute(value, quote),\n quote,\n leading: options.leading ?? ' ',\n equals: '=',\n }\n const index = options.index ?? element.attributes.length\n element.attributes.splice(\n Math.max(0, Math.min(index, element.attributes.length)),\n 0,\n attr,\n )\n return attr\n}\n\nexport function removeAttribute(element: XmlElement, name: string): boolean {\n const index = element.attributes.findIndex((attr) => attr.name === name)\n if (index === -1) return false\n element.attributes.splice(index, 1)\n return true\n}\n\n/** Replace an element's content with one text node (none for ''). */\nexport function setTextContent(element: XmlElement, value: string): void {\n replaceChildren(element, value ? [createText(value)] : [])\n // `<a/>` would read back as '' either way; an explicit pair is clearer\n // for a property that was just given a value.\n if (value) element.selfClosing = false\n}\n\n/** The decoded text of an element's direct text and CDATA children. */\nexport function textContent(element: XmlElement): string {\n let out = ''\n for (const child of element.children) {\n if (child.type === 'text' || child.type === 'cdata') out += child.value\n }\n return out\n}\n\nexport function elementChildren(parent: XmlParent): XmlElement[] {\n return parent.children.filter(\n (child): child is XmlElement => child.type === 'element',\n )\n}\n\n/** Whether a text node is nothing but XML whitespace. */\nexport function isWhitespaceText(node: XmlNode | undefined): node is XmlText {\n return node?.type === 'text' && ALL_WHITESPACE.test(node.raw)\n}\n\n/**\n * Visit every element in document order, iteratively. Return `false` from\n * `visit` to skip an element's descendants.\n */\nexport function walkElements(\n root: XmlParent,\n visit: (element: XmlElement) => boolean | void,\n): void {\n const pending: XmlNode[] = [...root.children].reverse()\n while (pending.length) {\n const node = pending.pop()\n if (!node || node.type !== 'element') continue\n if (visit(node) === false) continue\n for (let i = node.children.length - 1; i >= 0; i--) {\n const child = node.children[i]\n if (child) pending.push(child)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Namespaces (Namespaces in XML 1.0, Third Edition).\n// ---------------------------------------------------------------------------\n\n/** `dc:title` → `{ prefix: 'dc', local: 'title' }`; no colon → prefix ''. */\nexport function splitQName(name: string): { prefix: string; local: string } {\n const colon = name.indexOf(':')\n return colon === -1\n ? { prefix: '', local: name }\n : { prefix: name.slice(0, colon), local: name.slice(colon + 1) }\n}\n\n/**\n * The namespace URI `prefix` is bound to at `element`, through the nearest\n * `xmlns:prefix` (or, for `''`, `xmlns`) on it or an ancestor. Null when\n * unbound — or, for the default namespace, explicitly undeclared (§6.2).\n */\nexport function resolvePrefix(\n element: XmlElement,\n prefix: string,\n): string | null {\n if (prefix === 'xml') return XML_NAMESPACE\n if (prefix === 'xmlns') return XMLNS_NAMESPACE\n const declaration = prefix ? `xmlns:${prefix}` : 'xmlns'\n let cursor: XmlParent | null = element\n while (cursor && cursor.type === 'element') {\n const attr = getAttribute(cursor, declaration)\n if (attr) return attr.value || null\n cursor = cursor.parent\n }\n return null\n}\n\n/** An element's namespace URI: its prefix's, or the default namespace. */\nexport function elementNamespace(element: XmlElement): string | null {\n return resolvePrefix(element, splitQName(element.name).prefix)\n}\n\n/**\n * An attribute's namespace URI. An unprefixed attribute is in NO namespace\n * — the default namespace does not apply to attributes (§6.2).\n */\nexport function attributeNamespace(\n element: XmlElement,\n attr: XmlAttribute,\n): string | null {\n if (attr.name === 'xmlns') return XMLNS_NAMESPACE\n const { prefix } = splitQName(attr.name)\n return prefix ? resolvePrefix(element, prefix) : null\n}\n\n/** Whether an attribute is a namespace declaration. */\nexport function isNamespaceDeclaration(attr: XmlAttribute): boolean {\n return attr.name === 'xmlns' || attr.name.startsWith('xmlns:')\n}\n\n/**\n * A prefix bound to `uri` in scope at `element` and not shadowed by a\n * nearer declaration of the same prefix, or null. The default namespace is\n * never returned: an attribute cannot use it.\n */\nexport function prefixForNamespace(\n element: XmlElement,\n uri: string,\n): string | null {\n let cursor: XmlParent | null = element\n while (cursor && cursor.type === 'element') {\n for (const attr of cursor.attributes) {\n if (!attr.name.startsWith('xmlns:') || attr.value !== uri) continue\n const prefix = attr.name.slice(6)\n if (resolvePrefix(element, prefix) === uri) return prefix\n }\n cursor = cursor.parent\n }\n return null\n}\n"],"names":["XML_NAMESPACE","XMLNS_NAMESPACE","XML_MAX_DEPTH","XML_MAX_NODES","XML_MAX_LENGTH","NAME_START","NAME_CHAR","NAME","RegExp","WHITESPACE","EQUALS","ALL_WHITESPACE","matchAt","pattern","input","pos","lastIndex","match","exec","isXmlChar","code","PREDEFINED_ENTITIES","lt","gt","amp","quot","apos","decodeXmlText","raw","attribute","text","includes","replace","test","out","indexOf","semi","ref","slice","decoded","startsWith","parseInt","String","fromCodePoint","Object","prototype","hasOwnProperty","call","undefined","escapeXmlText","value","ch","escapeXmlAttribute","quote","hasNonXmlCharacters","i","length","charCodeAt","next","parseXml","limits","parse","maxDepth","maxNodes","maxLength","doc","type","children","stack","nodes","current","add","node","parent","push","textEnd","end","target","data","name","cursor","tail","open","endTagTail","pop","element","attributes","selfClosing","tagTail","seen","Set","space","attrName","equals","close","has","leading","serializeXml","write","join","child","attr","createText","createWhitespace","clean","createElement","map","insertChildren","index","splice","replaceChildren","removeChild","getAttribute","find","setAttribute","options","existing","Math","max","min","removeAttribute","findIndex","setTextContent","textContent","elementChildren","filter","isWhitespaceText","walkElements","root","visit","pending","reverse","splitQName","colon","prefix","local","resolvePrefix","declaration","elementNamespace","attributeNamespace","isNamespaceDeclaration","prefixForNamespace","uri"],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { type EmbeddedCandidate, type EmbeddedPatch } from './types';
|
|
18
|
+
/** Namespace URIs, by the prefix their specifications use. */
|
|
19
|
+
export declare const XMP_NAMESPACES: {
|
|
20
|
+
readonly rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
|
|
21
|
+
readonly x: "adobe:ns:meta/";
|
|
22
|
+
readonly dc: "http://purl.org/dc/elements/1.1/";
|
|
23
|
+
readonly xmp: "http://ns.adobe.com/xap/1.0/";
|
|
24
|
+
readonly xmpRights: "http://ns.adobe.com/xap/1.0/rights/";
|
|
25
|
+
readonly xmpMM: "http://ns.adobe.com/xap/1.0/mm/";
|
|
26
|
+
readonly xmpidq: "http://ns.adobe.com/xmp/Identifier/qual/1.0/";
|
|
27
|
+
readonly xmpNote: "http://ns.adobe.com/xmp/note/";
|
|
28
|
+
readonly xmpG: "http://ns.adobe.com/xap/1.0/g/";
|
|
29
|
+
readonly xmpGImg: "http://ns.adobe.com/xap/1.0/g/img/";
|
|
30
|
+
readonly xmpTPg: "http://ns.adobe.com/xap/1.0/t/pg/";
|
|
31
|
+
readonly stEvt: "http://ns.adobe.com/xap/1.0/sType/ResourceEvent#";
|
|
32
|
+
readonly stRef: "http://ns.adobe.com/xap/1.0/sType/ResourceRef#";
|
|
33
|
+
readonly stDim: "http://ns.adobe.com/xap/1.0/sType/Dimensions#";
|
|
34
|
+
readonly stFnt: "http://ns.adobe.com/xap/1.0/sType/Font#";
|
|
35
|
+
readonly stArea: "http://ns.adobe.com/xmp/sType/Area#";
|
|
36
|
+
readonly photoshop: "http://ns.adobe.com/photoshop/1.0/";
|
|
37
|
+
readonly illustrator: "http://ns.adobe.com/illustrator/1.0/";
|
|
38
|
+
readonly crs: "http://ns.adobe.com/camera-raw-settings/1.0/";
|
|
39
|
+
readonly crss: "http://ns.adobe.com/camera-raw-saved-settings/1.0/";
|
|
40
|
+
readonly tiff: "http://ns.adobe.com/tiff/1.0/";
|
|
41
|
+
readonly exif: "http://ns.adobe.com/exif/1.0/";
|
|
42
|
+
readonly exifEX: "http://cipa.jp/exif/1.0/";
|
|
43
|
+
readonly aux: "http://ns.adobe.com/exif/1.0/aux/";
|
|
44
|
+
readonly pdf: "http://ns.adobe.com/pdf/1.3/";
|
|
45
|
+
readonly pdfx: "http://ns.adobe.com/pdfx/1.3/";
|
|
46
|
+
readonly Iptc4xmpCore: "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/";
|
|
47
|
+
readonly 'mwg-rs': "http://www.metadataworkinggroup.com/schemas/regions/";
|
|
48
|
+
readonly cc: "http://creativecommons.org/ns#";
|
|
49
|
+
};
|
|
50
|
+
export type XmpProfile = 'image' | 'pdf';
|
|
51
|
+
export interface XmpReadOptions {
|
|
52
|
+
/**
|
|
53
|
+
* `pdf` reads `createdAt` from `xmp:CreateDate` only, as a PDF's XMP
|
|
54
|
+
* mirrors the document info's `/CreationDate` there. Default `image`.
|
|
55
|
+
*/
|
|
56
|
+
profile?: XmpProfile;
|
|
57
|
+
}
|
|
58
|
+
export interface XmpWriteOptions {
|
|
59
|
+
profile: XmpProfile;
|
|
60
|
+
/** The instant stamped into `xmp:MetadataDate` (and PDF ModifyDate). */
|
|
61
|
+
now: Date;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* An XMP date (XMP Part 1 §8.2.1.1: ISO 8601 as profiled by the W3C
|
|
65
|
+
* datetime note) in the catalog's format. Fractional seconds are cut to
|
|
66
|
+
* milliseconds, a `+0200` zone gains its colon, and the EXIF spelling
|
|
67
|
+
* `2021:05:03 10:11:12` some writers put in XMP is accepted. A zone is
|
|
68
|
+
* kept only when the file wrote one. Reduced precision (`2021`,
|
|
69
|
+
* `2021-05`) is returned as written — a month cannot be invented.
|
|
70
|
+
*/
|
|
71
|
+
export declare function normalizeXmpDate(raw: string): string | null;
|
|
72
|
+
/**
|
|
73
|
+
* Read an XMP packet into candidates. Accepts a whole packet (`<?xpacket`
|
|
74
|
+
* wrapper and `x:xmpmeta`), a bare `x:xmpmeta`, or a bare `rdf:RDF`
|
|
75
|
+
* fragment. Never throws; unreadable input yields `[]`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function readXmp(packet: string, options?: XmpReadOptions): EmbeddedCandidate[];
|
|
78
|
+
/**
|
|
79
|
+
* Apply `patch` to `packet` and return the new packet.
|
|
80
|
+
*
|
|
81
|
+
* - `null` removes a key; a string or string[] sets it. An empty string or
|
|
82
|
+
* list is a removal.
|
|
83
|
+
* - Canonical keys fan out as {@link canonicalWrites} lists them. Keys XMP
|
|
84
|
+
* has no place for (`subject`, a `png|…` key) are ignored — the patch is
|
|
85
|
+
* shared with the file's other writers — and the camera's measurements
|
|
86
|
+
* (`exposure`, …) throw.
|
|
87
|
+
* - `gps: null` removes every `exif:GPS*` property. Setting it throws.
|
|
88
|
+
* - An `xmp|<uri>|<local>` key edits or removes a property that already
|
|
89
|
+
* exists; one that does not, or that the reader would never offer,
|
|
90
|
+
* throws.
|
|
91
|
+
* - `xmp:MetadataDate` is set to `now` on every write; in the `pdf`
|
|
92
|
+
* profile `xmp:ModifyDate` is too, unless the patch sets `modifiedAt`.
|
|
93
|
+
* - With `packet === null`, a fresh packet is created if the patch sets
|
|
94
|
+
* anything XMP holds; otherwise the result is `null`.
|
|
95
|
+
*
|
|
96
|
+
* Throws {@link EmbeddedWriteError} when the packet cannot be parsed, has
|
|
97
|
+
* no `rdf:RDF`, or the edit is not one XMP can take. Never returns a
|
|
98
|
+
* packet it could not re-read.
|
|
99
|
+
*/
|
|
100
|
+
export declare function writeXmp(packet: string | null, patch: EmbeddedPatch, options: XmpWriteOptions): string | null;
|