@limetech/lime-elements 37.56.0 → 37.56.2
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 +16 -0
- package/dist/cjs/limel-dialog.cjs.entry.js +1 -1
- package/dist/cjs/limel-dialog.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +315 -247
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-snackbar.cjs.entry.js +1 -0
- package/dist/cjs/limel-snackbar.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-text-editor.cjs.entry.js +2 -2
- package/dist/cjs/limel-text-editor.cjs.entry.js.map +1 -1
- package/dist/collection/components/dialog/dialog.css +1 -2
- package/dist/collection/components/snackbar/snackbar.js +1 -0
- package/dist/collection/components/snackbar/snackbar.js.map +1 -1
- package/dist/collection/components/text-editor/text-editor.css +6 -13
- package/dist/collection/components/text-editor/text-editor.js +1 -1
- package/dist/collection/components/text-editor/text-editor.js.map +1 -1
- package/dist/esm/limel-dialog.entry.js +1 -1
- package/dist/esm/limel-dialog.entry.js.map +1 -1
- package/dist/esm/limel-prosemirror-adapter.entry.js +315 -247
- package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
- package/dist/esm/limel-snackbar.entry.js +1 -0
- package/dist/esm/limel-snackbar.entry.js.map +1 -1
- package/dist/esm/limel-text-editor.entry.js +2 -2
- package/dist/esm/limel-text-editor.entry.js.map +1 -1
- package/dist/lime-elements/lime-elements.esm.js +1 -1
- package/dist/lime-elements/p-232dd438.entry.js +2 -0
- package/dist/lime-elements/p-232dd438.entry.js.map +1 -0
- package/dist/lime-elements/p-4ae6f448.entry.js +2 -0
- package/dist/lime-elements/p-4ae6f448.entry.js.map +1 -0
- package/dist/lime-elements/{p-385f680b.entry.js → p-84c9482c.entry.js} +2 -2
- package/dist/lime-elements/{p-385f680b.entry.js.map → p-84c9482c.entry.js.map} +1 -1
- package/dist/lime-elements/{p-adf6cbe8.entry.js → p-d2077011.entry.js} +2 -2
- package/dist/lime-elements/{p-adf6cbe8.entry.js.map → p-d2077011.entry.js.map} +1 -1
- package/package.json +2 -2
- package/dist/lime-elements/p-200b7739.entry.js +0 -2
- package/dist/lime-elements/p-200b7739.entry.js.map +0 -1
- package/dist/lime-elements/p-a82054c2.entry.js +0 -2
- package/dist/lime-elements/p-a82054c2.entry.js.map +0 -1
|
@@ -1029,7 +1029,7 @@ class Fragment {
|
|
|
1029
1029
|
/**
|
|
1030
1030
|
Find the index and inner offset corresponding to a given relative
|
|
1031
1031
|
position in this fragment. The result object will be reused
|
|
1032
|
-
(overwritten) the next time the function is called.
|
|
1032
|
+
(overwritten) the next time the function is called. @internal
|
|
1033
1033
|
*/
|
|
1034
1034
|
findIndex(pos, round = -1) {
|
|
1035
1035
|
if (pos == 0)
|
|
@@ -1262,7 +1262,9 @@ class Mark {
|
|
|
1262
1262
|
let type = schema.marks[json.type];
|
|
1263
1263
|
if (!type)
|
|
1264
1264
|
throw new RangeError(`There is no mark type ${json.type} in this schema`);
|
|
1265
|
-
|
|
1265
|
+
let mark = type.create(json.attrs);
|
|
1266
|
+
type.checkAttrs(mark.attrs);
|
|
1267
|
+
return mark;
|
|
1266
1268
|
}
|
|
1267
1269
|
/**
|
|
1268
1270
|
Test whether two sets of marks are identical.
|
|
@@ -1820,17 +1822,29 @@ class ResolvedPos {
|
|
|
1820
1822
|
@internal
|
|
1821
1823
|
*/
|
|
1822
1824
|
static resolveCached(doc, pos) {
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1825
|
+
let cache = resolveCache.get(doc);
|
|
1826
|
+
if (cache) {
|
|
1827
|
+
for (let i = 0; i < cache.elts.length; i++) {
|
|
1828
|
+
let elt = cache.elts[i];
|
|
1829
|
+
if (elt.pos == pos)
|
|
1830
|
+
return elt;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
else {
|
|
1834
|
+
resolveCache.set(doc, cache = new ResolveCache);
|
|
1827
1835
|
}
|
|
1828
|
-
let result =
|
|
1829
|
-
|
|
1836
|
+
let result = cache.elts[cache.i] = ResolvedPos.resolve(doc, pos);
|
|
1837
|
+
cache.i = (cache.i + 1) % resolveCacheSize;
|
|
1830
1838
|
return result;
|
|
1831
1839
|
}
|
|
1832
1840
|
}
|
|
1833
|
-
|
|
1841
|
+
class ResolveCache {
|
|
1842
|
+
constructor() {
|
|
1843
|
+
this.elts = [];
|
|
1844
|
+
this.i = 0;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
const resolveCacheSize = 12, resolveCache = new WeakMap();
|
|
1834
1848
|
/**
|
|
1835
1849
|
Represents a flat range of content, i.e. one that starts and
|
|
1836
1850
|
ends in the same node.
|
|
@@ -2230,13 +2244,17 @@ class Node$1 {
|
|
|
2230
2244
|
}
|
|
2231
2245
|
/**
|
|
2232
2246
|
Check whether this node and its descendants conform to the
|
|
2233
|
-
schema, and raise
|
|
2247
|
+
schema, and raise an exception when they do not.
|
|
2234
2248
|
*/
|
|
2235
2249
|
check() {
|
|
2236
2250
|
this.type.checkContent(this.content);
|
|
2251
|
+
this.type.checkAttrs(this.attrs);
|
|
2237
2252
|
let copy = Mark.none;
|
|
2238
|
-
for (let i = 0; i < this.marks.length; i++)
|
|
2239
|
-
|
|
2253
|
+
for (let i = 0; i < this.marks.length; i++) {
|
|
2254
|
+
let mark = this.marks[i];
|
|
2255
|
+
mark.type.checkAttrs(mark.attrs);
|
|
2256
|
+
copy = mark.addToSet(copy);
|
|
2257
|
+
}
|
|
2240
2258
|
if (!Mark.sameSet(copy, this.marks))
|
|
2241
2259
|
throw new RangeError(`Invalid collection of marks for node ${this.type.name}: ${this.marks.map(m => m.type.name)}`);
|
|
2242
2260
|
this.content.forEach(node => node.check());
|
|
@@ -2262,7 +2280,7 @@ class Node$1 {
|
|
|
2262
2280
|
static fromJSON(schema, json) {
|
|
2263
2281
|
if (!json)
|
|
2264
2282
|
throw new RangeError("Invalid input for Node.fromJSON");
|
|
2265
|
-
let marks =
|
|
2283
|
+
let marks = undefined;
|
|
2266
2284
|
if (json.marks) {
|
|
2267
2285
|
if (!Array.isArray(json.marks))
|
|
2268
2286
|
throw new RangeError("Invalid mark data for Node.fromJSON");
|
|
@@ -2274,7 +2292,9 @@ class Node$1 {
|
|
|
2274
2292
|
return schema.text(json.text, marks);
|
|
2275
2293
|
}
|
|
2276
2294
|
let content = Fragment.fromJSON(schema, json.content);
|
|
2277
|
-
|
|
2295
|
+
let node = schema.nodeType(json.type).create(json.attrs, content, marks);
|
|
2296
|
+
node.type.checkAttrs(node.attrs);
|
|
2297
|
+
return node;
|
|
2278
2298
|
}
|
|
2279
2299
|
}
|
|
2280
2300
|
Node$1.prototype.text = undefined;
|
|
@@ -2791,11 +2811,21 @@ function computeAttrs(attrs, value) {
|
|
|
2791
2811
|
}
|
|
2792
2812
|
return built;
|
|
2793
2813
|
}
|
|
2794
|
-
function
|
|
2814
|
+
function checkAttrs(attrs, values, type, name) {
|
|
2815
|
+
for (let name in values)
|
|
2816
|
+
if (!(name in attrs))
|
|
2817
|
+
throw new RangeError(`Unsupported attribute ${name} for ${type} of type ${name}`);
|
|
2818
|
+
for (let name in attrs) {
|
|
2819
|
+
let attr = attrs[name];
|
|
2820
|
+
if (attr.validate)
|
|
2821
|
+
attr.validate(values[name]);
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
function initAttrs(typeName, attrs) {
|
|
2795
2825
|
let result = Object.create(null);
|
|
2796
2826
|
if (attrs)
|
|
2797
2827
|
for (let name in attrs)
|
|
2798
|
-
result[name] = new Attribute(attrs[name]);
|
|
2828
|
+
result[name] = new Attribute(typeName, name, attrs[name]);
|
|
2799
2829
|
return result;
|
|
2800
2830
|
}
|
|
2801
2831
|
/**
|
|
@@ -2830,7 +2860,7 @@ class NodeType$1 {
|
|
|
2830
2860
|
*/
|
|
2831
2861
|
this.markSet = null;
|
|
2832
2862
|
this.groups = spec.group ? spec.group.split(" ") : [];
|
|
2833
|
-
this.attrs = initAttrs(spec.attrs);
|
|
2863
|
+
this.attrs = initAttrs(name, spec.attrs);
|
|
2834
2864
|
this.defaultAttrs = defaultAttrs(this.attrs);
|
|
2835
2865
|
this.contentMatch = null;
|
|
2836
2866
|
this.inlineContent = null;
|
|
@@ -2934,7 +2964,7 @@ class NodeType$1 {
|
|
|
2934
2964
|
}
|
|
2935
2965
|
/**
|
|
2936
2966
|
Returns true if the given fragment is valid content for this node
|
|
2937
|
-
type
|
|
2967
|
+
type.
|
|
2938
2968
|
*/
|
|
2939
2969
|
validContent(content) {
|
|
2940
2970
|
let result = this.contentMatch.matchFragment(content);
|
|
@@ -2955,6 +2985,12 @@ class NodeType$1 {
|
|
|
2955
2985
|
throw new RangeError(`Invalid content for node ${this.name}: ${content.toString().slice(0, 50)}`);
|
|
2956
2986
|
}
|
|
2957
2987
|
/**
|
|
2988
|
+
@internal
|
|
2989
|
+
*/
|
|
2990
|
+
checkAttrs(attrs) {
|
|
2991
|
+
checkAttrs(this.attrs, attrs, "node");
|
|
2992
|
+
}
|
|
2993
|
+
/**
|
|
2958
2994
|
Check whether the given mark type is allowed in this node.
|
|
2959
2995
|
*/
|
|
2960
2996
|
allowsMarkType(markType) {
|
|
@@ -3005,11 +3041,20 @@ class NodeType$1 {
|
|
|
3005
3041
|
return result;
|
|
3006
3042
|
}
|
|
3007
3043
|
}
|
|
3044
|
+
function validateType(typeName, attrName, type) {
|
|
3045
|
+
let types = type.split("|");
|
|
3046
|
+
return (value) => {
|
|
3047
|
+
let name = value === null ? "null" : typeof value;
|
|
3048
|
+
if (types.indexOf(name) < 0)
|
|
3049
|
+
throw new RangeError(`Expected value of type ${types} for attribute ${attrName} on type ${typeName}, got ${name}`);
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3008
3052
|
// Attribute descriptors
|
|
3009
3053
|
class Attribute {
|
|
3010
|
-
constructor(options) {
|
|
3054
|
+
constructor(typeName, attrName, options) {
|
|
3011
3055
|
this.hasDefault = Object.prototype.hasOwnProperty.call(options, "default");
|
|
3012
3056
|
this.default = options.default;
|
|
3057
|
+
this.validate = typeof options.validate == "string" ? validateType(typeName, attrName, options.validate) : options.validate;
|
|
3013
3058
|
}
|
|
3014
3059
|
get isRequired() {
|
|
3015
3060
|
return !this.hasDefault;
|
|
@@ -3047,7 +3092,7 @@ class MarkType {
|
|
|
3047
3092
|
this.rank = rank;
|
|
3048
3093
|
this.schema = schema;
|
|
3049
3094
|
this.spec = spec;
|
|
3050
|
-
this.attrs = initAttrs(spec.attrs);
|
|
3095
|
+
this.attrs = initAttrs(name, spec.attrs);
|
|
3051
3096
|
this.excluded = null;
|
|
3052
3097
|
let defaults = defaultAttrs(this.attrs);
|
|
3053
3098
|
this.instance = defaults ? new Mark(this, defaults) : null;
|
|
@@ -3091,6 +3136,12 @@ class MarkType {
|
|
|
3091
3136
|
return set[i];
|
|
3092
3137
|
}
|
|
3093
3138
|
/**
|
|
3139
|
+
@internal
|
|
3140
|
+
*/
|
|
3141
|
+
checkAttrs(attrs) {
|
|
3142
|
+
checkAttrs(this.attrs, attrs, "mark");
|
|
3143
|
+
}
|
|
3144
|
+
/**
|
|
3094
3145
|
Queries whether a given mark type is
|
|
3095
3146
|
[excluded](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) by this one.
|
|
3096
3147
|
*/
|
|
@@ -3112,6 +3163,12 @@ class Schema {
|
|
|
3112
3163
|
Construct a schema from a schema [specification](https://prosemirror.net/docs/ref/#model.SchemaSpec).
|
|
3113
3164
|
*/
|
|
3114
3165
|
constructor(spec) {
|
|
3166
|
+
/**
|
|
3167
|
+
The [linebreak
|
|
3168
|
+
replacement](https://prosemirror.net/docs/ref/#model.NodeSpec.linebreakReplacement) node defined
|
|
3169
|
+
in this schema, if any.
|
|
3170
|
+
*/
|
|
3171
|
+
this.linebreakReplacement = null;
|
|
3115
3172
|
/**
|
|
3116
3173
|
An object for storing whatever values modules may want to
|
|
3117
3174
|
compute and cache per schema. (If you want to store something
|
|
@@ -3133,6 +3190,13 @@ class Schema {
|
|
|
3133
3190
|
type.contentMatch = contentExprCache[contentExpr] ||
|
|
3134
3191
|
(contentExprCache[contentExpr] = ContentMatch.parse(contentExpr, this.nodes));
|
|
3135
3192
|
type.inlineContent = type.contentMatch.inlineContent;
|
|
3193
|
+
if (type.spec.linebreakReplacement) {
|
|
3194
|
+
if (this.linebreakReplacement)
|
|
3195
|
+
throw new RangeError("Multiple linebreak nodes defined");
|
|
3196
|
+
if (!type.isInline || !type.isLeaf)
|
|
3197
|
+
throw new RangeError("Linebreak replacement nodes must be inline leaf nodes");
|
|
3198
|
+
this.linebreakReplacement = type;
|
|
3199
|
+
}
|
|
3136
3200
|
type.markSet = markExpr == "_" ? null :
|
|
3137
3201
|
markExpr ? gatherMarks(this, markExpr.split(" ")) :
|
|
3138
3202
|
markExpr == "" || !type.inlineContent ? [] : null;
|
|
@@ -3221,6 +3285,8 @@ function gatherMarks(schema, marks) {
|
|
|
3221
3285
|
return found;
|
|
3222
3286
|
}
|
|
3223
3287
|
|
|
3288
|
+
function isTagRule(rule) { return rule.tag != null; }
|
|
3289
|
+
function isStyleRule(rule) { return rule.style != null; }
|
|
3224
3290
|
/**
|
|
3225
3291
|
A DOM parser represents a strategy for parsing DOM content into a
|
|
3226
3292
|
ProseMirror document conforming to a given schema. Its behavior is
|
|
@@ -3251,11 +3317,17 @@ class DOMParser {
|
|
|
3251
3317
|
@internal
|
|
3252
3318
|
*/
|
|
3253
3319
|
this.styles = [];
|
|
3320
|
+
let matchedStyles = this.matchedStyles = [];
|
|
3254
3321
|
rules.forEach(rule => {
|
|
3255
|
-
if (rule
|
|
3322
|
+
if (isTagRule(rule)) {
|
|
3256
3323
|
this.tags.push(rule);
|
|
3257
|
-
|
|
3324
|
+
}
|
|
3325
|
+
else if (isStyleRule(rule)) {
|
|
3326
|
+
let prop = /[^=]*/.exec(rule.style)[0];
|
|
3327
|
+
if (matchedStyles.indexOf(prop) < 0)
|
|
3328
|
+
matchedStyles.push(prop);
|
|
3258
3329
|
this.styles.push(rule);
|
|
3330
|
+
}
|
|
3259
3331
|
});
|
|
3260
3332
|
// Only normalize list elements when lists in the schema can't directly contain themselves
|
|
3261
3333
|
this.normalizeLists = !this.tags.some(r => {
|
|
@@ -3270,7 +3342,7 @@ class DOMParser {
|
|
|
3270
3342
|
*/
|
|
3271
3343
|
parse(dom, options = {}) {
|
|
3272
3344
|
let context = new ParseContext(this, options, false);
|
|
3273
|
-
context.addAll(dom, options.from, options.to);
|
|
3345
|
+
context.addAll(dom, Mark.none, options.from, options.to);
|
|
3274
3346
|
return context.finish();
|
|
3275
3347
|
}
|
|
3276
3348
|
/**
|
|
@@ -3283,7 +3355,7 @@ class DOMParser {
|
|
|
3283
3355
|
*/
|
|
3284
3356
|
parseSlice(dom, options = {}) {
|
|
3285
3357
|
let context = new ParseContext(this, options, true);
|
|
3286
|
-
context.addAll(dom, options.from, options.to);
|
|
3358
|
+
context.addAll(dom, Mark.none, options.from, options.to);
|
|
3287
3359
|
return Slice.maxOpen(context.finish());
|
|
3288
3360
|
}
|
|
3289
3361
|
/**
|
|
@@ -3392,22 +3464,15 @@ function wsOptionsFor(type, preserveWhitespace, base) {
|
|
|
3392
3464
|
return type && type.whitespace == "pre" ? OPT_PRESERVE_WS | OPT_PRESERVE_WS_FULL : base & ~OPT_OPEN_LEFT;
|
|
3393
3465
|
}
|
|
3394
3466
|
class NodeContext {
|
|
3395
|
-
constructor(type, attrs,
|
|
3396
|
-
// Marks applied to this node itself
|
|
3397
|
-
marks,
|
|
3398
|
-
// Marks that can't apply here, but will be used in children if possible
|
|
3399
|
-
pendingMarks, solid, match, options) {
|
|
3467
|
+
constructor(type, attrs, marks, solid, match, options) {
|
|
3400
3468
|
this.type = type;
|
|
3401
3469
|
this.attrs = attrs;
|
|
3402
3470
|
this.marks = marks;
|
|
3403
|
-
this.pendingMarks = pendingMarks;
|
|
3404
3471
|
this.solid = solid;
|
|
3405
3472
|
this.options = options;
|
|
3406
3473
|
this.content = [];
|
|
3407
3474
|
// Marks applied to the node's children
|
|
3408
3475
|
this.activeMarks = Mark.none;
|
|
3409
|
-
// Nested Marks with same type
|
|
3410
|
-
this.stashMarks = [];
|
|
3411
3476
|
this.match = match || (options & OPT_OPEN_LEFT ? null : type.contentMatch);
|
|
3412
3477
|
}
|
|
3413
3478
|
findWrapping(node) {
|
|
@@ -3447,21 +3512,6 @@ class NodeContext {
|
|
|
3447
3512
|
content = content.append(this.match.fillBefore(Fragment.empty, true));
|
|
3448
3513
|
return this.type ? this.type.create(this.attrs, content, this.marks) : content;
|
|
3449
3514
|
}
|
|
3450
|
-
popFromStashMark(mark) {
|
|
3451
|
-
for (let i = this.stashMarks.length - 1; i >= 0; i--)
|
|
3452
|
-
if (mark.eq(this.stashMarks[i]))
|
|
3453
|
-
return this.stashMarks.splice(i, 1)[0];
|
|
3454
|
-
}
|
|
3455
|
-
applyPending(nextType) {
|
|
3456
|
-
for (let i = 0, pending = this.pendingMarks; i < pending.length; i++) {
|
|
3457
|
-
let mark = pending[i];
|
|
3458
|
-
if ((this.type ? this.type.allowsMarkType(mark.type) : markMayApply(mark.type, nextType)) &&
|
|
3459
|
-
!mark.isInSet(this.activeMarks)) {
|
|
3460
|
-
this.activeMarks = mark.addToSet(this.activeMarks);
|
|
3461
|
-
this.pendingMarks = mark.removeFromSet(this.pendingMarks);
|
|
3462
|
-
}
|
|
3463
|
-
}
|
|
3464
|
-
}
|
|
3465
3515
|
inlineContext(node) {
|
|
3466
3516
|
if (this.type)
|
|
3467
3517
|
return this.type.inlineContent;
|
|
@@ -3483,11 +3533,11 @@ class ParseContext {
|
|
|
3483
3533
|
let topNode = options.topNode, topContext;
|
|
3484
3534
|
let topOptions = wsOptionsFor(null, options.preserveWhitespace, 0) | (isOpen ? OPT_OPEN_LEFT : 0);
|
|
3485
3535
|
if (topNode)
|
|
3486
|
-
topContext = new NodeContext(topNode.type, topNode.attrs, Mark.none,
|
|
3536
|
+
topContext = new NodeContext(topNode.type, topNode.attrs, Mark.none, true, options.topMatch || topNode.type.contentMatch, topOptions);
|
|
3487
3537
|
else if (isOpen)
|
|
3488
|
-
topContext = new NodeContext(null, null, Mark.none,
|
|
3538
|
+
topContext = new NodeContext(null, null, Mark.none, true, null, topOptions);
|
|
3489
3539
|
else
|
|
3490
|
-
topContext = new NodeContext(parser.schema.topNodeType, null, Mark.none,
|
|
3540
|
+
topContext = new NodeContext(parser.schema.topNodeType, null, Mark.none, true, null, topOptions);
|
|
3491
3541
|
this.nodes = [topContext];
|
|
3492
3542
|
this.find = options.findPositions;
|
|
3493
3543
|
this.needsBlock = false;
|
|
@@ -3498,31 +3548,13 @@ class ParseContext {
|
|
|
3498
3548
|
// Add a DOM node to the content. Text is inserted as text node,
|
|
3499
3549
|
// otherwise, the node is passed to `addElement` or, if it has a
|
|
3500
3550
|
// `style` attribute, `addElementWithStyles`.
|
|
3501
|
-
addDOM(dom) {
|
|
3551
|
+
addDOM(dom, marks) {
|
|
3502
3552
|
if (dom.nodeType == 3)
|
|
3503
|
-
this.addTextNode(dom);
|
|
3553
|
+
this.addTextNode(dom, marks);
|
|
3504
3554
|
else if (dom.nodeType == 1)
|
|
3505
|
-
this.addElement(dom);
|
|
3506
|
-
}
|
|
3507
|
-
withStyleRules(dom, f) {
|
|
3508
|
-
let style = dom.getAttribute("style");
|
|
3509
|
-
if (!style)
|
|
3510
|
-
return f();
|
|
3511
|
-
let marks = this.readStyles(parseStyles(style));
|
|
3512
|
-
if (!marks)
|
|
3513
|
-
return; // A style with ignore: true
|
|
3514
|
-
let [addMarks, removeMarks] = marks, top = this.top;
|
|
3515
|
-
for (let i = 0; i < removeMarks.length; i++)
|
|
3516
|
-
this.removePendingMark(removeMarks[i], top);
|
|
3517
|
-
for (let i = 0; i < addMarks.length; i++)
|
|
3518
|
-
this.addPendingMark(addMarks[i]);
|
|
3519
|
-
f();
|
|
3520
|
-
for (let i = 0; i < addMarks.length; i++)
|
|
3521
|
-
this.removePendingMark(addMarks[i], top);
|
|
3522
|
-
for (let i = 0; i < removeMarks.length; i++)
|
|
3523
|
-
this.addPendingMark(removeMarks[i]);
|
|
3555
|
+
this.addElement(dom, marks);
|
|
3524
3556
|
}
|
|
3525
|
-
addTextNode(dom) {
|
|
3557
|
+
addTextNode(dom, marks) {
|
|
3526
3558
|
let value = dom.nodeValue;
|
|
3527
3559
|
let top = this.top;
|
|
3528
3560
|
if (top.options & OPT_PRESERVE_WS_FULL ||
|
|
@@ -3549,7 +3581,7 @@ class ParseContext {
|
|
|
3549
3581
|
value = value.replace(/\r\n?/g, "\n");
|
|
3550
3582
|
}
|
|
3551
3583
|
if (value)
|
|
3552
|
-
this.insertNode(this.parser.schema.text(value));
|
|
3584
|
+
this.insertNode(this.parser.schema.text(value), marks);
|
|
3553
3585
|
this.findInText(dom);
|
|
3554
3586
|
}
|
|
3555
3587
|
else {
|
|
@@ -3558,7 +3590,7 @@ class ParseContext {
|
|
|
3558
3590
|
}
|
|
3559
3591
|
// Try to find a handler for the given tag and use that to parse. If
|
|
3560
3592
|
// none is found, the element's content nodes are added directly.
|
|
3561
|
-
addElement(dom, matchAfter) {
|
|
3593
|
+
addElement(dom, marks, matchAfter) {
|
|
3562
3594
|
let name = dom.nodeName.toLowerCase(), ruleID;
|
|
3563
3595
|
if (listTags.hasOwnProperty(name) && this.parser.normalizeLists)
|
|
3564
3596
|
normalizeList(dom);
|
|
@@ -3566,7 +3598,7 @@ class ParseContext {
|
|
|
3566
3598
|
(ruleID = this.parser.matchTag(dom, this, matchAfter));
|
|
3567
3599
|
if (rule ? rule.ignore : ignoreTags.hasOwnProperty(name)) {
|
|
3568
3600
|
this.findInside(dom);
|
|
3569
|
-
this.ignoreFallback(dom);
|
|
3601
|
+
this.ignoreFallback(dom, marks);
|
|
3570
3602
|
}
|
|
3571
3603
|
else if (!rule || rule.skip || rule.closeParent) {
|
|
3572
3604
|
if (rule && rule.closeParent)
|
|
@@ -3584,92 +3616,97 @@ class ParseContext {
|
|
|
3584
3616
|
this.needsBlock = true;
|
|
3585
3617
|
}
|
|
3586
3618
|
else if (!dom.firstChild) {
|
|
3587
|
-
this.leafFallback(dom);
|
|
3619
|
+
this.leafFallback(dom, marks);
|
|
3588
3620
|
return;
|
|
3589
3621
|
}
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
this.withStyleRules(dom, () => this.addAll(dom));
|
|
3622
|
+
let innerMarks = rule && rule.skip ? marks : this.readStyles(dom, marks);
|
|
3623
|
+
if (innerMarks)
|
|
3624
|
+
this.addAll(dom, innerMarks);
|
|
3594
3625
|
if (sync)
|
|
3595
3626
|
this.sync(top);
|
|
3596
3627
|
this.needsBlock = oldNeedsBlock;
|
|
3597
3628
|
}
|
|
3598
3629
|
else {
|
|
3599
|
-
this.
|
|
3600
|
-
|
|
3601
|
-
|
|
3630
|
+
let innerMarks = this.readStyles(dom, marks);
|
|
3631
|
+
if (innerMarks)
|
|
3632
|
+
this.addElementByRule(dom, rule, innerMarks, rule.consuming === false ? ruleID : undefined);
|
|
3602
3633
|
}
|
|
3603
3634
|
}
|
|
3604
3635
|
// Called for leaf DOM nodes that would otherwise be ignored
|
|
3605
|
-
leafFallback(dom) {
|
|
3636
|
+
leafFallback(dom, marks) {
|
|
3606
3637
|
if (dom.nodeName == "BR" && this.top.type && this.top.type.inlineContent)
|
|
3607
|
-
this.addTextNode(dom.ownerDocument.createTextNode("\n"));
|
|
3638
|
+
this.addTextNode(dom.ownerDocument.createTextNode("\n"), marks);
|
|
3608
3639
|
}
|
|
3609
3640
|
// Called for ignored nodes
|
|
3610
|
-
ignoreFallback(dom) {
|
|
3641
|
+
ignoreFallback(dom, marks) {
|
|
3611
3642
|
// Ignored BR nodes should at least create an inline context
|
|
3612
3643
|
if (dom.nodeName == "BR" && (!this.top.type || !this.top.type.inlineContent))
|
|
3613
|
-
this.findPlace(this.parser.schema.text("-"));
|
|
3644
|
+
this.findPlace(this.parser.schema.text("-"), marks);
|
|
3614
3645
|
}
|
|
3615
3646
|
// Run any style parser associated with the node's styles. Either
|
|
3616
|
-
// return an array of marks, or null to indicate some of the
|
|
3617
|
-
// had a rule with `ignore` set.
|
|
3618
|
-
readStyles(
|
|
3619
|
-
let
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3647
|
+
// return an updated array of marks, or null to indicate some of the
|
|
3648
|
+
// styles had a rule with `ignore` set.
|
|
3649
|
+
readStyles(dom, marks) {
|
|
3650
|
+
let styles = dom.style;
|
|
3651
|
+
// Because many properties will only show up in 'normalized' form
|
|
3652
|
+
// in `style.item` (i.e. text-decoration becomes
|
|
3653
|
+
// text-decoration-line, text-decoration-color, etc), we directly
|
|
3654
|
+
// query the styles mentioned in our rules instead of iterating
|
|
3655
|
+
// over the items.
|
|
3656
|
+
if (styles && styles.length)
|
|
3657
|
+
for (let i = 0; i < this.parser.matchedStyles.length; i++) {
|
|
3658
|
+
let name = this.parser.matchedStyles[i], value = styles.getPropertyValue(name);
|
|
3659
|
+
if (value)
|
|
3660
|
+
for (let after = undefined;;) {
|
|
3661
|
+
let rule = this.parser.matchStyle(name, value, this, after);
|
|
3662
|
+
if (!rule)
|
|
3663
|
+
break;
|
|
3664
|
+
if (rule.ignore)
|
|
3665
|
+
return null;
|
|
3666
|
+
if (rule.clearMark)
|
|
3667
|
+
marks = marks.filter(m => !rule.clearMark(m));
|
|
3668
|
+
else
|
|
3669
|
+
marks = marks.concat(this.parser.schema.marks[rule.mark].create(rule.attrs));
|
|
3670
|
+
if (rule.consuming === false)
|
|
3671
|
+
after = rule;
|
|
3672
|
+
else
|
|
3673
|
+
break;
|
|
3674
|
+
}
|
|
3640
3675
|
}
|
|
3641
|
-
|
|
3642
|
-
return [add, remove];
|
|
3676
|
+
return marks;
|
|
3643
3677
|
}
|
|
3644
3678
|
// Look up a handler for the given node. If none are found, return
|
|
3645
3679
|
// false. Otherwise, apply it, use its return value to drive the way
|
|
3646
3680
|
// the node's content is wrapped, and return true.
|
|
3647
|
-
addElementByRule(dom, rule, continueAfter) {
|
|
3648
|
-
let sync, nodeType
|
|
3681
|
+
addElementByRule(dom, rule, marks, continueAfter) {
|
|
3682
|
+
let sync, nodeType;
|
|
3649
3683
|
if (rule.node) {
|
|
3650
3684
|
nodeType = this.parser.schema.nodes[rule.node];
|
|
3651
3685
|
if (!nodeType.isLeaf) {
|
|
3652
|
-
|
|
3686
|
+
let inner = this.enter(nodeType, rule.attrs || null, marks, rule.preserveWhitespace);
|
|
3687
|
+
if (inner) {
|
|
3688
|
+
sync = true;
|
|
3689
|
+
marks = inner;
|
|
3690
|
+
}
|
|
3653
3691
|
}
|
|
3654
|
-
else if (!this.insertNode(nodeType.create(rule.attrs))) {
|
|
3655
|
-
this.leafFallback(dom);
|
|
3692
|
+
else if (!this.insertNode(nodeType.create(rule.attrs), marks)) {
|
|
3693
|
+
this.leafFallback(dom, marks);
|
|
3656
3694
|
}
|
|
3657
3695
|
}
|
|
3658
3696
|
else {
|
|
3659
3697
|
let markType = this.parser.schema.marks[rule.mark];
|
|
3660
|
-
|
|
3661
|
-
this.addPendingMark(mark);
|
|
3698
|
+
marks = marks.concat(markType.create(rule.attrs));
|
|
3662
3699
|
}
|
|
3663
3700
|
let startIn = this.top;
|
|
3664
3701
|
if (nodeType && nodeType.isLeaf) {
|
|
3665
3702
|
this.findInside(dom);
|
|
3666
3703
|
}
|
|
3667
3704
|
else if (continueAfter) {
|
|
3668
|
-
this.addElement(dom, continueAfter);
|
|
3705
|
+
this.addElement(dom, marks, continueAfter);
|
|
3669
3706
|
}
|
|
3670
3707
|
else if (rule.getContent) {
|
|
3671
3708
|
this.findInside(dom);
|
|
3672
|
-
rule.getContent(dom, this.parser.schema).forEach(node => this.insertNode(node));
|
|
3709
|
+
rule.getContent(dom, this.parser.schema).forEach(node => this.insertNode(node, marks));
|
|
3673
3710
|
}
|
|
3674
3711
|
else {
|
|
3675
3712
|
let contentDOM = dom;
|
|
@@ -3680,28 +3717,26 @@ class ParseContext {
|
|
|
3680
3717
|
else if (rule.contentElement)
|
|
3681
3718
|
contentDOM = rule.contentElement;
|
|
3682
3719
|
this.findAround(dom, contentDOM, true);
|
|
3683
|
-
this.addAll(contentDOM);
|
|
3720
|
+
this.addAll(contentDOM, marks);
|
|
3684
3721
|
}
|
|
3685
3722
|
if (sync && this.sync(startIn))
|
|
3686
3723
|
this.open--;
|
|
3687
|
-
if (mark)
|
|
3688
|
-
this.removePendingMark(mark, startIn);
|
|
3689
3724
|
}
|
|
3690
3725
|
// Add all child nodes between `startIndex` and `endIndex` (or the
|
|
3691
3726
|
// whole node, if not given). If `sync` is passed, use it to
|
|
3692
3727
|
// synchronize after every block element.
|
|
3693
|
-
addAll(parent, startIndex, endIndex) {
|
|
3728
|
+
addAll(parent, marks, startIndex, endIndex) {
|
|
3694
3729
|
let index = startIndex || 0;
|
|
3695
3730
|
for (let dom = startIndex ? parent.childNodes[startIndex] : parent.firstChild, end = endIndex == null ? null : parent.childNodes[endIndex]; dom != end; dom = dom.nextSibling, ++index) {
|
|
3696
3731
|
this.findAtPoint(parent, index);
|
|
3697
|
-
this.addDOM(dom);
|
|
3732
|
+
this.addDOM(dom, marks);
|
|
3698
3733
|
}
|
|
3699
3734
|
this.findAtPoint(parent, index);
|
|
3700
3735
|
}
|
|
3701
3736
|
// Try to find a way to fit the given node type into the current
|
|
3702
3737
|
// context. May add intermediate wrappers and/or leave non-solid
|
|
3703
3738
|
// nodes that we're in.
|
|
3704
|
-
findPlace(node) {
|
|
3739
|
+
findPlace(node, marks) {
|
|
3705
3740
|
let route, sync;
|
|
3706
3741
|
for (let depth = this.open; depth >= 0; depth--) {
|
|
3707
3742
|
let cx = this.nodes[depth];
|
|
@@ -3716,53 +3751,61 @@ class ParseContext {
|
|
|
3716
3751
|
break;
|
|
3717
3752
|
}
|
|
3718
3753
|
if (!route)
|
|
3719
|
-
return
|
|
3754
|
+
return null;
|
|
3720
3755
|
this.sync(sync);
|
|
3721
3756
|
for (let i = 0; i < route.length; i++)
|
|
3722
|
-
this.enterInner(route[i], null, false);
|
|
3723
|
-
return
|
|
3757
|
+
marks = this.enterInner(route[i], null, marks, false);
|
|
3758
|
+
return marks;
|
|
3724
3759
|
}
|
|
3725
3760
|
// Try to insert the given node, adjusting the context when needed.
|
|
3726
|
-
insertNode(node) {
|
|
3761
|
+
insertNode(node, marks) {
|
|
3727
3762
|
if (node.isInline && this.needsBlock && !this.top.type) {
|
|
3728
3763
|
let block = this.textblockFromContext();
|
|
3729
3764
|
if (block)
|
|
3730
|
-
this.enterInner(block);
|
|
3765
|
+
marks = this.enterInner(block, null, marks);
|
|
3731
3766
|
}
|
|
3732
|
-
|
|
3767
|
+
let innerMarks = this.findPlace(node, marks);
|
|
3768
|
+
if (innerMarks) {
|
|
3733
3769
|
this.closeExtra();
|
|
3734
3770
|
let top = this.top;
|
|
3735
|
-
top.applyPending(node.type);
|
|
3736
3771
|
if (top.match)
|
|
3737
3772
|
top.match = top.match.matchType(node.type);
|
|
3738
|
-
let
|
|
3739
|
-
for (let
|
|
3740
|
-
if (
|
|
3741
|
-
|
|
3742
|
-
top.content.push(node.mark(
|
|
3773
|
+
let nodeMarks = Mark.none;
|
|
3774
|
+
for (let m of innerMarks.concat(node.marks))
|
|
3775
|
+
if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, node.type))
|
|
3776
|
+
nodeMarks = m.addToSet(nodeMarks);
|
|
3777
|
+
top.content.push(node.mark(nodeMarks));
|
|
3743
3778
|
return true;
|
|
3744
3779
|
}
|
|
3745
3780
|
return false;
|
|
3746
3781
|
}
|
|
3747
3782
|
// Try to start a node of the given type, adjusting the context when
|
|
3748
3783
|
// necessary.
|
|
3749
|
-
enter(type, attrs, preserveWS) {
|
|
3750
|
-
let
|
|
3751
|
-
if (
|
|
3752
|
-
this.enterInner(type, attrs, true, preserveWS);
|
|
3753
|
-
return
|
|
3784
|
+
enter(type, attrs, marks, preserveWS) {
|
|
3785
|
+
let innerMarks = this.findPlace(type.create(attrs), marks);
|
|
3786
|
+
if (innerMarks)
|
|
3787
|
+
innerMarks = this.enterInner(type, attrs, marks, true, preserveWS);
|
|
3788
|
+
return innerMarks;
|
|
3754
3789
|
}
|
|
3755
3790
|
// Open a node of the given type
|
|
3756
|
-
enterInner(type, attrs
|
|
3791
|
+
enterInner(type, attrs, marks, solid = false, preserveWS) {
|
|
3757
3792
|
this.closeExtra();
|
|
3758
3793
|
let top = this.top;
|
|
3759
|
-
top.applyPending(type);
|
|
3760
3794
|
top.match = top.match && top.match.matchType(type);
|
|
3761
3795
|
let options = wsOptionsFor(type, preserveWS, top.options);
|
|
3762
3796
|
if ((top.options & OPT_OPEN_LEFT) && top.content.length == 0)
|
|
3763
3797
|
options |= OPT_OPEN_LEFT;
|
|
3764
|
-
|
|
3798
|
+
let applyMarks = Mark.none;
|
|
3799
|
+
marks = marks.filter(m => {
|
|
3800
|
+
if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, type)) {
|
|
3801
|
+
applyMarks = m.addToSet(applyMarks);
|
|
3802
|
+
return false;
|
|
3803
|
+
}
|
|
3804
|
+
return true;
|
|
3805
|
+
});
|
|
3806
|
+
this.nodes.push(new NodeContext(type, attrs, applyMarks, solid, null, options));
|
|
3765
3807
|
this.open++;
|
|
3808
|
+
return marks;
|
|
3766
3809
|
}
|
|
3767
3810
|
// Make sure all nodes above this.open are finished and added to
|
|
3768
3811
|
// their parents
|
|
@@ -3876,29 +3919,6 @@ class ParseContext {
|
|
|
3876
3919
|
return type;
|
|
3877
3920
|
}
|
|
3878
3921
|
}
|
|
3879
|
-
addPendingMark(mark) {
|
|
3880
|
-
let found = findSameMarkInSet(mark, this.top.pendingMarks);
|
|
3881
|
-
if (found)
|
|
3882
|
-
this.top.stashMarks.push(found);
|
|
3883
|
-
this.top.pendingMarks = mark.addToSet(this.top.pendingMarks);
|
|
3884
|
-
}
|
|
3885
|
-
removePendingMark(mark, upto) {
|
|
3886
|
-
for (let depth = this.open; depth >= 0; depth--) {
|
|
3887
|
-
let level = this.nodes[depth];
|
|
3888
|
-
let found = level.pendingMarks.lastIndexOf(mark);
|
|
3889
|
-
if (found > -1) {
|
|
3890
|
-
level.pendingMarks = mark.removeFromSet(level.pendingMarks);
|
|
3891
|
-
}
|
|
3892
|
-
else {
|
|
3893
|
-
level.activeMarks = mark.removeFromSet(level.activeMarks);
|
|
3894
|
-
let stashMark = level.popFromStashMark(mark);
|
|
3895
|
-
if (stashMark && level.type && level.type.allowsMarkType(stashMark.type))
|
|
3896
|
-
level.activeMarks = stashMark.addToSet(level.activeMarks);
|
|
3897
|
-
}
|
|
3898
|
-
if (level == upto)
|
|
3899
|
-
break;
|
|
3900
|
-
}
|
|
3901
|
-
}
|
|
3902
3922
|
}
|
|
3903
3923
|
// Kludge to work around directly nested list nodes produced by some
|
|
3904
3924
|
// tools and allowed by browsers to mean that the nested list is
|
|
@@ -3922,13 +3942,6 @@ function normalizeList(dom) {
|
|
|
3922
3942
|
function matches(dom, selector) {
|
|
3923
3943
|
return (dom.matches || dom.msMatchesSelector || dom.webkitMatchesSelector || dom.mozMatchesSelector).call(dom, selector);
|
|
3924
3944
|
}
|
|
3925
|
-
// Tokenize a style attribute into property/value pairs.
|
|
3926
|
-
function parseStyles(style) {
|
|
3927
|
-
let re = /\s*([\w-]+)\s*:\s*([^;]+)/g, m, result = [];
|
|
3928
|
-
while (m = re.exec(style))
|
|
3929
|
-
result.push(m[1], m[2].trim());
|
|
3930
|
-
return result;
|
|
3931
|
-
}
|
|
3932
3945
|
function copy(obj) {
|
|
3933
3946
|
let copy = {};
|
|
3934
3947
|
for (let prop in obj)
|
|
@@ -3958,12 +3971,6 @@ function markMayApply(markType, nodeType) {
|
|
|
3958
3971
|
return true;
|
|
3959
3972
|
}
|
|
3960
3973
|
}
|
|
3961
|
-
function findSameMarkInSet(mark, set) {
|
|
3962
|
-
for (let i = 0; i < set.length; i++) {
|
|
3963
|
-
if (mark.eq(set[i]))
|
|
3964
|
-
return set[i];
|
|
3965
|
-
}
|
|
3966
|
-
}
|
|
3967
3974
|
|
|
3968
3975
|
/**
|
|
3969
3976
|
A DOM serializer knows how to convert ProseMirror nodes and
|
|
@@ -4035,7 +4042,7 @@ class DOMSerializer {
|
|
|
4035
4042
|
@internal
|
|
4036
4043
|
*/
|
|
4037
4044
|
serializeNodeInner(node, options) {
|
|
4038
|
-
let { dom, contentDOM } =
|
|
4045
|
+
let { dom, contentDOM } = renderSpec(doc$1(options), this.nodes[node.type.name](node), null, node.attrs);
|
|
4039
4046
|
if (contentDOM) {
|
|
4040
4047
|
if (node.isLeaf)
|
|
4041
4048
|
throw new RangeError("Content hole not allowed in a leaf node spec");
|
|
@@ -4066,57 +4073,10 @@ class DOMSerializer {
|
|
|
4066
4073
|
*/
|
|
4067
4074
|
serializeMark(mark, inline, options = {}) {
|
|
4068
4075
|
let toDOM = this.marks[mark.type.name];
|
|
4069
|
-
return toDOM &&
|
|
4070
|
-
}
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
the spec has a hole (zero) in it, `contentDOM` will point at the
|
|
4074
|
-
node with the hole.
|
|
4075
|
-
*/
|
|
4076
|
-
static renderSpec(doc, structure, xmlNS = null) {
|
|
4077
|
-
if (typeof structure == "string")
|
|
4078
|
-
return { dom: doc.createTextNode(structure) };
|
|
4079
|
-
if (structure.nodeType != null)
|
|
4080
|
-
return { dom: structure };
|
|
4081
|
-
if (structure.dom && structure.dom.nodeType != null)
|
|
4082
|
-
return structure;
|
|
4083
|
-
let tagName = structure[0], space = tagName.indexOf(" ");
|
|
4084
|
-
if (space > 0) {
|
|
4085
|
-
xmlNS = tagName.slice(0, space);
|
|
4086
|
-
tagName = tagName.slice(space + 1);
|
|
4087
|
-
}
|
|
4088
|
-
let contentDOM;
|
|
4089
|
-
let dom = (xmlNS ? doc.createElementNS(xmlNS, tagName) : doc.createElement(tagName));
|
|
4090
|
-
let attrs = structure[1], start = 1;
|
|
4091
|
-
if (attrs && typeof attrs == "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
|
|
4092
|
-
start = 2;
|
|
4093
|
-
for (let name in attrs)
|
|
4094
|
-
if (attrs[name] != null) {
|
|
4095
|
-
let space = name.indexOf(" ");
|
|
4096
|
-
if (space > 0)
|
|
4097
|
-
dom.setAttributeNS(name.slice(0, space), name.slice(space + 1), attrs[name]);
|
|
4098
|
-
else
|
|
4099
|
-
dom.setAttribute(name, attrs[name]);
|
|
4100
|
-
}
|
|
4101
|
-
}
|
|
4102
|
-
for (let i = start; i < structure.length; i++) {
|
|
4103
|
-
let child = structure[i];
|
|
4104
|
-
if (child === 0) {
|
|
4105
|
-
if (i < structure.length - 1 || i > start)
|
|
4106
|
-
throw new RangeError("Content hole must be the only child of its parent node");
|
|
4107
|
-
return { dom, contentDOM: dom };
|
|
4108
|
-
}
|
|
4109
|
-
else {
|
|
4110
|
-
let { dom: inner, contentDOM: innerContent } = DOMSerializer.renderSpec(doc, child, xmlNS);
|
|
4111
|
-
dom.appendChild(inner);
|
|
4112
|
-
if (innerContent) {
|
|
4113
|
-
if (contentDOM)
|
|
4114
|
-
throw new RangeError("Multiple content holes");
|
|
4115
|
-
contentDOM = innerContent;
|
|
4116
|
-
}
|
|
4117
|
-
}
|
|
4118
|
-
}
|
|
4119
|
-
return { dom, contentDOM };
|
|
4076
|
+
return toDOM && renderSpec(doc$1(options), toDOM(mark, inline), null, mark.attrs);
|
|
4077
|
+
}
|
|
4078
|
+
static renderSpec(doc, structure, xmlNS = null, blockArraysIn) {
|
|
4079
|
+
return renderSpec(doc, structure, xmlNS, blockArraysIn);
|
|
4120
4080
|
}
|
|
4121
4081
|
/**
|
|
4122
4082
|
Build a serializer using the [`toDOM`](https://prosemirror.net/docs/ref/#model.NodeSpec.toDOM)
|
|
@@ -4155,6 +4115,88 @@ function gatherToDOM(obj) {
|
|
|
4155
4115
|
function doc$1(options) {
|
|
4156
4116
|
return options.document || window.document;
|
|
4157
4117
|
}
|
|
4118
|
+
const suspiciousAttributeCache = new WeakMap();
|
|
4119
|
+
function suspiciousAttributes(attrs) {
|
|
4120
|
+
let value = suspiciousAttributeCache.get(attrs);
|
|
4121
|
+
if (value === undefined)
|
|
4122
|
+
suspiciousAttributeCache.set(attrs, value = suspiciousAttributesInner(attrs));
|
|
4123
|
+
return value;
|
|
4124
|
+
}
|
|
4125
|
+
function suspiciousAttributesInner(attrs) {
|
|
4126
|
+
let result = null;
|
|
4127
|
+
function scan(value) {
|
|
4128
|
+
if (value && typeof value == "object") {
|
|
4129
|
+
if (Array.isArray(value)) {
|
|
4130
|
+
if (typeof value[0] == "string") {
|
|
4131
|
+
if (!result)
|
|
4132
|
+
result = [];
|
|
4133
|
+
result.push(value);
|
|
4134
|
+
}
|
|
4135
|
+
else {
|
|
4136
|
+
for (let i = 0; i < value.length; i++)
|
|
4137
|
+
scan(value[i]);
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
else {
|
|
4141
|
+
for (let prop in value)
|
|
4142
|
+
scan(value[prop]);
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
}
|
|
4146
|
+
scan(attrs);
|
|
4147
|
+
return result;
|
|
4148
|
+
}
|
|
4149
|
+
function renderSpec(doc, structure, xmlNS, blockArraysIn) {
|
|
4150
|
+
if (typeof structure == "string")
|
|
4151
|
+
return { dom: doc.createTextNode(structure) };
|
|
4152
|
+
if (structure.nodeType != null)
|
|
4153
|
+
return { dom: structure };
|
|
4154
|
+
if (structure.dom && structure.dom.nodeType != null)
|
|
4155
|
+
return structure;
|
|
4156
|
+
let tagName = structure[0], suspicious;
|
|
4157
|
+
if (typeof tagName != "string")
|
|
4158
|
+
throw new RangeError("Invalid array passed to renderSpec");
|
|
4159
|
+
if (blockArraysIn && (suspicious = suspiciousAttributes(blockArraysIn)) &&
|
|
4160
|
+
suspicious.indexOf(structure) > -1)
|
|
4161
|
+
throw new RangeError("Using an array from an attribute object as a DOM spec. This may be an attempted cross site scripting attack.");
|
|
4162
|
+
let space = tagName.indexOf(" ");
|
|
4163
|
+
if (space > 0) {
|
|
4164
|
+
xmlNS = tagName.slice(0, space);
|
|
4165
|
+
tagName = tagName.slice(space + 1);
|
|
4166
|
+
}
|
|
4167
|
+
let contentDOM;
|
|
4168
|
+
let dom = (xmlNS ? doc.createElementNS(xmlNS, tagName) : doc.createElement(tagName));
|
|
4169
|
+
let attrs = structure[1], start = 1;
|
|
4170
|
+
if (attrs && typeof attrs == "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
|
|
4171
|
+
start = 2;
|
|
4172
|
+
for (let name in attrs)
|
|
4173
|
+
if (attrs[name] != null) {
|
|
4174
|
+
let space = name.indexOf(" ");
|
|
4175
|
+
if (space > 0)
|
|
4176
|
+
dom.setAttributeNS(name.slice(0, space), name.slice(space + 1), attrs[name]);
|
|
4177
|
+
else
|
|
4178
|
+
dom.setAttribute(name, attrs[name]);
|
|
4179
|
+
}
|
|
4180
|
+
}
|
|
4181
|
+
for (let i = start; i < structure.length; i++) {
|
|
4182
|
+
let child = structure[i];
|
|
4183
|
+
if (child === 0) {
|
|
4184
|
+
if (i < structure.length - 1 || i > start)
|
|
4185
|
+
throw new RangeError("Content hole must be the only child of its parent node");
|
|
4186
|
+
return { dom, contentDOM: dom };
|
|
4187
|
+
}
|
|
4188
|
+
else {
|
|
4189
|
+
let { dom: inner, contentDOM: innerContent } = renderSpec(doc, child, xmlNS, blockArraysIn);
|
|
4190
|
+
dom.appendChild(inner);
|
|
4191
|
+
if (innerContent) {
|
|
4192
|
+
if (contentDOM)
|
|
4193
|
+
throw new RangeError("Multiple content holes");
|
|
4194
|
+
contentDOM = innerContent;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
return { dom, contentDOM };
|
|
4199
|
+
}
|
|
4158
4200
|
|
|
4159
4201
|
// Recovery values encode a range index and an offset. They are
|
|
4160
4202
|
// represented as numbers, because tons of them will be created when
|
|
@@ -24875,9 +24917,9 @@ const schema = new Schema({
|
|
|
24875
24917
|
strong: {
|
|
24876
24918
|
parseDOM: [
|
|
24877
24919
|
{ tag: "strong" },
|
|
24878
|
-
{ tag: "b", getAttrs:
|
|
24920
|
+
{ tag: "b", getAttrs: node => node.style.fontWeight != "normal" && null },
|
|
24879
24921
|
{ style: "font-weight=400", clearMark: m => m.type.name == "strong" },
|
|
24880
|
-
{ style: "font-weight", getAttrs:
|
|
24922
|
+
{ style: "font-weight", getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null }
|
|
24881
24923
|
],
|
|
24882
24924
|
toDOM() { return ["strong"]; }
|
|
24883
24925
|
},
|
|
@@ -25131,6 +25173,7 @@ new MarkdownParser(schema, MarkdownIt("commonmark", { html: false }), {
|
|
|
25131
25173
|
code_inline: { mark: "code", noCloseToken: true }
|
|
25132
25174
|
});
|
|
25133
25175
|
|
|
25176
|
+
const blankMark = { open: "", close: "", mixable: true };
|
|
25134
25177
|
/**
|
|
25135
25178
|
A specification for serializing a ProseMirror document as
|
|
25136
25179
|
Markdown/CommonMark text.
|
|
@@ -25338,6 +25381,18 @@ class MarkdownSerializerState {
|
|
|
25338
25381
|
}
|
|
25339
25382
|
}
|
|
25340
25383
|
/**
|
|
25384
|
+
@internal
|
|
25385
|
+
*/
|
|
25386
|
+
getMark(name) {
|
|
25387
|
+
let info = this.marks[name];
|
|
25388
|
+
if (!info) {
|
|
25389
|
+
if (this.options.strict !== false)
|
|
25390
|
+
throw new Error(`Mark type \`${name}\` not supported by Markdown renderer`);
|
|
25391
|
+
info = blankMark;
|
|
25392
|
+
}
|
|
25393
|
+
return info;
|
|
25394
|
+
}
|
|
25395
|
+
/**
|
|
25341
25396
|
Render a block, prefixing each line with `delim`, and the first
|
|
25342
25397
|
line in `firstDelim`. `node` should be the node that is closed at
|
|
25343
25398
|
the end of the block, and `f` is a function that renders the
|
|
@@ -25402,9 +25457,22 @@ class MarkdownSerializerState {
|
|
|
25402
25457
|
Render the given node as a block.
|
|
25403
25458
|
*/
|
|
25404
25459
|
render(node, parent, index) {
|
|
25405
|
-
if (
|
|
25406
|
-
|
|
25407
|
-
|
|
25460
|
+
if (this.nodes[node.type.name]) {
|
|
25461
|
+
this.nodes[node.type.name](this, node, parent, index);
|
|
25462
|
+
}
|
|
25463
|
+
else {
|
|
25464
|
+
if (this.options.strict !== false) {
|
|
25465
|
+
throw new Error("Token type `" + node.type.name + "` not supported by Markdown renderer");
|
|
25466
|
+
}
|
|
25467
|
+
else if (!node.type.isLeaf) {
|
|
25468
|
+
if (node.type.inlineContent)
|
|
25469
|
+
this.renderInline(node);
|
|
25470
|
+
else
|
|
25471
|
+
this.renderContent(node);
|
|
25472
|
+
if (node.isBlock)
|
|
25473
|
+
this.closeBlock(node);
|
|
25474
|
+
}
|
|
25475
|
+
}
|
|
25408
25476
|
}
|
|
25409
25477
|
/**
|
|
25410
25478
|
Render the contents of `parent` as block nodes.
|
|
@@ -25435,7 +25503,7 @@ class MarkdownSerializerState {
|
|
|
25435
25503
|
// If whitespace has to be expelled from the node, adjust
|
|
25436
25504
|
// leading and trailing accordingly.
|
|
25437
25505
|
if (node && node.isText && marks.some(mark => {
|
|
25438
|
-
let info = this.
|
|
25506
|
+
let info = this.getMark(mark.type.name);
|
|
25439
25507
|
return info && info.expelEnclosingWhitespace && !mark.isInSet(active);
|
|
25440
25508
|
})) {
|
|
25441
25509
|
let [_, lead, rest] = /^(\s*)(.*)$/m.exec(node.text);
|
|
@@ -25447,7 +25515,7 @@ class MarkdownSerializerState {
|
|
|
25447
25515
|
}
|
|
25448
25516
|
}
|
|
25449
25517
|
if (node && node.isText && marks.some(mark => {
|
|
25450
|
-
let info = this.
|
|
25518
|
+
let info = this.getMark(mark.type.name);
|
|
25451
25519
|
return info && info.expelEnclosingWhitespace &&
|
|
25452
25520
|
(index == parent.childCount - 1 || !mark.isInSet(parent.child(index + 1).marks));
|
|
25453
25521
|
})) {
|
|
@@ -25460,7 +25528,7 @@ class MarkdownSerializerState {
|
|
|
25460
25528
|
}
|
|
25461
25529
|
}
|
|
25462
25530
|
let inner = marks.length ? marks[marks.length - 1] : null;
|
|
25463
|
-
let noEsc = inner && this.
|
|
25531
|
+
let noEsc = inner && this.getMark(inner.type.name).escape === false;
|
|
25464
25532
|
let len = marks.length - (noEsc ? 1 : 0);
|
|
25465
25533
|
// Try to reorder 'mixable' marks, such as em and strong, which
|
|
25466
25534
|
// in Markdown may be opened and closed in different order, so
|
|
@@ -25468,11 +25536,11 @@ class MarkdownSerializerState {
|
|
|
25468
25536
|
// active.
|
|
25469
25537
|
outer: for (let i = 0; i < len; i++) {
|
|
25470
25538
|
let mark = marks[i];
|
|
25471
|
-
if (!this.
|
|
25539
|
+
if (!this.getMark(mark.type.name).mixable)
|
|
25472
25540
|
break;
|
|
25473
25541
|
for (let j = 0; j < active.length; j++) {
|
|
25474
25542
|
let other = active[j];
|
|
25475
|
-
if (!this.
|
|
25543
|
+
if (!this.getMark(other.type.name).mixable)
|
|
25476
25544
|
break;
|
|
25477
25545
|
if (mark.eq(other)) {
|
|
25478
25546
|
if (i > j)
|
|
@@ -25578,7 +25646,7 @@ class MarkdownSerializerState {
|
|
|
25578
25646
|
Get the markdown string for a given opening or closing mark.
|
|
25579
25647
|
*/
|
|
25580
25648
|
markString(mark, open, parent, index) {
|
|
25581
|
-
let info = this.
|
|
25649
|
+
let info = this.getMark(mark.type.name);
|
|
25582
25650
|
let value = open ? info.open : info.close;
|
|
25583
25651
|
return typeof value == "string" ? value : value(this, mark, parent, index);
|
|
25584
25652
|
}
|