@usejunior/odf-core 0.9.1

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 (54) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/comments.d.ts +55 -0
  3. package/dist/comments.d.ts.map +1 -0
  4. package/dist/comments.js +230 -0
  5. package/dist/comments.js.map +1 -0
  6. package/dist/compare/diff.d.ts +51 -0
  7. package/dist/compare/diff.d.ts.map +1 -0
  8. package/dist/compare/diff.js +189 -0
  9. package/dist/compare/diff.js.map +1 -0
  10. package/dist/compare/emit.d.ts +64 -0
  11. package/dist/compare/emit.d.ts.map +1 -0
  12. package/dist/compare/emit.js +404 -0
  13. package/dist/compare/emit.js.map +1 -0
  14. package/dist/compare/index.d.ts +49 -0
  15. package/dist/compare/index.d.ts.map +1 -0
  16. package/dist/compare/index.js +59 -0
  17. package/dist/compare/index.js.map +1 -0
  18. package/dist/compare/inline_diff.d.ts +32 -0
  19. package/dist/compare/inline_diff.d.ts.map +1 -0
  20. package/dist/compare/inline_diff.js +102 -0
  21. package/dist/compare/inline_diff.js.map +1 -0
  22. package/dist/compare/inline_map.d.ts +40 -0
  23. package/dist/compare/inline_map.d.ts.map +1 -0
  24. package/dist/compare/inline_map.js +153 -0
  25. package/dist/compare/inline_map.js.map +1 -0
  26. package/dist/document.d.ts +98 -0
  27. package/dist/document.d.ts.map +1 -0
  28. package/dist/document.js +172 -0
  29. package/dist/document.js.map +1 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +6 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/odf_archive_safety.d.ts +18 -0
  35. package/dist/odf_archive_safety.d.ts.map +1 -0
  36. package/dist/odf_archive_safety.js +72 -0
  37. package/dist/odf_archive_safety.js.map +1 -0
  38. package/dist/shared/odf/OdfArchive.d.ts +50 -0
  39. package/dist/shared/odf/OdfArchive.d.ts.map +1 -0
  40. package/dist/shared/odf/OdfArchive.js +118 -0
  41. package/dist/shared/odf/OdfArchive.js.map +1 -0
  42. package/dist/shared/odf/blocks.d.ts +15 -0
  43. package/dist/shared/odf/blocks.d.ts.map +1 -0
  44. package/dist/shared/odf/blocks.js +36 -0
  45. package/dist/shared/odf/blocks.js.map +1 -0
  46. package/dist/shared/odf/namespaces.d.ts +27 -0
  47. package/dist/shared/odf/namespaces.d.ts.map +1 -0
  48. package/dist/shared/odf/namespaces.js +29 -0
  49. package/dist/shared/odf/namespaces.js.map +1 -0
  50. package/dist/shared/odf/text_segments.d.ts +63 -0
  51. package/dist/shared/odf/text_segments.d.ts.map +1 -0
  52. package/dist/shared/odf/text_segments.js +90 -0
  53. package/dist/shared/odf/text_segments.js.map +1 -0
  54. package/package.json +54 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Pure intra-paragraph diff for ODF comparison (issue #356).
3
+ *
4
+ * Token-level LCS over a single paragraph pair's visible text, returning char-offset spans.
5
+ * Tokens are maximal runs of whitespace or non-whitespace — a partition of the string — so
6
+ * every token boundary maps losslessly back to a character offset and the emitted spans land
7
+ * on clean word boundaries (no ragged mid-word matches). Common token prefix/suffix are
8
+ * trimmed before the O(N·M) DP, so the dominant case — one edited word in a long clause —
9
+ * costs close to the edit size, not the paragraph size.
10
+ *
11
+ * Order convention mirrors `diffParagraphs`: at a mismatch the deletion branch wins, so a
12
+ * replaced word surfaces as a `delete` immediately followed by an `insert` sharing `revStart`.
13
+ * The emitter relies on that ordering when both anchor at the same offset.
14
+ */
15
+ /** Split into maximal whitespace / non-whitespace runs (a partition: tokens concat to the input). */
16
+ function tokenizeRuns(text) {
17
+ return text.match(/\s+|\S+/g) ?? [];
18
+ }
19
+ /**
20
+ * Diff two visible-text strings into an ordered span script.
21
+ * Adjacent same-kind spans are coalesced; zero-length spans are never emitted.
22
+ */
23
+ export function diffInline(original, revised) {
24
+ const origTokens = tokenizeRuns(original);
25
+ const revTokens = tokenizeRuns(revised);
26
+ // Trim the common token prefix/suffix; the DP only sees the differing middle window.
27
+ let prefix = 0;
28
+ const maxPrefix = Math.min(origTokens.length, revTokens.length);
29
+ while (prefix < maxPrefix && origTokens[prefix] === revTokens[prefix])
30
+ prefix++;
31
+ let suffix = 0;
32
+ const maxSuffix = Math.min(origTokens.length, revTokens.length) - prefix;
33
+ while (suffix < maxSuffix &&
34
+ origTokens[origTokens.length - 1 - suffix] === revTokens[revTokens.length - 1 - suffix]) {
35
+ suffix++;
36
+ }
37
+ const midOrig = origTokens.slice(prefix, origTokens.length - suffix);
38
+ const midRev = revTokens.slice(prefix, revTokens.length - suffix);
39
+ // dp[i][j] = LCS length of midOrig[i..] and midRev[j..] (same shape as diffParagraphs).
40
+ const n = midOrig.length;
41
+ const m = midRev.length;
42
+ const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
43
+ for (let i = n - 1; i >= 0; i--) {
44
+ for (let j = m - 1; j >= 0; j--) {
45
+ dp[i][j] =
46
+ midOrig[i] === midRev[j] ? dp[i + 1][j + 1] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);
47
+ }
48
+ }
49
+ // Walk tokens emitting per-token kinds, tracking char cursors in both strings.
50
+ const ops = [];
51
+ let origPos = 0;
52
+ let revPos = 0;
53
+ const push = (kind, origLen, revLen) => {
54
+ if (origLen === 0 && revLen === 0)
55
+ return;
56
+ const last = ops[ops.length - 1];
57
+ if (last && last.kind === kind) {
58
+ last.origEnd += origLen;
59
+ last.revEnd += revLen;
60
+ }
61
+ else {
62
+ ops.push({
63
+ kind,
64
+ origStart: origPos,
65
+ origEnd: origPos + origLen,
66
+ revStart: revPos,
67
+ revEnd: revPos + revLen,
68
+ });
69
+ }
70
+ origPos += origLen;
71
+ revPos += revLen;
72
+ };
73
+ for (let k = 0; k < prefix; k++)
74
+ push('equal', origTokens[k].length, revTokens[k].length);
75
+ let i = 0;
76
+ let j = 0;
77
+ while (i < n && j < m) {
78
+ if (midOrig[i] === midRev[j]) {
79
+ push('equal', midOrig[i].length, midRev[j].length);
80
+ i++;
81
+ j++;
82
+ }
83
+ else if (dp[i + 1][j] >= dp[i][j + 1]) {
84
+ // Prefer deletion at a tie so a replaced word surfaces as delete-then-insert.
85
+ push('delete', midOrig[i].length, 0);
86
+ i++;
87
+ }
88
+ else {
89
+ push('insert', 0, midRev[j].length);
90
+ j++;
91
+ }
92
+ }
93
+ while (i < n)
94
+ push('delete', midOrig[i++].length, 0);
95
+ while (j < m)
96
+ push('insert', 0, midRev[j++].length);
97
+ for (let k = suffix; k > 0; k--) {
98
+ push('equal', origTokens[origTokens.length - k].length, revTokens[revTokens.length - k].length);
99
+ }
100
+ return ops;
101
+ }
102
+ //# sourceMappingURL=inline_diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline_diff.js","sourceRoot":"","sources":["../../src/compare/inline_diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Visible-offset → DOM mapping for the intra-paragraph compare emitter (issue #356).
3
+ *
4
+ * `resolveOffset` turns a visible-text offset in a block into a concrete DOM insertion point,
5
+ * splitting a `#text` node or a `text:s` run when the offset falls strictly inside one.
6
+ * `extractVisibleRange` clones a visible range's inline content (preserving `text:span` /
7
+ * hyperlink structure) for out-of-line storage in a `text:deletion` changed-region.
8
+ *
9
+ * Contract for callers that mutate: `resolveOffset` re-segments the block on every call and
10
+ * never trusts a previously computed `Segment[]`. Marker insertion (zero visible width) at an
11
+ * offset never changes the visible offsets BELOW it, so emitters processing offsets in
12
+ * DESCENDING order stay correct across splits. `#text` splits are done manually (truncate
13
+ * `.data` + insert a sibling) — `Text.splitText` is not assumed to exist in xmldom.
14
+ */
15
+ /** A visible offset could not be mapped onto the block's DOM. The emitter degrades the pair. */
16
+ export declare class OdfMapError extends Error {
17
+ }
18
+ /** A DOM insertion point: `parent.insertBefore(node, before)`. */
19
+ export type DomPoint = {
20
+ parent: Node;
21
+ before: Node | null;
22
+ };
23
+ /**
24
+ * Resolve visible offset `vis` in `block` to a DOM insertion point at the offset's natural
25
+ * nesting depth (inside a `text:span` when the offset is inside one — the LibreOffice-authored
26
+ * placement). Offsets 0 and `visible.length` resolve to block-level prepend/append. An offset
27
+ * strictly inside a `#text` node splits it; strictly inside a `text:s` run splits the run,
28
+ * rebalancing `text:c`. Throws `OdfMapError` when `vis` is out of range.
29
+ */
30
+ export declare function resolveOffset(block: Element, vis: number): DomPoint;
31
+ /**
32
+ * Clone the inline content of `block`'s visible range [start, end) as nodes owned by
33
+ * `targetDoc`, for storage inside a `text:deletion` changed-region. Ancestor inline elements
34
+ * (`text:span`, hyperlinks) of covered content are shallow-cloned with their attributes;
35
+ * `#text` is trimmed at the edges; a partially covered `text:s` is rebalanced to the covered
36
+ * count; `text:tab` / `text:line-break` are copied whole (length 1 — never split). Pure with
37
+ * respect to `block`. Throws `OdfMapError` on an empty or out-of-range span.
38
+ */
39
+ export declare function extractVisibleRange(block: Element, start: number, end: number, targetDoc: Document): Node[];
40
+ //# sourceMappingURL=inline_map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline_map.d.ts","sourceRoot":"","sources":["../../src/compare/inline_map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAWH,gGAAgG;AAChG,qBAAa,WAAY,SAAQ,KAAK;CAAG;AAEzC,kEAAkE;AAClE,MAAM,MAAM,QAAQ,GAAG;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,CAAC;AAkB7D;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CA8CnE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,EAAE,CAkD3G"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Visible-offset → DOM mapping for the intra-paragraph compare emitter (issue #356).
3
+ *
4
+ * `resolveOffset` turns a visible-text offset in a block into a concrete DOM insertion point,
5
+ * splitting a `#text` node or a `text:s` run when the offset falls strictly inside one.
6
+ * `extractVisibleRange` clones a visible range's inline content (preserving `text:span` /
7
+ * hyperlink structure) for out-of-line storage in a `text:deletion` changed-region.
8
+ *
9
+ * Contract for callers that mutate: `resolveOffset` re-segments the block on every call and
10
+ * never trusts a previously computed `Segment[]`. Marker insertion (zero visible width) at an
11
+ * offset never changes the visible offsets BELOW it, so emitters processing offsets in
12
+ * DESCENDING order stay correct across splits. `#text` splits are done manually (truncate
13
+ * `.data` + insert a sibling) — `Text.splitText` is not assumed to exist in xmldom.
14
+ */
15
+ import { ODF_NS } from '../shared/odf/namespaces.js';
16
+ import { ELEMENT_NODE, TEXT_NODE, buildSegments, isAnnotationSubtree, isTrackedChangesSubtree, } from '../shared/odf/text_segments.js';
17
+ /** A visible offset could not be mapped onto the block's DOM. The emitter degrades the pair. */
18
+ export class OdfMapError extends Error {
19
+ }
20
+ /** Read a `text:s` run length the way `buildSegments` does. */
21
+ function spaceCount(el) {
22
+ const countRaw = el.getAttributeNS(ODF_NS.TEXT, 'c') ?? el.getAttribute('text:c');
23
+ return Math.max(1, Number.parseInt(countRaw ?? '1', 10) || 1);
24
+ }
25
+ /** Set a `text:s` run length, omitting the attribute for the default count of 1. */
26
+ function setSpaceCount(el, count) {
27
+ if (count === 1) {
28
+ el.removeAttributeNS(ODF_NS.TEXT, 'c');
29
+ el.removeAttribute('text:c');
30
+ }
31
+ else {
32
+ el.setAttributeNS(ODF_NS.TEXT, 'text:c', String(count));
33
+ }
34
+ }
35
+ /**
36
+ * Resolve visible offset `vis` in `block` to a DOM insertion point at the offset's natural
37
+ * nesting depth (inside a `text:span` when the offset is inside one — the LibreOffice-authored
38
+ * placement). Offsets 0 and `visible.length` resolve to block-level prepend/append. An offset
39
+ * strictly inside a `#text` node splits it; strictly inside a `text:s` run splits the run,
40
+ * rebalancing `text:c`. Throws `OdfMapError` when `vis` is out of range.
41
+ */
42
+ export function resolveOffset(block, vis) {
43
+ const { segments, visible } = buildSegments(block);
44
+ if (vis < 0 || vis > visible.length) {
45
+ throw new OdfMapError(`offset ${vis} outside visible range 0..${visible.length}`);
46
+ }
47
+ if (vis === 0)
48
+ return { parent: block, before: block.firstChild };
49
+ if (vis === visible.length)
50
+ return { parent: block, before: null };
51
+ // A boundary between segments: insert before the segment that starts at `vis`, at its depth.
52
+ const startingHere = segments.find((s) => s.visStart === vis);
53
+ if (startingHere) {
54
+ const host = startingHere.kind === 'text' ? startingHere.node : startingHere.node;
55
+ const parent = host.parentNode;
56
+ if (!parent)
57
+ throw new OdfMapError(`segment host at offset ${vis} has no parent`);
58
+ return { parent, before: host };
59
+ }
60
+ const seg = segments.find((s) => s.visStart < vis && vis < s.visStart + s.length);
61
+ if (!seg)
62
+ throw new OdfMapError(`offset ${vis} maps to no segment`);
63
+ const off = vis - seg.visStart;
64
+ if (seg.kind === 'text') {
65
+ const textNode = seg.node;
66
+ const parent = textNode.parentNode;
67
+ const doc = textNode.ownerDocument;
68
+ if (!parent || !doc)
69
+ throw new OdfMapError(`text node at offset ${vis} is detached`);
70
+ const tail = doc.createTextNode(textNode.data.slice(off));
71
+ textNode.data = textNode.data.slice(0, off);
72
+ parent.insertBefore(tail, textNode.nextSibling);
73
+ return { parent, before: tail };
74
+ }
75
+ if (seg.virtual === 'space') {
76
+ const run = seg.node;
77
+ const parent = run.parentNode;
78
+ const doc = run.ownerDocument;
79
+ if (!parent || !doc)
80
+ throw new OdfMapError(`text:s at offset ${vis} is detached`);
81
+ const tail = doc.importNode(run, false);
82
+ setSpaceCount(run, off);
83
+ setSpaceCount(tail, seg.length - off);
84
+ parent.insertBefore(tail, run.nextSibling);
85
+ return { parent, before: tail };
86
+ }
87
+ // tab / line-break are length 1 — an offset strictly inside one cannot exist.
88
+ throw new OdfMapError(`offset ${vis} falls inside an atomic ${seg.virtual} element`);
89
+ }
90
+ /**
91
+ * Clone the inline content of `block`'s visible range [start, end) as nodes owned by
92
+ * `targetDoc`, for storage inside a `text:deletion` changed-region. Ancestor inline elements
93
+ * (`text:span`, hyperlinks) of covered content are shallow-cloned with their attributes;
94
+ * `#text` is trimmed at the edges; a partially covered `text:s` is rebalanced to the covered
95
+ * count; `text:tab` / `text:line-break` are copied whole (length 1 — never split). Pure with
96
+ * respect to `block`. Throws `OdfMapError` on an empty or out-of-range span.
97
+ */
98
+ export function extractVisibleRange(block, start, end, targetDoc) {
99
+ const { visible } = buildSegments(block);
100
+ if (!(start >= 0 && start < end && end <= visible.length)) {
101
+ throw new OdfMapError(`range [${start}, ${end}) invalid for visible length ${visible.length}`);
102
+ }
103
+ let pos = 0;
104
+ const out = [];
105
+ const walk = (node, sink) => {
106
+ for (let child = node.firstChild; child; child = child.nextSibling) {
107
+ if (child.nodeType === TEXT_NODE) {
108
+ const data = child.data ?? '';
109
+ const from = Math.max(start, pos);
110
+ const to = Math.min(end, pos + data.length);
111
+ if (to > from)
112
+ sink.push(targetDoc.createTextNode(data.slice(from - pos, to - pos)));
113
+ pos += data.length;
114
+ continue;
115
+ }
116
+ if (child.nodeType !== ELEMENT_NODE)
117
+ continue;
118
+ const el = child;
119
+ if (isAnnotationSubtree(el) || isTrackedChangesSubtree(el))
120
+ continue;
121
+ if (el.namespaceURI === ODF_NS.TEXT && el.localName === 's') {
122
+ const count = spaceCount(el);
123
+ const covered = Math.min(end, pos + count) - Math.max(start, pos);
124
+ if (covered > 0) {
125
+ const clone = targetDoc.importNode(el, false);
126
+ setSpaceCount(clone, covered);
127
+ sink.push(clone);
128
+ }
129
+ pos += count;
130
+ continue;
131
+ }
132
+ if (el.namespaceURI === ODF_NS.TEXT && (el.localName === 'tab' || el.localName === 'line-break')) {
133
+ if (start <= pos && pos < end)
134
+ sink.push(targetDoc.importNode(el, false));
135
+ pos += 1;
136
+ continue;
137
+ }
138
+ // Container element (text:span, text:a, …): recurse; shallow-clone it only when it
139
+ // actually contributes covered content, so uncovered formatting never leaks into storage.
140
+ const sub = [];
141
+ walk(el, sub);
142
+ if (sub.length > 0) {
143
+ const clone = targetDoc.importNode(el, false);
144
+ for (const n of sub)
145
+ clone.appendChild(n);
146
+ sink.push(clone);
147
+ }
148
+ }
149
+ };
150
+ walk(block, out);
151
+ return out;
152
+ }
153
+ //# sourceMappingURL=inline_map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline_map.js","sourceRoot":"","sources":["../../src/compare/inline_map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Minimal ODF (.odt) document view over `content.xml`.
3
+ *
4
+ * Phase 1 scope: enumerate block-level text elements (`text:p` / `text:h`) in
5
+ * document order — including those nested in `table:table-cell` — with deterministic
6
+ * structural paragraph IDs, read a paragraph's visible text, and replace text within
7
+ * a paragraph when the match lies in a single `#text` node. See the `add-odf-core`
8
+ * OpenSpec change for the full rationale.
9
+ *
10
+ * Namespaces: ODF is heavily namespaced and prefixes are not guaranteed, so all
11
+ * element matching is by `namespaceURI` + `localName`, never by prefixed tag name.
12
+ */
13
+ import { type OdfComment } from './comments.js';
14
+ export type OdfParagraph = {
15
+ /** Deterministic structural ID (document-order ordinal), stable for identical bytes. */
16
+ id: string;
17
+ /** Visible text with `text:s` expanded to spaces and `text:tab` to a tab. */
18
+ text: string;
19
+ };
20
+ export type ReplaceResult = {
21
+ ok: true;
22
+ } | {
23
+ ok: false;
24
+ code: 'ANCHOR_NOT_FOUND' | 'TEXT_NOT_FOUND' | 'MATCH_SPANS_MULTIPLE_NODES';
25
+ message: string;
26
+ };
27
+ export type InsertResult = {
28
+ ok: true;
29
+ newIds: string[];
30
+ } | {
31
+ ok: false;
32
+ code: 'ANCHOR_NOT_FOUND';
33
+ message: string;
34
+ };
35
+ /** Parameters for {@link OdfDocument.addComment}. A `start`/`end` range is optional; omit for whole-paragraph. */
36
+ export type AddCommentParams = {
37
+ paragraphId: string;
38
+ start?: number;
39
+ end?: number;
40
+ author: string;
41
+ text: string;
42
+ initials?: string;
43
+ };
44
+ export type AddCommentResult = {
45
+ ok: true;
46
+ commentId: number;
47
+ } | {
48
+ ok: false;
49
+ code: 'ANCHOR_NOT_FOUND' | 'MATCH_SPANS_MULTIPLE_NODES' | 'INVALID_RANGE';
50
+ message: string;
51
+ };
52
+ export declare class OdfDocument {
53
+ private doc;
54
+ /** Block-level text elements in document order; index is the structural ID ordinal. */
55
+ private blocks;
56
+ private constructor();
57
+ /** Parse a `content.xml` string into a document view. */
58
+ static fromContentXml(contentXml: string): OdfDocument;
59
+ private idForIndex;
60
+ private blockForId;
61
+ /** All paragraphs in document order. */
62
+ getParagraphs(): OdfParagraph[];
63
+ /** Visible text of a paragraph by ID, or null if the ID does not resolve. */
64
+ getParagraphTextById(id: string): string | null;
65
+ /**
66
+ * Replace `findText` with `replaceWith` in the paragraph identified by `id`.
67
+ * Phase 1 only edits when the match lies entirely within a single `#text` node.
68
+ */
69
+ replaceTextById(id: string, findText: string, replaceWith: string): ReplaceResult;
70
+ /**
71
+ * Insert one or more paragraphs relative to the anchor paragraph identified by `id`.
72
+ *
73
+ * `text` is split on blank lines (`\n{2,}`) into separate `text:p` blocks (parity with
74
+ * the DOCX `insert_paragraph` tool); a single `\n` within a block becomes a
75
+ * `text:line-break`. Inserted blocks inherit the anchor's `text:style-name` ONLY when
76
+ * the anchor is itself a `text:p` — inserting after a heading (`text:h`) produces
77
+ * default body paragraphs, never more headings.
78
+ *
79
+ * Paragraph IDs are positional ordinals, so every ID at or after the insertion point
80
+ * shifts by the number of inserted blocks. Returns the inserted blocks' freshly
81
+ * recomputed IDs in document order; callers must re-read before issuing further edits
82
+ * that target IDs near or after the insertion point.
83
+ */
84
+ insertParagraph(id: string, text: string, position: 'BEFORE' | 'AFTER'): InsertResult;
85
+ /**
86
+ * Insert an `office:annotation` comment on the paragraph identified by `paragraphId`.
87
+ * Omit `start`/`end` to bracket the whole paragraph (structural insertion, independent of
88
+ * text segmentation); supply a visible `start`/`end` range to bracket a substring (which must
89
+ * lie within a single `#text` node, else `MATCH_SPANS_MULTIPLE_NODES`). Annotations are inline
90
+ * children, so positional paragraph IDs do NOT shift.
91
+ */
92
+ addComment(params: AddCommentParams): AddCommentResult;
93
+ /** All `office:annotation` comments in document order. */
94
+ getComments(): OdfComment[];
95
+ /** Serialize the (possibly edited) document back to a `content.xml` string. */
96
+ toXml(): string;
97
+ }
98
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAA4D,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAE1G,MAAM,MAAM,YAAY,GAAG;IACzB,wFAAwF;IACxF,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,4BAA4B,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/G,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,kHAAkH;AAClH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,GAAG,4BAA4B,GAAG,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9G,qBAAa,WAAW;IACtB,OAAO,CAAC,GAAG,CAAW;IACtB,uFAAuF;IACvF,OAAO,CAAC,MAAM,CAAY;IAE1B,OAAO;IAKP,yDAAyD;IACzD,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW;IAOtD,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,UAAU;IAOlB,wCAAwC;IACxC,aAAa,IAAI,YAAY,EAAE;IAO/B,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAM/C;;;OAGG;IACH,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa;IA+BjF;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,YAAY;IA4CrF;;;;;;OAMG;IACH,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB;IAgBtD,0DAA0D;IAC1D,WAAW,IAAI,UAAU,EAAE;IAI3B,+EAA+E;IAC/E,KAAK,IAAI,MAAM;CAGhB"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Minimal ODF (.odt) document view over `content.xml`.
3
+ *
4
+ * Phase 1 scope: enumerate block-level text elements (`text:p` / `text:h`) in
5
+ * document order — including those nested in `table:table-cell` — with deterministic
6
+ * structural paragraph IDs, read a paragraph's visible text, and replace text within
7
+ * a paragraph when the match lies in a single `#text` node. See the `add-odf-core`
8
+ * OpenSpec change for the full rationale.
9
+ *
10
+ * Namespaces: ODF is heavily namespaced and prefixes are not guaranteed, so all
11
+ * element matching is by `namespaceURI` + `localName`, never by prefixed tag name.
12
+ */
13
+ import { parseXml, serializeXml } from '@usejunior/docx-core';
14
+ import { ODF_NS } from './shared/odf/namespaces.js';
15
+ import { buildSegments } from './shared/odf/text_segments.js';
16
+ import { collectBlocks } from './shared/odf/blocks.js';
17
+ import { addAnnotation, readAnnotations } from './comments.js';
18
+ export class OdfDocument {
19
+ doc;
20
+ /** Block-level text elements in document order; index is the structural ID ordinal. */
21
+ blocks;
22
+ constructor(doc, blocks) {
23
+ this.doc = doc;
24
+ this.blocks = blocks;
25
+ }
26
+ /** Parse a `content.xml` string into a document view. */
27
+ static fromContentXml(contentXml) {
28
+ const doc = parseXml(contentXml);
29
+ const blocks = [];
30
+ collectBlocks(doc.documentElement, blocks);
31
+ return new OdfDocument(doc, blocks);
32
+ }
33
+ idForIndex(index) {
34
+ return `p${index}`;
35
+ }
36
+ blockForId(id) {
37
+ const m = /^p(\d+)$/.exec(id);
38
+ if (!m)
39
+ return null;
40
+ const idx = Number.parseInt(m[1], 10);
41
+ return this.blocks[idx] ?? null;
42
+ }
43
+ /** All paragraphs in document order. */
44
+ getParagraphs() {
45
+ return this.blocks.map((el, i) => ({
46
+ id: this.idForIndex(i),
47
+ text: buildSegments(el).visible,
48
+ }));
49
+ }
50
+ /** Visible text of a paragraph by ID, or null if the ID does not resolve. */
51
+ getParagraphTextById(id) {
52
+ const el = this.blockForId(id);
53
+ if (!el)
54
+ return null;
55
+ return buildSegments(el).visible;
56
+ }
57
+ /**
58
+ * Replace `findText` with `replaceWith` in the paragraph identified by `id`.
59
+ * Phase 1 only edits when the match lies entirely within a single `#text` node.
60
+ */
61
+ replaceTextById(id, findText, replaceWith) {
62
+ const el = this.blockForId(id);
63
+ if (!el) {
64
+ return { ok: false, code: 'ANCHOR_NOT_FOUND', message: `Paragraph not found: ${id}` };
65
+ }
66
+ const { segments, visible } = buildSegments(el);
67
+ const matchStart = visible.indexOf(findText);
68
+ if (matchStart < 0) {
69
+ return { ok: false, code: 'TEXT_NOT_FOUND', message: `Text not found in paragraph ${id}: ${JSON.stringify(findText)}` };
70
+ }
71
+ const matchEnd = matchStart + findText.length;
72
+ const host = segments.find((seg) => seg.kind === 'text' && matchStart >= seg.visStart && matchEnd <= seg.visStart + seg.length);
73
+ if (!host || host.kind !== 'text') {
74
+ return {
75
+ ok: false,
76
+ code: 'MATCH_SPANS_MULTIPLE_NODES',
77
+ message: `Match for ${JSON.stringify(findText)} in paragraph ${id} crosses node boundaries ` +
78
+ `(spans, spaces, or tabs). Phase 1 only replaces matches contained in a single text run.`,
79
+ };
80
+ }
81
+ const localStart = matchStart - host.visStart;
82
+ const localEnd = matchEnd - host.visStart;
83
+ host.node.data = host.node.data.slice(0, localStart) + replaceWith + host.node.data.slice(localEnd);
84
+ return { ok: true };
85
+ }
86
+ /**
87
+ * Insert one or more paragraphs relative to the anchor paragraph identified by `id`.
88
+ *
89
+ * `text` is split on blank lines (`\n{2,}`) into separate `text:p` blocks (parity with
90
+ * the DOCX `insert_paragraph` tool); a single `\n` within a block becomes a
91
+ * `text:line-break`. Inserted blocks inherit the anchor's `text:style-name` ONLY when
92
+ * the anchor is itself a `text:p` — inserting after a heading (`text:h`) produces
93
+ * default body paragraphs, never more headings.
94
+ *
95
+ * Paragraph IDs are positional ordinals, so every ID at or after the insertion point
96
+ * shifts by the number of inserted blocks. Returns the inserted blocks' freshly
97
+ * recomputed IDs in document order; callers must re-read before issuing further edits
98
+ * that target IDs near or after the insertion point.
99
+ */
100
+ insertParagraph(id, text, position) {
101
+ const anchor = this.blockForId(id);
102
+ if (!anchor) {
103
+ return { ok: false, code: 'ANCHOR_NOT_FOUND', message: `Paragraph not found: ${id}` };
104
+ }
105
+ const parent = anchor.parentNode;
106
+ if (!parent) {
107
+ return { ok: false, code: 'ANCHOR_NOT_FOUND', message: `Paragraph ${id} has no parent element` };
108
+ }
109
+ // Inherit the anchor's paragraph style only when the anchor is a body paragraph.
110
+ // Inserting relative to a heading must not produce another heading.
111
+ const inheritStyle = anchor.localName === 'p'
112
+ ? anchor.getAttributeNS(ODF_NS.TEXT, 'style-name') ?? anchor.getAttribute('text:style-name')
113
+ : null;
114
+ const blockTexts = text.replace(/\r\n/g, '\n').split(/\n{2,}/);
115
+ const newEls = blockTexts.map((blockText) => {
116
+ const p = this.doc.createElementNS(ODF_NS.TEXT, 'text:p');
117
+ if (inheritStyle)
118
+ p.setAttributeNS(ODF_NS.TEXT, 'text:style-name', inheritStyle);
119
+ const lines = blockText.split('\n');
120
+ lines.forEach((line, i) => {
121
+ if (i > 0)
122
+ p.appendChild(this.doc.createElementNS(ODF_NS.TEXT, 'text:line-break'));
123
+ if (line.length > 0)
124
+ p.appendChild(this.doc.createTextNode(line));
125
+ });
126
+ return p;
127
+ });
128
+ // `insertBefore(el, null)` appends, so AFTER on the last child appends correctly.
129
+ const refNode = position === 'AFTER' ? anchor.nextSibling : anchor;
130
+ for (const el of newEls) {
131
+ parent.insertBefore(el, refNode);
132
+ }
133
+ // Rebuild the structural block index; positional IDs shift accordingly.
134
+ const blocks = [];
135
+ collectBlocks(this.doc.documentElement, blocks);
136
+ this.blocks = blocks;
137
+ const newIds = newEls.map((el) => this.idForIndex(blocks.indexOf(el)));
138
+ return { ok: true, newIds };
139
+ }
140
+ /**
141
+ * Insert an `office:annotation` comment on the paragraph identified by `paragraphId`.
142
+ * Omit `start`/`end` to bracket the whole paragraph (structural insertion, independent of
143
+ * text segmentation); supply a visible `start`/`end` range to bracket a substring (which must
144
+ * lie within a single `#text` node, else `MATCH_SPANS_MULTIPLE_NODES`). Annotations are inline
145
+ * children, so positional paragraph IDs do NOT shift.
146
+ */
147
+ addComment(params) {
148
+ const block = this.blockForId(params.paragraphId);
149
+ if (!block) {
150
+ return { ok: false, code: 'ANCHOR_NOT_FOUND', message: `Paragraph not found: ${params.paragraphId}` };
151
+ }
152
+ const result = addAnnotation(this.doc, block, {
153
+ start: params.start,
154
+ end: params.end,
155
+ author: params.author,
156
+ text: params.text,
157
+ initials: params.initials,
158
+ });
159
+ if (!result.ok)
160
+ return result;
161
+ return { ok: true, commentId: result.commentId };
162
+ }
163
+ /** All `office:annotation` comments in document order. */
164
+ getComments() {
165
+ return readAnnotations(this.blocks);
166
+ }
167
+ /** Serialize the (possibly edited) document back to a `content.xml` string. */
168
+ toXml() {
169
+ return serializeXml(this.doc);
170
+ }
171
+ }
172
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { OdfArchive } from './shared/odf/OdfArchive.js';
2
+ export { OdfDocument, type OdfParagraph, type ReplaceResult, type InsertResult, type AddCommentParams, type AddCommentResult, } from './document.js';
3
+ export { type OdfComment } from './comments.js';
4
+ export { compareOdf, OdfEmitError, type OdfCompareResult, type OdfCompareStats, type OdfCompareOptions, } from './compare/index.js';
5
+ export { validateOdfArchiveSafety, type OdfArchiveSafetyResult } from './odf_archive_safety.js';
6
+ export { ODF_NS, ODF_PATHS, ODT_MIMETYPE } from './shared/odf/namespaces.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EACL,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,wBAAwB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { OdfArchive } from './shared/odf/OdfArchive.js';
2
+ export { OdfDocument, } from './document.js';
3
+ export { compareOdf, OdfEmitError, } from './compare/index.js';
4
+ export { validateOdfArchiveSafety } from './odf_archive_safety.js';
5
+ export { ODF_NS, ODF_PATHS, ODT_MIMETYPE } from './shared/odf/namespaces.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EACL,WAAW,GAMZ,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,UAAU,EACV,YAAY,GAIb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,wBAAwB,EAA+B,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC"}