@stll/folio-core 0.52.0 → 0.53.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 +23 -0
- package/dist/ai-edits/apply.d.ts +26 -1
- package/dist/ai-edits/apply.js +1519 -105
- package/dist/ai-edits/batch-claims.d.ts +130 -0
- package/dist/ai-edits/batch-claims.js +244 -0
- package/dist/ai-edits/blockRange.js +9 -3
- package/dist/ai-edits/character-boundaries.d.ts +43 -0
- package/dist/ai-edits/character-boundaries.js +95 -0
- package/dist/ai-edits/clean-text.d.ts +33 -3
- package/dist/ai-edits/clean-text.js +52 -6
- package/dist/ai-edits/comment-lifecycle.d.ts +18 -0
- package/dist/ai-edits/comment-lifecycle.js +52 -0
- package/dist/ai-edits/headless.d.ts +71 -7
- package/dist/ai-edits/headless.js +381 -41
- package/dist/ai-edits/index.d.ts +2 -1
- package/dist/ai-edits/index.js +2 -1
- package/dist/ai-edits/minimal-replacement.d.ts +21 -6
- package/dist/ai-edits/minimal-replacement.js +134 -15
- package/dist/ai-edits/newListNumbering.d.ts +23 -0
- package/dist/ai-edits/newListNumbering.js +94 -0
- package/dist/ai-edits/note-references.d.ts +96 -0
- package/dist/ai-edits/note-references.js +139 -0
- package/dist/ai-edits/pending-suggestions.d.ts +79 -0
- package/dist/ai-edits/pending-suggestions.js +306 -0
- package/dist/ai-edits/read.d.ts +1 -1
- package/dist/ai-edits/read.js +56 -43
- package/dist/ai-edits/result-validation.d.ts +29 -0
- package/dist/ai-edits/result-validation.js +164 -0
- package/dist/ai-edits/snapshot.d.ts +36 -3
- package/dist/ai-edits/snapshot.js +177 -23
- package/dist/ai-edits/table-cell-mutations.d.ts +1 -1
- package/dist/ai-edits/table-cell-mutations.js +4 -1
- package/dist/ai-edits/table-geometry.d.ts +1 -1
- package/dist/ai-edits/table-row-column-mutations.d.ts +38 -16
- package/dist/ai-edits/table-row-column-mutations.js +61 -26
- package/dist/ai-edits/types.d.ts +155 -16
- package/dist/compare/compare.d.ts +1 -1
- package/dist/compare/compare.js +65 -16
- package/dist/compare/content-alignment.js +13 -2
- package/dist/compare/content-types.d.ts +7 -0
- package/dist/compare/content.d.ts +4 -1
- package/dist/compare/content.js +6 -1
- package/dist/compare/formatting.js +2 -1
- package/dist/compare/inline-atoms.d.ts +21 -4
- package/dist/compare/inline-atoms.js +138 -16
- package/dist/compare/plan.js +10 -5
- package/dist/compare/scenario.js +14 -3
- package/dist/compare/section-boundary-properties.js +1 -1
- package/dist/compare/types.d.ts +4 -2
- package/dist/compare/types.js +2 -1
- package/dist/compare/verification.d.ts +1 -1
- package/dist/compare/verification.js +15 -3
- package/dist/controller/committedLayoutDiff.d.ts +25 -0
- package/dist/controller/committedLayoutDiff.js +71 -0
- package/dist/controller/contentControlWidgetController.d.ts +1 -1
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/fontReadiness.d.ts +70 -3
- package/dist/controller/fontReadiness.js +100 -10
- package/dist/controller/headerFooterEditorManager.js +6 -1
- package/dist/controller/layoutPipeline.d.ts +12 -10
- package/dist/controller/layoutPipeline.js +62 -9
- package/dist/controller/layoutRunOptions.d.ts +24 -0
- package/dist/controller/layoutRunOptions.js +17 -0
- package/dist/controller/layoutScheduler.d.ts +19 -14
- package/dist/controller/layoutScheduler.js +15 -12
- package/dist/controller/layoutSession.d.ts +26 -2
- package/dist/controller/layoutSession.js +1 -1
- package/dist/controller/noteEditorManager.js +8 -3
- package/dist/document-operations.d.ts +11 -2
- package/dist/document-operations.js +230 -21
- package/dist/docx/altChunk.d.ts +8 -0
- package/dist/docx/altChunk.js +17 -0
- package/dist/docx/attributeRemainder.d.ts +1 -1
- package/dist/docx/blockContentParser.d.ts +64 -1
- package/dist/docx/blockContentParser.js +17 -4
- package/dist/docx/blockCustomXmlShell.d.ts +7 -0
- package/dist/docx/blockCustomXmlShell.js +14 -0
- package/dist/docx/blockPlainText.js +7 -0
- package/dist/docx/commentAnchorIndex.js +1 -1
- package/dist/docx/commentRangeIntegrity.js +8 -3
- package/dist/docx/commentReferenceNormalization.js +1 -1
- package/dist/docx/commentReplyMarkers.js +20 -1
- package/dist/docx/compatibility.d.ts +1 -1
- package/dist/docx/compatibility.js +34 -13
- package/dist/docx/containerChildren.gen.d.ts +1 -1
- package/dist/docx/containerChildren.gen.js +1 -0
- package/dist/docx/documentParser.js +12 -12
- package/dist/docx/drawingIdNormalization.d.ts +3 -1
- package/dist/docx/drawingIdNormalization.js +6 -1
- package/dist/docx/ensureParaIds.js +119 -97
- package/dist/docx/footnoteParser.js +8 -4
- package/dist/docx/headerFooterParser.js +3 -3
- package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
- package/dist/docx/headerFooterReferenceNormalization.js +52 -27
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/listNumberingInstances.d.ts +59 -0
- package/dist/docx/listNumberingInstances.js +249 -0
- package/dist/docx/normalizeBaseDirection.js +2 -1
- package/dist/docx/opaqueCarrier.d.ts +7 -0
- package/dist/docx/opaqueCarrier.js +38 -0
- package/dist/docx/packageParts.js +4 -1
- package/dist/docx/paragraphParser.js +91 -24
- package/dist/docx/paragraphPropertySource.d.ts +4 -2
- package/dist/docx/paragraphPropertySource.js +7 -1
- package/dist/docx/paragraphTraversal.js +1 -0
- package/dist/docx/parseWarningMessage.js +4 -1
- package/dist/docx/parser.js +173 -20
- package/dist/docx/rezip.js +27 -5
- package/dist/docx/sdtProperties.js +1 -1
- package/dist/docx/sdtPropertiesPatch.js +3 -0
- package/dist/docx/selectiveSave.js +16 -9
- package/dist/docx/selectiveXmlPatch.js +106 -37
- package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
- package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
- package/dist/docx/serializer/documentSerializer.js +2 -0
- package/dist/docx/serializer/headerFooterSerializer.js +2 -0
- package/dist/docx/serializer/noteSerializer.js +3 -1
- package/dist/docx/serializer/paragraphSerializer.js +33 -9
- package/dist/docx/serializer/tableSerializer.js +25 -38
- package/dist/docx/server/createBilingualDocument.js +3 -3
- package/dist/docx/tableParser.d.ts +157 -1
- package/dist/docx/tableParser.js +89 -10
- package/dist/docx/textBoxParser.js +1 -1
- package/dist/docx/unzip.d.ts +2 -1
- package/dist/docx/unzip.js +1 -1
- package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
- package/dist/docx/wordprocessingPrefixes.js +286 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +136 -0
- package/dist/i18n/messages/catalogs.gen.js +153 -17
- package/dist/i18n/messages/messages.gen.d.ts +8 -0
- package/dist/internal/compare/inline-presentation.d.ts +2 -1
- package/dist/internal/compare/inline-presentation.js +11 -10
- package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
- package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
- package/dist/internal/indexedPositionMap.d.ts +11 -0
- package/dist/internal/indexedPositionMap.js +42 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/revisionResolutionEdits.d.ts +13 -0
- package/dist/internal/revisionResolutionEdits.js +19 -0
- package/dist/internal/revisionResolutionInline.d.ts +24 -0
- package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
- package/dist/internal/revisionResolutionStep.d.ts +34 -0
- package/dist/internal/revisionResolutionStep.js +282 -0
- package/dist/internal/revisionResolutionTracking.d.ts +11 -0
- package/dist/internal/revisionResolutionTracking.js +124 -0
- package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
- package/dist/internal/wholeStoryRevisionResolution.js +530 -0
- package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
- package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
- package/dist/layout-bridge/convert/tableConversion.js +1 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
- package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
- package/dist/layout-engine/layoutInstrumentation.js +4 -1
- package/dist/layout-engine/measure/cache.d.ts +18 -1
- package/dist/layout-engine/measure/cache.js +31 -1
- package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
- package/dist/layout-engine/measure/measureContainer.js +7 -47
- package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
- package/dist/layout-engine/measure/measureHelpers.js +22 -2
- package/dist/layout-engine/measure/measureWorker.js +2 -3
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
- package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
- package/dist/layout-engine/types.d.ts +6 -0
- package/dist/layout-painter/renderPage.js +1 -0
- package/dist/layout-painter/renderParagraph.js +1 -1
- package/dist/managers/ContextMenuManager.js +5 -2
- package/dist/managers/types.d.ts +3 -0
- package/dist/markdown/fromMarkdown.js +2 -1
- package/dist/markdown/internals.d.ts +11 -1
- package/dist/markdown/internals.js +24 -3
- package/dist/markdown/renderBlock.js +39 -9
- package/dist/markdown/renderParagraph.d.ts +13 -1
- package/dist/markdown/renderParagraph.js +85 -38
- package/dist/markdown/renderRuns.js +3 -10
- package/dist/markdown/renderTable.js +24 -12
- package/dist/markdown/trailers.js +2 -2
- package/dist/markdown/types.d.ts +29 -7
- package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
- package/dist/paged-layout/incrementalMeasure.js +1 -9
- package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
- package/dist/paged-layout/transactionDirtyRange.js +29 -41
- package/dist/panel-layout.d.ts +83 -0
- package/dist/panel-layout.js +96 -0
- package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
- package/dist/prosemirror/anchoredTextBoxes.js +156 -0
- package/dist/prosemirror/attrs/index.d.ts +6 -2
- package/dist/prosemirror/attrs/index.js +172 -1
- package/dist/prosemirror/commands/comments.d.ts +7 -8
- package/dist/prosemirror/commands/comments.js +241 -207
- package/dist/prosemirror/commands/contentControls.d.ts +1 -1
- package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
- package/dist/prosemirror/commands/formatting.d.ts +1 -1
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/paragraph.d.ts +7 -1
- package/dist/prosemirror/commands/paragraph.js +9 -1
- package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
- package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
- package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
- package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
- package/dist/prosemirror/commands/resolveAllTableChanges.js +615 -0
- package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
- package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.js +59 -0
- package/dist/prosemirror/commands/sectionBreak.js +2 -1
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +8 -2
- package/dist/prosemirror/commands/tableCellMergeResolution.js +1 -1
- package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +181 -31
- package/dist/prosemirror/conversion/toProseDoc.js +39 -4
- package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
- package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
- package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
- package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
- package/dist/prosemirror/extensions/StarterKit.js +3 -1
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -0
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +161 -123
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
- package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
- package/dist/prosemirror/extensions/features/pastedHtmlLists.js +126 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +21 -5
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +7 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +8 -2
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +10 -0
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +35 -0
- package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +19 -18
- package/dist/prosemirror/extensions/types.d.ts +4 -1
- package/dist/prosemirror/findReplaceSelection.js +1 -1
- package/dist/prosemirror/index.d.ts +3 -2
- package/dist/prosemirror/index.js +3 -2
- package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
- package/dist/prosemirror/indexedNodeLookup.js +103 -0
- package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
- package/dist/prosemirror/listAutoformatMarkers.js +98 -0
- package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
- package/dist/prosemirror/listInstanceReferences.js +72 -0
- package/dist/prosemirror/listLabels.d.ts +24 -0
- package/dist/prosemirror/listLabels.js +111 -0
- package/dist/prosemirror/listNumbering.d.ts +110 -0
- package/dist/prosemirror/listNumbering.js +345 -0
- package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
- package/dist/prosemirror/listRenderingAttrs.js +8 -1
- package/dist/prosemirror/markupViewProjection.d.ts +95 -0
- package/dist/prosemirror/markupViewProjection.js +83 -0
- package/dist/prosemirror/numberingAttr.d.ts +9 -1
- package/dist/prosemirror/numberingAttr.js +9 -1
- package/dist/prosemirror/outlineLevelAttr.js +1 -1
- package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
- package/dist/prosemirror/paragraphIndentation.js +29 -7
- package/dist/prosemirror/paragraphMarkJoin.d.ts +19 -0
- package/dist/prosemirror/paragraphMarkJoin.js +24 -0
- package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
- package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
- package/dist/prosemirror/plugins/documentNumbering.js +97 -11
- package/dist/prosemirror/plugins/documentStyles.d.ts +10 -1
- package/dist/prosemirror/plugins/documentStyles.js +14 -1
- package/dist/prosemirror/plugins/suggestionMode.d.ts +16 -2
- package/dist/prosemirror/plugins/suggestionMode.js +116 -52
- package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
- package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
- package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
- package/dist/prosemirror/positionSweep.d.ts +24 -0
- package/dist/prosemirror/positionSweep.js +222 -0
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +1 -1
- package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
- package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
- package/dist/prosemirror/replacedAnnotations.js +170 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/index.js +3 -0
- package/dist/prosemirror/schema/nodes.d.ts +42 -11
- package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
- package/dist/prosemirror/sectionMarkEdits.js +59 -0
- package/dist/prosemirror/storyListNumbering.d.ts +17 -0
- package/dist/prosemirror/storyListNumbering.js +102 -0
- package/dist/prosemirror/tableGridMutation.d.ts +48 -2
- package/dist/prosemirror/tableGridMutation.js +106 -1
- package/dist/prosemirror/validation.js +5 -1
- package/dist/redline.js +93 -9
- package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
- package/dist/render-dom/BodySelectionOverlay.js +3 -2
- package/dist/utils/findReplace.js +2 -2
- package/dist/utils/mergeDocumentContent.js +1 -1
- package/dist/utils/noteReferenceLabels.d.ts +36 -0
- package/dist/utils/noteReferenceLabels.js +32 -0
- package/dist/utils/replaceText.js +1 -1
- package/dist/version-comparison.d.ts +1 -0
- package/dist/version-comparison.js +1 -0
- package/package.json +3 -2
- package/dist/internal/headlessRevisionResolution.d.ts +0 -23
|
@@ -6,5 +6,17 @@ import { RenderContext } from "./types.js";
|
|
|
6
6
|
* caller joins blocks.
|
|
7
7
|
*/
|
|
8
8
|
declare function renderParagraph(ctx: RenderContext, pkg: document_d_exports.DocxPackage | undefined, para: document_d_exports.Paragraph): string;
|
|
9
|
+
/** A rendered paragraph, and whether it is a Markdown list item. */
|
|
10
|
+
type RenderedParagraph = {
|
|
11
|
+
markdown: string;
|
|
12
|
+
isListItem: boolean;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Render a paragraph. A list item is a paragraph that shows a marker, which is
|
|
16
|
+
* when the list counter gives it a label: a numbered heading renders as a
|
|
17
|
+
* heading, and a level that hides its marker (`w:vanish`) or that its list
|
|
18
|
+
* does not define as prose, as every other reader reads them.
|
|
19
|
+
*/
|
|
20
|
+
declare function renderParagraphBlock(ctx: RenderContext, pkg: document_d_exports.DocxPackage | undefined, para: document_d_exports.Paragraph): RenderedParagraph;
|
|
9
21
|
//#endregion
|
|
10
|
-
export { renderParagraph };
|
|
22
|
+
export { RenderedParagraph, renderParagraph, renderParagraphBlock };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isQuoteStyle, resolveHeadingLevel } from "../docx/builtInStyles.js";
|
|
2
|
-
import {
|
|
2
|
+
import { listLabelAttrsFromRendering } from "../prosemirror/listLabels.js";
|
|
3
3
|
import { renderParagraphInline } from "./renderRuns.js";
|
|
4
4
|
//#region src/markdown/renderParagraph.ts
|
|
5
5
|
/**
|
|
@@ -9,6 +9,8 @@ import { renderParagraphInline } from "./renderRuns.js";
|
|
|
9
9
|
* `IntenseQuote` styles become blockquotes. Ported from eigenpal/docx-editor
|
|
10
10
|
* PR #595.
|
|
11
11
|
*
|
|
12
|
+
* A numbered heading keeps its number after the hashes (`## 1. Scope`).
|
|
13
|
+
*
|
|
12
14
|
* Which paragraphs those are is `builtInStyles`' decision, not this file's: the
|
|
13
15
|
* id `Nadpis1` and the id `Heading1` are the same heading, and `ClauseHeading1`
|
|
14
16
|
* is not one at all.
|
|
@@ -20,19 +22,59 @@ const MAX_MARKDOWN_HEADING_LEVEL = 6;
|
|
|
20
22
|
* caller joins blocks.
|
|
21
23
|
*/
|
|
22
24
|
function renderParagraph(ctx, pkg, para) {
|
|
25
|
+
return renderParagraphBlock(ctx, pkg, para).markdown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Render a paragraph. A list item is a paragraph that shows a marker, which is
|
|
29
|
+
* when the list counter gives it a label: a numbered heading renders as a
|
|
30
|
+
* heading, and a level that hides its marker (`w:vanish`) or that its list
|
|
31
|
+
* does not define as prose, as every other reader reads them.
|
|
32
|
+
*/
|
|
33
|
+
function renderParagraphBlock(ctx, pkg, para) {
|
|
34
|
+
const label = ctx.nextListLabel(listLabelAttrs(para));
|
|
23
35
|
const inline = renderParagraphInline(ctx, pkg, para.content, para.paraId);
|
|
24
36
|
const styleId = para.formatting?.styleId;
|
|
25
|
-
const headingLevel =
|
|
26
|
-
outlineLevel: para.formatting?.outlineLevel,
|
|
27
|
-
styleId
|
|
28
|
-
}, ctx.builtInStyles);
|
|
37
|
+
const headingLevel = markdownHeadingLevel(ctx, para);
|
|
29
38
|
if (headingLevel !== void 0) {
|
|
30
|
-
if (!inline) return
|
|
31
|
-
|
|
39
|
+
if (!inline) return {
|
|
40
|
+
markdown: "",
|
|
41
|
+
isListItem: false
|
|
42
|
+
};
|
|
43
|
+
const hashes = "#".repeat(Math.min(MAX_MARKDOWN_HEADING_LEVEL, headingLevel + 1));
|
|
44
|
+
return {
|
|
45
|
+
markdown: label ? `${hashes} ${label} ${inline}` : `${hashes} ${inline}`,
|
|
46
|
+
isListItem: false
|
|
47
|
+
};
|
|
32
48
|
}
|
|
33
|
-
if (para.listRendering &&
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
if (para.listRendering && label !== void 0) return {
|
|
50
|
+
markdown: renderListItem(ctx, para.listRendering, label, inline),
|
|
51
|
+
isListItem: true
|
|
52
|
+
};
|
|
53
|
+
if (isQuoteStyle(styleId, ctx.builtInStyles)) return {
|
|
54
|
+
markdown: inline.split("\n").map((line) => `> ${line}`).join("\n"),
|
|
55
|
+
isListItem: false
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
markdown: escapeLeadingBlockMarker(inline),
|
|
59
|
+
isListItem: false
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** The paragraph's 0-based heading level, as `builtInStyles` classifies it. */
|
|
63
|
+
function markdownHeadingLevel(ctx, para) {
|
|
64
|
+
return resolveHeadingLevel({
|
|
65
|
+
outlineLevel: para.formatting?.outlineLevel,
|
|
66
|
+
styleId: para.formatting?.styleId
|
|
67
|
+
}, ctx.builtInStyles);
|
|
68
|
+
}
|
|
69
|
+
const UNNUMBERED = Object.freeze({});
|
|
70
|
+
/**
|
|
71
|
+
* The attrs the page's list counter reads, projected from the paragraph the
|
|
72
|
+
* way the editor projects them (`toProseDoc`). A paragraph without a list
|
|
73
|
+
* rendering counts as unnumbered.
|
|
74
|
+
*/
|
|
75
|
+
function listLabelAttrs(para) {
|
|
76
|
+
const list = para.listRendering;
|
|
77
|
+
return list ? listLabelAttrsFromRendering(list, para.formatting?.numPrFromStyle) : UNNUMBERED;
|
|
36
78
|
}
|
|
37
79
|
/**
|
|
38
80
|
* A plain paragraph whose visible text begins with markdown block syntax (e.g.
|
|
@@ -43,36 +85,41 @@ function renderParagraph(ctx, pkg, para) {
|
|
|
43
85
|
function escapeLeadingBlockMarker(text) {
|
|
44
86
|
return text.replace(/^(?<ws>[ \t]*)(?<marker>[#>])/gmu, "$<ws>\\$<marker>").replace(/^(?<ws>[ \t]*)(?<marker>[-+*])(?<after>[ \t])/gmu, "$<ws>\\$<marker>$<after>").replace(/^(?<ws>[ \t]*)(?<num>\d{1,9})(?<marker>[.)])(?<after>[ \t])/gmu, "$<ws>$<num>\\$<marker>$<after>");
|
|
45
87
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
88
|
+
/**
|
|
89
|
+
* A markdown list marker's width when no ancestor at that level has rendered
|
|
90
|
+
* yet (e.g. a DOCX paragraph numbered at a level its list skipped over). Two
|
|
91
|
+
* spaces is the old fixed-indent behaviour, kept as a fallback rather than a
|
|
92
|
+
* guess of zero.
|
|
93
|
+
*/
|
|
94
|
+
const DEFAULT_LIST_INDENT_WIDTH = 2;
|
|
95
|
+
/**
|
|
96
|
+
* The indent a level's item needs: the combined marker width of every
|
|
97
|
+
* shallower level's most recently rendered item (see
|
|
98
|
+
* `RenderContext.listIndentWidths`), so a child sits inside its parent's
|
|
99
|
+
* content column per CommonMark's list-nesting rule, not a fixed guess.
|
|
100
|
+
*/
|
|
101
|
+
function listIndentWidth(ctx, level) {
|
|
102
|
+
let width = 0;
|
|
103
|
+
for (let ancestor = 0; ancestor < level; ancestor++) width += ctx.listIndentWidths[ancestor] ?? DEFAULT_LIST_INDENT_WIDTH;
|
|
104
|
+
return width;
|
|
50
105
|
}
|
|
51
106
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* the
|
|
107
|
+
* A list item line with the label the page shows (`1.`, `a)`, `i.`), counted
|
|
108
|
+
* in document order across the whole render, list items inside tables and
|
|
109
|
+
* block SDTs included. A bullet is Markdown's `-`.
|
|
110
|
+
*
|
|
111
|
+
* The indent before the marker is not a fixed two spaces: CommonMark keeps a
|
|
112
|
+
* child nested under its parent only when it starts at or past the column
|
|
113
|
+
* where the parent item's content begins, which is the width of the parent's
|
|
114
|
+
* marker plus its one trailing space (`1. ` is 3 columns, `10. ` is 4, `- ` is
|
|
115
|
+
* 2). `ctx.listIndentWidths` is updated with this item's own marker width so
|
|
116
|
+
* a following, deeper item can indent correctly under it.
|
|
57
117
|
*/
|
|
58
|
-
function
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
ctx.listSeenLevels.add(seenKey);
|
|
64
|
-
if (list.startOverride !== void 0) counters[level] = list.startOverride - 1;
|
|
65
|
-
}
|
|
66
|
-
counters[level] = (counters[level] ?? 0) + 1;
|
|
67
|
-
for (let i = level + 1; i < counters.length; i += 1) counters[i] = 0;
|
|
68
|
-
ctx.listCounters.set(list.numId, counters);
|
|
69
|
-
const levelFormats = list.levelNumFmts ?? (list.numFmt ? [list.numFmt] : void 0);
|
|
70
|
-
return resolveListTemplate({
|
|
71
|
-
template: list.marker,
|
|
72
|
-
counters,
|
|
73
|
-
levelFormats,
|
|
74
|
-
forceDecimal: list.isLegal
|
|
75
|
-
}).trim();
|
|
118
|
+
function renderListItem(ctx, list, label, inline) {
|
|
119
|
+
const indent = " ".repeat(listIndentWidth(ctx, list.level));
|
|
120
|
+
const marker = list.isBullet ? "- " : `${label} `;
|
|
121
|
+
ctx.listIndentWidths[list.level] = marker.length;
|
|
122
|
+
return `${indent}${marker}${inline}`.trimEnd();
|
|
76
123
|
}
|
|
77
124
|
//#endregion
|
|
78
|
-
export { renderParagraph };
|
|
125
|
+
export { renderParagraph, renderParagraphBlock };
|
|
@@ -4,7 +4,7 @@ import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
|
|
|
4
4
|
import { wrapComment, wrapDeletion, wrapInsertion, wrapMoveFrom, wrapMoveTo } from "./annotations.js";
|
|
5
5
|
import { escapeAltText, escapeInline, escapeLinkUrl } from "./escape.js";
|
|
6
6
|
import { registerImage } from "./images.js";
|
|
7
|
-
import { pushWarning } from "./internals.js";
|
|
7
|
+
import { numberNoteReference, pushWarning } from "./internals.js";
|
|
8
8
|
//#region src/markdown/renderRuns.ts
|
|
9
9
|
const MARK_DELIMS = {
|
|
10
10
|
bold: "**",
|
|
@@ -81,17 +81,10 @@ function renderRunContent(ctx, pkg, content, paraId) {
|
|
|
81
81
|
out += escapeInline(item.text);
|
|
82
82
|
break;
|
|
83
83
|
case "footnoteRef":
|
|
84
|
-
case "endnoteRef":
|
|
84
|
+
case "endnoteRef":
|
|
85
85
|
if (ctx.opts.footnotes === "strip") break;
|
|
86
|
-
|
|
87
|
-
ctx.footnoteRefs.push({
|
|
88
|
-
refId: item.id,
|
|
89
|
-
markerNumber,
|
|
90
|
-
kind: item.type === "endnoteRef" ? "endnote" : "footnote"
|
|
91
|
-
});
|
|
92
|
-
out += `[^${markerNumber}]`;
|
|
86
|
+
out += numberNoteReference(ctx, item.type === "endnoteRef" ? "endnote" : "footnote", item.id).marker;
|
|
93
87
|
break;
|
|
94
|
-
}
|
|
95
88
|
case "drawing": {
|
|
96
89
|
const ref = resolveRelationshipIdOfType(pkg?.relationships, item.image.rId, RELATIONSHIP_TYPES.image);
|
|
97
90
|
const media = ref.status === "resolved" ? pkg?.media?.get(ref.relationship.target) : void 0;
|
|
@@ -1,18 +1,25 @@
|
|
|
1
|
+
import { ALT_CHUNK_READER_DIAGNOSTIC, isAltChunkMarkup } from "../docx/altChunk.js";
|
|
1
2
|
import { getHyperlinkRuns } from "../docx/hyperlinkParser.js";
|
|
3
|
+
import { OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC, isOpaqueNestedRowMarkup, opaqueRevisionCarrierName } from "../docx/opaqueCarrier.js";
|
|
2
4
|
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "../docx/relsParser.js";
|
|
3
5
|
import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
|
|
4
6
|
import { escapeTableCell } from "./escape.js";
|
|
5
7
|
import { registerImage } from "./images.js";
|
|
6
|
-
import { pushWarning } from "./internals.js";
|
|
8
|
+
import { numberNoteReference, pushWarning } from "./internals.js";
|
|
7
9
|
import { renderParagraph } from "./renderParagraph.js";
|
|
8
10
|
//#region src/markdown/renderTable.ts
|
|
9
11
|
/** Render a `Table` as markdown. Picks GFM vs HTML based on cell features. */
|
|
10
12
|
function renderTable(ctx, pkg, table) {
|
|
11
13
|
const { rows } = table;
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
return renderGfmTable(ctx, pkg, rows, true);
|
|
14
|
+
const diagnostics = [...preservedCarrierDiagnostics(table.preserved?.children), ...rows.flatMap((row) => preservedCarrierDiagnostics(row.preserved?.children))];
|
|
15
|
+
if (!rows.length) return diagnostics.join("\n");
|
|
16
|
+
return [needsHtmlFallback(rows) ? renderHtmlTable(ctx, pkg, rows, true) : renderGfmTable(ctx, pkg, rows, true), ...diagnostics].filter(Boolean).join("\n\n");
|
|
15
17
|
}
|
|
18
|
+
const preservedCarrierDiagnostics = (children) => (children ?? []).flatMap(({ xml }) => {
|
|
19
|
+
if (isAltChunkMarkup(xml)) return [ALT_CHUNK_READER_DIAGNOSTIC];
|
|
20
|
+
if (opaqueRevisionCarrierName(xml) !== void 0) return [OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC];
|
|
21
|
+
return isOpaqueNestedRowMarkup(xml) ? ["[Unsupported nested w:tr content]"] : [];
|
|
22
|
+
});
|
|
16
23
|
function needsHtmlFallback(rows) {
|
|
17
24
|
for (const row of rows) for (const cell of row.cells) {
|
|
18
25
|
if ((cell.formatting?.gridSpan ?? 1) > 1) return true;
|
|
@@ -64,10 +71,15 @@ function renderGfmCell(ctx, pkg, cell) {
|
|
|
64
71
|
break;
|
|
65
72
|
}
|
|
66
73
|
case "blockSdt":
|
|
74
|
+
case "blockCustomXml":
|
|
67
75
|
renderBlocks(item.content);
|
|
68
76
|
break;
|
|
69
|
-
case "table":
|
|
77
|
+
case "table": break;
|
|
70
78
|
case "preservedBlock":
|
|
79
|
+
if (isAltChunkMarkup(item.xml)) blocks.push(item.readerText === void 0 ? ALT_CHUNK_READER_DIAGNOSTIC : `${ALT_CHUNK_READER_DIAGNOSTIC}\n${item.readerText}`);
|
|
80
|
+
else if (opaqueRevisionCarrierName(item.xml) !== void 0) blocks.push(OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC);
|
|
81
|
+
else if (isOpaqueNestedRowMarkup(item.xml)) blocks.push("[Unsupported nested w:tr content]");
|
|
82
|
+
break;
|
|
71
83
|
case "bookmarkStart":
|
|
72
84
|
case "bookmarkEnd": break;
|
|
73
85
|
default: return item;
|
|
@@ -139,9 +151,14 @@ function renderHtmlCell(ctx, pkg, cell) {
|
|
|
139
151
|
break;
|
|
140
152
|
}
|
|
141
153
|
case "blockSdt":
|
|
154
|
+
case "blockCustomXml":
|
|
142
155
|
renderBlocks(item.content);
|
|
143
156
|
break;
|
|
144
157
|
case "preservedBlock":
|
|
158
|
+
if (isAltChunkMarkup(item.xml)) parts.push(item.readerText === void 0 ? ALT_CHUNK_READER_DIAGNOSTIC : `${ALT_CHUNK_READER_DIAGNOSTIC} ${item.readerText}`);
|
|
159
|
+
else if (opaqueRevisionCarrierName(item.xml) !== void 0) parts.push(OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC);
|
|
160
|
+
else if (isOpaqueNestedRowMarkup(item.xml)) parts.push("[Unsupported nested w:tr content]");
|
|
161
|
+
break;
|
|
145
162
|
case "bookmarkStart":
|
|
146
163
|
case "bookmarkEnd": break;
|
|
147
164
|
default: return item;
|
|
@@ -257,13 +274,8 @@ function renderHtmlRun(ctx, pkg, run, paraId) {
|
|
|
257
274
|
case "footnoteRef":
|
|
258
275
|
case "endnoteRef": {
|
|
259
276
|
if (ctx.opts.footnotes === "strip") break;
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
refId: item.id,
|
|
263
|
-
markerNumber,
|
|
264
|
-
kind: item.type === "endnoteRef" ? "endnote" : "footnote"
|
|
265
|
-
});
|
|
266
|
-
text += `<sup>[${markerNumber}]</sup>`;
|
|
277
|
+
const { token } = numberNoteReference(ctx, item.type === "endnoteRef" ? "endnote" : "footnote", item.id);
|
|
278
|
+
text += `<sup>[${token}]</sup>`;
|
|
267
279
|
break;
|
|
268
280
|
}
|
|
269
281
|
default: break;
|
|
@@ -18,9 +18,9 @@ import { panic } from "better-result";
|
|
|
18
18
|
function appendTrailers(ctx, doc, body) {
|
|
19
19
|
const sections = body.trim() ? [body] : [];
|
|
20
20
|
if (ctx.footnoteRefs.length > 0) {
|
|
21
|
-
const refs = ctx.footnoteRefs.map(({ refId,
|
|
21
|
+
const refs = ctx.footnoteRefs.map(({ refId, marker, kind }) => {
|
|
22
22
|
const note = kind === "endnote" ? doc.package.endnotes?.find((n) => n.id === refId) : doc.package.footnotes?.find((f) => f.id === refId);
|
|
23
|
-
return
|
|
23
|
+
return `${marker}: ${note ? noteText(ctx, doc, note) : ""}`;
|
|
24
24
|
});
|
|
25
25
|
sections.push(refs.join("\n"));
|
|
26
26
|
}
|
package/dist/markdown/types.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { NoteReferenceKind, NoteReferenceNumbering } from "../utils/noteReferenceLabels.js";
|
|
1
2
|
import { BuiltInStyleIndex } from "../docx/builtInStyles.js";
|
|
3
|
+
import { ListLabelCounter } from "../prosemirror/listLabels.js";
|
|
2
4
|
//#region src/markdown/types.d.ts
|
|
3
5
|
/**
|
|
4
6
|
* Metadata describing a single image registration. Owned by the markdown
|
|
@@ -106,12 +108,18 @@ type RenderContext = {
|
|
|
106
108
|
imagesByPath: Map<string, ImageRef>;
|
|
107
109
|
/** Diagnostics accumulator. */
|
|
108
110
|
warnings: string[];
|
|
109
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Footnote/endnote refs collected during this render, one per note in the
|
|
113
|
+
* order it is first referenced. `marker` is what the body line shows
|
|
114
|
+
* (`[^1]`, `[^e1]`) and what the definition trailer repeats.
|
|
115
|
+
*/
|
|
110
116
|
footnoteRefs: {
|
|
111
117
|
refId: number;
|
|
112
|
-
|
|
113
|
-
kind:
|
|
118
|
+
marker: string;
|
|
119
|
+
kind: NoteReferenceKind;
|
|
114
120
|
}[];
|
|
121
|
+
/** Reading-order note numbering, shared with the AI text view. */
|
|
122
|
+
noteNumbering: NoteReferenceNumbering;
|
|
115
123
|
/** Comment refs collected during this render (sidecar mode only). */
|
|
116
124
|
commentRefs: {
|
|
117
125
|
commentId: number;
|
|
@@ -124,12 +132,26 @@ type RenderContext = {
|
|
|
124
132
|
}[];
|
|
125
133
|
/** 1-based counter for default virtual paths. */
|
|
126
134
|
imageCounter: number;
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Advances past one paragraph, in document order, and answers the list
|
|
137
|
+
* label it shows: the page's own counter, so the numbers follow the
|
|
138
|
+
* document as it stands rather than the markers resolved when it was read.
|
|
139
|
+
*/
|
|
140
|
+
nextListLabel: ListLabelCounter;
|
|
131
141
|
/** The document's styles indexed by the built-in they are; classifies headings and quotes. */
|
|
132
142
|
builtInStyles: BuiltInStyleIndex;
|
|
143
|
+
/**
|
|
144
|
+
* The rendered width (marker text + one trailing space) of the most
|
|
145
|
+
* recently emitted list item at each level, indexed by `ListRendering.level`.
|
|
146
|
+
* A nested item's indent is the sum of every shallower level's width here,
|
|
147
|
+
* not a fixed two spaces: CommonMark only keeps a child nested under its
|
|
148
|
+
* parent when the child starts at or past the column where the parent's
|
|
149
|
+
* content begins, and a marker like `10. ` or `1. ` is wider than `- `.
|
|
150
|
+
* Document order visits a parent before its children, so by the time a
|
|
151
|
+
* level-N item renders, levels `0..N-1` already hold the current ancestor
|
|
152
|
+
* chain's widths.
|
|
153
|
+
*/
|
|
154
|
+
listIndentWidths: number[];
|
|
133
155
|
};
|
|
134
156
|
//#endregion
|
|
135
157
|
export { ImageMeta, ImageRef, MarkdownOptions, MarkdownResult, RenderContext, ResolvedOptions };
|
|
@@ -17,8 +17,7 @@ type IncrementalMeasureResult = {
|
|
|
17
17
|
measures: Measure[];
|
|
18
18
|
measuredBlockIndexes: number[];
|
|
19
19
|
};
|
|
20
|
-
declare function mergeDirtyRanges(first: DirtyRange | null, second: DirtyRange | null): DirtyRange | null;
|
|
21
20
|
declare function findDirtyBlockIndexes(blocks: FlowBlock[], dirtyRange: DirtyRange): number[];
|
|
22
21
|
declare function tryBuildIncrementalMeasures({ previousBlocks, previousMeasures, previousBlockWidths, nextBlocks, nextBlockWidths, dirtyRange, measureBlock }: IncrementalMeasureInput): IncrementalMeasureResult | null;
|
|
23
22
|
//#endregion
|
|
24
|
-
export { DirtyRange, IncrementalMeasureInput, IncrementalMeasureResult, findDirtyBlockIndexes,
|
|
23
|
+
export { DirtyRange, IncrementalMeasureInput, IncrementalMeasureResult, findDirtyBlockIndexes, tryBuildIncrementalMeasures };
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
//#region src/paged-layout/incrementalMeasure.ts
|
|
2
|
-
function mergeDirtyRanges(first, second) {
|
|
3
|
-
if (!first) return second;
|
|
4
|
-
if (!second) return first;
|
|
5
|
-
return {
|
|
6
|
-
from: Math.min(first.from, second.from),
|
|
7
|
-
to: Math.max(first.to, second.to)
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
2
|
function findDirtyBlockIndexes(blocks, dirtyRange) {
|
|
11
3
|
const indexes = [];
|
|
12
4
|
const dirtyFrom = Math.min(dirtyRange.from, dirtyRange.to);
|
|
@@ -53,4 +45,4 @@ function isIncrementalMeasureEligibleBlock(block) {
|
|
|
53
45
|
});
|
|
54
46
|
}
|
|
55
47
|
//#endregion
|
|
56
|
-
export { findDirtyBlockIndexes,
|
|
48
|
+
export { findDirtyBlockIndexes, tryBuildIncrementalMeasures };
|
|
@@ -2,7 +2,5 @@ import { DirtyRange } from "./incrementalMeasure.js";
|
|
|
2
2
|
import { Transaction } from "prosemirror-state";
|
|
3
3
|
//#region src/paged-layout/transactionDirtyRange.d.ts
|
|
4
4
|
declare function getTransactionDirtyRange(transaction: Transaction): DirtyRange | null;
|
|
5
|
-
/** Collect every transaction in an applied batch in the final document's coordinates. */
|
|
6
|
-
declare function getTransactionsDirtyRange(transactions: readonly Transaction[]): DirtyRange | null;
|
|
7
5
|
//#endregion
|
|
8
|
-
export { getTransactionDirtyRange
|
|
6
|
+
export { getTransactionDirtyRange };
|
|
@@ -1,49 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sweepPositions } from "../prosemirror/positionSweep.js";
|
|
2
2
|
import { AddMarkStep, RemoveMarkStep } from "prosemirror-transform";
|
|
3
3
|
//#region src/paged-layout/transactionDirtyRange.ts
|
|
4
4
|
function getTransactionDirtyRange(transaction) {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
let combinedRange = null;
|
|
16
|
-
for (let index = 0; index < transactions.length; index += 1) {
|
|
17
|
-
const transaction = transactions[index];
|
|
18
|
-
if (!transaction) continue;
|
|
19
|
-
const range = getTransactionDirtyRange(transaction);
|
|
20
|
-
if (!range) continue;
|
|
21
|
-
let from = range.from;
|
|
22
|
-
let to = range.to;
|
|
23
|
-
for (const followingTransaction of transactions.slice(index + 1)) {
|
|
24
|
-
from = followingTransaction.mapping.map(from, -1);
|
|
25
|
-
to = followingTransaction.mapping.map(to, 1);
|
|
26
|
-
}
|
|
27
|
-
combinedRange = mergeDirtyRanges(combinedRange, {
|
|
28
|
-
from,
|
|
29
|
-
to
|
|
5
|
+
const queries = [];
|
|
6
|
+
const extend = (newStart, newEnd, from) => {
|
|
7
|
+
queries.push({
|
|
8
|
+
pos: newStart,
|
|
9
|
+
assoc: -1,
|
|
10
|
+
from
|
|
11
|
+
}, {
|
|
12
|
+
pos: newEnd,
|
|
13
|
+
assoc: 1,
|
|
14
|
+
from
|
|
30
15
|
});
|
|
16
|
+
};
|
|
17
|
+
for (let stepIndex = 0; stepIndex < transaction.mapping.maps.length; stepIndex += 1) {
|
|
18
|
+
const map = transaction.mapping.maps[stepIndex];
|
|
19
|
+
if (!map) continue;
|
|
20
|
+
map.forEach((_oldStart, _oldEnd, newStart, newEnd) => extend(newStart, newEnd, stepIndex + 1));
|
|
21
|
+
const step = transaction.steps[stepIndex];
|
|
22
|
+
if (step instanceof AddMarkStep || step instanceof RemoveMarkStep) extend(step.from, step.to, stepIndex + 1);
|
|
31
23
|
}
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
dirtyRange.to = Math.max(dirtyRange.to, finalStart, finalEnd);
|
|
24
|
+
if (queries.length === 0) return null;
|
|
25
|
+
let from = Number.POSITIVE_INFINITY;
|
|
26
|
+
let to = Number.NEGATIVE_INFINITY;
|
|
27
|
+
for (const { pos } of sweepPositions([transaction.mapping], queries)) {
|
|
28
|
+
from = Math.min(from, pos);
|
|
29
|
+
to = Math.max(to, pos);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
from,
|
|
33
|
+
to
|
|
43
34
|
};
|
|
44
|
-
map.forEach((_oldStart, _oldEnd, newStart, newEnd) => extend(newStart, newEnd));
|
|
45
|
-
const step = transaction.steps[stepIndex];
|
|
46
|
-
if (step instanceof AddMarkStep || step instanceof RemoveMarkStep) extend(step.from, step.to);
|
|
47
35
|
}
|
|
48
36
|
//#endregion
|
|
49
|
-
export { getTransactionDirtyRange
|
|
37
|
+
export { getTransactionDirtyRange };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/panel-layout.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* One layout model for the editor's side panels: the page is centred between
|
|
4
|
+
* a start track (the document outline) and an end track (the comments).
|
|
5
|
+
*
|
|
6
|
+
* The editor measures the width it has once, and this module decides how
|
|
7
|
+
* each panel is presented. Every track the page shares the row with is
|
|
8
|
+
* counted here, so the page, the outline and the comments cannot overlap:
|
|
9
|
+
* a panel either gets a track of its own or becomes a drawer the user opens
|
|
10
|
+
* on purpose. A drawer takes no track.
|
|
11
|
+
*
|
|
12
|
+
* Space goes to the page first, then the outline rail, then the comments
|
|
13
|
+
* column, then the full outline column:
|
|
14
|
+
*
|
|
15
|
+
* - comments: a column when the page, the comments and the outline rail fit;
|
|
16
|
+
* otherwise a drawer.
|
|
17
|
+
* - outline: a column when it fits beside the page and the comments column;
|
|
18
|
+
* otherwise a rail of heading ticks when that fits; otherwise a drawer.
|
|
19
|
+
*
|
|
20
|
+
* The tier names the result: `wide` when every panel has its full column,
|
|
21
|
+
* `medium` when the outline is a rail, `narrow` when a panel is a drawer.
|
|
22
|
+
* The thresholds derive from the page width (at the current zoom) and the
|
|
23
|
+
* panel widths below, never from fixed breakpoints: a zoomed-out page or a
|
|
24
|
+
* landscape section moves them.
|
|
25
|
+
*/
|
|
26
|
+
/** Widths, in CSS pixels, every tier is derived from. */
|
|
27
|
+
declare const PANEL_METRICS: {
|
|
28
|
+
/** The outline column in the `wide` tier, border included. */
|
|
29
|
+
readonly outlineColumnWidth: 256;
|
|
30
|
+
/** The outline rail in the `medium` tier, border included. */
|
|
31
|
+
readonly outlineRailWidth: 32;
|
|
32
|
+
/** A comment card column. */
|
|
33
|
+
readonly commentsWidth: 280;
|
|
34
|
+
/** Space between the page edge and the comment cards, and after them. */
|
|
35
|
+
readonly commentsGap: 12;
|
|
36
|
+
/** Canvas kept clear on either side of the page. */
|
|
37
|
+
readonly pageMargin: 20;
|
|
38
|
+
/** An outline or comments drawer, capped by the width it opens over. */
|
|
39
|
+
readonly drawerWidth: 304;
|
|
40
|
+
};
|
|
41
|
+
/** Width the comments take beside the page: gap, cards, gap. */
|
|
42
|
+
declare const COMMENTS_TRACK_WIDTH: number;
|
|
43
|
+
type PanelLayoutTier = "wide" | "medium" | "narrow";
|
|
44
|
+
/** How the outline is shown: a column, a rail of ticks, a drawer, or not at all. */
|
|
45
|
+
type OutlinePresentation = "none" | "column" | "rail" | "drawer";
|
|
46
|
+
/** How the comments are shown: a column beside the page, a drawer, or not at all. */
|
|
47
|
+
type CommentsPresentation = "hidden" | "column" | "drawer";
|
|
48
|
+
type PanelLayoutInput = {
|
|
49
|
+
/** Width of the row the outline track and the scroll viewport share, scrollbar excluded. */
|
|
50
|
+
availableWidth: number;
|
|
51
|
+
/** Width of the widest page at the current zoom. */
|
|
52
|
+
pageWidth: number;
|
|
53
|
+
/** Whether the document has an outline to show. */
|
|
54
|
+
outline: "absent" | "available";
|
|
55
|
+
/** Whether the user (or the auto-open) wants the comments shown. */
|
|
56
|
+
comments: "closed" | "open";
|
|
57
|
+
};
|
|
58
|
+
type PanelLayout = {
|
|
59
|
+
tier: PanelLayoutTier;
|
|
60
|
+
outline: OutlinePresentation;
|
|
61
|
+
comments: CommentsPresentation;
|
|
62
|
+
/** Width of the outline track at the page's start (outside the scroll viewport). */
|
|
63
|
+
outlineTrackWidth: number;
|
|
64
|
+
/** Width reserved after the page inside the scroll viewport for the comments. */
|
|
65
|
+
commentsGutter: number;
|
|
66
|
+
/** Smallest available width for each tier, for the same page and panels. */
|
|
67
|
+
thresholds: {
|
|
68
|
+
wide: number;
|
|
69
|
+
medium: number;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The smallest available width for each tier with the comments wanted as
|
|
74
|
+
* given: `wide` fits every column, `medium` fits the outline rail and the
|
|
75
|
+
* comments column.
|
|
76
|
+
*/
|
|
77
|
+
declare const panelLayoutThresholds: ({ pageWidth, outline, comments }: Omit<PanelLayoutInput, "availableWidth">) => PanelLayout["thresholds"];
|
|
78
|
+
/** Decide each panel's presentation for the width the editor has. */
|
|
79
|
+
declare const computePanelLayout: (input: PanelLayoutInput) => PanelLayout;
|
|
80
|
+
/** Which drawer is open over the page: at most one at a time. */
|
|
81
|
+
type PanelOverlay = "none" | "outline" | "comments";
|
|
82
|
+
//#endregion
|
|
83
|
+
export { COMMENTS_TRACK_WIDTH, CommentsPresentation, OutlinePresentation, PANEL_METRICS, PanelLayout, PanelLayoutInput, PanelLayoutTier, PanelOverlay, computePanelLayout, panelLayoutThresholds };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
//#region src/panel-layout.ts
|
|
2
|
+
/**
|
|
3
|
+
* One layout model for the editor's side panels: the page is centred between
|
|
4
|
+
* a start track (the document outline) and an end track (the comments).
|
|
5
|
+
*
|
|
6
|
+
* The editor measures the width it has once, and this module decides how
|
|
7
|
+
* each panel is presented. Every track the page shares the row with is
|
|
8
|
+
* counted here, so the page, the outline and the comments cannot overlap:
|
|
9
|
+
* a panel either gets a track of its own or becomes a drawer the user opens
|
|
10
|
+
* on purpose. A drawer takes no track.
|
|
11
|
+
*
|
|
12
|
+
* Space goes to the page first, then the outline rail, then the comments
|
|
13
|
+
* column, then the full outline column:
|
|
14
|
+
*
|
|
15
|
+
* - comments: a column when the page, the comments and the outline rail fit;
|
|
16
|
+
* otherwise a drawer.
|
|
17
|
+
* - outline: a column when it fits beside the page and the comments column;
|
|
18
|
+
* otherwise a rail of heading ticks when that fits; otherwise a drawer.
|
|
19
|
+
*
|
|
20
|
+
* The tier names the result: `wide` when every panel has its full column,
|
|
21
|
+
* `medium` when the outline is a rail, `narrow` when a panel is a drawer.
|
|
22
|
+
* The thresholds derive from the page width (at the current zoom) and the
|
|
23
|
+
* panel widths below, never from fixed breakpoints: a zoomed-out page or a
|
|
24
|
+
* landscape section moves them.
|
|
25
|
+
*/
|
|
26
|
+
/** Widths, in CSS pixels, every tier is derived from. */
|
|
27
|
+
const PANEL_METRICS = {
|
|
28
|
+
/** The outline column in the `wide` tier, border included. */
|
|
29
|
+
outlineColumnWidth: 256,
|
|
30
|
+
/** The outline rail in the `medium` tier, border included. */
|
|
31
|
+
outlineRailWidth: 32,
|
|
32
|
+
/** A comment card column. */
|
|
33
|
+
commentsWidth: 280,
|
|
34
|
+
/** Space between the page edge and the comment cards, and after them. */
|
|
35
|
+
commentsGap: 12,
|
|
36
|
+
/** Canvas kept clear on either side of the page. */
|
|
37
|
+
pageMargin: 20,
|
|
38
|
+
/** An outline or comments drawer, capped by the width it opens over. */
|
|
39
|
+
drawerWidth: 304
|
|
40
|
+
};
|
|
41
|
+
/** Width the comments take beside the page: gap, cards, gap. */
|
|
42
|
+
const COMMENTS_TRACK_WIDTH = PANEL_METRICS.commentsWidth + 2 * PANEL_METRICS.commentsGap;
|
|
43
|
+
const pageTrackWidth = (pageWidth) => pageWidth + 2 * PANEL_METRICS.pageMargin;
|
|
44
|
+
/**
|
|
45
|
+
* The smallest available width for each tier with the comments wanted as
|
|
46
|
+
* given: `wide` fits every column, `medium` fits the outline rail and the
|
|
47
|
+
* comments column.
|
|
48
|
+
*/
|
|
49
|
+
const panelLayoutThresholds = ({ pageWidth, outline, comments }) => {
|
|
50
|
+
const page = pageTrackWidth(pageWidth);
|
|
51
|
+
const commentsTrack = comments === "open" ? COMMENTS_TRACK_WIDTH : 0;
|
|
52
|
+
const hasOutline = outline === "available";
|
|
53
|
+
return {
|
|
54
|
+
wide: page + commentsTrack + (hasOutline ? PANEL_METRICS.outlineColumnWidth : 0),
|
|
55
|
+
medium: page + commentsTrack + (hasOutline ? PANEL_METRICS.outlineRailWidth : 0)
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const OUTLINE_TRACK_WIDTH = {
|
|
59
|
+
none: 0,
|
|
60
|
+
column: PANEL_METRICS.outlineColumnWidth,
|
|
61
|
+
rail: PANEL_METRICS.outlineRailWidth,
|
|
62
|
+
drawer: 0
|
|
63
|
+
};
|
|
64
|
+
const tierFor = (outline, comments) => {
|
|
65
|
+
if (outline === "drawer" || comments === "drawer") return "narrow";
|
|
66
|
+
if (outline === "rail") return "medium";
|
|
67
|
+
return "wide";
|
|
68
|
+
};
|
|
69
|
+
/** Decide each panel's presentation for the width the editor has. */
|
|
70
|
+
const computePanelLayout = (input) => {
|
|
71
|
+
const { availableWidth } = input;
|
|
72
|
+
const thresholds = panelLayoutThresholds(input);
|
|
73
|
+
const page = pageTrackWidth(input.pageWidth);
|
|
74
|
+
const comments = (() => {
|
|
75
|
+
if (input.comments === "closed") return "hidden";
|
|
76
|
+
return availableWidth >= thresholds.medium ? "column" : "drawer";
|
|
77
|
+
})();
|
|
78
|
+
const commentsGutter = comments === "column" ? COMMENTS_TRACK_WIDTH : 0;
|
|
79
|
+
const outline = (() => {
|
|
80
|
+
if (input.outline === "absent") return "none";
|
|
81
|
+
const beside = page + commentsGutter;
|
|
82
|
+
if (availableWidth >= thresholds.wide) return "column";
|
|
83
|
+
if (availableWidth >= beside + PANEL_METRICS.outlineRailWidth) return "rail";
|
|
84
|
+
return "drawer";
|
|
85
|
+
})();
|
|
86
|
+
return {
|
|
87
|
+
tier: tierFor(outline, comments),
|
|
88
|
+
outline,
|
|
89
|
+
comments,
|
|
90
|
+
outlineTrackWidth: OUTLINE_TRACK_WIDTH[outline],
|
|
91
|
+
commentsGutter,
|
|
92
|
+
thresholds
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
//#endregion
|
|
96
|
+
export { COMMENTS_TRACK_WIDTH, PANEL_METRICS, computePanelLayout, panelLayoutThresholds };
|