@stll/folio-core 0.32.2 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/__fixtures__/paragraphs.d.ts +17 -0
- package/dist/ai-edits/__fixtures__/paragraphs.js +33 -0
- package/dist/ai-edits/apply.d.ts +49 -3
- package/dist/ai-edits/apply.js +649 -85
- package/dist/ai-edits/blockRange.d.ts +7 -3
- package/dist/ai-edits/blockRange.js +14 -6
- package/dist/ai-edits/headless.d.ts +39 -5
- package/dist/ai-edits/headless.js +76 -17
- package/dist/ai-edits/index.d.ts +6 -6
- package/dist/ai-edits/index.js +3 -3
- package/dist/ai-edits/read.d.ts +4 -0
- package/dist/ai-edits/read.js +30 -6
- package/dist/ai-edits/scoped-reading.js +4 -3
- package/dist/ai-edits/snapshot.d.ts +42 -2
- package/dist/ai-edits/snapshot.js +127 -62
- package/dist/ai-edits/table-row-column-mutations.d.ts +24 -1
- package/dist/ai-edits/table-row-column-mutations.js +98 -6
- package/dist/ai-edits/table-targets.d.ts +12 -3
- package/dist/ai-edits/table-targets.js +15 -5
- package/dist/ai-edits/types.d.ts +219 -15
- package/dist/ai-edits/word-diff.d.ts +54 -11
- package/dist/ai-edits/word-diff.js +221 -61
- package/dist/compare/__fixtures__/body-sequence.d.ts +33 -0
- package/dist/compare/__fixtures__/body-sequence.js +67 -0
- package/dist/compare/__fixtures__/nested-table.d.ts +16 -0
- package/dist/compare/__fixtures__/nested-table.js +50 -0
- package/dist/compare/__fixtures__/numbered-list.d.ts +34 -0
- package/dist/compare/__fixtures__/numbered-list.js +85 -0
- package/dist/compare/column-alignment.d.ts +27 -0
- package/dist/compare/column-alignment.js +162 -0
- package/dist/compare/compare.d.ts +107 -0
- package/dist/compare/compare.js +406 -0
- package/dist/compare/formatting.d.ts +29 -0
- package/dist/compare/formatting.js +84 -0
- package/dist/compare/plan.d.ts +22 -0
- package/dist/compare/plan.js +1059 -0
- package/dist/compare/reproducible-package.d.ts +17 -0
- package/dist/compare/reproducible-package.js +30 -0
- package/dist/compare/scenario.d.ts +77 -0
- package/dist/compare/scenario.js +263 -0
- package/dist/compare/types.d.ts +282 -0
- package/dist/compare/types.js +32 -0
- package/dist/compare/verification.d.ts +55 -0
- package/dist/compare/verification.js +146 -0
- package/dist/compat/eigenpal.d.ts +9 -6
- package/dist/compat/eigenpal.js +6 -3
- package/dist/controller/layoutPipeline.d.ts +13 -0
- package/dist/controller/layoutPipeline.js +15 -1
- package/dist/display-list/build/buildContext.d.ts +39 -0
- package/dist/display-list/build/buildContext.js +31 -0
- package/dist/display-list/build/buildDisplayList.d.ts +79 -0
- package/dist/display-list/build/buildDisplayList.js +283 -0
- package/dist/display-list/build/colors.d.ts +20 -0
- package/dist/display-list/build/colors.js +136 -0
- package/dist/display-list/build/floatingImages.d.ts +24 -0
- package/dist/display-list/build/floatingImages.js +41 -0
- package/dist/display-list/build/fontTable.d.ts +31 -0
- package/dist/display-list/build/fontTable.js +97 -0
- package/dist/display-list/build/furniture.d.ts +86 -0
- package/dist/display-list/build/furniture.js +98 -0
- package/dist/display-list/build/glyphs.d.ts +55 -0
- package/dist/display-list/build/glyphs.js +103 -0
- package/dist/display-list/build/headerFooterPrimitives.d.ts +17 -0
- package/dist/display-list/build/headerFooterPrimitives.js +40 -0
- package/dist/display-list/build/imagePrimitives.d.ts +35 -0
- package/dist/display-list/build/imagePrimitives.js +264 -0
- package/dist/display-list/build/pageBorderPrimitives.d.ts +23 -0
- package/dist/display-list/build/pageBorderPrimitives.js +111 -0
- package/dist/display-list/build/pageFurniture.d.ts +35 -0
- package/dist/display-list/build/pageFurniture.js +141 -0
- package/dist/display-list/build/paragraphPrimitives.d.ts +19 -0
- package/dist/display-list/build/paragraphPrimitives.js +819 -0
- package/dist/display-list/build/regions.d.ts +46 -0
- package/dist/display-list/build/regions.js +56 -0
- package/dist/display-list/build/storyPrimitives.d.ts +29 -0
- package/dist/display-list/build/storyPrimitives.js +279 -0
- package/dist/display-list/build/strokes.d.ts +19 -0
- package/dist/display-list/build/strokes.js +78 -0
- package/dist/display-list/build/tablePrimitives.d.ts +38 -0
- package/dist/display-list/build/tablePrimitives.js +409 -0
- package/dist/display-list/build/textBoxPrimitives.d.ts +14 -0
- package/dist/display-list/build/textBoxPrimitives.js +129 -0
- package/dist/display-list/build/textDecorations.d.ts +29 -0
- package/dist/display-list/build/textDecorations.js +29 -0
- package/dist/display-list/build/unsupported.d.ts +57 -0
- package/dist/display-list/build/unsupported.js +0 -0
- package/dist/display-list/build/watermarkPrimitives.d.ts +15 -0
- package/dist/display-list/build/watermarkPrimitives.js +128 -0
- package/dist/display-list/dom/renderDisplayListToDom.d.ts +26 -0
- package/dist/display-list/dom/renderDisplayListToDom.js +620 -0
- package/dist/display-list/editor/displayListPagePainter.d.ts +22 -0
- package/dist/display-list/editor/displayListPagePainter.js +63 -0
- package/dist/display-list/editor/pageRenderer.d.ts +24 -0
- package/dist/display-list/editor/pageRenderer.js +36 -0
- package/dist/display-list/primitives.d.ts +95 -0
- package/dist/display-list/primitives.js +127 -0
- package/dist/display-list/types.d.ts +472 -0
- package/dist/display-list/types.js +0 -0
- package/dist/document-operations.d.ts +39 -8
- package/dist/document-operations.js +169 -16
- package/dist/document-stories.d.ts +16 -0
- package/dist/document-stories.js +48 -4
- package/dist/docx/packageParts.d.ts +35 -0
- package/dist/docx/packageParts.js +120 -0
- package/dist/docx/paragraphParser.js +22 -22
- package/dist/docx/paragraphTraversal.js +1 -1
- package/dist/docx/renderedPageBreakNormalization.js +3 -1
- package/dist/docx/revisionIdNormalization.d.ts +13 -0
- package/dist/docx/revisionIdNormalization.js +103 -0
- package/dist/docx/rezip.js +26 -17
- package/dist/docx/selectiveSave.js +2 -2
- package/dist/docx/serializer/commentSerializer.js +6 -1
- package/dist/docx/serializer/paragraphSerializer.js +33 -4
- package/dist/docx/serializer/runSerializer.js +11 -10
- package/dist/docx/serializer/tableSerializer.js +2 -1
- package/dist/docx/server/applyDocxXmlPatchProposal.js +1 -1
- package/dist/docx/server/createBilingualDocx.js +3 -2
- package/dist/docx/streamingXmlParser.d.ts +13 -1
- package/dist/docx/streamingXmlParser.js +49 -11
- package/dist/docx/unzip.d.ts +1 -2
- package/dist/docx/unzip.js +25 -6
- package/dist/docx/xmlParser.d.ts +3 -1
- package/dist/docx/xmlParser.js +33 -27
- package/dist/export-pdf.d.ts +43 -0
- package/dist/export-pdf.js +98 -0
- package/dist/fonts/headlessMeasure.d.ts +76 -0
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/fonts/sfnt/parse.d.ts +51 -0
- package/dist/fonts/sfnt/parse.js +525 -0
- package/dist/fonts/sfnt/subset.d.ts +20 -0
- package/dist/fonts/sfnt/subset.js +350 -0
- package/dist/fonts/sfnt/tables.d.ts +88 -0
- package/dist/fonts/sfnt/tables.js +131 -0
- package/dist/fonts/sfnt/woff.d.ts +14 -0
- package/dist/fonts/sfnt/woff.js +163 -0
- package/dist/generated/text_shaper.js +324 -0
- package/dist/generated/text_shaper_bg.wasm +0 -0
- package/dist/headless-layout.d.ts +75 -0
- package/dist/headless-layout.js +350 -0
- package/dist/index.d.ts +9 -6
- package/dist/index.js +6 -3
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -0
- package/dist/layout-engine/measure/advanceComposition.d.ts +62 -0
- package/dist/layout-engine/measure/advanceComposition.js +148 -0
- package/dist/layout-engine/measure/cache.d.ts +2 -0
- package/dist/layout-engine/measure/measureContainer.js +13 -0
- package/dist/layout-engine/measure/measureParagraph.js +1 -2
- package/dist/layout-engine/measure/measureTypes.d.ts +12 -0
- package/dist/layout-engine/measure/tableInlinePlacement.d.ts +3 -2
- package/dist/layout-engine/measure/tableInlinePlacement.js +14 -1
- package/dist/layout-engine/tableIndentCompatibility.d.ts +5 -0
- package/dist/layout-engine/tableIndentCompatibility.js +15 -0
- package/dist/layout-engine/types.d.ts +8 -0
- package/dist/layout-painter/renderPage.d.ts +29 -1
- package/dist/layout-painter/renderPage.js +47 -19
- package/dist/layout-painter/renderParagraph.d.ts +21 -2
- package/dist/layout-painter/renderParagraph.js +1 -1
- package/dist/layout-painter/renderTable.js +37 -4
- package/dist/managers/editorShortcuts.d.ts +33 -1
- package/dist/managers/editorShortcuts.js +20 -1
- package/dist/markdown/renderRuns.js +7 -2
- package/dist/markdown/renderTable.js +5 -1
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/pdf/contentStream.d.ts +73 -0
- package/dist/pdf/contentStream.js +143 -0
- package/dist/pdf/fonts.d.ts +96 -0
- package/dist/pdf/fonts.js +593 -0
- package/dist/pdf/images.d.ts +28 -0
- package/dist/pdf/images.js +439 -0
- package/dist/pdf/objects.d.ts +93 -0
- package/dist/pdf/objects.js +237 -0
- package/dist/pdf/pageSpace.d.ts +43 -0
- package/dist/pdf/pageSpace.js +57 -0
- package/dist/pdf/paint.d.ts +32 -0
- package/dist/pdf/paint.js +442 -0
- package/dist/pdf/writePdf.d.ts +56 -0
- package/dist/pdf/writePdf.js +345 -0
- package/dist/prosemirror/commands/comments.js +91 -6
- package/dist/prosemirror/conversion/fromProseDoc.js +41 -7
- package/dist/prosemirror/conversion/toProseDoc.js +41 -4
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +15 -2
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +35 -6
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +2 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +4 -3
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +3 -1
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +5 -3
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -1
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +9 -3
- package/dist/prosemirror/extensions/nodes/TableExtension.js +56 -39
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +3 -1
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +5 -3
- package/dist/prosemirror/plugins/suggestionMode.js +1 -0
- package/dist/prosemirror/revisionCarriers.js +19 -2
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +2 -2
- package/dist/prosemirror/utils/extractTrackedChanges.js +59 -23
- package/dist/prosemirror/validation.js +55 -27
- package/dist/prosemirror/zeroWidthAnchors.d.ts +10 -0
- package/dist/prosemirror/zeroWidthAnchors.js +23 -0
- package/dist/redline.js +12 -79
- package/dist/server.d.ts +3 -3
- package/dist/server.js +2 -2
- package/dist/shaping/placeRun.d.ts +51 -0
- package/dist/shaping/placeRun.js +84 -0
- package/dist/shaping/shaper.d.ts +92 -0
- package/dist/shaping/shaper.js +102 -0
- package/dist/types/block-id.d.ts +18 -2
- package/dist/types/block-id.js +49 -5
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/clipboard.js +4 -3
- package/dist/utils/fontResolver.js +183 -0
- package/dist/utils/htmlComments.d.ts +17 -0
- package/dist/utils/htmlComments.js +22 -0
- package/dist/utils/scriptSegments.d.ts +12 -1
- package/dist/utils/scriptSegments.js +17 -1
- package/dist/version-comparison.d.ts +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import __wbg_init, { shapeRun } from "../generated/text_shaper.js";
|
|
2
|
+
import { TaggedError } from "better-result";
|
|
3
|
+
//#region src/shaping/shaper.ts
|
|
4
|
+
/**
|
|
5
|
+
* The boundary to the text shaper.
|
|
6
|
+
*
|
|
7
|
+
* Shaping is the one part of text layout that cannot be derived from code
|
|
8
|
+
* points: Arabic letters take their form from their neighbours, lam-alef
|
|
9
|
+
* ligates, Devanagari reorders and forms conjuncts, Hebrew points hang off the
|
|
10
|
+
* letter they belong to. One implementation answers that question, in Rust, and
|
|
11
|
+
* every caller reaches it through this module: a measurement in CSS pixels and
|
|
12
|
+
* a PDF text matrix scale the same glyph ids and the same advances, so the two
|
|
13
|
+
* cannot describe different text.
|
|
14
|
+
*
|
|
15
|
+
* The artifact is loaded on demand. It carries the OpenType layout engine and
|
|
16
|
+
* the Unicode data that engine needs, and a document in Latin, Cyrillic or
|
|
17
|
+
* Greek needs none of it: `getShaper` is called only once a run in a shaping
|
|
18
|
+
* script is about to be measured or painted, and never before.
|
|
19
|
+
*/
|
|
20
|
+
/** Which way a run advances. Resolved by the producer, never guessed here. */
|
|
21
|
+
const SHAPING_DIRECTION = {
|
|
22
|
+
leftToRight: "ltr",
|
|
23
|
+
rightToLeft: "rtl"
|
|
24
|
+
};
|
|
25
|
+
var ShaperError = class extends TaggedError("ShaperError") {};
|
|
26
|
+
/**
|
|
27
|
+
* The flat buffer the WebAssembly entry returns:
|
|
28
|
+
* `[unitsPerEm, glyphCount, (glyphId, cluster, xAdvance, yAdvance, xOffset,
|
|
29
|
+
* yOffset) * glyphCount]`. A page of Arabic is tens of thousands of glyphs, and
|
|
30
|
+
* an object each would cost more in boundary crossings than the shaping itself.
|
|
31
|
+
*/
|
|
32
|
+
const HEADER_FIELDS = 2;
|
|
33
|
+
const FIELDS_PER_GLYPH = 6;
|
|
34
|
+
const decode = (buffer) => {
|
|
35
|
+
const unitsPerEm = buffer[0] ?? 0;
|
|
36
|
+
const glyphCount = buffer[1] ?? 0;
|
|
37
|
+
const glyphs = [];
|
|
38
|
+
for (let index = 0; index < glyphCount; index += 1) {
|
|
39
|
+
const at = HEADER_FIELDS + index * FIELDS_PER_GLYPH;
|
|
40
|
+
glyphs.push({
|
|
41
|
+
glyphId: buffer[at] ?? 0,
|
|
42
|
+
cluster: buffer[at + 1] ?? 0,
|
|
43
|
+
xAdvance: buffer[at + 2] ?? 0,
|
|
44
|
+
yAdvance: buffer[at + 3] ?? 0,
|
|
45
|
+
xOffset: buffer[at + 4] ?? 0,
|
|
46
|
+
yOffset: buffer[at + 5] ?? 0
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
glyphs,
|
|
51
|
+
unitsPerEm
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
const shaper = { shapeRun: ({ font, faceIndex = 0, text, direction, script = "", language = "", featuresOn = [], featuresOff = [] }) => {
|
|
55
|
+
try {
|
|
56
|
+
return decode(shapeRun(font, faceIndex, text, direction === SHAPING_DIRECTION.rightToLeft, script, language, [...featuresOn], [...featuresOff]));
|
|
57
|
+
} catch (cause) {
|
|
58
|
+
throw new ShaperError({
|
|
59
|
+
message: "Could not shape a run of text",
|
|
60
|
+
cause
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
} };
|
|
64
|
+
let loading;
|
|
65
|
+
/**
|
|
66
|
+
* Loads the shaper, once, and hands back the single implementation both the
|
|
67
|
+
* measurer and the PDF backend use.
|
|
68
|
+
*
|
|
69
|
+
* Calling this is what fetches the artifact, so a caller asks for it only after
|
|
70
|
+
* establishing that some run actually needs shaping.
|
|
71
|
+
*/
|
|
72
|
+
const getShaper = () => {
|
|
73
|
+
loading ??= __wbg_init().then(() => {
|
|
74
|
+
resolved = shaper;
|
|
75
|
+
return shaper;
|
|
76
|
+
}).catch((cause) => {
|
|
77
|
+
loading = void 0;
|
|
78
|
+
throw new ShaperError({
|
|
79
|
+
message: "Could not initialize the text shaper",
|
|
80
|
+
cause
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
return loading;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Whether the artifact has been loaded in this process.
|
|
87
|
+
*
|
|
88
|
+
* Exists for the test that a document in a non-shaping script never pays for
|
|
89
|
+
* it, which is the whole reason this is a separate artifact.
|
|
90
|
+
*/
|
|
91
|
+
const shaperLoaded = () => loading !== void 0;
|
|
92
|
+
let resolved = null;
|
|
93
|
+
/**
|
|
94
|
+
* The shaper if it is already loaded, and never a load.
|
|
95
|
+
*
|
|
96
|
+
* The measure seam is synchronous: a measurement cannot await an artifact. So
|
|
97
|
+
* whoever is about to measure text that shapes resolves {@link getShaper}
|
|
98
|
+
* first, and the measurer reads the result here.
|
|
99
|
+
*/
|
|
100
|
+
const resolvedShaper = () => resolved;
|
|
101
|
+
//#endregion
|
|
102
|
+
export { SHAPING_DIRECTION, ShaperError, getShaper, resolvedShaper, shaperLoaded };
|
package/dist/types/block-id.d.ts
CHANGED
|
@@ -11,12 +11,21 @@
|
|
|
11
11
|
* branded type makes the divergence a compile-time error rather
|
|
12
12
|
* than a silent "scrollToBlock retries 20 times and gives up".
|
|
13
13
|
*
|
|
14
|
-
*
|
|
14
|
+
* Three id shapes are allowed:
|
|
15
15
|
* - Word's `w14:paraId` (or any non-empty allocator-generated id),
|
|
16
16
|
* surfaced verbatim when the source paragraph carries one.
|
|
17
17
|
* - A zero-padded `seq-NNNN` fallback derived from document order,
|
|
18
18
|
* used when the paragraph has no paraId or the paraId collides
|
|
19
19
|
* with one already taken in the same derivation pass.
|
|
20
|
+
* - A zero-padded `blank-NNNN` fallback for a paragraph that holds no
|
|
21
|
+
* text, numbered in its own sequence.
|
|
22
|
+
*
|
|
23
|
+
* The two sequences are separate on purpose. `seq-NNNN` counts the
|
|
24
|
+
* paragraphs that carry text, and that count is the published
|
|
25
|
+
* contract: the server extractor derives the same numbers, and a
|
|
26
|
+
* citation stored against one has to keep naming the same paragraph.
|
|
27
|
+
* Numbering blank paragraphs into the same sequence would renumber
|
|
28
|
+
* every stored citation after the first blank line in a document.
|
|
20
29
|
*/
|
|
21
30
|
type FolioBlockId = string & {
|
|
22
31
|
readonly __brand: "folio.blockId";
|
|
@@ -37,7 +46,14 @@ type DeriveBlockIdInput = {
|
|
|
37
46
|
taken: ReadonlySet<string>;
|
|
38
47
|
};
|
|
39
48
|
declare const deriveBlockId: ({ paraId, index, taken }: DeriveBlockIdInput) => FolioBlockId;
|
|
49
|
+
/**
|
|
50
|
+
* The id for a paragraph that holds no text, when it carries no
|
|
51
|
+
* paraId to be named by. Numbered in its own sequence so the
|
|
52
|
+
* published `seq-NNNN` positions stay where they are.
|
|
53
|
+
*/
|
|
54
|
+
declare const deriveBlankBlockId: ({ paraId, index, taken }: DeriveBlockIdInput) => FolioBlockId;
|
|
40
55
|
declare const isSequentialFolioBlockId: (id: string) => boolean;
|
|
56
|
+
declare const isBlankFolioBlockId: (id: string) => boolean;
|
|
41
57
|
/**
|
|
42
58
|
* Extract the paraId an id was derived from, if any. Returns `null`
|
|
43
59
|
* for sequential fallbacks. Accepts plain `string` so consumers that
|
|
@@ -60,4 +76,4 @@ declare const getSequentialFolioBlockIdIndex: (id: string) => number | null;
|
|
|
60
76
|
*/
|
|
61
77
|
declare const isFolioBlockId: (value: unknown) => value is FolioBlockId;
|
|
62
78
|
//#endregion
|
|
63
|
-
export { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId };
|
|
79
|
+
export { DeriveBlockIdInput, FolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId };
|
package/dist/types/block-id.js
CHANGED
|
@@ -11,17 +11,29 @@
|
|
|
11
11
|
* branded type makes the divergence a compile-time error rather
|
|
12
12
|
* than a silent "scrollToBlock retries 20 times and gives up".
|
|
13
13
|
*
|
|
14
|
-
*
|
|
14
|
+
* Three id shapes are allowed:
|
|
15
15
|
* - Word's `w14:paraId` (or any non-empty allocator-generated id),
|
|
16
16
|
* surfaced verbatim when the source paragraph carries one.
|
|
17
17
|
* - A zero-padded `seq-NNNN` fallback derived from document order,
|
|
18
18
|
* used when the paragraph has no paraId or the paraId collides
|
|
19
19
|
* with one already taken in the same derivation pass.
|
|
20
|
+
* - A zero-padded `blank-NNNN` fallback for a paragraph that holds no
|
|
21
|
+
* text, numbered in its own sequence.
|
|
22
|
+
*
|
|
23
|
+
* The two sequences are separate on purpose. `seq-NNNN` counts the
|
|
24
|
+
* paragraphs that carry text, and that count is the published
|
|
25
|
+
* contract: the server extractor derives the same numbers, and a
|
|
26
|
+
* citation stored against one has to keep naming the same paragraph.
|
|
27
|
+
* Numbering blank paragraphs into the same sequence would renumber
|
|
28
|
+
* every stored citation after the first blank line in a document.
|
|
20
29
|
*/
|
|
21
30
|
const SEQUENTIAL_BLOCK_ID_PREFIX = "seq-";
|
|
31
|
+
const BLANK_BLOCK_ID_PREFIX = "blank-";
|
|
22
32
|
const SEQUENTIAL_BLOCK_ID_PADDING = 4;
|
|
23
33
|
const SEQUENTIAL_BLOCK_ID_PATTERN = /^seq-\d{4,}$/u;
|
|
24
|
-
const
|
|
34
|
+
const BLANK_BLOCK_ID_PATTERN = /^blank-\d{4,}$/u;
|
|
35
|
+
const formatWithPrefix = (prefix, index) => `${prefix}${String(index).padStart(SEQUENTIAL_BLOCK_ID_PADDING, "0")}`;
|
|
36
|
+
const formatSequentialBlockId = (index) => formatWithPrefix(SEQUENTIAL_BLOCK_ID_PREFIX, index);
|
|
25
37
|
/**
|
|
26
38
|
* The opaque `FolioBlockId` brand has no constructor; an unchecked
|
|
27
39
|
* cast is the runtime no-op that mints one. Centralising the cast
|
|
@@ -29,8 +41,22 @@ const formatSequentialBlockId = (index) => `${SEQUENTIAL_BLOCK_ID_PREFIX}${Strin
|
|
|
29
41
|
* on.
|
|
30
42
|
*/
|
|
31
43
|
const brand = (value) => value;
|
|
44
|
+
/**
|
|
45
|
+
* Whether a source id would be read back as one this module generated.
|
|
46
|
+
*
|
|
47
|
+
* `seq-` and `blank-` are reserved: `getFolioParaIdFromBlockId` reports an id
|
|
48
|
+
* in either shape as having no source paragraph, and `isFolioBlockId` holds
|
|
49
|
+
* both to their exact pattern. A `w14:paraId` that happened to look like one
|
|
50
|
+
* would therefore be told apart from itself, so it is not used verbatim and
|
|
51
|
+
* the paragraph takes a generated id instead. (A real `w14:paraId` is eight
|
|
52
|
+
* hex digits, so this costs nothing on any package Word writes; it is here so
|
|
53
|
+
* a hand-written or synthesized source cannot break the round trip.)
|
|
54
|
+
*/
|
|
55
|
+
const isReservedShape = (paraId) => paraId.startsWith(SEQUENTIAL_BLOCK_ID_PREFIX) || paraId.startsWith(BLANK_BLOCK_ID_PREFIX);
|
|
56
|
+
const usableParaId = (paraId, taken) => paraId !== null && paraId.length > 0 && !taken.has(paraId) && !isReservedShape(paraId) ? paraId : null;
|
|
32
57
|
const deriveBlockId = ({ paraId, index, taken }) => {
|
|
33
|
-
|
|
58
|
+
const usable = usableParaId(paraId, taken);
|
|
59
|
+
if (usable !== null) return brand(usable);
|
|
34
60
|
let candidate = index;
|
|
35
61
|
let formatted = formatSequentialBlockId(candidate);
|
|
36
62
|
while (taken.has(formatted)) {
|
|
@@ -39,14 +65,31 @@ const deriveBlockId = ({ paraId, index, taken }) => {
|
|
|
39
65
|
}
|
|
40
66
|
return brand(formatted);
|
|
41
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* The id for a paragraph that holds no text, when it carries no
|
|
70
|
+
* paraId to be named by. Numbered in its own sequence so the
|
|
71
|
+
* published `seq-NNNN` positions stay where they are.
|
|
72
|
+
*/
|
|
73
|
+
const deriveBlankBlockId = ({ paraId, index, taken }) => {
|
|
74
|
+
const usable = usableParaId(paraId, taken);
|
|
75
|
+
if (usable !== null) return brand(usable);
|
|
76
|
+
let candidate = index;
|
|
77
|
+
let formatted = formatWithPrefix(BLANK_BLOCK_ID_PREFIX, candidate);
|
|
78
|
+
while (taken.has(formatted)) {
|
|
79
|
+
candidate += 1;
|
|
80
|
+
formatted = formatWithPrefix(BLANK_BLOCK_ID_PREFIX, candidate);
|
|
81
|
+
}
|
|
82
|
+
return brand(formatted);
|
|
83
|
+
};
|
|
42
84
|
const isSequentialFolioBlockId = (id) => SEQUENTIAL_BLOCK_ID_PATTERN.test(id);
|
|
85
|
+
const isBlankFolioBlockId = (id) => BLANK_BLOCK_ID_PATTERN.test(id);
|
|
43
86
|
/**
|
|
44
87
|
* Extract the paraId an id was derived from, if any. Returns `null`
|
|
45
88
|
* for sequential fallbacks. Accepts plain `string` so consumers that
|
|
46
89
|
* have a raw id (snapshot anchors, operation blockIds) can call it
|
|
47
90
|
* without an upfront brand check.
|
|
48
91
|
*/
|
|
49
|
-
const getFolioParaIdFromBlockId = (id) => isSequentialFolioBlockId(id) ? null : id;
|
|
92
|
+
const getFolioParaIdFromBlockId = (id) => isSequentialFolioBlockId(id) || isBlankFolioBlockId(id) ? null : id;
|
|
50
93
|
/**
|
|
51
94
|
* The 1-based document position encoded in a sequential fallback id
|
|
52
95
|
* (`seq-0011` -> 11), or `null` for paraId-backed ids. The number is
|
|
@@ -67,7 +110,8 @@ const getSequentialFolioBlockIdIndex = (id) => {
|
|
|
67
110
|
const isFolioBlockId = (value) => {
|
|
68
111
|
if (typeof value !== "string" || value.length === 0) return false;
|
|
69
112
|
if (value.startsWith(SEQUENTIAL_BLOCK_ID_PREFIX)) return SEQUENTIAL_BLOCK_ID_PATTERN.test(value);
|
|
113
|
+
if (value.startsWith(BLANK_BLOCK_ID_PREFIX)) return BLANK_BLOCK_ID_PATTERN.test(value);
|
|
70
114
|
return true;
|
|
71
115
|
};
|
|
72
116
|
//#endregion
|
|
73
|
-
export { deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId };
|
|
117
|
+
export { deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId };
|
package/dist/types/content.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, VerticalAlign } from "@stll/docx-core/model";
|
|
2
|
-
export type { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, VerticalAlign };
|
|
1
|
+
import { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, TrackedRunContent, VerticalAlign } from "@stll/docx-core/model";
|
|
2
|
+
export type { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, TrackedRunContent, VerticalAlign };
|
package/dist/utils/clipboard.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { htmlCommentEnd } from "./htmlComments.js";
|
|
1
2
|
import { stripXmlDeclarations } from "./stripXmlDeclarations.js";
|
|
2
3
|
import createDOMPurify from "dompurify";
|
|
3
4
|
//#region src/utils/clipboard.ts
|
|
@@ -259,9 +260,9 @@ function stripHtmlComments(html) {
|
|
|
259
260
|
break;
|
|
260
261
|
}
|
|
261
262
|
result += html.slice(cursor, start);
|
|
262
|
-
const end = html
|
|
263
|
-
if (end ===
|
|
264
|
-
cursor = end
|
|
263
|
+
const end = htmlCommentEnd(html, start);
|
|
264
|
+
if (end === null) break;
|
|
265
|
+
cursor = end;
|
|
265
266
|
}
|
|
266
267
|
return result;
|
|
267
268
|
}
|
|
@@ -445,6 +445,189 @@ const FONT_MAPPINGS = {
|
|
|
445
445
|
unitsPerEm: 2048
|
|
446
446
|
})
|
|
447
447
|
},
|
|
448
|
+
"arial narrow": {
|
|
449
|
+
googleFont: "Arimo",
|
|
450
|
+
category: "sans-serif",
|
|
451
|
+
fallbackStack: [
|
|
452
|
+
"Arial Narrow",
|
|
453
|
+
"Arimo",
|
|
454
|
+
"Arial",
|
|
455
|
+
"Helvetica",
|
|
456
|
+
"sans-serif"
|
|
457
|
+
],
|
|
458
|
+
singleLineRatio: singleLineRatioOf({
|
|
459
|
+
source: "hhea",
|
|
460
|
+
hheaAscent: 1916,
|
|
461
|
+
hheaDescent: -434,
|
|
462
|
+
hheaLineGap: 0,
|
|
463
|
+
unitsPerEm: 2048
|
|
464
|
+
})
|
|
465
|
+
},
|
|
466
|
+
helvetica: {
|
|
467
|
+
googleFont: "Arimo",
|
|
468
|
+
category: "sans-serif",
|
|
469
|
+
fallbackStack: [
|
|
470
|
+
"Helvetica",
|
|
471
|
+
"Arimo",
|
|
472
|
+
"Arial",
|
|
473
|
+
"sans-serif"
|
|
474
|
+
],
|
|
475
|
+
singleLineRatio: singleLineRatioOf({
|
|
476
|
+
source: "measured",
|
|
477
|
+
ratio: 1.2,
|
|
478
|
+
note: "Measured at 11pt against a 13.2pt reference-layout line pitch. Helvetica's hhea ascent and descent sum to exactly one em, and that 1.0 ratio is not the rendered pitch, so the formula does not apply here."
|
|
479
|
+
})
|
|
480
|
+
},
|
|
481
|
+
"bookman old style": {
|
|
482
|
+
googleFont: "EB Garamond",
|
|
483
|
+
category: "serif",
|
|
484
|
+
fallbackStack: [
|
|
485
|
+
"Bookman Old Style",
|
|
486
|
+
"EB Garamond",
|
|
487
|
+
"Georgia",
|
|
488
|
+
"serif"
|
|
489
|
+
],
|
|
490
|
+
singleLineRatio: singleLineRatioOf({
|
|
491
|
+
source: "hhea",
|
|
492
|
+
hheaAscent: 1929,
|
|
493
|
+
hheaDescent: -475,
|
|
494
|
+
hheaLineGap: 0,
|
|
495
|
+
unitsPerEm: 2048
|
|
496
|
+
})
|
|
497
|
+
},
|
|
498
|
+
"franklin gothic book": {
|
|
499
|
+
googleFont: "Libre Franklin",
|
|
500
|
+
category: "sans-serif",
|
|
501
|
+
fallbackStack: [
|
|
502
|
+
"Franklin Gothic Book",
|
|
503
|
+
"Libre Franklin",
|
|
504
|
+
"Arial",
|
|
505
|
+
"sans-serif"
|
|
506
|
+
],
|
|
507
|
+
singleLineRatio: singleLineRatioOf({
|
|
508
|
+
source: "hhea",
|
|
509
|
+
hheaAscent: 1877,
|
|
510
|
+
hheaDescent: -445,
|
|
511
|
+
hheaLineGap: 0,
|
|
512
|
+
unitsPerEm: 2048
|
|
513
|
+
})
|
|
514
|
+
},
|
|
515
|
+
"calibri light": {
|
|
516
|
+
googleFont: "Carlito",
|
|
517
|
+
category: "sans-serif",
|
|
518
|
+
fallbackStack: [
|
|
519
|
+
"Calibri Light",
|
|
520
|
+
"Calibri",
|
|
521
|
+
"Carlito",
|
|
522
|
+
"Arial",
|
|
523
|
+
"sans-serif"
|
|
524
|
+
],
|
|
525
|
+
singleLineRatio: singleLineRatioOf({
|
|
526
|
+
source: "hhea",
|
|
527
|
+
hheaAscent: 1950,
|
|
528
|
+
hheaDescent: -550,
|
|
529
|
+
hheaLineGap: 0,
|
|
530
|
+
unitsPerEm: 2048
|
|
531
|
+
})
|
|
532
|
+
},
|
|
533
|
+
candara: {
|
|
534
|
+
googleFont: "Carlito",
|
|
535
|
+
category: "sans-serif",
|
|
536
|
+
fallbackStack: [
|
|
537
|
+
"Candara",
|
|
538
|
+
"Carlito",
|
|
539
|
+
"Arial",
|
|
540
|
+
"sans-serif"
|
|
541
|
+
],
|
|
542
|
+
singleLineRatio: singleLineRatioOf({
|
|
543
|
+
source: "hhea",
|
|
544
|
+
hheaAscent: 1484,
|
|
545
|
+
hheaDescent: -564,
|
|
546
|
+
hheaLineGap: 452,
|
|
547
|
+
unitsPerEm: 2048
|
|
548
|
+
})
|
|
549
|
+
},
|
|
550
|
+
constantia: {
|
|
551
|
+
googleFont: "Caladea",
|
|
552
|
+
category: "serif",
|
|
553
|
+
fallbackStack: [
|
|
554
|
+
"Constantia",
|
|
555
|
+
"Caladea",
|
|
556
|
+
"Georgia",
|
|
557
|
+
"serif"
|
|
558
|
+
],
|
|
559
|
+
singleLineRatio: singleLineRatioOf({
|
|
560
|
+
source: "hhea",
|
|
561
|
+
hheaAscent: 1538,
|
|
562
|
+
hheaDescent: -510,
|
|
563
|
+
hheaLineGap: 452,
|
|
564
|
+
unitsPerEm: 2048
|
|
565
|
+
})
|
|
566
|
+
},
|
|
567
|
+
corbel: {
|
|
568
|
+
googleFont: "Carlito",
|
|
569
|
+
category: "sans-serif",
|
|
570
|
+
fallbackStack: [
|
|
571
|
+
"Corbel",
|
|
572
|
+
"Carlito",
|
|
573
|
+
"Arial",
|
|
574
|
+
"sans-serif"
|
|
575
|
+
],
|
|
576
|
+
singleLineRatio: singleLineRatioOf({
|
|
577
|
+
source: "hhea",
|
|
578
|
+
hheaAscent: 1523,
|
|
579
|
+
hheaDescent: -525,
|
|
580
|
+
hheaLineGap: 425,
|
|
581
|
+
unitsPerEm: 2048
|
|
582
|
+
})
|
|
583
|
+
},
|
|
584
|
+
dubai: {
|
|
585
|
+
googleFont: "Noto Sans Arabic",
|
|
586
|
+
category: "sans-serif",
|
|
587
|
+
fallbackStack: [
|
|
588
|
+
"Dubai",
|
|
589
|
+
"Noto Sans Arabic",
|
|
590
|
+
"Arial",
|
|
591
|
+
"sans-serif"
|
|
592
|
+
],
|
|
593
|
+
singleLineRatio: singleLineRatioOf({
|
|
594
|
+
source: "hhea",
|
|
595
|
+
hheaAscent: 1129,
|
|
596
|
+
hheaDescent: -559,
|
|
597
|
+
hheaLineGap: 0,
|
|
598
|
+
unitsPerEm: 1e3
|
|
599
|
+
})
|
|
600
|
+
},
|
|
601
|
+
"simplified arabic": {
|
|
602
|
+
googleFont: "Noto Naskh Arabic",
|
|
603
|
+
category: "serif",
|
|
604
|
+
fallbackStack: [
|
|
605
|
+
"Simplified Arabic",
|
|
606
|
+
"Noto Naskh Arabic",
|
|
607
|
+
"Times New Roman",
|
|
608
|
+
"serif"
|
|
609
|
+
],
|
|
610
|
+
singleLineRatio: singleLineRatioOf({
|
|
611
|
+
source: "measured",
|
|
612
|
+
ratio: 1.6582,
|
|
613
|
+
note: "Measured at 11pt against an 18.24pt reference-layout line pitch; the face ships with the office suite, not as a readable font file."
|
|
614
|
+
})
|
|
615
|
+
},
|
|
616
|
+
"sakkal majalla": {
|
|
617
|
+
googleFont: "Noto Naskh Arabic",
|
|
618
|
+
category: "serif",
|
|
619
|
+
fallbackStack: [
|
|
620
|
+
"Sakkal Majalla",
|
|
621
|
+
"Noto Naskh Arabic",
|
|
622
|
+
"Times New Roman",
|
|
623
|
+
"serif"
|
|
624
|
+
],
|
|
625
|
+
singleLineRatio: singleLineRatioOf({
|
|
626
|
+
source: "measured",
|
|
627
|
+
ratio: 1.3964,
|
|
628
|
+
note: "Measured at 11pt against a 15.36pt reference-layout line pitch; the face ships with the office suite, not as a readable font file."
|
|
629
|
+
})
|
|
630
|
+
},
|
|
448
631
|
"ms mincho": {
|
|
449
632
|
googleFont: "Noto Serif JP",
|
|
450
633
|
category: "serif",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/utils/htmlComments.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Index just past the HTML comment that opens at `start`, or `null` when the
|
|
4
|
+
* comment is never closed.
|
|
5
|
+
*
|
|
6
|
+
* `<!-->` and `<!--->` are ABRUPT-CLOSING comments: the tokenizer's comment
|
|
7
|
+
* start and comment-start-dash states end the comment at that `>` (HTML
|
|
8
|
+
* §13.2.5.42-43). Scanning for `-->` from `start + 4` runs straight past them,
|
|
9
|
+
* finds nothing, and every caller then treats the rest of the document as one
|
|
10
|
+
* unterminated comment — a pasted payload that opens with `<!-->` is dropped
|
|
11
|
+
* whole and silently.
|
|
12
|
+
*
|
|
13
|
+
* Both comment strippers resolve the terminator here so the two cannot drift.
|
|
14
|
+
*/
|
|
15
|
+
declare const htmlCommentEnd: (html: string, start: number) => number | null;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { htmlCommentEnd };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/utils/htmlComments.ts
|
|
2
|
+
/**
|
|
3
|
+
* Index just past the HTML comment that opens at `start`, or `null` when the
|
|
4
|
+
* comment is never closed.
|
|
5
|
+
*
|
|
6
|
+
* `<!-->` and `<!--->` are ABRUPT-CLOSING comments: the tokenizer's comment
|
|
7
|
+
* start and comment-start-dash states end the comment at that `>` (HTML
|
|
8
|
+
* §13.2.5.42-43). Scanning for `-->` from `start + 4` runs straight past them,
|
|
9
|
+
* finds nothing, and every caller then treats the rest of the document as one
|
|
10
|
+
* unterminated comment — a pasted payload that opens with `<!-->` is dropped
|
|
11
|
+
* whole and silently.
|
|
12
|
+
*
|
|
13
|
+
* Both comment strippers resolve the terminator here so the two cannot drift.
|
|
14
|
+
*/
|
|
15
|
+
const htmlCommentEnd = (html, start) => {
|
|
16
|
+
if (html[start + 4] === ">") return start + 5;
|
|
17
|
+
if (html[start + 4] === "-" && html[start + 5] === ">") return start + 6;
|
|
18
|
+
const end = html.indexOf("-->", start + 4);
|
|
19
|
+
return end === -1 ? null : end + 3;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { htmlCommentEnd };
|
|
@@ -56,6 +56,17 @@ declare function scriptClassOf(cp: number): ScriptClass;
|
|
|
56
56
|
* True when the text contains at least one complex-script code point. Callers
|
|
57
57
|
* use this to skip segmentation entirely on the common all-Latin path.
|
|
58
58
|
*/
|
|
59
|
+
/**
|
|
60
|
+
* True when a code point belongs to a right-to-left script.
|
|
61
|
+
*
|
|
62
|
+
* A subset of the complex-script ranges: Thai, Lao, Khmer, Myanmar, Tibetan and
|
|
63
|
+
* the Indic scripts shape but read left to right. Shaping needs the answer
|
|
64
|
+
* because the direction decides the order glyphs come back in, and a run shaped
|
|
65
|
+
* the wrong way round reads backwards.
|
|
66
|
+
*/
|
|
67
|
+
declare function isRightToLeftCodePoint(cp: number): boolean;
|
|
68
|
+
/** True when the text contains at least one right-to-left code point. */
|
|
69
|
+
declare function hasRightToLeft(text: string): boolean;
|
|
59
70
|
declare function hasComplexScript(text: string): boolean;
|
|
60
71
|
/**
|
|
61
72
|
* Split text into maximal runs of one script class (CJK vs. non-CJK). Iterates
|
|
@@ -64,4 +75,4 @@ declare function hasComplexScript(text: string): boolean;
|
|
|
64
75
|
*/
|
|
65
76
|
declare function segmentByScript(text: string): ScriptSegment[];
|
|
66
77
|
//#endregion
|
|
67
|
-
export { SCRIPT_CLASS, ScriptClass, ScriptSegment, hasCjk, hasComplexScript, isCjkCodePoint, isComplexScriptCodePoint, scriptClassOf, segmentByScript };
|
|
78
|
+
export { SCRIPT_CLASS, ScriptClass, ScriptSegment, hasCjk, hasComplexScript, hasRightToLeft, isCjkCodePoint, isComplexScriptCodePoint, isRightToLeftCodePoint, scriptClassOf, segmentByScript };
|
|
@@ -62,6 +62,22 @@ function scriptClassOf(cp) {
|
|
|
62
62
|
* True when the text contains at least one complex-script code point. Callers
|
|
63
63
|
* use this to skip segmentation entirely on the common all-Latin path.
|
|
64
64
|
*/
|
|
65
|
+
/**
|
|
66
|
+
* True when a code point belongs to a right-to-left script.
|
|
67
|
+
*
|
|
68
|
+
* A subset of the complex-script ranges: Thai, Lao, Khmer, Myanmar, Tibetan and
|
|
69
|
+
* the Indic scripts shape but read left to right. Shaping needs the answer
|
|
70
|
+
* because the direction decides the order glyphs come back in, and a run shaped
|
|
71
|
+
* the wrong way round reads backwards.
|
|
72
|
+
*/
|
|
73
|
+
function isRightToLeftCodePoint(cp) {
|
|
74
|
+
return cp >= 1424 && cp <= 1535 || cp >= 1536 && cp <= 1791 || cp >= 1792 && cp <= 1871 || cp >= 1872 && cp <= 1919 || cp >= 1920 && cp <= 1983 || cp >= 1984 && cp <= 2047 || cp >= 2048 && cp <= 2111 || cp >= 2112 && cp <= 2143 || cp >= 2144 && cp <= 2159 || cp >= 2160 && cp <= 2207 || cp >= 2208 && cp <= 2303 || cp >= 64285 && cp <= 64335 || cp >= 64336 && cp <= 65023 || cp >= 65136 && cp <= 65279 || cp >= 68864 && cp <= 68927 || cp >= 69312 && cp <= 69375 || cp >= 69424 && cp <= 69487 || cp >= 69488 && cp <= 69551 || cp >= 125184 && cp <= 125279 || cp >= 126464 && cp <= 126719;
|
|
75
|
+
}
|
|
76
|
+
/** True when the text contains at least one right-to-left code point. */
|
|
77
|
+
function hasRightToLeft(text) {
|
|
78
|
+
for (const ch of text) if (isRightToLeftCodePoint(ch.codePointAt(0))) return true;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
65
81
|
function hasComplexScript(text) {
|
|
66
82
|
for (const ch of text) if (isComplexScriptCodePoint(ch.codePointAt(0))) return true;
|
|
67
83
|
return false;
|
|
@@ -100,4 +116,4 @@ function segmentByScript(text) {
|
|
|
100
116
|
return segments;
|
|
101
117
|
}
|
|
102
118
|
//#endregion
|
|
103
|
-
export { SCRIPT_CLASS, hasCjk, hasComplexScript, isCjkCodePoint, isComplexScriptCodePoint, scriptClassOf, segmentByScript };
|
|
119
|
+
export { SCRIPT_CLASS, hasCjk, hasComplexScript, hasRightToLeft, isCjkCodePoint, isComplexScriptCodePoint, isRightToLeftCodePoint, scriptClassOf, segmentByScript };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FolioAIBlock } from "./ai-edits/types.js";
|
|
2
|
-
import { FolioDocumentStoryHandle } from "./ai-edits/headless.js";
|
|
3
2
|
import { WordDiffSegment } from "./ai-edits/word-diff.js";
|
|
3
|
+
import { FolioDocumentStoryHandle } from "./ai-edits/headless.js";
|
|
4
4
|
import { FOLIO_DOCUMENT_METADATA_PROPERTIES, FolioDocumentMetadataProperty, FolioDocumentPrivacyOptions, FolioDocumentPrivacyReport, FolioDocumentPrivacyTransform } from "./docx/metadataPrivacy.js";
|
|
5
5
|
//#region src/version-comparison.d.ts
|
|
6
6
|
/** One word-level diff segment within a `modified` block. Mirrors {@link WordDiffSegment}. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/folio-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
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",
|
|
@@ -108,12 +108,14 @@
|
|
|
108
108
|
"prepack": "bun run build",
|
|
109
109
|
"pack:dry-run": "bun pm pack --dry-run",
|
|
110
110
|
"typecheck": "bun ../../scripts/tsc-native.ts --noEmit -p tsconfig.build.json",
|
|
111
|
-
"test": "bun test src",
|
|
111
|
+
"test": "bun test src scripts",
|
|
112
|
+
"wasm:check": "bun ../../scripts/build-shaper-wasm.ts --check",
|
|
113
|
+
"wasm:generate": "bun ../../scripts/build-shaper-wasm.ts --write",
|
|
112
114
|
"test:property": "bun test $(grep -rlF 'fc.assert' src --include='*.test.ts')",
|
|
113
115
|
"perf": "bun scripts/profile-editor.ts"
|
|
114
116
|
},
|
|
115
117
|
"dependencies": {
|
|
116
|
-
"@stll/docx-core": "^0.
|
|
118
|
+
"@stll/docx-core": "^0.19.0",
|
|
117
119
|
"@stll/docx-utils": "^0.1.0",
|
|
118
120
|
"@stll/template-conditions": "^0.1.0",
|
|
119
121
|
"better-result": "3.0.1",
|
|
@@ -138,6 +140,8 @@
|
|
|
138
140
|
"yjs": "^13.6.31"
|
|
139
141
|
},
|
|
140
142
|
"devDependencies": {
|
|
143
|
+
"@fontsource/noto-sans-devanagari": "^5.3.0",
|
|
144
|
+
"@fontsource/noto-sans-hebrew": "^5.3.0",
|
|
141
145
|
"@types/hyphen": "1.14.0"
|
|
142
146
|
},
|
|
143
147
|
"main": "./dist/index.js",
|