@stll/folio-core 0.41.0 → 0.43.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/README.md +16 -0
- package/dist/compat/eigenpal.d.ts +3 -3
- package/dist/controller/layoutPipeline.d.ts +2 -1
- package/dist/controller/layoutPipeline.js +5 -2
- package/dist/controller/layoutSession.d.ts +2 -1
- package/dist/controller/layoutSession.js +1 -0
- package/dist/docx/blockContentParser.js +2 -1
- package/dist/docx/commentIdNormalization.d.ts +8 -0
- package/dist/docx/commentIdNormalization.js +16 -0
- package/dist/docx/defaultParagraphStyle.d.ts +22 -0
- package/dist/docx/defaultParagraphStyle.js +32 -0
- package/dist/docx/footnoteParser.js +2 -0
- package/dist/docx/headerFooterRefParser.d.ts +12 -1
- package/dist/docx/headerFooterRefParser.js +9 -2
- package/dist/docx/numberingParser.js +2 -1
- package/dist/docx/numberingReference.d.ts +21 -0
- package/dist/docx/numberingReference.js +21 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +11 -2
- package/dist/docx/numberingReferenceNormalization.js +32 -9
- package/dist/docx/paragraphParser.js +3 -2
- package/dist/docx/parser.js +10 -2
- package/dist/docx/rezip.d.ts +20 -3
- package/dist/docx/rezip.js +46 -18
- package/dist/docx/server/createBilingualDocument.js +5 -4
- package/dist/docx/styleParser.js +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +2 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +7 -5
- package/dist/layout-bridge/convert/templatePreviewFlow.d.ts +19 -11
- package/dist/layout-bridge/convert/templatePreviewFlow.js +103 -38
- package/dist/layout-bridge/convert/toFlowBlocks.js +12 -3
- package/dist/prosemirror/commands/pageBreak.js +12 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +2 -1
- package/dist/prosemirror/conversion/toProseDoc.js +27 -12
- package/dist/prosemirror/extensions/features/ListExtension.js +42 -4
- package/dist/prosemirror/listMarker.js +2 -1
- package/dist/prosemirror/numberedRefFields.js +2 -1
- package/dist/prosemirror/pageBreakRunProjection.d.ts +11 -3
- package/dist/prosemirror/pageBreakRunProjection.js +16 -8
- package/dist/prosemirror/plugins/templatePreviewValues.d.ts +42 -1
- package/dist/prosemirror/plugins/templatePreviewValues.js +217 -14
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -1
- package/dist/prosemirror/styles/styleResolver.js +3 -6
- package/dist/prosemirror/utils/visualLineNavigation.d.ts +22 -2
- package/dist/prosemirror/utils/visualLineNavigation.js +80 -63
- package/dist/server.d.ts +2 -2
- package/dist/style-engine/styleEngine.d.ts +1 -1
- package/dist/style-sets/extract.js +57 -11
- package/package.json +2 -1
package/dist/docx/rezip.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { consumeTrackedSectionEndpointRemoval } from "../internal/sectionEndpointResolution.js";
|
|
2
2
|
import { consumeSectionReferenceResolution } from "../internal/sectionReferenceResolution.js";
|
|
3
3
|
import { isAllowedExternalWatermarkImageUrl } from "../watermark/index.js";
|
|
4
|
-
import { normalizeAppVersionInExtendedProperties } from "./appVersionNormalization.js";
|
|
4
|
+
import { appVersionInSchemaForm, normalizeAppVersionInExtendedProperties } from "./appVersionNormalization.js";
|
|
5
5
|
import { withoutOrphanCommentRanges } from "./commentRangeIntegrity.js";
|
|
6
6
|
import { applyReplyThreadMarkers } from "./commentReplyMarkers.js";
|
|
7
7
|
import { normalizeDrawingIds } from "./drawingIdNormalization.js";
|
|
8
8
|
import { rebindDrawingImageRelationship } from "./drawingRelationships.js";
|
|
9
9
|
import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
|
|
10
|
+
import { parseHeaderFooterType } from "./headerFooterRefParser.js";
|
|
10
11
|
import { assertValidFolioDocumentModel } from "./modelValidation.js";
|
|
11
12
|
import { isNewDataUrlDrawing } from "./newImage.js";
|
|
12
13
|
import { parseNumbering } from "./numberingParser.js";
|
|
14
|
+
import { isNumberingReference } from "./numberingReference.js";
|
|
13
15
|
import { isUnsafePackagePath, reconcilePackageReferences, removeUnsafeEntries } from "./packageParts.js";
|
|
14
16
|
import { normalizeParaIdRangeInXmlParts } from "./paraIdRangeNormalization.js";
|
|
15
17
|
import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
|
|
@@ -113,7 +115,7 @@ const extractHeaderFooterReferences = (xml) => {
|
|
|
113
115
|
const rId = getAttributeByNamespaceUri(node, OFFICE_RELATIONSHIP_NAMESPACE_URIS, "id");
|
|
114
116
|
if (rId) references.push({
|
|
115
117
|
element,
|
|
116
|
-
type: getAttributeByNamespaceUri(node, WORDPROCESSINGML_NAMESPACE_URIS, "type")
|
|
118
|
+
type: parseHeaderFooterType(getAttributeByNamespaceUri(node, WORDPROCESSINGML_NAMESPACE_URIS, "type")),
|
|
117
119
|
rId
|
|
118
120
|
});
|
|
119
121
|
}
|
|
@@ -1524,14 +1526,24 @@ function isDocxBuffer(buffer) {
|
|
|
1524
1526
|
return view[0] === 80 && view[1] === 75;
|
|
1525
1527
|
}
|
|
1526
1528
|
/**
|
|
1529
|
+
* The application version a newly created package states.
|
|
1530
|
+
*
|
|
1531
|
+
* `AppVersion` describes the application, so it is written only alongside one,
|
|
1532
|
+
* and it says nothing about the host beyond the `XX.YYYY` form the schema
|
|
1533
|
+
* fixes. Deriving it from the mapping every save exit already uses keeps the
|
|
1534
|
+
* two from drifting apart.
|
|
1535
|
+
*/
|
|
1536
|
+
const CREATED_APP_VERSION = appVersionInSchemaForm("1");
|
|
1537
|
+
/**
|
|
1527
1538
|
* Create a new empty DOCX file
|
|
1528
1539
|
*
|
|
1540
|
+
* @param properties - Document properties the package states about itself
|
|
1529
1541
|
* @returns Promise resolving to minimal DOCX as ArrayBuffer
|
|
1530
1542
|
*/
|
|
1531
|
-
function createEmptyDocx() {
|
|
1532
|
-
return generateDocxZip(createEmptyDocxZip(), 6);
|
|
1543
|
+
function createEmptyDocx(properties = {}) {
|
|
1544
|
+
return generateDocxZip(createEmptyDocxZip(properties), 6);
|
|
1533
1545
|
}
|
|
1534
|
-
const createEmptyDocxZip = () => {
|
|
1546
|
+
const createEmptyDocxZip = ({ creator, application }) => {
|
|
1535
1547
|
const zip = new JSZip();
|
|
1536
1548
|
zip.file("[Content_Types].xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
1537
1549
|
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
|
@@ -1586,16 +1598,15 @@ const createEmptyDocxZip = () => {
|
|
|
1586
1598
|
</w:style>
|
|
1587
1599
|
</w:styles>`);
|
|
1588
1600
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1601
|
+
const creatorElement = creator === void 0 ? "" : `\n <dc:creator>${escapeXml(creator)}</dc:creator>`;
|
|
1589
1602
|
zip.file("docProps/core.xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
1590
|
-
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
1591
|
-
<dc:creator>EigenPal DOCX Editor</dc:creator>
|
|
1603
|
+
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">${creatorElement}
|
|
1592
1604
|
<dcterms:created xsi:type="dcterms:W3CDTF">${now}</dcterms:created>
|
|
1593
1605
|
<dcterms:modified xsi:type="dcterms:W3CDTF">${now}</dcterms:modified>
|
|
1594
1606
|
</cp:coreProperties>`);
|
|
1607
|
+
const applicationElements = application === void 0 ? "" : `\n <Application>${escapeXml(application)}</Application>\n <AppVersion>${CREATED_APP_VERSION}</AppVersion>`;
|
|
1595
1608
|
zip.file("docProps/app.xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
1596
|
-
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"
|
|
1597
|
-
<Application>EigenPal DOCX Editor</Application>
|
|
1598
|
-
<AppVersion>1.0000</AppVersion>
|
|
1609
|
+
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">${applicationElements}
|
|
1599
1610
|
</Properties>`);
|
|
1600
1611
|
return zip;
|
|
1601
1612
|
};
|
|
@@ -1603,9 +1614,11 @@ const createEmptyDocxZip = () => {
|
|
|
1603
1614
|
* Create a new DOCX from a Document (without requiring original buffer)
|
|
1604
1615
|
*
|
|
1605
1616
|
* @param doc - Document to serialize
|
|
1617
|
+
* @param properties - Document properties a package built from scratch states
|
|
1618
|
+
* about itself; ignored when `doc` carries a source package
|
|
1606
1619
|
* @returns Promise resolving to DOCX as ArrayBuffer
|
|
1607
1620
|
*/
|
|
1608
|
-
async function createDocx(doc) {
|
|
1621
|
+
async function createDocx(doc, properties = {}) {
|
|
1609
1622
|
if (doc.originalBuffer) {
|
|
1610
1623
|
const source = await loadParsedZipSource(doc, doc.originalBuffer);
|
|
1611
1624
|
return finishRepack({
|
|
@@ -1618,7 +1631,7 @@ async function createDocx(doc) {
|
|
|
1618
1631
|
updateModifiedDate: true
|
|
1619
1632
|
});
|
|
1620
1633
|
}
|
|
1621
|
-
const zip = await createDocumentSeedZip(doc);
|
|
1634
|
+
const zip = await createDocumentSeedZip(doc, properties);
|
|
1622
1635
|
return finishRepack({
|
|
1623
1636
|
document: withoutOrphanCommentRanges(doc),
|
|
1624
1637
|
originalZip: zip,
|
|
@@ -1629,8 +1642,8 @@ async function createDocx(doc) {
|
|
|
1629
1642
|
updateModifiedDate: true
|
|
1630
1643
|
});
|
|
1631
1644
|
}
|
|
1632
|
-
const createDocumentSeedZip = async (doc) => {
|
|
1633
|
-
const zip = createEmptyDocxZip();
|
|
1645
|
+
const createDocumentSeedZip = async (doc, properties) => {
|
|
1646
|
+
const zip = createEmptyDocxZip(properties);
|
|
1634
1647
|
const relationships = ["<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>"];
|
|
1635
1648
|
const overrides = [];
|
|
1636
1649
|
let nextRelationshipId = 2;
|
|
@@ -1673,17 +1686,32 @@ const createDocumentSeedZip = async (doc) => {
|
|
|
1673
1686
|
};
|
|
1674
1687
|
const relationshipXml = (id, type, target) => `<Relationship Id="rId${id}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/${type}" Target="${target}"/>`;
|
|
1675
1688
|
const overrideXml = (partName, contentType) => `<Override PartName="${partName}" ContentType="${contentType}"/>`;
|
|
1689
|
+
/**
|
|
1690
|
+
* A package this build assembles from a Document must define the numbering its
|
|
1691
|
+
* styles name: Word reads a styles.xml reference nothing resolves as no
|
|
1692
|
+
* numbering at all, silently dropping the style's list.
|
|
1693
|
+
*
|
|
1694
|
+
* The panic is an invariant over Folio's own output, not input validation. A
|
|
1695
|
+
* source file can carry a dangling style reference, and it never arrives here:
|
|
1696
|
+
* `normalizeStyleNumberingReferences` rewrites one to the "no numbering"
|
|
1697
|
+
* sentinel at every boundary that mints a Document from user styles (`parseDocx`
|
|
1698
|
+
* and the style-set extraction entry points). What reaches this point is what
|
|
1699
|
+
* Folio itself put in the model, so a miss is a defect in Folio.
|
|
1700
|
+
*/
|
|
1676
1701
|
const assertStyleNumberingReferences = (doc) => {
|
|
1677
1702
|
const referenced = /* @__PURE__ */ new Set();
|
|
1678
1703
|
for (const style of doc.package.styles?.styles ?? []) {
|
|
1679
1704
|
const numId = style.pPr?.numPr?.numId;
|
|
1680
|
-
if (numId
|
|
1705
|
+
if (isNumberingReference(numId)) referenced.add(numId);
|
|
1681
1706
|
}
|
|
1682
1707
|
if (referenced.size === 0) return;
|
|
1683
|
-
const available = new
|
|
1684
|
-
for (const numId of referenced) if (!available.has(numId)) panic(`Style references missing numbering definition ${numId}`);
|
|
1708
|
+
const available = new Map(doc.package.numbering?.nums.map((numbering) => [numbering.numId, numbering]) ?? []);
|
|
1685
1709
|
const availableAbstract = new Set(doc.package.numbering?.abstractNums.map((numbering) => numbering.abstractNumId) ?? []);
|
|
1686
|
-
for (const
|
|
1710
|
+
for (const numId of referenced) {
|
|
1711
|
+
const numbering = available.get(numId);
|
|
1712
|
+
if (!numbering) panic(`Style references missing numbering definition ${numId}`);
|
|
1713
|
+
if (!availableAbstract.has(numbering.abstractNumId)) panic(`Numbering definition ${numbering.numId} references missing abstract numbering`);
|
|
1714
|
+
}
|
|
1687
1715
|
};
|
|
1688
1716
|
//#endregion
|
|
1689
1717
|
export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocxPackageFidelityError, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, collectHyperlinksWithoutRId, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, hasUnmaterializedInlineResources, isDocxBuffer, notePartRelsPath, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx, withoutAttachedTemplate };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { deterministicHexId } from "../../utils/hexId.js";
|
|
2
|
+
import { isNumberingReference } from "../numberingReference.js";
|
|
2
3
|
import { getParagraphText } from "../paragraphParser.js";
|
|
3
4
|
import { cloneParagraphWithoutPropertySource } from "../paragraphPropertySource.js";
|
|
4
5
|
import { getRunText } from "../runParser.js";
|
|
@@ -257,7 +258,7 @@ const resolveInheritedOutlineLevel = (style, styleById) => {
|
|
|
257
258
|
/** The numbering a paragraph renders with: direct `numPr`, else the style chain's. */
|
|
258
259
|
const effectiveNumPr = (paragraph, styleById) => {
|
|
259
260
|
const direct = paragraph.formatting?.numPr;
|
|
260
|
-
if (direct?.numId !== void 0) return direct.numId
|
|
261
|
+
if (direct?.numId !== void 0) return isNumberingReference(direct.numId) ? direct : void 0;
|
|
261
262
|
const styleId = paragraph.formatting?.styleId;
|
|
262
263
|
return styleId ? styleNumPr(styleById.get(styleId), styleById) : void 0;
|
|
263
264
|
};
|
|
@@ -267,7 +268,7 @@ const styleNumPr = (style, styleById) => {
|
|
|
267
268
|
while (current && !seen.has(current.styleId)) {
|
|
268
269
|
seen.add(current.styleId);
|
|
269
270
|
const numPr = current.pPr?.numPr;
|
|
270
|
-
if (numPr?.numId !== void 0) return numPr.numId
|
|
271
|
+
if (numPr?.numId !== void 0) return isNumberingReference(numPr.numId) ? numPr : void 0;
|
|
271
272
|
current = current.basedOn ? styleById.get(current.basedOn) : void 0;
|
|
272
273
|
}
|
|
273
274
|
};
|
|
@@ -396,11 +397,11 @@ const cloneParagraphForTarget = (paragraph, targetParaId, styleCloner, cloner, b
|
|
|
396
397
|
const nextFormatting = formatting && {
|
|
397
398
|
...formatting,
|
|
398
399
|
...formatting.styleId !== void 0 && { styleId: styleCloner.styleIdFor(formatting.styleId) },
|
|
399
|
-
...formatting.numPr
|
|
400
|
+
...formatting.numPr !== void 0 && isNumberingReference(formatting.numPr.numId) && { numPr: {
|
|
400
401
|
...formatting.numPr,
|
|
401
402
|
numId: cloner.cloneNumId(formatting.numPr.numId)
|
|
402
403
|
} },
|
|
403
|
-
...formatting.numPrFromStyle
|
|
404
|
+
...formatting.numPrFromStyle !== void 0 && isNumberingReference(formatting.numPrFromStyle.numId) && { numPrFromStyle: {
|
|
404
405
|
...formatting.numPrFromStyle,
|
|
405
406
|
numId: cloner.cloneNumId(formatting.numPrFromStyle.numId)
|
|
406
407
|
} }
|
package/dist/docx/styleParser.js
CHANGED
|
@@ -2,6 +2,7 @@ import { isValidHexColor } from "../utils/colorResolver.js";
|
|
|
2
2
|
import { parseHorizontalScalePercent } from "../utils/horizontalScale.js";
|
|
3
3
|
import { mergeParagraphFormatting } from "../utils/paragraphFormattingMerge.js";
|
|
4
4
|
import { mergeStyleTextFormatting } from "../utils/textFormattingMerge.js";
|
|
5
|
+
import { resolveDefaultParagraphStyle } from "./defaultParagraphStyle.js";
|
|
5
6
|
import { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FontHintSchema, FontThemeSchema, HighlightColorSchema, LineSpacingRuleSchema, ParagraphAlignmentSchema, ShadingPatternSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
|
|
6
7
|
import { resolveThemeFontRef } from "./themeParser.js";
|
|
7
8
|
import { findChild, findChildren, getAttribute, getLocalName, parseBooleanElement, parseNumberingLevelAttribute, parseNumericAttribute, parseOnOffValue, parseTableMeasurementValue, parseXmlDocument } from "./xmlParser.js";
|
|
@@ -916,8 +917,7 @@ function getResolvedStyle(styleId, styleMap) {
|
|
|
916
917
|
* Get the default paragraph style
|
|
917
918
|
*/
|
|
918
919
|
function getDefaultParagraphStyle(styleMap) {
|
|
919
|
-
|
|
920
|
-
return styleMap.get("Normal");
|
|
920
|
+
return resolveDefaultParagraphStyle(styleMap.values());
|
|
921
921
|
}
|
|
922
922
|
/**
|
|
923
923
|
* Get the default character style
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { CreateEmptyDocumentOptions, createEmptyDocument } from "./utils/createD
|
|
|
20
20
|
import { mergeDocumentContent } from "./utils/mergeDocumentContent.js";
|
|
21
21
|
import { DocumentStyleCatalog, DocumentStyleCatalogEntry, ExtractDocumentStyleSetOptions, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, inspectDocumentStyles, inspectDocumentStylesFromDocx } from "./style-sets/extract.js";
|
|
22
22
|
import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet } from "./style-sets/stellaStyle.js";
|
|
23
|
-
import { createDocx } from "./docx/rezip.js";
|
|
23
|
+
import { DocumentPropertiesOptions, createDocx } from "./docx/rezip.js";
|
|
24
24
|
import { DRAWING_SAFETY_CLASSES, DrawingSafetyClass } from "./docx/imageRawXml.js";
|
|
25
25
|
import { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, DocxDrawingClassification, FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, InspectDocxCompatibilityOptions, inspectDocxCompatibility } from "./docx/compatibility.js";
|
|
26
26
|
import { BlockRect } from "./paged-layout/blockGeometry.js";
|
|
@@ -30,7 +30,7 @@ import { getFolioCaretViewportRect, getFolioSelectionViewportRect } from "./page
|
|
|
30
30
|
import { AICitationRange, createAICitationDecorationsPlugin, setAICitationsMeta, setActiveCitationMeta } from "./prosemirror/plugins/aiCitationDecorations.js";
|
|
31
31
|
import { AnonymizationMatch, AnonymizationTerm, anonymizationDecorationsKey, getAnonymizationMatches, setAnonymizationTermsMeta } from "./prosemirror/plugins/anonymizationDecorations.js";
|
|
32
32
|
import { DirectiveKind, DirectiveRange, getTemplateDirectives, scanDirectives } from "./prosemirror/plugins/templateDirectives.js";
|
|
33
|
-
import { TemplatePreviewSpan, TemplatePreviewValue, TemplatePreviewValues, setTemplatePreviewValues } from "./prosemirror/plugins/templatePreviewValues.js";
|
|
33
|
+
import { TemplatePreviewHiddenRange, TemplatePreviewSpan, TemplatePreviewValue, TemplatePreviewValues, setTemplatePreviewValues } from "./prosemirror/plugins/templatePreviewValues.js";
|
|
34
34
|
import { TemplateSlashMenuKeyAction, TemplateSlashMenuState, clearTemplateSlashMenu, consumeTemplateSlashQuery, getTemplateSlashMenu, resetTemplateSlashQuery, templateSlashMenuKey } from "./prosemirror/plugins/templateSlashMenu.js";
|
|
35
35
|
import { AcceptAutocompleteResult, AutocompleteSuggestionPluginOptions, AutocompleteSuggestionState, AutocompleteSuggestionStatus, AutocompleteTriggerCheck, AutocompleteTriggerOptions, AutocompleteTriggerSkipReason, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, acceptAutocompleteSuggestion, acceptAutocompleteWord, appendAutocompleteToken, autocompleteSuggestionKey, autocompleteSuggestionPlugin, clearAutocompleteSuggestion, finishAutocompleteSuggestion, getAutocompleteSuggestion, shouldTriggerAutocomplete, startAutocompleteSuggestion } from "./prosemirror/plugins/autocompleteSuggestion.js";
|
|
36
36
|
import { ImageMeta, ImageRef, MarkdownOptions, MarkdownResult } from "./markdown/types.js";
|
|
@@ -41,4 +41,4 @@ import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled
|
|
|
41
41
|
import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
|
|
42
42
|
type Document = document_d_exports.Document;
|
|
43
43
|
type DocxConformanceClass = document_d_exports.DocxConformanceClass;
|
|
44
|
-
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
44
|
+
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
@@ -2,6 +2,8 @@ import { document_d_exports } from "../types/document.js";
|
|
|
2
2
|
//#region src/internal/pageBreakRunSourceDescendantIndex.d.ts
|
|
3
3
|
type PageBreakRunSourceDescendantIndex = {
|
|
4
4
|
containsPageBreakRun: (content: readonly document_d_exports.BlockContent[]) => boolean;
|
|
5
|
+
/** The same question about one block, so a caller can ask it per sibling. */
|
|
6
|
+
blockContainsPageBreakRun: (block: document_d_exports.BlockContent) => boolean;
|
|
5
7
|
paragraphFeatures: (paragraph: document_d_exports.Paragraph) => PageBreakRunSourceParagraphFeatures;
|
|
6
8
|
};
|
|
7
9
|
type PageBreakRunSourceParagraphFeatures = {
|
|
@@ -105,12 +105,14 @@ const buildPageBreakRunSourceDescendantIndex = (rootContent) => {
|
|
|
105
105
|
return flags;
|
|
106
106
|
}
|
|
107
107
|
inspectBlocks(rootContent);
|
|
108
|
+
const indexedFlags = (node) => {
|
|
109
|
+
const flags = flagsByObject.get(node);
|
|
110
|
+
if (flags === void 0) panic("Page-break source ownership was queried outside its conversion index");
|
|
111
|
+
return flags;
|
|
112
|
+
};
|
|
108
113
|
return {
|
|
109
|
-
containsPageBreakRun: (content) =>
|
|
110
|
-
|
|
111
|
-
if (flags === void 0) panic("Page-break source ownership was queried outside its conversion index");
|
|
112
|
-
return hasFlag(flags, SOURCE_FLAGS.containsPageBreak);
|
|
113
|
-
},
|
|
114
|
+
containsPageBreakRun: (content) => hasFlag(indexedFlags(content), SOURCE_FLAGS.containsPageBreak),
|
|
115
|
+
blockContainsPageBreakRun: (block) => hasFlag(indexedFlags(block), SOURCE_FLAGS.containsPageBreak),
|
|
114
116
|
paragraphFeatures: (paragraph) => {
|
|
115
117
|
const flags = flagsByObject.get(paragraph);
|
|
116
118
|
if (flags === void 0) panic("Page-break paragraph ownership was queried outside its conversion index");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TemplatePreviewValue } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
1
|
+
import { TemplatePreviewHiddenRange, TemplatePreviewValue } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
2
2
|
import { FlowBlock } from "../../layout-engine/types.js";
|
|
3
3
|
//#region src/layout-bridge/convert/templatePreviewFlow.d.ts
|
|
4
4
|
/** One marker→value substitution, in PM doc positions. */
|
|
@@ -10,27 +10,35 @@ type TemplatePreviewFlowEntry = {
|
|
|
10
10
|
/** The typed value displayed in place of the marker. */
|
|
11
11
|
value: TemplatePreviewValue;
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
/** What the preview substitutes and what it hides, as the flow stage sees it. */
|
|
14
|
+
type TemplatePreviewFlowState = {
|
|
14
15
|
entries: readonly TemplatePreviewFlowEntry[];
|
|
16
|
+
/** Conditional spans a `false` condition hides, in PM doc positions. */
|
|
17
|
+
hidden: readonly TemplatePreviewHiddenRange[];
|
|
18
|
+
};
|
|
19
|
+
type TemplatePreviewFlowOptions = TemplatePreviewFlowState & {
|
|
15
20
|
/** `highlighted` marks substituted runs for the accent-chip CSS. */
|
|
16
21
|
mode: "highlighted" | "plain";
|
|
17
22
|
};
|
|
18
23
|
/**
|
|
19
24
|
* Replace each entry's marker range with its preview value across the given
|
|
20
|
-
* flow blocks (recursing into table cells and text boxes)
|
|
21
|
-
*
|
|
25
|
+
* flow blocks (recursing into table cells and text boxes), and drop the blocks
|
|
26
|
+
* a hidden conditional span swallows whole. Returns the input array unchanged
|
|
27
|
+
* when there is nothing to substitute and nothing to hide.
|
|
22
28
|
*/
|
|
23
|
-
declare function applyTemplatePreviewToBlocks(blocks: FlowBlock[], { entries, mode }: TemplatePreviewFlowOptions): FlowBlock[];
|
|
29
|
+
declare function applyTemplatePreviewToBlocks(blocks: FlowBlock[], { entries, hidden, mode }: TemplatePreviewFlowOptions): FlowBlock[];
|
|
24
30
|
/**
|
|
25
|
-
* PM range covering every substitution
|
|
26
|
-
* states (changed, added, or removed
|
|
27
|
-
*
|
|
31
|
+
* PM range covering every substitution and every hidden span that differs
|
|
32
|
+
* between two preview states (changed, added, or removed), or `null` when the
|
|
33
|
+
* flow content both produce is identical. Feeds the layout pipeline's
|
|
28
34
|
* dirty-range invalidation so typing a value re-measures only the blocks
|
|
29
|
-
* hosting the affected markers.
|
|
35
|
+
* hosting the affected markers. A hidden span that appears or disappears also
|
|
36
|
+
* changes the block count, which sends the measure path down its full-remeasure
|
|
37
|
+
* branch regardless of how wide this range is.
|
|
30
38
|
*/
|
|
31
|
-
declare function templatePreviewDirtyRange(previous:
|
|
39
|
+
declare function templatePreviewDirtyRange(previous: TemplatePreviewFlowState, next: TemplatePreviewFlowState): {
|
|
32
40
|
from: number;
|
|
33
41
|
to: number;
|
|
34
42
|
} | null;
|
|
35
43
|
//#endregion
|
|
36
|
-
export { TemplatePreviewFlowEntry, TemplatePreviewFlowOptions, applyTemplatePreviewToBlocks, templatePreviewDirtyRange };
|
|
44
|
+
export { TemplatePreviewFlowEntry, TemplatePreviewFlowOptions, TemplatePreviewFlowState, applyTemplatePreviewToBlocks, templatePreviewDirtyRange };
|
|
@@ -1,16 +1,41 @@
|
|
|
1
|
-
import { templatePreviewValueFingerprint } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
1
|
+
import { templatePreviewHidesWholeBlock, templatePreviewValueFingerprint } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
2
2
|
//#region src/layout-bridge/convert/templatePreviewFlow.ts
|
|
3
3
|
/**
|
|
4
|
+
* A top-level block a hidden span swallows whole, which therefore leaves the
|
|
5
|
+
* flow. A block the span only partly covers stays: its text is authored content
|
|
6
|
+
* outside the conditional, and dropping the block would take that text with it.
|
|
7
|
+
*
|
|
8
|
+
* A block carrying no PM positions stays too. That is every section break,
|
|
9
|
+
* which is the safe answer rather than an accident: a section break sets the
|
|
10
|
+
* page geometry that follows it, so hiding text must not take it out of the
|
|
11
|
+
* flow. `SectionBreakBlock` is the one `FlowBlock` variant without the fields,
|
|
12
|
+
* hence the `in` test, matching `findDirtyBlockIndexes`.
|
|
13
|
+
*/
|
|
14
|
+
const isHiddenWholeBlock = (block, hidden) => {
|
|
15
|
+
const pmStart = "pmStart" in block ? block.pmStart : void 0;
|
|
16
|
+
const pmEnd = "pmEnd" in block ? block.pmEnd : void 0;
|
|
17
|
+
if (pmStart === void 0 || pmEnd === void 0) return false;
|
|
18
|
+
return hidden.some((range) => templatePreviewHidesWholeBlock(range, {
|
|
19
|
+
pmStart,
|
|
20
|
+
pmEnd
|
|
21
|
+
}));
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
4
24
|
* Replace each entry's marker range with its preview value across the given
|
|
5
|
-
* flow blocks (recursing into table cells and text boxes)
|
|
6
|
-
*
|
|
25
|
+
* flow blocks (recursing into table cells and text boxes), and drop the blocks
|
|
26
|
+
* a hidden conditional span swallows whole. Returns the input array unchanged
|
|
27
|
+
* when there is nothing to substitute and nothing to hide.
|
|
7
28
|
*/
|
|
8
|
-
function applyTemplatePreviewToBlocks(blocks, { entries, mode }) {
|
|
9
|
-
if (entries.length === 0) return blocks;
|
|
29
|
+
function applyTemplatePreviewToBlocks(blocks, { entries, hidden, mode }) {
|
|
30
|
+
if (entries.length === 0 && hidden.length === 0) return blocks;
|
|
10
31
|
const sorted = [...entries].sort((a, b) => a.from - b.from);
|
|
11
32
|
let changed = false;
|
|
12
33
|
const next = [];
|
|
13
34
|
for (const block of blocks) {
|
|
35
|
+
if (isHiddenWholeBlock(block, hidden)) {
|
|
36
|
+
changed = true;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
14
39
|
const transformed = transformBlock(block, sorted, mode);
|
|
15
40
|
changed ||= transformed !== block;
|
|
16
41
|
next.push(transformed);
|
|
@@ -117,60 +142,100 @@ function sliceTextRun(run, base, from, to) {
|
|
|
117
142
|
pmEnd: to
|
|
118
143
|
};
|
|
119
144
|
}
|
|
145
|
+
/** Every newline form a host value may carry; `\r\n` counts once. */
|
|
146
|
+
const VALUE_LINE_BREAK_RE = /\r\n|[\n\r]/u;
|
|
147
|
+
/**
|
|
148
|
+
* Push one span of value text, breaking its lines the way the editor does: each
|
|
149
|
+
* newline becomes a `lineBreak` run, which is the `w:br` the measurer starts a
|
|
150
|
+
* new line on. Consecutive newlines emit consecutive breaks, so a blank line
|
|
151
|
+
* stays a blank line; an empty segment contributes no text run of its own.
|
|
152
|
+
*
|
|
153
|
+
* A rich value's spans are one text stream, so a `\r\n` the host split across a
|
|
154
|
+
* formatting boundary is still one break: `pendingCr` carries a `\r` that ended
|
|
155
|
+
* the previous span, and the returned flag carries this span's. Without it the
|
|
156
|
+
* halves would count as two breaks and the value would gain a blank line.
|
|
157
|
+
*/
|
|
158
|
+
function pushValueSpan(out, valueRun, pendingCr) {
|
|
159
|
+
const text = pendingCr && valueRun.text.startsWith("\n") ? valueRun.text.slice(1) : valueRun.text;
|
|
160
|
+
const segments = text.split(VALUE_LINE_BREAK_RE);
|
|
161
|
+
for (const [index, segment] of segments.entries()) {
|
|
162
|
+
if (index > 0) out.push({
|
|
163
|
+
kind: "lineBreak",
|
|
164
|
+
pmStart: valueRun.pmStart,
|
|
165
|
+
pmEnd: valueRun.pmEnd
|
|
166
|
+
});
|
|
167
|
+
if (segment !== "") out.push({
|
|
168
|
+
...valueRun,
|
|
169
|
+
text: segment
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return text.endsWith("\r");
|
|
173
|
+
}
|
|
120
174
|
/**
|
|
121
175
|
* The value run(s) replacing a marker. A plain value is one run carrying the
|
|
122
176
|
* host run's formatting; a rich value emits one run per span, each layering
|
|
123
177
|
* its own bold/italic over the host formatting (host bold stays bold, a
|
|
124
|
-
* span's flags OR in).
|
|
125
|
-
*
|
|
178
|
+
* span's flags OR in). A newline in either splits its span around a line
|
|
179
|
+
* break run. Every run keeps the marker's full PM range so click-to-position
|
|
180
|
+
* keeps resolving into the marker.
|
|
126
181
|
*/
|
|
127
182
|
function buildValueRuns(host, entry, mode) {
|
|
128
|
-
|
|
183
|
+
const runs = [];
|
|
184
|
+
const base = {
|
|
129
185
|
...host,
|
|
130
|
-
text: entry.value,
|
|
131
186
|
pmStart: entry.from,
|
|
132
187
|
pmEnd: entry.to,
|
|
133
188
|
templatePreview: mode
|
|
134
|
-
}
|
|
135
|
-
|
|
189
|
+
};
|
|
190
|
+
if (typeof entry.value === "string") {
|
|
191
|
+
pushValueSpan(runs, {
|
|
192
|
+
...base,
|
|
193
|
+
text: entry.value
|
|
194
|
+
}, false);
|
|
195
|
+
return runs;
|
|
196
|
+
}
|
|
197
|
+
let pendingCr = false;
|
|
198
|
+
for (const span of entry.value.runs) {
|
|
136
199
|
const valueRun = {
|
|
137
|
-
...
|
|
138
|
-
text: span.text
|
|
139
|
-
pmStart: entry.from,
|
|
140
|
-
pmEnd: entry.to,
|
|
141
|
-
templatePreview: mode
|
|
200
|
+
...base,
|
|
201
|
+
text: span.text
|
|
142
202
|
};
|
|
143
203
|
if (span.bold === true) valueRun.bold = true;
|
|
144
204
|
if (span.italic === true) valueRun.italic = true;
|
|
145
|
-
|
|
146
|
-
}
|
|
205
|
+
pendingCr = pushValueSpan(runs, valueRun, pendingCr);
|
|
206
|
+
}
|
|
207
|
+
return runs;
|
|
147
208
|
}
|
|
148
209
|
const entryKey = (entry) => `${entry.from}:${entry.to}:${templatePreviewValueFingerprint(entry.value)}`;
|
|
210
|
+
const hiddenKey = (range) => `${range.from}:${range.to}:${range.expr}`;
|
|
211
|
+
/** Widen `bounds` over every range whose key is absent from `known`. */
|
|
212
|
+
const growOverUnknown = (ranges, key, known, bounds) => {
|
|
213
|
+
for (const range of ranges) {
|
|
214
|
+
if (known.has(key(range))) continue;
|
|
215
|
+
bounds.from = Math.min(bounds.from, range.from);
|
|
216
|
+
bounds.to = Math.max(bounds.to, range.to);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
149
219
|
/**
|
|
150
|
-
* PM range covering every substitution
|
|
151
|
-
* states (changed, added, or removed
|
|
152
|
-
*
|
|
220
|
+
* PM range covering every substitution and every hidden span that differs
|
|
221
|
+
* between two preview states (changed, added, or removed), or `null` when the
|
|
222
|
+
* flow content both produce is identical. Feeds the layout pipeline's
|
|
153
223
|
* dirty-range invalidation so typing a value re-measures only the blocks
|
|
154
|
-
* hosting the affected markers.
|
|
224
|
+
* hosting the affected markers. A hidden span that appears or disappears also
|
|
225
|
+
* changes the block count, which sends the measure path down its full-remeasure
|
|
226
|
+
* branch regardless of how wide this range is.
|
|
155
227
|
*/
|
|
156
228
|
function templatePreviewDirtyRange(previous, next) {
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
let to = Number.NEGATIVE_INFINITY;
|
|
161
|
-
for (const entry of previous) if (!nextKeys.has(entryKey(entry))) {
|
|
162
|
-
from = Math.min(from, entry.from);
|
|
163
|
-
to = Math.max(to, entry.to);
|
|
164
|
-
}
|
|
165
|
-
for (const entry of next) if (!previousKeys.has(entryKey(entry))) {
|
|
166
|
-
from = Math.min(from, entry.from);
|
|
167
|
-
to = Math.max(to, entry.to);
|
|
168
|
-
}
|
|
169
|
-
if (from === Number.POSITIVE_INFINITY) return null;
|
|
170
|
-
return {
|
|
171
|
-
from,
|
|
172
|
-
to
|
|
229
|
+
const bounds = {
|
|
230
|
+
from: Number.POSITIVE_INFINITY,
|
|
231
|
+
to: Number.NEGATIVE_INFINITY
|
|
173
232
|
};
|
|
233
|
+
growOverUnknown(previous.entries, entryKey, new Set(next.entries.map(entryKey)), bounds);
|
|
234
|
+
growOverUnknown(next.entries, entryKey, new Set(previous.entries.map(entryKey)), bounds);
|
|
235
|
+
growOverUnknown(previous.hidden, hiddenKey, new Set(next.hidden.map(hiddenKey)), bounds);
|
|
236
|
+
growOverUnknown(next.hidden, hiddenKey, new Set(previous.hidden.map(hiddenKey)), bounds);
|
|
237
|
+
if (bounds.from === Number.POSITIVE_INFINITY) return null;
|
|
238
|
+
return bounds;
|
|
174
239
|
}
|
|
175
240
|
//#endregion
|
|
176
241
|
export { applyTemplatePreviewToBlocks, templatePreviewDirtyRange };
|
|
@@ -1175,6 +1175,15 @@ const runIsZeroWidthBoundaryMarker = (run) => {
|
|
|
1175
1175
|
default: return run;
|
|
1176
1176
|
}
|
|
1177
1177
|
};
|
|
1178
|
+
/** Every page-break run under a node, nested tables and text boxes included. */
|
|
1179
|
+
const countPageBreakRuns = (node) => {
|
|
1180
|
+
let count = node.type.name === "pageBreakRun" ? 1 : 0;
|
|
1181
|
+
node.descendants((descendant) => {
|
|
1182
|
+
if (descendant.type.name === "pageBreakRun") count += 1;
|
|
1183
|
+
return true;
|
|
1184
|
+
});
|
|
1185
|
+
return count;
|
|
1186
|
+
};
|
|
1178
1187
|
/** Decide leading-break eligibility from the exact projected runs consumed by layout. */
|
|
1179
1188
|
const hasSingleLeadingProjectedPageBreak = (runs, pageBreaks) => {
|
|
1180
1189
|
if (pageBreaks.length !== 1) return false;
|
|
@@ -1348,12 +1357,12 @@ function convertTableCell(node, startPos, options, tableCellMargins) {
|
|
|
1348
1357
|
const blocks = [];
|
|
1349
1358
|
let offset = startPos + 1;
|
|
1350
1359
|
const authoredPageBreakPosition = options.firstPageBreakRunPosition(node);
|
|
1351
|
-
const
|
|
1352
|
-
if (authoredPageBreakPosition !== void 0 &&
|
|
1360
|
+
const leadingParagraph = node.firstChild?.type.name === "paragraph" ? node.firstChild : void 0;
|
|
1361
|
+
if (authoredPageBreakPosition !== void 0 && (leadingParagraph === void 0 || countPageBreakRuns(node) !== 1 || options.firstPageBreakRunPosition(leadingParagraph) !== authoredPageBreakPosition)) panic(`An explicit page-break run at ${String(authoredPageBreakPosition)} cannot be projected inside a table cell`);
|
|
1353
1362
|
const pageBreaks = [];
|
|
1354
1363
|
node.forEach((child) => {
|
|
1355
1364
|
if (child.type.name === "paragraph") {
|
|
1356
|
-
const block = convertParagraph(child, offset, options, child ===
|
|
1365
|
+
const block = convertParagraph(child, offset, options, child === leadingParagraph ? pageBreaks : void 0);
|
|
1357
1366
|
blocks.push(block);
|
|
1358
1367
|
} else if (child.type.name === "table") blocks.push(convertTable(child, offset, options));
|
|
1359
1368
|
else if (child.type.name === "textBox") blocks.push(convertTextBoxNode(child, offset, options));
|
|
@@ -5,6 +5,17 @@ const UNSUPPORTED_PAGE_BREAK_RUN_ANCESTORS = /* @__PURE__ */ new Set([
|
|
|
5
5
|
"tableHeader",
|
|
6
6
|
"textBox"
|
|
7
7
|
]);
|
|
8
|
+
const hasTextBoxAnchorAtOrAfter = (paragraph, contentStart, position) => {
|
|
9
|
+
let found = false;
|
|
10
|
+
paragraph.descendants((descendant, offset) => {
|
|
11
|
+
if (descendant.type.name === "textBoxAnchor" && contentStart + offset >= position) {
|
|
12
|
+
found = true;
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return !found;
|
|
16
|
+
});
|
|
17
|
+
return found;
|
|
18
|
+
};
|
|
8
19
|
/**
|
|
9
20
|
* Insert a page-break run at the current text cursor.
|
|
10
21
|
*
|
|
@@ -18,7 +29,7 @@ const insertPageBreak = (state, dispatch) => {
|
|
|
18
29
|
const { $from } = state.selection;
|
|
19
30
|
if (!pageBreakRunType || !state.selection.empty || !$from.parent.isTextblock) return false;
|
|
20
31
|
for (let depth = $from.depth; depth >= 0; depth--) if (UNSUPPORTED_PAGE_BREAK_RUN_ANCESTORS.has($from.node(depth).type.name)) return false;
|
|
21
|
-
if ($from.parent.type.name !== "paragraph" || pageBreakRunParagraphProjectionDisposition($from.parent).status === "unsupported") return false;
|
|
32
|
+
if ($from.parent.type.name !== "paragraph" || pageBreakRunParagraphProjectionDisposition($from.parent).status === "unsupported" || hasTextBoxAnchorAtOrAfter($from.parent, $from.start(), $from.pos)) return false;
|
|
22
33
|
if (dispatch) {
|
|
23
34
|
const pageBreak = pageBreakRunType.create();
|
|
24
35
|
dispatch(state.tr.replaceSelectionWith(pageBreak).scrollIntoView());
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EDITED_PREVIEW_FINGERPRINT, imageRawXmlFingerprint } from "../../docx/imageRawXml.js";
|
|
2
|
+
import { isNumberingReference } from "../../docx/numberingReference.js";
|
|
2
3
|
import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, ParagraphPropertySourceValidationError, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, linkParagraphPropertySourceCandidate, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceTokenMatchesContract, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings } from "../../docx/paragraphPropertySource.js";
|
|
3
4
|
import { visitDocxParagraphs } from "../../docx/paragraphTraversal.js";
|
|
4
5
|
import { ShapeOutlineStyleSchema, narrowEnum } from "../../docx/parserEnums.js";
|
|
@@ -689,7 +690,7 @@ function removeTextBoxAnchorFromBlocks(blocks, marker) {
|
|
|
689
690
|
*/
|
|
690
691
|
function listRenderingFromAttrs(attrs) {
|
|
691
692
|
const numId = attrs.numPr?.numId;
|
|
692
|
-
if (numId
|
|
693
|
+
if (!isNumberingReference(numId)) return;
|
|
693
694
|
if (!(attrs.listMarker != null || attrs.listIsBullet || attrs.listNumFmt != null)) return;
|
|
694
695
|
return listRenderingFromAttrs$1({
|
|
695
696
|
attrs,
|