@stll/folio-core 0.34.0 → 0.35.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.
- package/dist/ai-edits/snapshot.d.ts +3 -1
- package/dist/ai-edits/snapshot.js +20 -2
- package/dist/compare/compare.js +15 -3
- package/dist/docx/runConsolidator.js +1 -0
- package/dist/prosemirror/plugins/templateDirectives.d.ts +14 -7
- package/dist/prosemirror/plugins/templateDirectives.js +26 -19
- package/dist/prosemirror/plugins/templateSlashMenu.js +2 -2
- package/package.json +2 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { FolioAIBlock, FolioAIEditSnapshot, FolioAITextRangeHandle } from "./types.js";
|
|
2
2
|
import { Node } from "prosemirror-model";
|
|
3
3
|
//#region src/ai-edits/snapshot.d.ts
|
|
4
|
+
/** @internal Numbering references collected during the snapshot's document walk. */
|
|
5
|
+
declare const numberingReferenceKeysOf: (snapshot: FolioAIEditSnapshot) => readonly string[];
|
|
4
6
|
declare const normalizeFolioAIBlockText: (text: string) => string;
|
|
5
7
|
/**
|
|
6
8
|
* Whether a block carries text a reader would see.
|
|
@@ -70,4 +72,4 @@ type FolioStoryTable = {
|
|
|
70
72
|
declare const folioStoryTables: (doc: Node) => FolioStoryTable[];
|
|
71
73
|
declare const createFolioAIEditSnapshot: (doc: Node) => FolioAIEditSnapshot;
|
|
72
74
|
//#endregion
|
|
73
|
-
export { FolioStoryTable, createFolioAIEditSnapshot, createFolioAITextRangeHandle, folioStoryTables, hashFolioAIBlockText, isFolioAIContentBlock, isHiddenTableRow, normalizeFolioAIBlockText, trailingBodyBlockId };
|
|
75
|
+
export { FolioStoryTable, createFolioAIEditSnapshot, createFolioAITextRangeHandle, folioStoryTables, hashFolioAIBlockText, isFolioAIContentBlock, isHiddenTableRow, normalizeFolioAIBlockText, numberingReferenceKeysOf, trailingBodyBlockId };
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { expectRunFormattingOverrideMarkAttrs } from "../prosemirror/attrs/index.js";
|
|
2
2
|
import { deriveBlankBlockId, deriveBlockId } from "../types/block-id.js";
|
|
3
3
|
import { buildCleanBlockText } from "./clean-text.js";
|
|
4
|
+
import { panic } from "better-result";
|
|
4
5
|
import { TableMap } from "prosemirror-tables";
|
|
5
6
|
//#region src/ai-edits/snapshot.ts
|
|
7
|
+
const numberingReferenceKeysBySnapshot = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
/** @internal Numbering references collected during the snapshot's document walk. */
|
|
9
|
+
const numberingReferenceKeysOf = (snapshot) => numberingReferenceKeysBySnapshot.get(snapshot) ?? panic("A numbering census was requested for a snapshot that did not record one");
|
|
6
10
|
const normalizeFolioAIBlockText = (text) => text.replace(/\s+/gu, " ").trim();
|
|
7
11
|
/**
|
|
8
12
|
* Whether a block carries text a reader would see.
|
|
@@ -126,6 +130,7 @@ const createFolioAIEditSnapshot = (doc) => {
|
|
|
126
130
|
const draftBlocks = [];
|
|
127
131
|
const hashCounts = /* @__PURE__ */ new Map();
|
|
128
132
|
const usedBlockIds = /* @__PURE__ */ new Set();
|
|
133
|
+
const numberingReferenceKeys = /* @__PURE__ */ new Set();
|
|
129
134
|
const tableIndexByStart = new Map(folioStoryTables(doc).map(({ start, index }) => [start, index]));
|
|
130
135
|
const path = [];
|
|
131
136
|
let blockIndex = 0;
|
|
@@ -171,6 +176,8 @@ const createFolioAIEditSnapshot = (doc) => {
|
|
|
171
176
|
const displayLabel = getDisplayLabel(node);
|
|
172
177
|
const styleId = getStyleId(node);
|
|
173
178
|
const listLevel = getListLevel(node);
|
|
179
|
+
const numberingReferenceKey = getNumberingReferenceKey(node);
|
|
180
|
+
if (numberingReferenceKey) numberingReferenceKeys.add(numberingReferenceKey);
|
|
174
181
|
const previewRuns = getPreviewRuns(node);
|
|
175
182
|
const table = getTableLocation({
|
|
176
183
|
path,
|
|
@@ -209,10 +216,12 @@ const createFolioAIEditSnapshot = (doc) => {
|
|
|
209
216
|
hashOccurrenceCount: hashCounts.get(draft.anchor.textHash) ?? 0
|
|
210
217
|
};
|
|
211
218
|
}
|
|
212
|
-
|
|
219
|
+
const snapshot = {
|
|
213
220
|
blocks,
|
|
214
221
|
anchors
|
|
215
222
|
};
|
|
223
|
+
numberingReferenceKeysBySnapshot.set(snapshot, [...numberingReferenceKeys]);
|
|
224
|
+
return snapshot;
|
|
216
225
|
};
|
|
217
226
|
const getBlockKind = (node, headingLevel) => {
|
|
218
227
|
const listMarker = node.attrs["listMarker"];
|
|
@@ -241,6 +250,15 @@ const getListLevel = (node) => {
|
|
|
241
250
|
const { ilvl } = numPr;
|
|
242
251
|
return typeof ilvl === "number" && Number.isInteger(ilvl) && ilvl >= 0 ? ilvl : void 0;
|
|
243
252
|
};
|
|
253
|
+
const getNumberingReferenceKey = (node) => {
|
|
254
|
+
const numPr = node.attrs["numPr"];
|
|
255
|
+
if (typeof numPr !== "object" || numPr === null || !("numId" in numPr)) return null;
|
|
256
|
+
const { numId } = numPr;
|
|
257
|
+
if (typeof numId !== "number" || !Number.isInteger(numId) || numId <= 0) return null;
|
|
258
|
+
const level = "ilvl" in numPr ? numPr.ilvl : void 0;
|
|
259
|
+
if (level !== void 0 && (typeof level !== "number" || !Number.isInteger(level) || level < 0)) return null;
|
|
260
|
+
return `${String(numId)}:${String(level ?? 0)}`;
|
|
261
|
+
};
|
|
244
262
|
const getStyleId = (node) => {
|
|
245
263
|
const styleId = node.attrs["styleId"];
|
|
246
264
|
return typeof styleId === "string" && styleId.length > 0 ? styleId : void 0;
|
|
@@ -376,4 +394,4 @@ const isEmptyPreviewRunStyle = ({ bold, italic, underline, strike, fontFamily, f
|
|
|
376
394
|
const sameDirectFormatting = (left, right) => left === void 0 && isEmptyPreviewRunStyle(right) || left !== void 0 && left.bold === right.bold && left.italic === right.italic && left.underline === right.underline && left.strike === right.strike && left.fontFamily === right.fontFamily && left.fontSizePt === right.fontSizePt && left.color === right.color;
|
|
377
395
|
const isUnstyledPreviewRun = ({ bold, italic, underline, strike, fontFamily, fontSizePt, color }) => bold === void 0 && italic === void 0 && underline === void 0 && strike === void 0 && fontFamily === void 0 && fontSizePt === void 0 && color === void 0;
|
|
378
396
|
//#endregion
|
|
379
|
-
export { createFolioAIEditSnapshot, createFolioAITextRangeHandle, folioStoryTables, hashFolioAIBlockText, isFolioAIContentBlock, isHiddenTableRow, normalizeFolioAIBlockText, trailingBodyBlockId };
|
|
397
|
+
export { createFolioAIEditSnapshot, createFolioAITextRangeHandle, folioStoryTables, hashFolioAIBlockText, isFolioAIContentBlock, isHiddenTableRow, normalizeFolioAIBlockText, numberingReferenceKeysOf, trailingBodyBlockId };
|
package/dist/compare/compare.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FolioDocxReviewer } from "../ai-edits/headless.js";
|
|
2
|
+
import { numberingReferenceKeysOf } from "../ai-edits/snapshot.js";
|
|
2
3
|
import { projectTableGeometry } from "../ai-edits/table-geometry.js";
|
|
3
4
|
import "../document-operations.js";
|
|
4
5
|
import { pairFolioDocumentStories } from "../document-stories.js";
|
|
@@ -114,11 +115,12 @@ const formattingRoundTripFailure = ({ invariant, story, changes, actualBlocks, e
|
|
|
114
115
|
};
|
|
115
116
|
const numberingKey = ({ numId, level }) => `${String(numId)}:${String(level)}`;
|
|
116
117
|
const sameNumbering = (left, right) => left.format === right.format && left.levelText === right.levelText && left.start === right.start;
|
|
117
|
-
const compareNumbering = (base, target) => {
|
|
118
|
+
const compareNumbering = (base, target, referenced) => {
|
|
118
119
|
const baseLevels = new Map(base.readNumberingDefinitions().map((level) => [numberingKey(level), level]));
|
|
119
120
|
const targetLevels = new Map(target.readNumberingDefinitions().map((level) => [numberingKey(level), level]));
|
|
120
121
|
const changes = [];
|
|
121
122
|
for (const [key, before] of baseLevels) {
|
|
123
|
+
if (!referenced.has(key)) continue;
|
|
122
124
|
const after = targetLevels.get(key) ?? null;
|
|
123
125
|
if (after === null || !sameNumbering(before, after)) changes.push({
|
|
124
126
|
kind: "numbering",
|
|
@@ -128,7 +130,7 @@ const compareNumbering = (base, target) => {
|
|
|
128
130
|
after
|
|
129
131
|
});
|
|
130
132
|
}
|
|
131
|
-
for (const [key, after] of targetLevels) if (!baseLevels.has(key)) changes.push({
|
|
133
|
+
for (const [key, after] of targetLevels) if (referenced.has(key) && !baseLevels.has(key)) changes.push({
|
|
132
134
|
kind: "numbering",
|
|
133
135
|
numId: after.numId,
|
|
134
136
|
level: after.level,
|
|
@@ -162,8 +164,15 @@ const parseComparison = async (base, target, options) => {
|
|
|
162
164
|
});
|
|
163
165
|
const pairs = [];
|
|
164
166
|
const unsupported = [];
|
|
167
|
+
const referencedNumberingLevels = /* @__PURE__ */ new Set();
|
|
168
|
+
const collectNumberingReferences = (snapshot) => {
|
|
169
|
+
if (!snapshot) return;
|
|
170
|
+
for (const referenceKey of numberingReferenceKeysOf(snapshot)) referencedNumberingLevels.add(referenceKey);
|
|
171
|
+
};
|
|
165
172
|
for (const { baseStory, revisedStory: targetStory } of pairFolioDocumentStories(reviewer.listStories().map(({ handle }) => handle), targetReviewer.listStories().map(({ handle }) => handle))) {
|
|
166
173
|
if (!baseStory) {
|
|
174
|
+
if (!targetStory) panic("A story pair contained neither a base nor a target story");
|
|
175
|
+
collectNumberingReferences(targetReviewer.snapshotStory(targetStory));
|
|
167
176
|
unsupported.push({
|
|
168
177
|
reason: "story-missing-in-base",
|
|
169
178
|
baseStory: null,
|
|
@@ -172,6 +181,7 @@ const parseComparison = async (base, target, options) => {
|
|
|
172
181
|
continue;
|
|
173
182
|
}
|
|
174
183
|
if (!targetStory) {
|
|
184
|
+
collectNumberingReferences(reviewer.snapshotStory(baseStory));
|
|
175
185
|
unsupported.push({
|
|
176
186
|
reason: "story-missing-in-target",
|
|
177
187
|
baseStory,
|
|
@@ -181,6 +191,8 @@ const parseComparison = async (base, target, options) => {
|
|
|
181
191
|
}
|
|
182
192
|
const baseSnapshot = reviewer.snapshotStory(baseStory);
|
|
183
193
|
const targetSnapshot = targetReviewer.snapshotStory(targetStory);
|
|
194
|
+
collectNumberingReferences(baseSnapshot);
|
|
195
|
+
collectNumberingReferences(targetSnapshot);
|
|
184
196
|
if (!baseSnapshot || !targetSnapshot) {
|
|
185
197
|
unsupported.push({
|
|
186
198
|
reason: "story-not-editable",
|
|
@@ -208,7 +220,7 @@ const parseComparison = async (base, target, options) => {
|
|
|
208
220
|
},
|
|
209
221
|
packageDate,
|
|
210
222
|
pairs,
|
|
211
|
-
numberingChanges: compareNumbering(reviewer, targetReviewer),
|
|
223
|
+
numberingChanges: compareNumbering(reviewer, targetReviewer, referencedNumberingLevels),
|
|
212
224
|
unsupported
|
|
213
225
|
});
|
|
214
226
|
};
|
|
@@ -98,6 +98,7 @@ function isMergeableContent(content) {
|
|
|
98
98
|
* Runs with breaks, tabs, images, fields, etc. act as merge boundaries
|
|
99
99
|
*/
|
|
100
100
|
function canMergeRun(run) {
|
|
101
|
+
if (run.propertyChanges && run.propertyChanges.length > 0) return false;
|
|
101
102
|
if (run.content.length === 0) return true;
|
|
102
103
|
return run.content.every(isMergeableContent);
|
|
103
104
|
}
|
|
@@ -9,10 +9,16 @@ type DirectiveRange = {
|
|
|
9
9
|
/** Exclusive PM doc position of the marker end. */
|
|
10
10
|
to: number;
|
|
11
11
|
kind: DirectiveKind;
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Field path, clause name, key, condition, or — for a `for` marker — the
|
|
14
|
+
* array path the loop iterates (`{% for row in items %}` ⇒ `items`).
|
|
15
|
+
*/
|
|
13
16
|
expr: string;
|
|
14
17
|
/** Clause-slot version selector, e.g. "v3" or "latest". */
|
|
15
18
|
clauseVersion?: string;
|
|
19
|
+
/** Loop alias of a `for` marker (`{% for row in items %}` ⇒ `row`); unset
|
|
20
|
+
* for every other kind. */
|
|
21
|
+
alias?: string;
|
|
16
22
|
/** True for block directives that occupy their own paragraph. */
|
|
17
23
|
block: boolean;
|
|
18
24
|
};
|
|
@@ -20,15 +26,16 @@ type DirectiveRange = {
|
|
|
20
26
|
* Nesting depth (0-based) of every block-directive opener, derived purely from
|
|
21
27
|
* the scanned ranges by containment: walk the block openers/closers in document
|
|
22
28
|
* order with a kind-aware stack, and record each opener's depth as the stack size
|
|
23
|
-
* before it is pushed. Only `block:true` if/
|
|
29
|
+
* before it is pushed. Only `block:true` if/for pairs participate (inline markers
|
|
24
30
|
* resolve within a paragraph and get no rail).
|
|
25
31
|
*
|
|
26
32
|
* Matching is kind-aware so a mid-edit / unbalanced template stays sane: a closer
|
|
27
|
-
* pops the nearest opener of the *same family* ({
|
|
28
|
-
* {{
|
|
29
|
-
* matching opener is ignored (never decrements a foreign block's
|
|
30
|
-
* open/close counter would mis-count here: e.g. a stray
|
|
31
|
-
*
|
|
33
|
+
* pops the nearest opener of the *same family* (`{% endif %}` ⇒ `{% if %}`,
|
|
34
|
+
* `{% endfor %}` ⇒ `{% for %}`), dropping any still-open openers nested above it;
|
|
35
|
+
* a closer with no matching opener is ignored (never decrements a foreign block's
|
|
36
|
+
* depth). A blind open/close counter would mis-count here: e.g. a stray
|
|
37
|
+
* `{% endfor %}` between `{% if %}` and a nested `{% for %}` would wrongly pull
|
|
38
|
+
* the inner `{% for %}` back to depth 0.
|
|
32
39
|
*
|
|
33
40
|
* Keyed by the opener's `from` PM position, which is unique per marker, so the
|
|
34
41
|
* overlay can look a band's depth up from its opener range. This is a pure
|
|
@@ -3,41 +3,42 @@ import { collectBlockChunks, joinChunks, offsetToDocPos } from "./pmTextScan.js"
|
|
|
3
3
|
import { PluginKey } from "prosemirror-state";
|
|
4
4
|
import { assertNever, isBlockDirectiveKind, scanMarkers } from "@stll/template-conditions";
|
|
5
5
|
//#region src/prosemirror/plugins/templateDirectives.ts
|
|
6
|
-
/** The display expression for a marker (field path, clause name, key,
|
|
6
|
+
/** The display expression for a marker (field path, clause name, key,
|
|
7
|
+
* condition, loop array path, loop property). */
|
|
7
8
|
const directiveExpr = (meta) => {
|
|
8
9
|
switch (meta.kind) {
|
|
9
10
|
case "placeholder": return meta.expr;
|
|
10
11
|
case "clause": return meta.name;
|
|
11
12
|
case "num":
|
|
12
13
|
case "ref": return meta.key;
|
|
14
|
+
case "loop": return meta.property;
|
|
13
15
|
case "if":
|
|
14
|
-
case "
|
|
15
|
-
case "
|
|
16
|
-
case "index":
|
|
17
|
-
case "count":
|
|
16
|
+
case "elif": return meta.expr;
|
|
17
|
+
case "for": return meta.path;
|
|
18
18
|
case "else":
|
|
19
19
|
case "endif":
|
|
20
|
-
case "
|
|
20
|
+
case "endfor": return "";
|
|
21
21
|
default: return assertNever(meta);
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
/** Block-directive openers ({
|
|
25
|
-
const BLOCK_OPENER_KINDS = /* @__PURE__ */ new Set(["if", "
|
|
26
|
-
/** Block-directive closers ({
|
|
27
|
-
const BLOCK_CLOSER_KINDS = /* @__PURE__ */ new Set(["endif", "
|
|
24
|
+
/** Block-directive openers (`{% if %}`, `{% for %}`) that start a gutter-rail band. */
|
|
25
|
+
const BLOCK_OPENER_KINDS = /* @__PURE__ */ new Set(["if", "for"]);
|
|
26
|
+
/** Block-directive closers (`{% endif %}`, `{% endfor %}`) that end a gutter-rail band. */
|
|
27
|
+
const BLOCK_CLOSER_KINDS = /* @__PURE__ */ new Set(["endif", "endfor"]);
|
|
28
28
|
/**
|
|
29
29
|
* Nesting depth (0-based) of every block-directive opener, derived purely from
|
|
30
30
|
* the scanned ranges by containment: walk the block openers/closers in document
|
|
31
31
|
* order with a kind-aware stack, and record each opener's depth as the stack size
|
|
32
|
-
* before it is pushed. Only `block:true` if/
|
|
32
|
+
* before it is pushed. Only `block:true` if/for pairs participate (inline markers
|
|
33
33
|
* resolve within a paragraph and get no rail).
|
|
34
34
|
*
|
|
35
35
|
* Matching is kind-aware so a mid-edit / unbalanced template stays sane: a closer
|
|
36
|
-
* pops the nearest opener of the *same family* ({
|
|
37
|
-
* {{
|
|
38
|
-
* matching opener is ignored (never decrements a foreign block's
|
|
39
|
-
* open/close counter would mis-count here: e.g. a stray
|
|
40
|
-
*
|
|
36
|
+
* pops the nearest opener of the *same family* (`{% endif %}` ⇒ `{% if %}`,
|
|
37
|
+
* `{% endfor %}` ⇒ `{% for %}`), dropping any still-open openers nested above it;
|
|
38
|
+
* a closer with no matching opener is ignored (never decrements a foreign block's
|
|
39
|
+
* depth). A blind open/close counter would mis-count here: e.g. a stray
|
|
40
|
+
* `{% endfor %}` between `{% if %}` and a nested `{% for %}` would wrongly pull
|
|
41
|
+
* the inner `{% for %}` back to depth 0.
|
|
41
42
|
*
|
|
42
43
|
* Keyed by the opener's `from` PM position, which is unique per marker, so the
|
|
43
44
|
* overlay can look a band's depth up from its opener range. This is a pure
|
|
@@ -54,12 +55,14 @@ const computeBlockDepths = (ranges) => {
|
|
|
54
55
|
stack.push(range.kind);
|
|
55
56
|
continue;
|
|
56
57
|
}
|
|
57
|
-
const wantOpener = range.kind === "endif" ? "if" : "
|
|
58
|
+
const wantOpener = range.kind === "endif" ? "if" : "for";
|
|
58
59
|
const matchIdx = stack.lastIndexOf(wantOpener);
|
|
59
60
|
if (matchIdx !== -1) stack.length = matchIdx;
|
|
60
61
|
}
|
|
61
62
|
return depths;
|
|
62
63
|
};
|
|
64
|
+
/** The loop alias a `for` marker binds, or undefined for every other kind. */
|
|
65
|
+
const directiveAlias = (meta) => meta.kind === "for" ? meta.alias : void 0;
|
|
63
66
|
const scanDirectives = (doc) => {
|
|
64
67
|
const ranges = [];
|
|
65
68
|
for (const chunks of collectBlockChunks(doc)) {
|
|
@@ -69,24 +72,28 @@ const scanDirectives = (doc) => {
|
|
|
69
72
|
const sole = lineMarkers.length === 1 ? lineMarkers[0] : void 0;
|
|
70
73
|
if (sole && sole.raw === trimmed && isBlockDirectiveKind(sole.meta.kind)) {
|
|
71
74
|
const last = chunks.at(-1);
|
|
75
|
+
const alias = directiveAlias(sole.meta);
|
|
72
76
|
ranges.push({
|
|
73
77
|
from: chunks[0]?.start ?? 0,
|
|
74
78
|
to: last ? last.end ?? last.start + last.text.length : 0,
|
|
75
79
|
kind: sole.meta.kind,
|
|
76
80
|
expr: directiveExpr(sole.meta),
|
|
77
|
-
block: true
|
|
81
|
+
block: true,
|
|
82
|
+
...alias !== void 0 ? { alias } : {}
|
|
78
83
|
});
|
|
79
84
|
continue;
|
|
80
85
|
}
|
|
81
86
|
for (const marker of scanMarkers(joined)) {
|
|
82
87
|
const clauseVersion = marker.meta.kind === "clause" ? marker.meta.version : void 0;
|
|
88
|
+
const alias = directiveAlias(marker.meta);
|
|
83
89
|
ranges.push({
|
|
84
90
|
from: offsetToDocPos(chunks, marker.start),
|
|
85
91
|
to: offsetToDocPos(chunks, marker.end, "end"),
|
|
86
92
|
kind: marker.meta.kind,
|
|
87
93
|
expr: directiveExpr(marker.meta),
|
|
88
94
|
block: false,
|
|
89
|
-
...clauseVersion !== void 0 ? { clauseVersion } : {}
|
|
95
|
+
...clauseVersion !== void 0 ? { clauseVersion } : {},
|
|
96
|
+
...alias !== void 0 ? { alias } : {}
|
|
90
97
|
});
|
|
91
98
|
}
|
|
92
99
|
}
|
|
@@ -24,8 +24,8 @@ const atTriggerBoundary = (state, pos) => {
|
|
|
24
24
|
/** Whether `pos` falls strictly inside an existing template directive. The
|
|
25
25
|
* slash activations insert markers as raw text rather than going through
|
|
26
26
|
* `insertInline`'s overlap guard, so opening here would nest markers — e.g. a
|
|
27
|
-
* `/` typed after
|
|
28
|
-
* `{
|
|
27
|
+
* `/` typed after `if ` inside `{% if condition %}` could produce
|
|
28
|
+
* `{% if {{ field }} %}`, which the scanner/fill grammar cannot interpret.
|
|
29
29
|
* Boundaries are exclusive: a caret right before `{{` or after `}}` is fine. */
|
|
30
30
|
const insideDirective = (state, pos) => getTemplateDirectives(state).some((range) => pos > range.from && pos < range.to);
|
|
31
31
|
/** Whether the `/` that opened the trigger is still present at `from`. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/folio-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.1",
|
|
4
4
|
"description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"document-model",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"dependencies": {
|
|
118
118
|
"@stll/docx-core": "^0.19.2",
|
|
119
119
|
"@stll/docx-utils": "^0.1.0",
|
|
120
|
-
"@stll/template-conditions": "
|
|
120
|
+
"@stll/template-conditions": ">=0.4.0 <1.0.0",
|
|
121
121
|
"better-result": "3.0.1",
|
|
122
122
|
"csstype": "^3.1.3",
|
|
123
123
|
"dompurify": "^3.4.13",
|