@gmickel/gno 1.45.1 → 2.0.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.
Files changed (236) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.md +46 -0
  3. package/assets/skill/SKILL.md +7 -6
  4. package/assets/skill/cli-reference.md +14 -6
  5. package/assets/skill/mcp-reference.md +4 -1
  6. package/assets/spa-production.json.gz +0 -0
  7. package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip +0 -0
  8. package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip.sha256 +1 -0
  9. package/browser-extension/dist/chunk-4tc9v0ja.js +74 -0
  10. package/browser-extension/dist/manifest.json +1 -1
  11. package/browser-extension/dist/preview.html +1 -1
  12. package/browser-extension/dist/service-worker.js +32 -33
  13. package/bunfig.toml +2 -0
  14. package/package.json +40 -26
  15. package/spec/cli.md +30 -11
  16. package/spec/db/schema.sql +146 -1
  17. package/spec/mcp.md +26 -0
  18. package/src/app/context-runtime-types.ts +3 -0
  19. package/src/app/context-runtime.ts +2 -0
  20. package/src/cli/commands/ask.ts +6 -1
  21. package/src/cli/commands/daemon.ts +21 -8
  22. package/src/cli/commands/embed.ts +77 -41
  23. package/src/cli/commands/mcp/install.ts +20 -0
  24. package/src/cli/commands/mcp/paths.ts +25 -0
  25. package/src/cli/commands/mcp/status.ts +6 -0
  26. package/src/cli/detach.ts +3 -2
  27. package/src/cli/program.ts +6 -0
  28. package/src/config/types.ts +3 -3
  29. package/src/converters/adapters/markitdownTs/adapter.ts +1 -2
  30. package/src/converters/adapters/officeparser/adapter.ts +1 -2
  31. package/src/converters/versions.ts +6 -8
  32. package/src/core/context-evidence.ts +8 -4
  33. package/src/core/job-manager.ts +95 -13
  34. package/src/core/network-boundary-inventory.ts +10 -0
  35. package/src/core/shutdown-budget.ts +45 -0
  36. package/src/embed/backlog.ts +107 -4
  37. package/src/embed/batch.ts +42 -2
  38. package/src/embed/fingerprint.ts +16 -0
  39. package/src/embed/retry.ts +113 -5
  40. package/src/embed/variant-backlog.ts +105 -0
  41. package/src/embed/variant-plan.ts +62 -0
  42. package/src/embed/variant-retry.ts +113 -0
  43. package/src/ingestion/graph-reconciliation.ts +327 -0
  44. package/src/ingestion/sync.ts +9 -272
  45. package/src/llm/http-inference.ts +6 -0
  46. package/src/llm/httpEmbedding.ts +37 -6
  47. package/src/llm/httpGeneration.ts +18 -3
  48. package/src/llm/httpRerank.ts +23 -5
  49. package/src/llm/inference-cancellation.ts +168 -0
  50. package/src/llm/inference-scope.ts +202 -0
  51. package/src/llm/lazy-ports.ts +115 -0
  52. package/src/llm/native-worker/client.ts +541 -0
  53. package/src/llm/native-worker/dispatcher.ts +228 -0
  54. package/src/llm/native-worker/embedding-identity.ts +33 -0
  55. package/src/llm/native-worker/entry.ts +173 -0
  56. package/src/llm/native-worker/errors.ts +32 -0
  57. package/src/llm/native-worker/evaluation.ts +16 -0
  58. package/src/llm/native-worker/owned-exit.ts +108 -0
  59. package/src/llm/native-worker/owner.ts +141 -0
  60. package/src/llm/native-worker/ports.ts +317 -0
  61. package/src/llm/native-worker/protocol.ts +442 -0
  62. package/src/llm/native-worker/runtime-config.ts +92 -0
  63. package/src/llm/nodeLlamaCpp/adapter.ts +77 -20
  64. package/src/llm/nodeLlamaCpp/embedding.ts +130 -46
  65. package/src/llm/nodeLlamaCpp/generation.ts +34 -5
  66. package/src/llm/nodeLlamaCpp/lifecycle-options.ts +99 -0
  67. package/src/llm/nodeLlamaCpp/lifecycle.ts +209 -204
  68. package/src/llm/nodeLlamaCpp/rerank-capacity.ts +111 -0
  69. package/src/llm/nodeLlamaCpp/rerank.ts +118 -27
  70. package/src/llm/nodeLlamaCpp/simulator-handle.ts +73 -0
  71. package/src/llm/nodeLlamaCpp/simulator-install.ts +124 -0
  72. package/src/llm/nodeLlamaCpp/simulator-session.ts +240 -0
  73. package/src/llm/nodeLlamaCpp/simulator-types.ts +80 -0
  74. package/src/llm/types.ts +35 -5
  75. package/src/mcp/context.ts +27 -0
  76. package/src/mcp/http-transport.ts +12 -10
  77. package/src/mcp/server.ts +3 -0
  78. package/src/mcp/tool-profile.ts +30 -8
  79. package/src/mcp/tools/context.ts +8 -11
  80. package/src/mcp/tools/embed.ts +1 -1
  81. package/src/mcp/tools/index-cmd.ts +1 -1
  82. package/src/mcp/tools/index.ts +10 -8
  83. package/src/mcp/tools/query.ts +14 -30
  84. package/src/mcp/tools/vsearch.ts +1 -1
  85. package/src/pipeline/answer.ts +23 -3
  86. package/src/pipeline/claim-verifier.ts +6 -0
  87. package/src/pipeline/expansion.ts +43 -40
  88. package/src/pipeline/explain.ts +6 -2
  89. package/src/pipeline/filters.ts +63 -0
  90. package/src/pipeline/fusion.ts +29 -9
  91. package/src/pipeline/graph-retrieval.ts +29 -9
  92. package/src/pipeline/hybrid.ts +198 -55
  93. package/src/pipeline/hydration.ts +161 -0
  94. package/src/pipeline/owner-fusion.ts +87 -0
  95. package/src/pipeline/rerank.ts +35 -11
  96. package/src/pipeline/search.ts +13 -2
  97. package/src/pipeline/types.ts +5 -3
  98. package/src/pipeline/vsearch.ts +87 -7
  99. package/src/sdk/client.ts +47 -3
  100. package/src/sdk/embed.ts +63 -39
  101. package/src/serve/background-runtime.ts +1 -1
  102. package/src/serve/context.ts +41 -56
  103. package/src/serve/embed-scheduler.ts +58 -35
  104. package/src/serve/public/components/IndexingProgress.tsx +46 -60
  105. package/src/serve/public/globals.built.css +1 -1
  106. package/src/serve/public/lib/shiki-language-ids.ts +14 -0
  107. package/src/serve/resident-admission.ts +36 -36
  108. package/src/serve/resident-background-work.ts +20 -2
  109. package/src/serve/resident-request.ts +11 -5
  110. package/src/serve/resident-runtime.ts +97 -61
  111. package/src/serve/resident-shutdown.ts +153 -0
  112. package/src/serve/routes/api.ts +3 -1
  113. package/src/serve/server.ts +47 -26
  114. package/src/store/migrations/028-vector-variants.ts +54 -0
  115. package/src/store/migrations/029-graph-reference-state.ts +77 -0
  116. package/src/store/migrations/index.ts +4 -0
  117. package/src/store/sqlite/adapter.ts +251 -183
  118. package/src/store/sqlite/eligibility.ts +174 -0
  119. package/src/store/sqlite/graph-edge-application.ts +66 -0
  120. package/src/store/sqlite/graph-reference-state.ts +194 -0
  121. package/src/store/sqlite/legacy-vector-ownership.ts +79 -0
  122. package/src/store/types.ts +80 -12
  123. package/src/store/vector/eligibility.ts +36 -0
  124. package/src/store/vector/freshness.ts +33 -6
  125. package/src/store/vector/lazy.ts +81 -0
  126. package/src/store/vector/sqlite-vec.ts +106 -54
  127. package/src/store/vector/stats.ts +14 -3
  128. package/src/store/vector/types.ts +35 -2
  129. package/src/store/vector/variant-search.ts +192 -0
  130. package/src/store/vector/variants.ts +451 -0
  131. package/vendor/converters/markitdown-ts/LICENSE +21 -0
  132. package/vendor/converters/markitdown-ts/dist/index.cjs +1180 -0
  133. package/vendor/converters/markitdown-ts/dist/index.d.cts +46 -0
  134. package/vendor/converters/markitdown-ts/dist/index.d.mts +46 -0
  135. package/vendor/converters/markitdown-ts/dist/index.d.ts +46 -0
  136. package/vendor/converters/markitdown-ts/dist/index.mjs +1152 -0
  137. package/vendor/converters/markitdown-ts/package.json +77 -0
  138. package/vendor/converters/officeparser/LICENSE +21 -0
  139. package/vendor/converters/officeparser/dist/OfficeConverter.d.ts +47 -0
  140. package/vendor/converters/officeparser/dist/OfficeConverter.js +76 -0
  141. package/vendor/converters/officeparser/dist/OfficeGenerator.d.ts +23 -0
  142. package/vendor/converters/officeparser/dist/OfficeGenerator.js +73 -0
  143. package/vendor/converters/officeparser/dist/OfficeParser.d.ts +106 -0
  144. package/vendor/converters/officeparser/dist/OfficeParser.js +332 -0
  145. package/vendor/converters/officeparser/dist/cli.d.ts +28 -0
  146. package/vendor/converters/officeparser/dist/cli.js +381 -0
  147. package/vendor/converters/officeparser/dist/defaults.d.ts +41 -0
  148. package/vendor/converters/officeparser/dist/defaults.js +218 -0
  149. package/vendor/converters/officeparser/dist/generators/BaseGenerator.d.ts +107 -0
  150. package/vendor/converters/officeparser/dist/generators/BaseGenerator.js +248 -0
  151. package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.d.ts +82 -0
  152. package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.js +797 -0
  153. package/vendor/converters/officeparser/dist/generators/CsvGenerator.d.ts +38 -0
  154. package/vendor/converters/officeparser/dist/generators/CsvGenerator.js +245 -0
  155. package/vendor/converters/officeparser/dist/generators/EpubGenerator.d.ts +43 -0
  156. package/vendor/converters/officeparser/dist/generators/EpubGenerator.js +315 -0
  157. package/vendor/converters/officeparser/dist/generators/HtmlGenerator.d.ts +59 -0
  158. package/vendor/converters/officeparser/dist/generators/HtmlGenerator.js +1942 -0
  159. package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.d.ts +96 -0
  160. package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.js +1175 -0
  161. package/vendor/converters/officeparser/dist/generators/PdfGenerator.d.ts +22 -0
  162. package/vendor/converters/officeparser/dist/generators/PdfGenerator.js +194 -0
  163. package/vendor/converters/officeparser/dist/generators/RtfGenerator.d.ts +29 -0
  164. package/vendor/converters/officeparser/dist/generators/RtfGenerator.js +316 -0
  165. package/vendor/converters/officeparser/dist/generators/TextGenerator.d.ts +13 -0
  166. package/vendor/converters/officeparser/dist/generators/TextGenerator.js +201 -0
  167. package/vendor/converters/officeparser/dist/index.d.ts +60 -0
  168. package/vendor/converters/officeparser/dist/index.js +72 -0
  169. package/vendor/converters/officeparser/dist/index.mjs +18 -0
  170. package/vendor/converters/officeparser/dist/officeparser.browser.d.ts +2621 -0
  171. package/vendor/converters/officeparser/dist/officeparser.browser.iife.js +1336 -0
  172. package/vendor/converters/officeparser/dist/officeparser.browser.mjs +1335 -0
  173. package/vendor/converters/officeparser/dist/officeparser.browser.slim.d.ts +2621 -0
  174. package/vendor/converters/officeparser/dist/officeparser.browser.slim.iife.js +1336 -0
  175. package/vendor/converters/officeparser/dist/officeparser.browser.slim.mjs +1335 -0
  176. package/vendor/converters/officeparser/dist/parsers/CsvParser.d.ts +9 -0
  177. package/vendor/converters/officeparser/dist/parsers/CsvParser.js +115 -0
  178. package/vendor/converters/officeparser/dist/parsers/EpubParser.d.ts +8 -0
  179. package/vendor/converters/officeparser/dist/parsers/EpubParser.js +217 -0
  180. package/vendor/converters/officeparser/dist/parsers/ExcelParser.d.ts +32 -0
  181. package/vendor/converters/officeparser/dist/parsers/ExcelParser.js +736 -0
  182. package/vendor/converters/officeparser/dist/parsers/HtmlParser.d.ts +2 -0
  183. package/vendor/converters/officeparser/dist/parsers/HtmlParser.js +1287 -0
  184. package/vendor/converters/officeparser/dist/parsers/MarkdownParser.d.ts +2 -0
  185. package/vendor/converters/officeparser/dist/parsers/MarkdownParser.js +1272 -0
  186. package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.d.ts +31 -0
  187. package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.js +1819 -0
  188. package/vendor/converters/officeparser/dist/parsers/PdfParser.d.ts +67 -0
  189. package/vendor/converters/officeparser/dist/parsers/PdfParser.js +848 -0
  190. package/vendor/converters/officeparser/dist/parsers/PowerPointParser.d.ts +32 -0
  191. package/vendor/converters/officeparser/dist/parsers/PowerPointParser.js +950 -0
  192. package/vendor/converters/officeparser/dist/parsers/RtfParser.d.ts +187 -0
  193. package/vendor/converters/officeparser/dist/parsers/RtfParser.js +1801 -0
  194. package/vendor/converters/officeparser/dist/parsers/WordParser.d.ts +79 -0
  195. package/vendor/converters/officeparser/dist/parsers/WordParser.js +1177 -0
  196. package/vendor/converters/officeparser/dist/sbom.cdx.json +1763 -0
  197. package/vendor/converters/officeparser/dist/types.d.ts +2507 -0
  198. package/vendor/converters/officeparser/dist/types.js +107 -0
  199. package/vendor/converters/officeparser/dist/utils/astUtils.d.ts +16 -0
  200. package/vendor/converters/officeparser/dist/utils/astUtils.js +33 -0
  201. package/vendor/converters/officeparser/dist/utils/chartUtils.d.ts +6 -0
  202. package/vendor/converters/officeparser/dist/utils/chartUtils.js +257 -0
  203. package/vendor/converters/officeparser/dist/utils/configUtils.d.ts +44 -0
  204. package/vendor/converters/officeparser/dist/utils/configUtils.js +315 -0
  205. package/vendor/converters/officeparser/dist/utils/dateUtils.d.ts +17 -0
  206. package/vendor/converters/officeparser/dist/utils/dateUtils.js +69 -0
  207. package/vendor/converters/officeparser/dist/utils/envUtils.d.ts +29 -0
  208. package/vendor/converters/officeparser/dist/utils/envUtils.js +152 -0
  209. package/vendor/converters/officeparser/dist/utils/errorUtils.d.ts +72 -0
  210. package/vendor/converters/officeparser/dist/utils/errorUtils.js +245 -0
  211. package/vendor/converters/officeparser/dist/utils/imageUtils.d.ts +66 -0
  212. package/vendor/converters/officeparser/dist/utils/imageUtils.js +133 -0
  213. package/vendor/converters/officeparser/dist/utils/mathUtils.d.ts +42 -0
  214. package/vendor/converters/officeparser/dist/utils/mathUtils.js +385 -0
  215. package/vendor/converters/officeparser/dist/utils/moduleLoader.d.ts +18 -0
  216. package/vendor/converters/officeparser/dist/utils/moduleLoader.js +106 -0
  217. package/vendor/converters/officeparser/dist/utils/ocrUtils.d.ts +42 -0
  218. package/vendor/converters/officeparser/dist/utils/ocrUtils.js +428 -0
  219. package/vendor/converters/officeparser/dist/utils/sanitize.d.ts +148 -0
  220. package/vendor/converters/officeparser/dist/utils/sanitize.js +344 -0
  221. package/vendor/converters/officeparser/dist/utils/sheetUtils.d.ts +7 -0
  222. package/vendor/converters/officeparser/dist/utils/sheetUtils.js +35 -0
  223. package/vendor/converters/officeparser/dist/utils/styleMapper.d.ts +36 -0
  224. package/vendor/converters/officeparser/dist/utils/styleMapper.js +224 -0
  225. package/vendor/converters/officeparser/dist/utils/xmlUtils.d.ts +163 -0
  226. package/vendor/converters/officeparser/dist/utils/xmlUtils.js +461 -0
  227. package/vendor/converters/officeparser/dist/utils/zipUtils.d.ts +134 -0
  228. package/vendor/converters/officeparser/dist/utils/zipUtils.js +337 -0
  229. package/vendor/converters/officeparser/package.json +147 -0
  230. package/vendor/converters/upstream-manifest.json +124 -0
  231. package/vendor/dependency-fixes/README.md +77 -0
  232. package/vendor/dependency-fixes/vendor-converters.py +83 -0
  233. package/browser-extension/artifacts/gno-browser-clipper-v1.45.1.zip +0 -0
  234. package/browser-extension/artifacts/gno-browser-clipper-v1.45.1.zip.sha256 +0 -1
  235. package/browser-extension/dist/chunk-627emwpj.js +0 -75
  236. /package/browser-extension/dist/{chunk-ydfx5d7p.css → chunk-z74y8n8c.css} +0 -0
@@ -0,0 +1,163 @@
1
+ /**
2
+ * XML Parsing Utilities
3
+ *
4
+ * Provides helper functions for parsing and navigating XML documents.
5
+ * Used extensively by OOXML parsers (DOCX, XLSX, PPTX) and OpenOffice parsers (ODT, ODP, ODS).
6
+ *
7
+ * OOXML (Office Open XML) is an XML-based format used by Microsoft Office.
8
+ * Documents are ZIP archives containing multiple XML files describing structure, content, and formatting.
9
+ *
10
+ * @module xmlUtils
11
+ */
12
+ import { OfficeMetadata } from '../types';
13
+ /**
14
+ * Type guard for Element nodes.
15
+ */
16
+ export declare const isElement: (node: Node) => node is Element;
17
+ /**
18
+ * Parses an XML string into a DOM Document object.
19
+ *
20
+ * Uses the @xmldom/xmldom library to parse XML strings in a Node.js environment.
21
+ *
22
+ * @param xml - The XML content as a string
23
+ * @param options - Optional parser settings (e.g., enable locators for source mapping)
24
+ * @returns A Document object that can be queried using standard DOM methods
25
+ */
26
+ export declare const parseXmlString: (xml: string, options?: {
27
+ locator?: boolean;
28
+ }) => Document;
29
+ /**
30
+ * Gets all elements with a specific tag name and returns them as an array.
31
+ *
32
+ * This is a convenience wrapper around the DOM API's getElementsByTagName method
33
+ * that converts the HTMLCollection/NodeList to a proper JavaScript array for easier manipulation.
34
+ *
35
+ * @param element - The element or document to search within
36
+ * @param tagName - The tag name to search for (e.g., 'w:t', 'w:p', 'item')
37
+ * @returns An array of matching elements (empty array if none found)
38
+ * @example
39
+ * ```typescript
40
+ * const paragraphs = getElementsByTagName(doc, 'w:p');
41
+ * paragraphs.forEach(p => console.log(p.textContent));
42
+ * ```
43
+ */
44
+ export declare const getElementsByTagName: (element: Element | Document, tagName: string) => Element[];
45
+ export declare const serializeXml: (node: Node, options?: {
46
+ preserveWhitespace?: boolean;
47
+ }) => string;
48
+ /**
49
+ * Attempts to extract the original raw substring from the source XML for a given node.
50
+ * Requires the document to have been parsed with { locator: true }.
51
+ *
52
+ * @param node - The DOM node to extract source for
53
+ * @param sourceXml - The original XML source string
54
+ * @returns The raw XML substring, or undefined if it cannot be reliably determined
55
+ */
56
+ export declare const getSourceSubstring: (node: any, sourceXml: string) => string | undefined;
57
+ /**
58
+ * High-level helper to get raw content for a node based on OfficeParserConfig.
59
+ *
60
+ * @param node - The DOM node
61
+ * @param sourceXml - The original source XML string
62
+ * @param config - The parser configuration
63
+ * @returns The raw content string (serialized or original)
64
+ */
65
+ export declare const getRawContent: (node: Node, sourceXml: string, config: {
66
+ serializeRawContent?: boolean;
67
+ preserveXmlWhitespace?: boolean;
68
+ }) => string;
69
+ /**
70
+ * Gets the first element with the specified tag name within a parent element.
71
+ *
72
+ * @param parent - The parent element or document to search within
73
+ * @param tagName - The tag name to search for
74
+ * @returns The first matching element, or undefined if none found
75
+ */
76
+ export declare const getFirstElementByTagName: (parent: Element | Document, tagName: string) => Element | undefined;
77
+ /**
78
+ * Gets the value of an attribute from an element.
79
+ *
80
+ * @param element - The element to get the attribute from
81
+ * @param attrName - The name of the attribute
82
+ * @returns The attribute value or undefined if not set
83
+ */
84
+ export declare const getAttribute: (element: Element, attrName: string) => string | undefined;
85
+ /**
86
+ * Gets direct child elements with a specific tag name.
87
+ * Unlike getElementsByTagName, this does not search recursively.
88
+ *
89
+ * @param parent - The parent element
90
+ * @param tagName - The tag name to search for
91
+ * @returns An array of matching direct child elements
92
+ */
93
+ export declare const getDirectChildren: (parent: Element, tagName: string) => Element[];
94
+ /**
95
+ * Parses OOXML document metadata from the docProps/core.xml file.
96
+ *
97
+ * OOXML documents (DOCX, XLSX, PPTX) store metadata in a standard location:
98
+ * `docProps/core.xml` within the ZIP archive.
99
+ *
100
+ * This file follows the Dublin Core metadata standard with OOXML-specific extensions.
101
+ * Common metadata elements:
102
+ * - dc:title - Document title
103
+ * - dc:creator - Original author
104
+ * - cp:lastModifiedBy - User who last modified the document
105
+ * - dcterms:created - Creation timestamp
106
+ * - dcterms:modified - Last modification timestamp
107
+ *
108
+ * @param xmlContent - The raw XML content string from docProps/core.xml
109
+ * @returns An OfficeMetadata object with extracted properties (empty object if parsing fails)
110
+ * @example
111
+ * ```typescript
112
+ * const coreXml = files.find(f => f.path === 'docProps/core.xml').content.toString();
113
+ * const metadata = parseOfficeMetadata(coreXml);
114
+ *
115
+ * console.log(metadata.author); // "John Smith"
116
+ * console.log(metadata.title); // "Annual Report"
117
+ * console.log(metadata.created); // Date object
118
+ * ```
119
+ *
120
+ * @see https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/6c085e39-c695-4f83-91e8-3f277bb4e111
121
+ */
122
+ export declare const parseOfficeMetadata: (xmlContent: string) => OfficeMetadata;
123
+ /**
124
+ * Parses OOXML custom document properties from `docProps/custom.xml`.
125
+ *
126
+ * Custom properties are user-defined key/value pairs that authors can attach to OOXML documents
127
+ * (DOCX, XLSX, PPTX). They are stored in `docProps/custom.xml` inside the ZIP archive.
128
+ *
129
+ * Property values are typed using the `vt:` namespace (docPropsVTypes):
130
+ * - `vt:lpwstr` / `vt:lpstr` / `vt:bstr` → string
131
+ * - `vt:bool` → boolean
132
+ * - `vt:i1`..`vt:i8`, `vt:int`, `vt:r4`, `vt:r8`, `vt:decimal` → number
133
+ * - `vt:filetime` / `vt:date` → Date
134
+ *
135
+ * @param xmlContent - Raw XML string from `docProps/custom.xml`
136
+ * @returns A record of property name → typed value (empty object if none found)
137
+ * @example
138
+ * ```typescript
139
+ * const customXml = files.find(f => f.path === 'docProps/custom.xml').content.toString();
140
+ * const props = parseOOXMLCustomProperties(customXml);
141
+ * console.log(props['Department']); // "Engineering"
142
+ * console.log(props['Priority']); // 1 (number)
143
+ * console.log(props['Reviewed']); // true (boolean)
144
+ * ```
145
+ */
146
+ export declare const parseOOXMLCustomProperties: (xmlContent: string) => Record<string, string | number | boolean | Date>;
147
+ /**
148
+ * Parses OOXML application properties from `docProps/app.xml`.
149
+ *
150
+ * Application properties contain document statistics and application settings.
151
+ *
152
+ * @param xmlContent - Raw XML string from `docProps/app.xml`
153
+ * @returns A record of property name -> typed value
154
+ */
155
+ export declare const parseOOXMLAppProperties: (xmlContent: string) => Record<string, string | number | boolean>;
156
+ /**
157
+ * Decodes XML entities (standard named entities, decimal, and hexadecimal entities) in a string.
158
+ * Useful when parsing content with regular expressions instead of a full DOM parser.
159
+ *
160
+ * @param text - The XML-encoded string
161
+ * @returns The decoded string
162
+ */
163
+ export declare const decodeXmlEntities: (text: string) => string;
@@ -0,0 +1,461 @@
1
+ "use strict";
2
+ /**
3
+ * XML Parsing Utilities
4
+ *
5
+ * Provides helper functions for parsing and navigating XML documents.
6
+ * Used extensively by OOXML parsers (DOCX, XLSX, PPTX) and OpenOffice parsers (ODT, ODP, ODS).
7
+ *
8
+ * OOXML (Office Open XML) is an XML-based format used by Microsoft Office.
9
+ * Documents are ZIP archives containing multiple XML files describing structure, content, and formatting.
10
+ *
11
+ * @module xmlUtils
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.decodeXmlEntities = exports.parseOOXMLAppProperties = exports.parseOOXMLCustomProperties = exports.parseOfficeMetadata = exports.getDirectChildren = exports.getAttribute = exports.getFirstElementByTagName = exports.getRawContent = exports.getSourceSubstring = exports.serializeXml = exports.getElementsByTagName = exports.parseXmlString = exports.isElement = void 0;
15
+ const xmldom_1 = require("@xmldom/xmldom");
16
+ const dateUtils_js_1 = require("./dateUtils.js");
17
+ /**
18
+ * Type guard for Element nodes.
19
+ */
20
+ const isElement = (node) => {
21
+ return node.nodeType === 1;
22
+ };
23
+ exports.isElement = isElement;
24
+ /**
25
+ * Parses an XML string into a DOM Document object.
26
+ *
27
+ * Uses the @xmldom/xmldom library to parse XML strings in a Node.js environment.
28
+ *
29
+ * @param xml - The XML content as a string
30
+ * @param options - Optional parser settings (e.g., enable locators for source mapping)
31
+ * @returns A Document object that can be queried using standard DOM methods
32
+ */
33
+ const parseXmlString = (xml, options = {}) => {
34
+ const parser = new xmldom_1.DOMParser(options);
35
+ // @xmldom/xmldom 0.9.x is strict: a UTF-8 BOM (U+FEFF) prepended to the
36
+ // XML string causes a fatalError because the XML declaration is no longer
37
+ // at position 0. Strip it before parsing.
38
+ const sanitized = xml.charCodeAt(0) === 0xFEFF ? xml.slice(1) : xml.trim();
39
+ return parser.parseFromString(sanitized, "text/xml");
40
+ };
41
+ exports.parseXmlString = parseXmlString;
42
+ /**
43
+ * Gets all elements with a specific tag name and returns them as an array.
44
+ *
45
+ * This is a convenience wrapper around the DOM API's getElementsByTagName method
46
+ * that converts the HTMLCollection/NodeList to a proper JavaScript array for easier manipulation.
47
+ *
48
+ * @param element - The element or document to search within
49
+ * @param tagName - The tag name to search for (e.g., 'w:t', 'w:p', 'item')
50
+ * @returns An array of matching elements (empty array if none found)
51
+ * @example
52
+ * ```typescript
53
+ * const paragraphs = getElementsByTagName(doc, 'w:p');
54
+ * paragraphs.forEach(p => console.log(p.textContent));
55
+ * ```
56
+ */
57
+ const getElementsByTagName = (element, tagName) => {
58
+ const results = Array.from(element.getElementsByTagName(tagName));
59
+ // Resilience: If prefixed tag (e.g., 'dc:title') not found, try local name (e.g., 'title')
60
+ if (results.length === 0 && tagName.includes(':')) {
61
+ const localName = tagName.split(':').pop();
62
+ return Array.from(element.getElementsByTagName(localName));
63
+ }
64
+ return results;
65
+ };
66
+ exports.getElementsByTagName = getElementsByTagName;
67
+ /**
68
+ * Serializes a DOM Node (Document, Element, etc.) back into an XML string.
69
+ * This is cross-platform and works in both Node.js and Browser environments.
70
+ *
71
+ * @param node - The DOM node to serialize
72
+ * @param options - Serialization options
73
+ * @returns The XML string representation
74
+ */
75
+ const serializer = new xmldom_1.XMLSerializer();
76
+ const serializeXml = (node, options = {}) => {
77
+ // Note: xmldom's XMLSerializer doesn't natively support a 'pretty' or 'preserve'
78
+ // flag in a way that matches all user expectations, but it defaults to
79
+ // preserving structure. Formatting (indentation) is usually handled by the
80
+ // parser's initial whitespace handling.
81
+ // @ts-ignore - xmldom's Node is compatible with the global Node interface
82
+ return serializer.serializeToString(node);
83
+ };
84
+ exports.serializeXml = serializeXml;
85
+ /**
86
+ * Attempts to extract the original raw substring from the source XML for a given node.
87
+ * Requires the document to have been parsed with { locator: true }.
88
+ *
89
+ * @param node - The DOM node to extract source for
90
+ * @param sourceXml - The original XML source string
91
+ * @returns The raw XML substring, or undefined if it cannot be reliably determined
92
+ */
93
+ const getSourceSubstring = (node, sourceXml) => {
94
+ if (!node || typeof node.lineNumber !== 'number' || typeof node.columnNumber !== 'number') {
95
+ return undefined;
96
+ }
97
+ // Convert line/column to absolute index
98
+ const lines = sourceXml.split('\n');
99
+ let startIdx = 0;
100
+ for (let i = 0; i < node.lineNumber - 1; i++) {
101
+ startIdx += lines[i].length + 1; // +1 for newline
102
+ }
103
+ startIdx += node.columnNumber - 1;
104
+ // To find the end of the node, we look for the closing tag.
105
+ // This is a heuristic approach that works well for simple structured nodes (p, tbl, etc.)
106
+ // but might be complex for overlapping namespaces or malformed XML.
107
+ if ((0, exports.isElement)(node)) {
108
+ const tagName = node.tagName;
109
+ const closingTag = `</${tagName}>`;
110
+ const endIdx = sourceXml.indexOf(closingTag, startIdx);
111
+ if (endIdx !== -1) {
112
+ return sourceXml.substring(startIdx, endIdx + closingTag.length);
113
+ }
114
+ // Self-closing tag handling (e.g., <w:p/>)
115
+ const selfClosingEnd = sourceXml.indexOf('/>', startIdx);
116
+ const nextOpenTag = sourceXml.indexOf('<', startIdx + 1);
117
+ if (selfClosingEnd !== -1 && (nextOpenTag === -1 || selfClosingEnd < nextOpenTag)) {
118
+ return sourceXml.substring(startIdx, selfClosingEnd + 2);
119
+ }
120
+ }
121
+ return undefined;
122
+ };
123
+ exports.getSourceSubstring = getSourceSubstring;
124
+ /**
125
+ * High-level helper to get raw content for a node based on OfficeParserConfig.
126
+ *
127
+ * @param node - The DOM node
128
+ * @param sourceXml - The original source XML string
129
+ * @param config - The parser configuration
130
+ * @returns The raw content string (serialized or original)
131
+ */
132
+ const getRawContent = (node, sourceXml, config) => {
133
+ if (config.serializeRawContent === false) {
134
+ const original = (0, exports.getSourceSubstring)(node, sourceXml);
135
+ if (original)
136
+ return original;
137
+ }
138
+ return (0, exports.serializeXml)(node, { preserveWhitespace: config.preserveXmlWhitespace });
139
+ };
140
+ exports.getRawContent = getRawContent;
141
+ /**
142
+ * Gets the first element with the specified tag name within a parent element.
143
+ *
144
+ * @param parent - The parent element or document to search within
145
+ * @param tagName - The tag name to search for
146
+ * @returns The first matching element, or undefined if none found
147
+ */
148
+ const getFirstElementByTagName = (parent, tagName) => {
149
+ const elements = parent.getElementsByTagName(tagName);
150
+ if (elements && elements.length > 0) {
151
+ return elements[0];
152
+ }
153
+ return undefined;
154
+ };
155
+ exports.getFirstElementByTagName = getFirstElementByTagName;
156
+ /**
157
+ * Gets the value of an attribute from an element.
158
+ *
159
+ * @param element - The element to get the attribute from
160
+ * @param attrName - The name of the attribute
161
+ * @returns The attribute value or undefined if not set
162
+ */
163
+ const getAttribute = (element, attrName) => {
164
+ const attr = element.getAttribute(attrName);
165
+ return attr !== null ? attr : undefined;
166
+ };
167
+ exports.getAttribute = getAttribute;
168
+ /**
169
+ * Gets direct child elements with a specific tag name.
170
+ * Unlike getElementsByTagName, this does not search recursively.
171
+ *
172
+ * @param parent - The parent element
173
+ * @param tagName - The tag name to search for
174
+ * @returns An array of matching direct child elements
175
+ */
176
+ const getDirectChildren = (parent, tagName) => {
177
+ const result = [];
178
+ if (!parent.childNodes)
179
+ return result;
180
+ for (let i = 0; i < parent.childNodes.length; i++) {
181
+ const child = parent.childNodes[i];
182
+ if ((0, exports.isElement)(child) && child.tagName === tagName) {
183
+ result.push(child);
184
+ }
185
+ }
186
+ return result;
187
+ };
188
+ exports.getDirectChildren = getDirectChildren;
189
+ /**
190
+ * Parses OOXML document metadata from the docProps/core.xml file.
191
+ *
192
+ * OOXML documents (DOCX, XLSX, PPTX) store metadata in a standard location:
193
+ * `docProps/core.xml` within the ZIP archive.
194
+ *
195
+ * This file follows the Dublin Core metadata standard with OOXML-specific extensions.
196
+ * Common metadata elements:
197
+ * - dc:title - Document title
198
+ * - dc:creator - Original author
199
+ * - cp:lastModifiedBy - User who last modified the document
200
+ * - dcterms:created - Creation timestamp
201
+ * - dcterms:modified - Last modification timestamp
202
+ *
203
+ * @param xmlContent - The raw XML content string from docProps/core.xml
204
+ * @returns An OfficeMetadata object with extracted properties (empty object if parsing fails)
205
+ * @example
206
+ * ```typescript
207
+ * const coreXml = files.find(f => f.path === 'docProps/core.xml').content.toString();
208
+ * const metadata = parseOfficeMetadata(coreXml);
209
+ *
210
+ * console.log(metadata.author); // "John Smith"
211
+ * console.log(metadata.title); // "Annual Report"
212
+ * console.log(metadata.created); // Date object
213
+ * ```
214
+ *
215
+ * @see https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/6c085e39-c695-4f83-91e8-3f277bb4e111
216
+ */
217
+ const parseOfficeMetadata = (xmlContent) => {
218
+ // Step 1: Parse the XML content into a DOM document
219
+ const xml = (0, exports.parseXmlString)(xmlContent);
220
+ const metadata = {};
221
+ // Check for OOXML Core Properties
222
+ const coreProperties = (0, exports.getElementsByTagName)(xml, "cp:coreProperties")[0];
223
+ if (coreProperties) {
224
+ metadata.nativeProperties = {};
225
+ for (let i = 0; i < coreProperties.childNodes.length; i++) {
226
+ const child = coreProperties.childNodes[i];
227
+ if ((0, exports.isElement)(child)) {
228
+ metadata.nativeProperties[child.tagName] = child.textContent;
229
+ }
230
+ }
231
+ // Step 3: Extract title (Dublin Core element)
232
+ const title = (0, exports.getElementsByTagName)(coreProperties, "dc:title")[0];
233
+ if (title && title.textContent)
234
+ metadata.title = title.textContent;
235
+ // Step 4: Extract author/creator (Dublin Core element)
236
+ const author = (0, exports.getElementsByTagName)(coreProperties, "dc:creator")[0];
237
+ if (author && author.textContent)
238
+ metadata.author = author.textContent;
239
+ // Step 5: Extract last modifier (OOXML Core Properties element)
240
+ const lastModifiedBy = (0, exports.getElementsByTagName)(coreProperties, "cp:lastModifiedBy")[0];
241
+ if (lastModifiedBy && lastModifiedBy.textContent)
242
+ metadata.lastModifiedBy = lastModifiedBy.textContent;
243
+ // Step 6: Extract creation date (Dublin Core Terms element)
244
+ const created = (0, exports.getElementsByTagName)(coreProperties, "dcterms:created")[0];
245
+ if (created && created.textContent)
246
+ metadata.created = (0, dateUtils_js_1.parseOfficeDate)(created.textContent);
247
+ // Step 7: Extract last modification date (Dublin Core Terms element)
248
+ const modified = (0, exports.getElementsByTagName)(coreProperties, "dcterms:modified")[0];
249
+ if (modified && modified.textContent)
250
+ metadata.modified = (0, dateUtils_js_1.parseOfficeDate)(modified.textContent);
251
+ // Step 8: Extract description and subject (Dublin Core elements)
252
+ const description = (0, exports.getElementsByTagName)(coreProperties, "dc:description")[0];
253
+ if (description && description.textContent)
254
+ metadata.description = description.textContent;
255
+ const subject = (0, exports.getElementsByTagName)(coreProperties, "dc:subject")[0];
256
+ if (subject && subject.textContent)
257
+ metadata.subject = subject.textContent;
258
+ const keywords = (0, exports.getElementsByTagName)(coreProperties, "cp:keywords")[0];
259
+ if (keywords && keywords.textContent)
260
+ metadata.keywords = keywords.textContent;
261
+ return metadata;
262
+ }
263
+ // Check for ODF Meta
264
+ const officeMeta = (0, exports.getElementsByTagName)(xml, "office:meta")[0];
265
+ if (officeMeta) {
266
+ metadata.nativeProperties = {};
267
+ for (let i = 0; i < officeMeta.childNodes.length; i++) {
268
+ const child = officeMeta.childNodes[i];
269
+ if ((0, exports.isElement)(child)) {
270
+ metadata.nativeProperties[child.tagName] = child.textContent;
271
+ }
272
+ }
273
+ const title = (0, exports.getElementsByTagName)(officeMeta, "dc:title")[0];
274
+ if (title && title.textContent)
275
+ metadata.title = title.textContent;
276
+ const author = (0, exports.getElementsByTagName)(officeMeta, "dc:creator")[0];
277
+ if (author && author.textContent)
278
+ metadata.author = author.textContent;
279
+ const description = (0, exports.getElementsByTagName)(officeMeta, "dc:description")[0];
280
+ if (description && description.textContent)
281
+ metadata.description = description.textContent;
282
+ const subject = (0, exports.getElementsByTagName)(officeMeta, "dc:subject")[0];
283
+ if (subject && subject.textContent)
284
+ metadata.subject = subject.textContent;
285
+ const keywordElements = (0, exports.getElementsByTagName)(officeMeta, "meta:keyword");
286
+ if (keywordElements.length > 0) {
287
+ metadata.keywords = keywordElements.map(k => k.textContent).filter(Boolean).join(', ');
288
+ }
289
+ const created = (0, exports.getElementsByTagName)(officeMeta, "meta:creation-date")[0];
290
+ if (created && created.textContent)
291
+ metadata.created = (0, dateUtils_js_1.parseOfficeDate)(created.textContent);
292
+ const modified = (0, exports.getElementsByTagName)(officeMeta, "dc:date")[0];
293
+ if (modified && modified.textContent)
294
+ metadata.modified = (0, dateUtils_js_1.parseOfficeDate)(modified.textContent);
295
+ // Extract user-defined custom properties (meta:user-defined)
296
+ const userDefined = (0, exports.getElementsByTagName)(officeMeta, "meta:user-defined");
297
+ if (userDefined.length > 0) {
298
+ const customProperties = {};
299
+ for (const el of userDefined) {
300
+ const name = el.getAttribute("meta:name");
301
+ if (!name || !el.textContent)
302
+ continue;
303
+ const valueType = el.getAttribute("meta:value-type") || "string";
304
+ const raw = el.textContent;
305
+ if (valueType === "boolean") {
306
+ customProperties[name] = raw.toLowerCase() === "true";
307
+ }
308
+ else if (valueType === "float") {
309
+ const num = Number(raw);
310
+ if (!isNaN(num))
311
+ customProperties[name] = num;
312
+ }
313
+ else if (valueType === "date" || valueType === "time") {
314
+ const date = (0, dateUtils_js_1.parseOfficeDate)(raw);
315
+ if (date)
316
+ customProperties[name] = date;
317
+ else
318
+ customProperties[name] = raw;
319
+ }
320
+ else {
321
+ customProperties[name] = raw;
322
+ }
323
+ }
324
+ if (Object.keys(customProperties).length > 0) {
325
+ metadata.customProperties = customProperties;
326
+ }
327
+ }
328
+ }
329
+ return metadata;
330
+ };
331
+ exports.parseOfficeMetadata = parseOfficeMetadata;
332
+ /**
333
+ * Parses OOXML custom document properties from `docProps/custom.xml`.
334
+ *
335
+ * Custom properties are user-defined key/value pairs that authors can attach to OOXML documents
336
+ * (DOCX, XLSX, PPTX). They are stored in `docProps/custom.xml` inside the ZIP archive.
337
+ *
338
+ * Property values are typed using the `vt:` namespace (docPropsVTypes):
339
+ * - `vt:lpwstr` / `vt:lpstr` / `vt:bstr` → string
340
+ * - `vt:bool` → boolean
341
+ * - `vt:i1`..`vt:i8`, `vt:int`, `vt:r4`, `vt:r8`, `vt:decimal` → number
342
+ * - `vt:filetime` / `vt:date` → Date
343
+ *
344
+ * @param xmlContent - Raw XML string from `docProps/custom.xml`
345
+ * @returns A record of property name → typed value (empty object if none found)
346
+ * @example
347
+ * ```typescript
348
+ * const customXml = files.find(f => f.path === 'docProps/custom.xml').content.toString();
349
+ * const props = parseOOXMLCustomProperties(customXml);
350
+ * console.log(props['Department']); // "Engineering"
351
+ * console.log(props['Priority']); // 1 (number)
352
+ * console.log(props['Reviewed']); // true (boolean)
353
+ * ```
354
+ */
355
+ const parseOOXMLCustomProperties = (xmlContent) => {
356
+ const xml = (0, exports.parseXmlString)(xmlContent);
357
+ const result = {};
358
+ const properties = (0, exports.getElementsByTagName)(xml, "property");
359
+ for (const prop of properties) {
360
+ const name = prop.getAttribute("name");
361
+ if (!name)
362
+ continue;
363
+ // The value is the first child element (typed using vt: namespace)
364
+ for (let i = 0; i < prop.childNodes.length; i++) {
365
+ const child = prop.childNodes[i];
366
+ if (child.nodeType !== 1)
367
+ continue; // skip non-elements
368
+ const el = child;
369
+ const tag = el.tagName || '';
370
+ const text = el.textContent || '';
371
+ if (/vt:lpwstr|vt:lpstr|vt:bstr/.test(tag)) {
372
+ result[name] = text;
373
+ }
374
+ else if (/vt:bool/.test(tag)) {
375
+ result[name] = text.toLowerCase() === 'true';
376
+ }
377
+ else if (/vt:(i[1248]|ui[1248]|int|uint|r4|r8|decimal)/.test(tag)) {
378
+ const num = Number(text);
379
+ if (!isNaN(num))
380
+ result[name] = num;
381
+ }
382
+ else if (/vt:filetime|vt:date/.test(tag)) {
383
+ const date = (0, dateUtils_js_1.parseOfficeDate)(text);
384
+ if (date)
385
+ result[name] = date;
386
+ else
387
+ result[name] = text;
388
+ }
389
+ else if (text) {
390
+ // Fallback: store as string for any other vt: type
391
+ result[name] = text;
392
+ }
393
+ break; // only one value element per property
394
+ }
395
+ }
396
+ return result;
397
+ };
398
+ exports.parseOOXMLCustomProperties = parseOOXMLCustomProperties;
399
+ /**
400
+ * Parses OOXML application properties from `docProps/app.xml`.
401
+ *
402
+ * Application properties contain document statistics and application settings.
403
+ *
404
+ * @param xmlContent - Raw XML string from `docProps/app.xml`
405
+ * @returns A record of property name -> typed value
406
+ */
407
+ const parseOOXMLAppProperties = (xmlContent) => {
408
+ const xml = (0, exports.parseXmlString)(xmlContent);
409
+ const result = {};
410
+ const appProperties = (0, exports.getElementsByTagName)(xml, "Properties")[0];
411
+ if (appProperties) {
412
+ for (let i = 0; i < appProperties.childNodes.length; i++) {
413
+ const child = appProperties.childNodes[i];
414
+ if ((0, exports.isElement)(child)) {
415
+ const text = child.textContent || '';
416
+ if (text.toLowerCase() === 'true')
417
+ result[child.tagName] = true;
418
+ else if (text.toLowerCase() === 'false')
419
+ result[child.tagName] = false;
420
+ else if (!isNaN(Number(text)) && text.trim() !== '')
421
+ result[child.tagName] = Number(text);
422
+ else
423
+ result[child.tagName] = text;
424
+ }
425
+ }
426
+ }
427
+ return result;
428
+ };
429
+ exports.parseOOXMLAppProperties = parseOOXMLAppProperties;
430
+ /**
431
+ * Decodes XML entities (standard named entities, decimal, and hexadecimal entities) in a string.
432
+ * Useful when parsing content with regular expressions instead of a full DOM parser.
433
+ *
434
+ * @param text - The XML-encoded string
435
+ * @returns The decoded string
436
+ */
437
+ const decodeXmlEntities = (text) => {
438
+ return text.replace(/&([^;]+);/g, (match, entity) => {
439
+ if (entity.startsWith('#')) {
440
+ if (entity[1] === 'x' || entity[1] === 'X') {
441
+ const hex = entity.slice(2);
442
+ const code = parseInt(hex, 16);
443
+ return (!isNaN(code) && code >= 0 && code <= 0x10FFFF) ? String.fromCodePoint(code) : match;
444
+ }
445
+ else {
446
+ const dec = entity.slice(1);
447
+ const code = parseInt(dec, 10);
448
+ return (!isNaN(code) && code >= 0 && code <= 0x10FFFF) ? String.fromCodePoint(code) : match;
449
+ }
450
+ }
451
+ switch (entity) {
452
+ case 'amp': return '&';
453
+ case 'lt': return '<';
454
+ case 'gt': return '>';
455
+ case 'quot': return '"';
456
+ case 'apos': return "'";
457
+ default: return match;
458
+ }
459
+ });
460
+ };
461
+ exports.decodeXmlEntities = decodeXmlEntities;