@stll/folio-core 0.53.0 → 0.54.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.js +415 -166
- package/dist/ai-edits/batch-claims.d.ts +21 -6
- package/dist/ai-edits/batch-claims.js +47 -16
- package/dist/ai-edits/headless.d.ts +20 -0
- package/dist/ai-edits/headless.js +140 -11
- package/dist/ai-edits/pending-suggestions.js +1 -1
- package/dist/ai-edits/read.d.ts +5 -3
- package/dist/ai-edits/read.js +97 -47
- package/dist/ai-edits/revisionStretches.d.ts +17 -0
- package/dist/ai-edits/revisionStretches.js +80 -0
- package/dist/ai-edits/snapshot.js +3 -2
- package/dist/ai-edits/table-cell-mutations.d.ts +3 -1
- package/dist/ai-edits/table-cell-mutations.js +2 -1
- package/dist/ai-edits/table-row-column-mutations.d.ts +6 -1
- package/dist/ai-edits/table-row-column-mutations.js +27 -10
- package/dist/compare/content-alignment.d.ts +5 -1
- package/dist/compare/content-alignment.js +39 -32
- package/dist/compare/inline-provenance.js +1 -1
- package/dist/controller/layoutPipeline.js +3 -2
- package/dist/docx/archiveInflation.d.ts +127 -0
- package/dist/docx/archiveInflation.js +181 -0
- package/dist/docx/metadataPrivacy.js +24 -1
- package/dist/docx/noteReferenceMark.d.ts +15 -0
- package/dist/docx/noteReferenceMark.js +48 -0
- package/dist/docx/paragraphParser.js +5 -3
- package/dist/docx/paragraphPropertySource.d.ts +1 -1
- package/dist/docx/paragraphPropertySource.js +4 -2
- package/dist/docx/parser.js +2 -2
- package/dist/docx/rezip.js +4 -2
- package/dist/docx/selectiveXmlPatch.d.ts +3 -1
- package/dist/docx/selectiveXmlPatch.js +81 -3
- package/dist/docx/server/boundedArchive.d.ts +8 -13
- package/dist/docx/server/boundedArchive.js +70 -59
- package/dist/docx/server/extractDocxText.d.ts +8 -2
- package/dist/docx/server/extractDocxText.js +2 -2
- package/dist/docx/server/validateDocxConformance.d.ts +1 -1
- package/dist/docx/server/validateDocxConformance.js +1 -0
- package/dist/docx/unzip.d.ts +19 -2
- package/dist/docx/unzip.js +135 -24
- package/dist/docx/verticalMergeProjection.d.ts +17 -0
- package/dist/docx/verticalMergeProjection.js +120 -0
- package/dist/fonts/embeddedFonts.js +1 -1
- package/dist/i18n/messages/catalogs.gen.d.ts +34 -34
- package/dist/i18n/messages/catalogs.gen.js +34 -34
- package/dist/i18n/messages/messages.gen.d.ts +2 -2
- package/dist/internal/wholeStoryRevisionResolution.js +95 -25
- package/dist/layout-engine/measure/measureParagraph.js +2 -2
- package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
- package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
- package/dist/markdown/escape.d.ts +2 -2
- package/dist/markdown/escape.js +4 -5
- package/dist/markdown/renderBlock.js +91 -25
- package/dist/markdown/renderRuns.d.ts +10 -1
- package/dist/markdown/renderRuns.js +320 -59
- package/dist/prosemirror/clearRunColor.d.ts +6 -0
- package/dist/prosemirror/clearRunColor.js +46 -0
- package/dist/prosemirror/commands/comments.js +62 -22
- package/dist/prosemirror/commands/formatPainter.js +1 -1
- package/dist/prosemirror/commands/hyperlink.js +2 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +28 -4
- package/dist/prosemirror/commands/resolveAllTableChanges.js +40 -41
- package/dist/prosemirror/commands/resolveParagraphProperties.js +33 -8
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +7 -1
- package/dist/prosemirror/commands/tableCellMergeResolution.js +39 -20
- package/dist/prosemirror/commands/tableMergeFoldDecisions.d.ts +61 -0
- package/dist/prosemirror/commands/tableMergeFoldDecisions.js +79 -0
- package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
- package/dist/prosemirror/containerFinalParagraph.js +7 -6
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
- package/dist/prosemirror/conversion/fromProseDoc.js +12 -590
- package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -13
- package/dist/prosemirror/conversion/toProseDoc.js +28 -262
- package/dist/prosemirror/documentSchema.d.ts +8 -0
- package/dist/prosemirror/documentSchema.js +18 -0
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +104 -63
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -1
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +10 -9
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
- package/dist/prosemirror/extensions/features/pastedHtmlLists.js +2 -4
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +14 -8
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
- package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -6
- package/dist/prosemirror/extensions/marks/markUtils.js +17 -8
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +3 -1
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +12 -1
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
- package/dist/prosemirror/extensions/nodes/TableExtension.js +104 -210
- package/dist/prosemirror/extensions/types.d.ts +7 -0
- package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
- package/dist/prosemirror/hyperlinkRemoval.js +129 -0
- package/dist/prosemirror/index.d.ts +2 -1
- package/dist/prosemirror/index.js +2 -1
- package/dist/prosemirror/listNumbering.d.ts +3 -21
- package/dist/prosemirror/listNumbering.js +24 -39
- package/dist/prosemirror/listRendering.d.ts +29 -0
- package/dist/prosemirror/listRendering.js +26 -0
- package/dist/prosemirror/markupViewNotes.d.ts +8 -0
- package/dist/prosemirror/markupViewNotes.js +49 -0
- package/dist/prosemirror/markupViewProjection.d.ts +3 -1
- package/dist/prosemirror/markupViewProjection.js +7 -2
- package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
- package/dist/prosemirror/noteReferenceReview.js +332 -0
- package/dist/prosemirror/paragraphIndentation.js +5 -2
- package/dist/prosemirror/paragraphMarkJoin.d.ts +6 -4
- package/dist/prosemirror/paragraphMarkJoin.js +21 -19
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
- package/dist/prosemirror/paragraphPropertyCarry.js +155 -0
- package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
- package/dist/prosemirror/plugins/documentStyleState.js +32 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +2 -21
- package/dist/prosemirror/plugins/documentStyles.js +66 -29
- package/dist/prosemirror/plugins/index.d.ts +2 -1
- package/dist/prosemirror/plugins/index.js +2 -1
- package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
- package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
- package/dist/prosemirror/plugins/suggestionMode.d.ts +12 -2
- package/dist/prosemirror/plugins/suggestionMode.js +387 -28
- package/dist/prosemirror/plugins/templateDirectives.d.ts +6 -0
- package/dist/prosemirror/plugins/templateDirectives.js +21 -7
- package/dist/prosemirror/plugins/templatePreviewValues.js +14 -21
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +22 -2
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
- package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
- package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
- package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
- package/dist/prosemirror/runFormattingFromMarks.js +567 -0
- package/dist/prosemirror/runFormattingReconciliation.js +10 -9
- package/dist/prosemirror/schema/nodes.d.ts +2 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
- package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
- package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
- package/dist/prosemirror/tableCellPaste.d.ts +74 -0
- package/dist/prosemirror/tableCellPaste.js +525 -0
- package/dist/prosemirror/tableGridMutation.d.ts +53 -14
- package/dist/prosemirror/tableGridMutation.js +166 -18
- package/dist/prosemirror/tableRunIn.d.ts +51 -0
- package/dist/prosemirror/tableRunIn.js +165 -0
- package/dist/prosemirror/textInput.js +11 -2
- package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
- package/dist/prosemirror/trackedRevisionPath.js +32 -0
- package/dist/server.d.ts +2 -2
- package/package.json +6 -6
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EMPTY_BUILT_IN_STYLE_INDEX } from "../../docx/builtInStyles.js";
|
|
2
|
+
import { PluginKey } from "prosemirror-state";
|
|
3
|
+
//#region src/prosemirror/plugins/documentStyleState.ts
|
|
4
|
+
const documentStylesKey = new PluginKey("documentStyles");
|
|
5
|
+
/** Read the document's StyleResolver, or null when the plugin isn't installed. */
|
|
6
|
+
function getDocumentStyleResolver(state) {
|
|
7
|
+
return documentStylesKey.getState(state) ?? null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The document's style definitions by id, or `null` when the state carries no
|
|
11
|
+
* styles plugin and so cannot say what the document defines. A document
|
|
12
|
+
* without a styles part defines none.
|
|
13
|
+
*/
|
|
14
|
+
function getDocumentStyleDefinitions(state) {
|
|
15
|
+
if (documentStylesKey.get(state) === void 0) return null;
|
|
16
|
+
const resolver = getDocumentStyleResolver(state);
|
|
17
|
+
return {
|
|
18
|
+
get: (styleId) => resolver?.getStyle(styleId),
|
|
19
|
+
paragraphStyles: () => resolver?.getParagraphStyles() ?? []
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Read the document's built-in style index, for the callers that classify
|
|
24
|
+
* paragraphs (heading collection, markdown export, the AI snapshot). Without
|
|
25
|
+
* the plugin every lookup misses, which degrades classification to the
|
|
26
|
+
* paragraph's own outline level rather than to English style ids.
|
|
27
|
+
*/
|
|
28
|
+
function getDocumentBuiltInStyles(state) {
|
|
29
|
+
return getDocumentStyleResolver(state)?.builtInStyles ?? EMPTY_BUILT_IN_STYLE_INDEX;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleDefinitions, getDocumentStyleResolver };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { document_d_exports } from "../../types/document.js";
|
|
2
|
-
import { BuiltInStyleIndex } from "../../docx/builtInStyles.js";
|
|
3
2
|
import { StyleResolver } from "../styles/styleResolver.js";
|
|
4
|
-
import {
|
|
3
|
+
import { documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleDefinitions, getDocumentStyleResolver } from "./documentStyleState.js";
|
|
4
|
+
import { EditorState, Plugin } from "prosemirror-state";
|
|
5
5
|
//#region src/prosemirror/plugins/documentStyles.d.ts
|
|
6
|
-
declare const documentStylesKey: PluginKey<StyleResolver | null>;
|
|
7
6
|
/**
|
|
8
7
|
* Create the plugin holding a StyleResolver for the document's `styles` for
|
|
9
8
|
* the lifetime of the EditorState. The resolver is fixed per document load;
|
|
@@ -12,24 +11,6 @@ declare const documentStylesKey: PluginKey<StyleResolver | null>;
|
|
|
12
11
|
* have one.
|
|
13
12
|
*/
|
|
14
13
|
declare function createDocumentStylesPlugin(styles: document_d_exports.StyleDefinitions | StyleResolver | null | undefined): Plugin;
|
|
15
|
-
/** Read the document's StyleResolver, or null when the plugin isn't installed. */
|
|
16
|
-
declare function getDocumentStyleResolver(state: EditorState): StyleResolver | null;
|
|
17
|
-
/**
|
|
18
|
-
* The document's style definitions by id, or `null` when the state carries no
|
|
19
|
-
* styles plugin and so cannot say what the document defines. A document
|
|
20
|
-
* without a styles part defines none.
|
|
21
|
-
*/
|
|
22
|
-
declare function getDocumentStyleDefinitions(state: EditorState): {
|
|
23
|
-
get: (styleId: string) => document_d_exports.Style | undefined;
|
|
24
|
-
paragraphStyles: () => document_d_exports.Style[];
|
|
25
|
-
} | null;
|
|
26
|
-
/**
|
|
27
|
-
* Read the document's built-in style index, for the callers that classify
|
|
28
|
-
* paragraphs (heading collection, markdown export, the AI snapshot). Without
|
|
29
|
-
* the plugin every lookup misses, which degrades classification to the
|
|
30
|
-
* paragraph's own outline level rather than to English style ids.
|
|
31
|
-
*/
|
|
32
|
-
declare function getDocumentBuiltInStyles(state: EditorState): BuiltInStyleIndex;
|
|
33
14
|
/** Reconfigure so ProseMirror replaces the keyed plugin's resolver state. */
|
|
34
15
|
declare const withDocumentStyles: (state: EditorState, styles: document_d_exports.StyleDefinitions | StyleResolver | null | undefined) => EditorState;
|
|
35
16
|
//#endregion
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../extensions/features/JoinedRunStyleExtension.js";
|
|
2
|
+
import { rebaseParagraphRuns } from "../rebaseParagraphRuns.js";
|
|
2
3
|
import { StyleResolver, createStyleResolver } from "../styles/styleResolver.js";
|
|
3
|
-
import {
|
|
4
|
+
import { getDocumentNumbering } from "./documentNumbering.js";
|
|
5
|
+
import { documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleDefinitions, getDocumentStyleResolver } from "./documentStyleState.js";
|
|
6
|
+
import { resolveEditedParagraphStyles } from "./paragraphStyleResolution.js";
|
|
7
|
+
import { Mark } from "prosemirror-model";
|
|
8
|
+
import { Mapping, ReplaceStep } from "prosemirror-transform";
|
|
9
|
+
import { Plugin } from "prosemirror-state";
|
|
10
|
+
import { isHistoryTransaction } from "prosemirror-history";
|
|
4
11
|
//#region src/prosemirror/plugins/documentStyles.ts
|
|
5
12
|
/**
|
|
6
13
|
* documentStyles plugin — makes the document's StyleResolver reachable from
|
|
@@ -18,7 +25,57 @@ import { Plugin, PluginKey } from "prosemirror-state";
|
|
|
18
25
|
* EditorState. When absent, style-aware commands fall back to their
|
|
19
26
|
* style-agnostic behavior.
|
|
20
27
|
*/
|
|
21
|
-
|
|
28
|
+
/** Rebase surviving right-hand runs when ordinary replacement steps consume a paragraph opening. */
|
|
29
|
+
const rebaseEditedParagraphJoins = (transactions, tr, resolver) => {
|
|
30
|
+
const maps = transactions.flatMap((transaction) => transaction.mapping.maps);
|
|
31
|
+
let offset = 0;
|
|
32
|
+
for (const transaction of transactions) {
|
|
33
|
+
if (isHistoryTransaction(transaction) || transaction.getMeta("joinedRunsRestyled") === true || !transaction.steps.every((step) => step instanceof ReplaceStep)) {
|
|
34
|
+
offset += transaction.steps.length;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
for (const [index, step] of transaction.steps.entries()) {
|
|
38
|
+
const before = transaction.docs[index];
|
|
39
|
+
if (!before) continue;
|
|
40
|
+
const map = step.getMap();
|
|
41
|
+
const mapping = new Mapping([map, ...new Mapping(maps.slice(offset + index + 1)).maps]);
|
|
42
|
+
map.forEach((oldFrom, oldTo) => {
|
|
43
|
+
before.nodesBetween(oldFrom, oldTo, (paragraph, position) => {
|
|
44
|
+
if (paragraph.type.name !== "paragraph") return true;
|
|
45
|
+
if (!map.mapResult(position, 1).deleted) return false;
|
|
46
|
+
const from = mapping.map(position + 1, 1);
|
|
47
|
+
const to = mapping.map(position + paragraph.nodeSize - 1, -1);
|
|
48
|
+
if (from >= to) return false;
|
|
49
|
+
const at = tr.doc.resolve(from);
|
|
50
|
+
if (at.parent.type.name !== "paragraph") return false;
|
|
51
|
+
const targetPosition = at.start() - 1;
|
|
52
|
+
if (targetPosition === mapping.map(position, 1)) return false;
|
|
53
|
+
const surviving = tr.doc.nodeAt(from);
|
|
54
|
+
const original = before.nodeAt(mapping.invert().map(from, 1));
|
|
55
|
+
if (!surviving || !original || !Mark.sameSet(surviving.marks, original.marks)) return false;
|
|
56
|
+
rebaseParagraphRuns({
|
|
57
|
+
tr,
|
|
58
|
+
position: targetPosition,
|
|
59
|
+
previous: paragraph,
|
|
60
|
+
styleResolver: resolver,
|
|
61
|
+
range: {
|
|
62
|
+
from,
|
|
63
|
+
to
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return false;
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
offset += transaction.steps.length;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
let bareStyleResolver;
|
|
74
|
+
/** The cascade of a package that defines no styles: docDefaults-free built-ins. */
|
|
75
|
+
const bareResolver = () => {
|
|
76
|
+
bareStyleResolver ??= createStyleResolver(void 0);
|
|
77
|
+
return bareStyleResolver;
|
|
78
|
+
};
|
|
22
79
|
/**
|
|
23
80
|
* Create the plugin holding a StyleResolver for the document's `styles` for
|
|
24
81
|
* the lifetime of the EditorState. The resolver is fixed per document load;
|
|
@@ -36,35 +93,15 @@ function createDocumentStylesPlugin(styles) {
|
|
|
36
93
|
state: {
|
|
37
94
|
init: () => resolver,
|
|
38
95
|
apply: (_tr, value) => value
|
|
96
|
+
},
|
|
97
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
98
|
+
const styleResolver = documentStylesKey.getState(newState) ?? bareResolver();
|
|
99
|
+
const tr = resolveEditedParagraphStyles(transactions, newState, styleResolver, () => getDocumentNumbering(newState)) ?? newState.tr;
|
|
100
|
+
rebaseEditedParagraphJoins(transactions, tr, styleResolver);
|
|
101
|
+
return tr.docChanged ? tr : null;
|
|
39
102
|
}
|
|
40
103
|
});
|
|
41
104
|
}
|
|
42
|
-
/** Read the document's StyleResolver, or null when the plugin isn't installed. */
|
|
43
|
-
function getDocumentStyleResolver(state) {
|
|
44
|
-
return documentStylesKey.getState(state) ?? null;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* The document's style definitions by id, or `null` when the state carries no
|
|
48
|
-
* styles plugin and so cannot say what the document defines. A document
|
|
49
|
-
* without a styles part defines none.
|
|
50
|
-
*/
|
|
51
|
-
function getDocumentStyleDefinitions(state) {
|
|
52
|
-
if (documentStylesKey.get(state) === void 0) return null;
|
|
53
|
-
const resolver = getDocumentStyleResolver(state);
|
|
54
|
-
return {
|
|
55
|
-
get: (styleId) => resolver?.getStyle(styleId),
|
|
56
|
-
paragraphStyles: () => resolver?.getParagraphStyles() ?? []
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Read the document's built-in style index, for the callers that classify
|
|
61
|
-
* paragraphs (heading collection, markdown export, the AI snapshot). Without
|
|
62
|
-
* the plugin every lookup misses, which degrades classification to the
|
|
63
|
-
* paragraph's own outline level rather than to English style ids.
|
|
64
|
-
*/
|
|
65
|
-
function getDocumentBuiltInStyles(state) {
|
|
66
|
-
return getDocumentStyleResolver(state)?.builtInStyles ?? EMPTY_BUILT_IN_STYLE_INDEX;
|
|
67
|
-
}
|
|
68
105
|
/** Reconfigure so ProseMirror replaces the keyed plugin's resolver state. */
|
|
69
106
|
const withDocumentStyles = (state, styles) => {
|
|
70
107
|
const previous = documentStylesKey.get(state);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { SelectionChangeCallback, SelectionContext, createSelectionTrackerPlugin, extractSelectionContext, getSelectionContext, selectionTrackerKey } from "./selectionTracker.js";
|
|
2
|
-
import {
|
|
2
|
+
import { documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleResolver } from "./documentStyleState.js";
|
|
3
|
+
import { createDocumentStylesPlugin } from "./documentStyles.js";
|
|
3
4
|
export { type SelectionChangeCallback, type SelectionContext, createDocumentStylesPlugin, createSelectionTrackerPlugin, documentStylesKey, extractSelectionContext, getDocumentBuiltInStyles, getDocumentStyleResolver, getSelectionContext, selectionTrackerKey };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleResolver } from "./documentStyleState.js";
|
|
2
|
+
import { createDocumentStylesPlugin } from "./documentStyles.js";
|
|
2
3
|
import { createSelectionTrackerPlugin, extractSelectionContext, getSelectionContext, selectionTrackerKey } from "./selectionTracker.js";
|
|
3
4
|
export { createDocumentStylesPlugin, createSelectionTrackerPlugin, documentStylesKey, extractSelectionContext, getDocumentBuiltInStyles, getDocumentStyleResolver, getSelectionContext, selectionTrackerKey };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StyleEngine } from "../../style-engine/styleEngine.js";
|
|
2
|
+
import "../../style-engine/index.js";
|
|
3
|
+
import { NumberingMap } from "../../docx/numberingParser.js";
|
|
4
|
+
import { ParagraphCascadeResolver } from "../styles/paragraphStyleCascade.js";
|
|
5
|
+
import { EditorState, Transaction } from "prosemirror-state";
|
|
6
|
+
//#region src/prosemirror/plugins/paragraphStyleResolution.d.ts
|
|
7
|
+
type ParagraphStyleResolver = ParagraphCascadeResolver & Pick<StyleEngine, "getDefaultTableStyle">;
|
|
8
|
+
/**
|
|
9
|
+
* Project the style cascade onto every paragraph the transactions touched
|
|
10
|
+
* that has not been projected yet. Returns the transaction to append, or null
|
|
11
|
+
* when every touched paragraph already reads as a reopened document would.
|
|
12
|
+
*/
|
|
13
|
+
declare const resolveEditedParagraphStyles: (transactions: readonly Transaction[], state: EditorState, resolver: ParagraphStyleResolver, numbering: () => NumberingMap | null) => Transaction | null;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { resolveEditedParagraphStyles };
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { resolveTableLook } from "../../docx/tableLook.js";
|
|
2
|
+
import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
|
|
3
|
+
import { expectParagraphAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs } from "../attrs/index.js";
|
|
4
|
+
import { setAutospacingBaseValue } from "../autospacingBase.js";
|
|
5
|
+
import { directionToAuthoredBidi } from "../paragraphDirection.js";
|
|
6
|
+
import { paragraphStyleCascadeAttrs, tableCellParagraphOverlay } from "../styles/paragraphStyleCascade.js";
|
|
7
|
+
import { listAttrsFromResolvedStyle } from "../styles/resolvedStyleAttrs.js";
|
|
8
|
+
import { tableCellStyleRegions, tableRowBand } from "../styles/tableStyleRegions.js";
|
|
9
|
+
import { TableMap } from "prosemirror-tables";
|
|
10
|
+
import { Mapping } from "prosemirror-transform";
|
|
11
|
+
import { isHistoryTransaction } from "prosemirror-history";
|
|
12
|
+
//#region src/prosemirror/plugins/paragraphStyleResolution.ts
|
|
13
|
+
/** The ranges of `doc` the given transactions changed, in its own positions. */
|
|
14
|
+
const changedRanges = (transactions) => {
|
|
15
|
+
const ranges = [];
|
|
16
|
+
const maps = transactions.flatMap((transaction) => transaction.mapping.maps);
|
|
17
|
+
let offset = 0;
|
|
18
|
+
for (const transaction of transactions) {
|
|
19
|
+
const own = transaction.mapping.maps.length;
|
|
20
|
+
if (transaction.docChanged && !isHistoryTransaction(transaction)) for (const [index, map] of transaction.mapping.maps.entries()) {
|
|
21
|
+
const following = new Mapping(maps.slice(offset + index + 1));
|
|
22
|
+
map.forEach((_oldFrom, _oldTo, from, to) => {
|
|
23
|
+
ranges.push([following.map(from, -1), following.map(to, 1)]);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
offset += own;
|
|
27
|
+
}
|
|
28
|
+
return ranges;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* What the paragraph states itself, as the cascade reads it: every attr the
|
|
32
|
+
* node holds a value for. Only called for paragraphs the load path never
|
|
33
|
+
* projected, whose attrs hold nothing inherited yet.
|
|
34
|
+
*/
|
|
35
|
+
const statedFormatting = (attrs) => {
|
|
36
|
+
const formatting = {};
|
|
37
|
+
const copy = (key) => {
|
|
38
|
+
const value = attrs[key];
|
|
39
|
+
if (value !== null && value !== void 0) Reflect.set(formatting, key, value);
|
|
40
|
+
};
|
|
41
|
+
copy("alignment");
|
|
42
|
+
copy("spaceBefore");
|
|
43
|
+
copy("spaceAfter");
|
|
44
|
+
copy("lineSpacing");
|
|
45
|
+
copy("lineSpacingRule");
|
|
46
|
+
copy("snapToGrid");
|
|
47
|
+
copy("indentLeft");
|
|
48
|
+
copy("indentRight");
|
|
49
|
+
copy("indentFirstLine");
|
|
50
|
+
if (attrs.indentFirstLine !== null && attrs.indentFirstLine !== void 0) copy("hangingIndent");
|
|
51
|
+
copy("borders");
|
|
52
|
+
copy("shading");
|
|
53
|
+
copy("tabs");
|
|
54
|
+
copy("kinsoku");
|
|
55
|
+
copy("overflowPunctuation");
|
|
56
|
+
copy("suppressAutoHyphens");
|
|
57
|
+
copy("pageBreakBefore");
|
|
58
|
+
copy("keepNext");
|
|
59
|
+
copy("keepLines");
|
|
60
|
+
copy("widowControl");
|
|
61
|
+
copy("contextualSpacing");
|
|
62
|
+
copy("runInWithNext");
|
|
63
|
+
copy("outlineLevel");
|
|
64
|
+
copy("numPr");
|
|
65
|
+
const bidi = directionToAuthoredBidi(attrs.direction);
|
|
66
|
+
if (bidi !== void 0) formatting.bidi = bidi;
|
|
67
|
+
return formatting;
|
|
68
|
+
};
|
|
69
|
+
const isUnset = (value) => value === null || value === void 0;
|
|
70
|
+
/**
|
|
71
|
+
* The attrs the cascade supplies that `paragraph` leaves unset, or null when
|
|
72
|
+
* it already reads the way a reopened document would.
|
|
73
|
+
*/
|
|
74
|
+
const cascadePatch = (node, resolver, tableParagraphOverlay, numbering) => {
|
|
75
|
+
const attrs = expectParagraphAttrs(node);
|
|
76
|
+
const styleId = attrs.styleId ?? void 0;
|
|
77
|
+
const { attrs: cascade, stylePpr } = paragraphStyleCascadeAttrs({
|
|
78
|
+
styleId,
|
|
79
|
+
formatting: statedFormatting(attrs),
|
|
80
|
+
styleResolver: resolver,
|
|
81
|
+
tableParagraphOverlay,
|
|
82
|
+
includeParagraphMarkRunProperties: false
|
|
83
|
+
});
|
|
84
|
+
const patch = {};
|
|
85
|
+
const fill = (key) => {
|
|
86
|
+
const value = cascade[key];
|
|
87
|
+
if (!isUnset(value) && isUnset(attrs[key])) patch[key] = value;
|
|
88
|
+
};
|
|
89
|
+
const lineProvenance = attrs.lineSpacingExplicit;
|
|
90
|
+
const filledSides = {
|
|
91
|
+
before: !attrs.spacingExplicit?.before && isUnset(attrs.spaceBefore),
|
|
92
|
+
after: !attrs.spacingExplicit?.after && isUnset(attrs.spaceAfter)
|
|
93
|
+
};
|
|
94
|
+
if (filledSides.before) fill("spaceBefore");
|
|
95
|
+
if (filledSides.after) fill("spaceAfter");
|
|
96
|
+
if (lineProvenance !== "value" && lineProvenance !== "both" && lineProvenance !== true) fill("lineSpacing");
|
|
97
|
+
if (lineProvenance !== "rule" && lineProvenance !== "both" && lineProvenance !== true) fill("lineSpacingRule");
|
|
98
|
+
for (const key of ["spacingFromDocDefaults", "spacingFromImplicitDefaultStyle"]) {
|
|
99
|
+
const inherited = cascade[key];
|
|
100
|
+
const side = {
|
|
101
|
+
...inherited?.before && filledSides.before ? { before: true } : {},
|
|
102
|
+
...inherited?.after && filledSides.after ? { after: true } : {}
|
|
103
|
+
};
|
|
104
|
+
if (side.before || side.after) patch[key] = {
|
|
105
|
+
...attrs[key],
|
|
106
|
+
...side
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (isUnset(attrs.indentFirstLine) && attrs.hangingIndent !== true) {
|
|
110
|
+
fill("indentFirstLine");
|
|
111
|
+
if (cascade.hangingIndent === true) patch.hangingIndent = true;
|
|
112
|
+
}
|
|
113
|
+
for (const key of [
|
|
114
|
+
"alignment",
|
|
115
|
+
"alignmentFromStyle",
|
|
116
|
+
"_resolvedFormatting",
|
|
117
|
+
"snapToGrid",
|
|
118
|
+
"indentLeft",
|
|
119
|
+
"indentRight",
|
|
120
|
+
"borders",
|
|
121
|
+
"shading",
|
|
122
|
+
"tabs",
|
|
123
|
+
"kinsoku",
|
|
124
|
+
"overflowPunctuation",
|
|
125
|
+
"suppressAutoHyphens",
|
|
126
|
+
"pageBreakBefore",
|
|
127
|
+
"keepNext",
|
|
128
|
+
"keepLines",
|
|
129
|
+
"widowControl",
|
|
130
|
+
"contextualSpacing",
|
|
131
|
+
"runInWithNext",
|
|
132
|
+
"outlineLevel",
|
|
133
|
+
"direction",
|
|
134
|
+
"defaultTextFormatting"
|
|
135
|
+
]) fill(key);
|
|
136
|
+
if (styleId !== void 0 && isUnset(attrs._tableOfContentsLevel)) {
|
|
137
|
+
const styleName = resolver.getStyle(styleId)?.name;
|
|
138
|
+
const level = tableOfContentsStyleLevel({
|
|
139
|
+
styleId,
|
|
140
|
+
...styleName ? { styleName } : {}
|
|
141
|
+
});
|
|
142
|
+
if (level !== void 0) patch._tableOfContentsLevel = level;
|
|
143
|
+
}
|
|
144
|
+
if (stylePpr?.numPr?.kind === "reference" && isUnset(attrs.numPr) && isUnset(attrs.numPrFromStyle)) {
|
|
145
|
+
const listAttrs = listAttrsFromResolvedStyle({ paragraphFormatting: stylePpr }, numbering());
|
|
146
|
+
const takesLevelIndent = {
|
|
147
|
+
indentLeft: isUnset(attrs.indentLeft) && patch.indentLeft === void 0,
|
|
148
|
+
indentFirstLine: isUnset(attrs.indentFirstLine) && attrs.hangingIndent !== true && patch.indentFirstLine === void 0
|
|
149
|
+
};
|
|
150
|
+
takesLevelIndent["hangingIndent"] = takesLevelIndent["indentFirstLine"] === true;
|
|
151
|
+
for (const [key, value] of Object.entries(listAttrs ?? {})) {
|
|
152
|
+
if (takesLevelIndent[key] === false) continue;
|
|
153
|
+
Reflect.set(patch, key, value);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const autospacingBase = {};
|
|
157
|
+
if (stylePpr?.beforeAutospacing && patch.spaceBefore !== void 0) setAutospacingBaseValue(autospacingBase, "before", patch.spaceBefore);
|
|
158
|
+
if (stylePpr?.afterAutospacing && patch.spaceAfter !== void 0) setAutospacingBaseValue(autospacingBase, "after", patch.spaceAfter);
|
|
159
|
+
if (Object.keys(autospacingBase).length > 0) patch._autospacingBase = {
|
|
160
|
+
...attrs._autospacingBase,
|
|
161
|
+
...autospacingBase
|
|
162
|
+
};
|
|
163
|
+
return Object.keys(patch).length > 0 ? patch : null;
|
|
164
|
+
};
|
|
165
|
+
/** The table-style regions for the cell at `depth` of `$pos`, as the load path picks them. */
|
|
166
|
+
const cellStyleRegions = ($pos, depth) => {
|
|
167
|
+
const table = $pos.node(depth - 2);
|
|
168
|
+
const row = $pos.node(depth - 1);
|
|
169
|
+
const map = TableMap.get(table);
|
|
170
|
+
const cellPos = $pos.before(depth) - $pos.start(depth - 2);
|
|
171
|
+
const rect = map.findCell(cellPos);
|
|
172
|
+
const look = resolveTableLook(expectTableAttrs(table).look ?? void 0);
|
|
173
|
+
return tableCellStyleRegions({
|
|
174
|
+
look,
|
|
175
|
+
rowIndex: rect.top,
|
|
176
|
+
totalRows: map.height,
|
|
177
|
+
column: rect.left,
|
|
178
|
+
colspan: rect.right - rect.left,
|
|
179
|
+
totalColumns: map.width,
|
|
180
|
+
rowBand: tableRowBand(look, rect.top, map.height),
|
|
181
|
+
rowConditionalFormat: expectTableRowAttrs(row)._originalFormatting?.conditionalFormat,
|
|
182
|
+
cellConditionalFormat: expectTableCellAttrs($pos.node(depth))._originalFormatting?.conditionalFormat
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* The table-style paragraph overlay for a paragraph directly inside a table
|
|
187
|
+
* cell (or a block container in one), as the load path layers it.
|
|
188
|
+
*/
|
|
189
|
+
const cellParagraphOverlay = ($pos, resolver) => {
|
|
190
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
191
|
+
const ancestor = $pos.node(depth);
|
|
192
|
+
const role = ancestor.type.spec["tableRole"];
|
|
193
|
+
if (role === "cell" || role === "header_cell") {
|
|
194
|
+
const styleId = $pos.node(depth - 2).attrs["styleId"];
|
|
195
|
+
return tableCellParagraphOverlay(resolver, typeof styleId === "string" ? styleId : null, cellStyleRegions($pos, depth));
|
|
196
|
+
}
|
|
197
|
+
if (ancestor.type.name === "textBox") return;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Project the style cascade onto every paragraph the transactions touched
|
|
202
|
+
* that has not been projected yet. Returns the transaction to append, or null
|
|
203
|
+
* when every touched paragraph already reads as a reopened document would.
|
|
204
|
+
*/
|
|
205
|
+
const resolveEditedParagraphStyles = (transactions, state, resolver, numbering) => {
|
|
206
|
+
const ranges = changedRanges(transactions);
|
|
207
|
+
if (ranges.length === 0) return null;
|
|
208
|
+
const tr = state.tr;
|
|
209
|
+
const seen = /* @__PURE__ */ new Set();
|
|
210
|
+
const docSize = state.doc.content.size;
|
|
211
|
+
for (const [rangeFrom, rangeTo] of ranges) {
|
|
212
|
+
const from = Math.max(0, Math.min(rangeFrom, docSize));
|
|
213
|
+
const to = Math.max(from, Math.min(rangeTo, docSize));
|
|
214
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
215
|
+
if (node.type.name !== "paragraph") return !node.isTextblock;
|
|
216
|
+
if (seen.has(pos)) return false;
|
|
217
|
+
seen.add(pos);
|
|
218
|
+
if (node.attrs["_originalFormatting"] !== null) return false;
|
|
219
|
+
const patch = cascadePatch(node, resolver, cellParagraphOverlay(state.doc.resolve(pos), resolver), numbering);
|
|
220
|
+
if (patch) for (const [key, value] of Object.entries(patch)) {
|
|
221
|
+
const current = node.attrs[key];
|
|
222
|
+
if (current !== value && !(isUnset(current) && isUnset(value))) tr.setNodeAttribute(pos, key, value);
|
|
223
|
+
}
|
|
224
|
+
return false;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return tr.docChanged ? tr : null;
|
|
228
|
+
};
|
|
229
|
+
//#endregion
|
|
230
|
+
export { resolveEditedParagraphStyles };
|
|
@@ -24,11 +24,21 @@ declare function makeRevisionInfo(state: EditorState): {
|
|
|
24
24
|
* With track changes on, pasting over a non-empty text selection marks the
|
|
25
25
|
* replaced text as a tracked deletion and the pasted slice as a tracked
|
|
26
26
|
* insertion (so they read as one replacement), matching typing over a
|
|
27
|
-
* selection.
|
|
27
|
+
* selection. Select-all (an `AllSelection`) counts as a text selection over the
|
|
28
|
+
* whole document. Returns false for a collapsed cursor or another selection so the
|
|
28
29
|
* default paste + the `appendTransaction` catch-all marks a plain insertion
|
|
29
30
|
* (eigenpal/docx-editor#784).
|
|
30
31
|
*/
|
|
31
32
|
declare function handleSuggestionPaste(view: EditorView, slice: Slice, pluginState: SuggestionModeState): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* With track changes on, a paste into a table's cells (a cell selection, or a
|
|
35
|
+
* block of copied cells) replaces each cell's content the way a paste over a
|
|
36
|
+
* text selection does: the old content struck through, the pasted content
|
|
37
|
+
* after it as an insertion. When the pasted content is whole paragraphs, the
|
|
38
|
+
* last one ends the cell, so its paragraph mark is tracked as added too:
|
|
39
|
+
* rejecting then drops it and accepting joins the struck paragraphs into it.
|
|
40
|
+
*/
|
|
41
|
+
declare function handleSuggestionTableCellPaste(view: EditorView, slice: Slice, pluginState: SuggestionModeState): boolean;
|
|
32
42
|
/**
|
|
33
43
|
* Remove `from`..`to` of `tr.doc` as a suggestion: text the current author
|
|
34
44
|
* inserted is retracted, anything else is marked deleted. `false` when the
|
|
@@ -80,4 +90,4 @@ declare function setSuggestionMode(active: boolean, state: EditorState, dispatch
|
|
|
80
90
|
*/
|
|
81
91
|
declare function isSuggestionModeActive(state: EditorState): boolean;
|
|
82
92
|
//#endregion
|
|
83
|
-
export { SUGGESTED_TEXT_INPUT_META, SUGGESTION_BYPASS_META, SUGGESTION_META, createSuggestionModePlugin, deleteSelectionAsSuggestion, handleSuggestionEnter, handleSuggestionPaste, isSuggestionModeActive, makeRevisionInfo, paragraphBoundaryTarget, setSuggestionMode, suggestRangeDeletion, suggestionModeKey, toggleSuggestionMode };
|
|
93
|
+
export { SUGGESTED_TEXT_INPUT_META, SUGGESTION_BYPASS_META, SUGGESTION_META, createSuggestionModePlugin, deleteSelectionAsSuggestion, handleSuggestionEnter, handleSuggestionPaste, handleSuggestionTableCellPaste, isSuggestionModeActive, makeRevisionInfo, paragraphBoundaryTarget, setSuggestionMode, suggestRangeDeletion, suggestionModeKey, toggleSuggestionMode };
|