@sametalmdr/word-editor 0.2.0-alpha → 0.3.0-alpha
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/CHANGELOG.md +108 -70
- package/LICENSE +21 -21
- package/README.md +286 -247
- package/dist/canvas/box-clipboard.js +238 -238
- package/dist/canvas/box-selection.js +80 -80
- package/dist/canvas/canvas-editor.js +502 -502
- package/dist/canvas/controller.js +717 -717
- package/dist/canvas/geometry.js +131 -131
- package/dist/canvas/gesture.d.ts +0 -1
- package/dist/canvas/gesture.js +289 -289
- package/dist/canvas/handles.js +212 -212
- package/dist/canvas/menu.js +82 -82
- package/dist/canvas/mode-controller.js +81 -81
- package/dist/canvas/nudge.js +108 -108
- package/dist/canvas/overlay.js +149 -149
- package/dist/canvas/snap.js +132 -132
- package/dist/canvas/viewport.js +112 -112
- package/dist/canvas/z-order.js +171 -171
- package/dist/commands/alignment.js +150 -150
- package/dist/commands/box.js +272 -272
- package/dist/commands/clipboard.js +93 -93
- package/dist/commands/graphemes.js +112 -112
- package/dist/commands/marks.js +153 -153
- package/dist/commands/paragraph-props.js +176 -176
- package/dist/commands/size.js +368 -368
- package/dist/commands/text.js +291 -291
- package/dist/docx.d.ts +1 -0
- package/dist/docx.js +15 -13
- package/dist/editor/editing-host.js +434 -434
- package/dist/element.js +41 -41
- package/dist/fonts/OFL-Carlito.txt +94 -0
- package/dist/fonts/calibri-metrics.d.ts +27 -0
- package/dist/fonts/calibri-metrics.js +88 -0
- package/dist/history/history.js +433 -433
- package/dist/index.js +63 -63
- package/dist/input/beforeinput.js +224 -224
- package/dist/input/clipboard.js +107 -107
- package/dist/input/composition.js +341 -341
- package/dist/input/keymap.js +54 -54
- package/dist/io/ooxml/custgeom.js +72 -72
- package/dist/io/ooxml/drawingml.js +232 -232
- package/dist/io/ooxml/edits.js +67 -67
- package/dist/io/ooxml/export-splice.js +880 -880
- package/dist/io/ooxml/export.js +365 -365
- package/dist/io/ooxml/fill.d.ts +93 -8
- package/dist/io/ooxml/fill.js +618 -562
- package/dist/io/ooxml/fit.d.ts +252 -0
- package/dist/io/ooxml/fit.js +598 -0
- package/dist/io/ooxml/import-gate.js +200 -200
- package/dist/io/ooxml/import.js +691 -691
- package/dist/io/ooxml/inflate.js +126 -126
- package/dist/io/ooxml/media.js +87 -87
- package/dist/io/ooxml/ns.d.ts +2 -0
- package/dist/io/ooxml/ns.js +26 -21
- package/dist/io/ooxml/numbering.js +290 -290
- package/dist/io/ooxml/opc-write.js +171 -171
- package/dist/io/ooxml/provenance.js +93 -93
- package/dist/io/ooxml/recipe.js +708 -708
- package/dist/io/ooxml/relationships.js +59 -59
- package/dist/io/ooxml/run-fonts.d.ts +89 -0
- package/dist/io/ooxml/run-fonts.js +378 -0
- package/dist/io/ooxml/slots.d.ts +4 -0
- package/dist/io/ooxml/slots.js +582 -581
- package/dist/io/ooxml/styles-resolve.js +257 -257
- package/dist/io/ooxml/units.js +43 -43
- package/dist/io/ooxml/value.js +120 -120
- package/dist/io/ooxml/xml-scan.js +616 -616
- package/dist/io/ooxml/zip-container.js +228 -228
- package/dist/io/ooxml/zip-reject.js +106 -106
- package/dist/measure/placement.js +83 -83
- package/dist/measure/report.js +75 -75
- package/dist/model/ids.js +70 -70
- package/dist/model/normalize.js +146 -146
- package/dist/model/position.js +283 -283
- package/dist/model/transaction.js +209 -209
- package/dist/platform/capabilities.js +25 -25
- package/dist/react/index.js +21 -21
- package/dist/selection/controller.js +315 -315
- package/dist/selection/dom-map.js +334 -334
- package/dist/state/editor-state.js +109 -109
- package/dist/styles.css +66 -66
- package/package.json +94 -93
package/dist/io/ooxml/value.js
CHANGED
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
// The fill engine's value policy (FR2, ADR-0037 Karar 5; ADR-0039). Pure.
|
|
2
|
-
//
|
|
3
|
-
// A value is a string, or null (empty). It may not hold a tab, a line break —
|
|
4
|
-
// except LF in a tag the caller names multi-line (ADR-0039) — nor any
|
|
5
|
-
// character XML 1.0 forbids or the engine refuses anyway. CR, U+2028 and
|
|
6
|
-
// U+2029 stay refused even in a multi-line tag: the engine never changes a
|
|
7
|
-
// value silently, so a CRLF the caller did not normalize is an error, not a
|
|
8
|
-
// rewrite. Re-scanning the output would NOT catch these: U+FFFE is valid
|
|
9
|
-
// UTF-8, and TextEncoder silently turns a lone surrogate into U+FFFD, so the
|
|
10
|
-
// check has to happen here.
|
|
11
|
-
//
|
|
12
|
-
// An issue names the code, the first offending index, its code point and how
|
|
13
|
-
// many such characters there are — never the value itself (KVKK: a report or
|
|
14
|
-
// an error message must not carry personal data into a log).
|
|
15
|
-
|
|
16
|
-
const encoder = new TextEncoder();
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {object} ValueIssue
|
|
20
|
-
* @property {string} code
|
|
21
|
-
* @property {number} [index] UTF-16 index of the first offending character
|
|
22
|
-
* @property {number} [codePoint]
|
|
23
|
-
* @property {number} [count] how many characters of this kind the value holds
|
|
24
|
-
* @property {string} [type] for VALUE_NOT_STRING: the value's type
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @typedef {object} ValueCheck
|
|
29
|
-
* @property {ValueIssue[]} errors
|
|
30
|
-
* @property {ValueIssue[]} warnings
|
|
31
|
-
* @property {boolean} empty null, "" or whitespace only — allowed, and reported
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Not an XML 1.0 Char, or one the engine refuses anyway: C0 controls (tab,
|
|
36
|
-
* LF and CR are classified before this), DEL and the C1 controls, a lone
|
|
37
|
-
* surrogate (a valid pair is combined before this), and the noncharacters —
|
|
38
|
-
* U+FDD0–U+FDEF and the last two code points of every plane (U+FFFE, U+FFFF,
|
|
39
|
-
* U+1FFFE …).
|
|
40
|
-
* @param {number} cp
|
|
41
|
-
* @returns {boolean}
|
|
42
|
-
*/
|
|
43
|
-
function isIllegalCodePoint(cp) {
|
|
44
|
-
return (
|
|
45
|
-
cp < 0x20 ||
|
|
46
|
-
(cp >= 0x7f && cp <= 0x9f) ||
|
|
47
|
-
(cp >= 0xd800 && cp <= 0xdfff) ||
|
|
48
|
-
(cp >= 0xfdd0 && cp <= 0xfdef) ||
|
|
49
|
-
(cp & 0xfffe) === 0xfffe
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @param {number} cp
|
|
55
|
-
* @param {boolean} multiline the tag is named in the fill's `multiline` option
|
|
56
|
-
* @returns {string | null}
|
|
57
|
-
*/
|
|
58
|
-
function classify(cp, multiline) {
|
|
59
|
-
if (cp === 0x0a) return multiline ? null : "VALUE_LINE_BREAK";
|
|
60
|
-
if (cp === 0x0d || cp === 0x2028 || cp === 0x2029) return "VALUE_LINE_BREAK";
|
|
61
|
-
if (cp === 0x09) return "VALUE_TAB";
|
|
62
|
-
if (isIllegalCodePoint(cp)) return "VALUE_ILLEGAL_CHAR";
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* @param {unknown} value
|
|
68
|
-
* @returns {string}
|
|
69
|
-
*/
|
|
70
|
-
function typeName(value) {
|
|
71
|
-
if (Array.isArray(value)) return "array";
|
|
72
|
-
return typeof value;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Checks one value the data supplied for a tag. The caller has already
|
|
77
|
-
* decided presence: an absent key or `undefined` is MISSING_VALUE there.
|
|
78
|
-
* A value of line breaks only is empty, like whitespace (`trim`).
|
|
79
|
-
* @param {unknown} value
|
|
80
|
-
* @param {{multiline?: boolean}} [options] `multiline`: LF is a line break, not an error (ADR-0039)
|
|
81
|
-
* @returns {ValueCheck}
|
|
82
|
-
*/
|
|
83
|
-
export function checkValue(value, { multiline = false } = {}) {
|
|
84
|
-
if (value === null) return { errors: [], warnings: [], empty: true };
|
|
85
|
-
if (typeof value !== "string") {
|
|
86
|
-
return { errors: [{ code: "VALUE_NOT_STRING", type: typeName(value) }], warnings: [], empty: false };
|
|
87
|
-
}
|
|
88
|
-
/** @type {Map<string, ValueIssue>} */
|
|
89
|
-
const found = new Map();
|
|
90
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
91
|
-
const unit = value.charCodeAt(i);
|
|
92
|
-
let cp = unit;
|
|
93
|
-
if (unit >= 0xd800 && unit <= 0xdbff && i + 1 < value.length) {
|
|
94
|
-
const next = value.charCodeAt(i + 1);
|
|
95
|
-
if (next >= 0xdc00 && next <= 0xdfff) cp = (unit - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000;
|
|
96
|
-
}
|
|
97
|
-
const code = classify(cp, multiline);
|
|
98
|
-
if (code !== null) {
|
|
99
|
-
const issue = found.get(code);
|
|
100
|
-
if (issue === undefined) found.set(code, { code, index: i, codePoint: cp, count: 1 });
|
|
101
|
-
else issue.count = /** @type {number} */ (issue.count) + 1;
|
|
102
|
-
}
|
|
103
|
-
if (cp > 0xffff) i += 1;
|
|
104
|
-
}
|
|
105
|
-
/** @type {ValueIssue[]} */
|
|
106
|
-
const warnings = [];
|
|
107
|
-
if (value.normalize("NFC") !== value) warnings.push({ code: "VALUE_NOT_NFC" });
|
|
108
|
-
return { errors: [...found.values()], warnings, empty: value.trim() === "" };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* The bytes that replace a tag's text: `&`, `<` and `>` escaped (escaping
|
|
113
|
-
* `>` also makes `]]>` impossible), UTF-8 encoded. Call only on a value
|
|
114
|
-
* `checkValue` accepted.
|
|
115
|
-
* @param {string} value
|
|
116
|
-
* @returns {Uint8Array}
|
|
117
|
-
*/
|
|
118
|
-
export function encodeTextValue(value) {
|
|
119
|
-
return encoder.encode(value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"));
|
|
120
|
-
}
|
|
1
|
+
// The fill engine's value policy (FR2, ADR-0037 Karar 5; ADR-0039). Pure.
|
|
2
|
+
//
|
|
3
|
+
// A value is a string, or null (empty). It may not hold a tab, a line break —
|
|
4
|
+
// except LF in a tag the caller names multi-line (ADR-0039) — nor any
|
|
5
|
+
// character XML 1.0 forbids or the engine refuses anyway. CR, U+2028 and
|
|
6
|
+
// U+2029 stay refused even in a multi-line tag: the engine never changes a
|
|
7
|
+
// value silently, so a CRLF the caller did not normalize is an error, not a
|
|
8
|
+
// rewrite. Re-scanning the output would NOT catch these: U+FFFE is valid
|
|
9
|
+
// UTF-8, and TextEncoder silently turns a lone surrogate into U+FFFD, so the
|
|
10
|
+
// check has to happen here.
|
|
11
|
+
//
|
|
12
|
+
// An issue names the code, the first offending index, its code point and how
|
|
13
|
+
// many such characters there are — never the value itself (KVKK: a report or
|
|
14
|
+
// an error message must not carry personal data into a log).
|
|
15
|
+
|
|
16
|
+
const encoder = new TextEncoder();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {object} ValueIssue
|
|
20
|
+
* @property {string} code
|
|
21
|
+
* @property {number} [index] UTF-16 index of the first offending character
|
|
22
|
+
* @property {number} [codePoint]
|
|
23
|
+
* @property {number} [count] how many characters of this kind the value holds
|
|
24
|
+
* @property {string} [type] for VALUE_NOT_STRING: the value's type
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {object} ValueCheck
|
|
29
|
+
* @property {ValueIssue[]} errors
|
|
30
|
+
* @property {ValueIssue[]} warnings
|
|
31
|
+
* @property {boolean} empty null, "" or whitespace only — allowed, and reported
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Not an XML 1.0 Char, or one the engine refuses anyway: C0 controls (tab,
|
|
36
|
+
* LF and CR are classified before this), DEL and the C1 controls, a lone
|
|
37
|
+
* surrogate (a valid pair is combined before this), and the noncharacters —
|
|
38
|
+
* U+FDD0–U+FDEF and the last two code points of every plane (U+FFFE, U+FFFF,
|
|
39
|
+
* U+1FFFE …).
|
|
40
|
+
* @param {number} cp
|
|
41
|
+
* @returns {boolean}
|
|
42
|
+
*/
|
|
43
|
+
function isIllegalCodePoint(cp) {
|
|
44
|
+
return (
|
|
45
|
+
cp < 0x20 ||
|
|
46
|
+
(cp >= 0x7f && cp <= 0x9f) ||
|
|
47
|
+
(cp >= 0xd800 && cp <= 0xdfff) ||
|
|
48
|
+
(cp >= 0xfdd0 && cp <= 0xfdef) ||
|
|
49
|
+
(cp & 0xfffe) === 0xfffe
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {number} cp
|
|
55
|
+
* @param {boolean} multiline the tag is named in the fill's `multiline` option
|
|
56
|
+
* @returns {string | null}
|
|
57
|
+
*/
|
|
58
|
+
function classify(cp, multiline) {
|
|
59
|
+
if (cp === 0x0a) return multiline ? null : "VALUE_LINE_BREAK";
|
|
60
|
+
if (cp === 0x0d || cp === 0x2028 || cp === 0x2029) return "VALUE_LINE_BREAK";
|
|
61
|
+
if (cp === 0x09) return "VALUE_TAB";
|
|
62
|
+
if (isIllegalCodePoint(cp)) return "VALUE_ILLEGAL_CHAR";
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {unknown} value
|
|
68
|
+
* @returns {string}
|
|
69
|
+
*/
|
|
70
|
+
function typeName(value) {
|
|
71
|
+
if (Array.isArray(value)) return "array";
|
|
72
|
+
return typeof value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Checks one value the data supplied for a tag. The caller has already
|
|
77
|
+
* decided presence: an absent key or `undefined` is MISSING_VALUE there.
|
|
78
|
+
* A value of line breaks only is empty, like whitespace (`trim`).
|
|
79
|
+
* @param {unknown} value
|
|
80
|
+
* @param {{multiline?: boolean}} [options] `multiline`: LF is a line break, not an error (ADR-0039)
|
|
81
|
+
* @returns {ValueCheck}
|
|
82
|
+
*/
|
|
83
|
+
export function checkValue(value, { multiline = false } = {}) {
|
|
84
|
+
if (value === null) return { errors: [], warnings: [], empty: true };
|
|
85
|
+
if (typeof value !== "string") {
|
|
86
|
+
return { errors: [{ code: "VALUE_NOT_STRING", type: typeName(value) }], warnings: [], empty: false };
|
|
87
|
+
}
|
|
88
|
+
/** @type {Map<string, ValueIssue>} */
|
|
89
|
+
const found = new Map();
|
|
90
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
91
|
+
const unit = value.charCodeAt(i);
|
|
92
|
+
let cp = unit;
|
|
93
|
+
if (unit >= 0xd800 && unit <= 0xdbff && i + 1 < value.length) {
|
|
94
|
+
const next = value.charCodeAt(i + 1);
|
|
95
|
+
if (next >= 0xdc00 && next <= 0xdfff) cp = (unit - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000;
|
|
96
|
+
}
|
|
97
|
+
const code = classify(cp, multiline);
|
|
98
|
+
if (code !== null) {
|
|
99
|
+
const issue = found.get(code);
|
|
100
|
+
if (issue === undefined) found.set(code, { code, index: i, codePoint: cp, count: 1 });
|
|
101
|
+
else issue.count = /** @type {number} */ (issue.count) + 1;
|
|
102
|
+
}
|
|
103
|
+
if (cp > 0xffff) i += 1;
|
|
104
|
+
}
|
|
105
|
+
/** @type {ValueIssue[]} */
|
|
106
|
+
const warnings = [];
|
|
107
|
+
if (value.normalize("NFC") !== value) warnings.push({ code: "VALUE_NOT_NFC" });
|
|
108
|
+
return { errors: [...found.values()], warnings, empty: value.trim() === "" };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The bytes that replace a tag's text: `&`, `<` and `>` escaped (escaping
|
|
113
|
+
* `>` also makes `]]>` impossible), UTF-8 encoded. Call only on a value
|
|
114
|
+
* `checkValue` accepted.
|
|
115
|
+
* @param {string} value
|
|
116
|
+
* @returns {Uint8Array}
|
|
117
|
+
*/
|
|
118
|
+
export function encodeTextValue(value) {
|
|
119
|
+
return encoder.encode(value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"));
|
|
120
|
+
}
|