From 1eb53581cffbe7f28ba40a7184bc325a9ecd794c Mon Sep 17 00:00:00 2001 From: lastnigtic <1113594660@qq.com> Date: Thu, 10 Sep 2020 23:48:38 +0800 Subject: [PATCH 001/112] Fix missing mark when parsing nested mark with same type --- src/from_dom.js | 25 +++++++++++++++++++++++-- test/test-dom.js | 4 ++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/from_dom.js b/src/from_dom.js index 68f78e7..ca7289f 100644 --- a/src/from_dom.js +++ b/src/from_dom.js @@ -302,6 +302,8 @@ class NodeContext { this.activeMarks = Mark.none // Marks that can't apply here, but will be used in children if possible this.pendingMarks = pendingMarks + // Nested Marks with same type + this.stashMarks = []; } findWrapping(node) { @@ -337,6 +339,15 @@ class NodeContext { return this.type ? this.type.create(this.attrs, content, this.marks) : content } + popFromStashMark(markType) { + for (let i = this.stashMarks.length - 1; i >= 0; i--) { + if (this.stashMarks[i].type == markType) { + return this.stashMarks.splice(i, 1)[0]; + } + } + return undefined + } + applyPending(nextType) { for (let i = 0, pending = this.pendingMarks; i < pending.length; i++) { let mark = pending[i] @@ -699,6 +710,8 @@ class ParseContext { } addPendingMark(mark) { + const found = this.top.pendingMarks.findIndex(_mark => _mark.type == mark.type) + if (found > -1) this.top.stashMarks.push(mark) this.top.pendingMarks = mark.addToSet(this.top.pendingMarks) } @@ -706,8 +719,16 @@ class ParseContext { for (let depth = this.open; depth >= 0; depth--) { let level = this.nodes[depth] let found = level.pendingMarks.lastIndexOf(mark) - if (found > -1) level.pendingMarks = mark.removeFromSet(level.pendingMarks) - else level.activeMarks = mark.removeFromSet(level.activeMarks) + if (found > -1) { + level.pendingMarks = mark.removeFromSet(level.pendingMarks) + } else { + const stashMark = level.popFromStashMark(mark.type); + if (stashMark) { + level.activeMarks = stashMark.addToSet(level.activeMarks); + } else { + level.activeMarks = mark.removeFromSet(level.activeMarks); + } + } if (level == upto) break } } diff --git a/test/test-dom.js b/test/test-dom.js index d4e02b1..7f27921 100644 --- a/test/test-dom.js +++ b/test/test-dom.js @@ -327,6 +327,10 @@ describe("DOMParser", () => { open("
foobarbaz
", + [p(strong("foobarbaz"))], 1, 1)) + it("will not apply invalid marks to nodes", open("foobarbaz
", - [p(strong("foobarbaz"))], 1, 1)) - it("will not apply invalid marks to nodes", open("foobarbaz
", + [p(strong("foobarbaz"))], 1, 1)) + + it("can parse nested mark with same type but different attrs", () => { + let markSchema = new Schema({ + nodes: schema.spec.nodes, + marks: schema.spec.marks.update("s", { + attrs: { + 'data-s': { default: 'tag' } + }, + parseDOM: [{ + tag: "s", + }, { + style: "text-decoration", + getAttrs() { + return { + 'data-s': 'style' + } + } + }] + }) + }) + let b = builders(markSchema); + let dom = document.createElement("div") + dom.innerHTML = "foo
foo
one
two
one
one
")), doc(p(em(strong("one")))), eq) + }) }) describe("schemaRules", () => { From cc53b08ac966d278f840966771b3144fe3df7ea3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbekefoo
ooo
ooo
one
")), doc(p(em(strong("one")))), eq) }) + + it("doesn't get confused by nested mark tags", + recover("xxbar
", doc(p(strong("xxbar"))))) + it("doesn't ignore whitespace-only nodes in preserveWhitespace full mode", + recover(" x", doc(p(" x")), {preserveWhitespace: "full"})) + function parse(html, options, doc) { return () => { let dom = document.createElement("div") From 3c0b054fbdeabbf45836b3441ec8ce5da8da2e5d Mon Sep 17 00:00:00 2001 From: Marijn Haverbekefoobarbaz
", [p(strong("foobarbaz"))], 1, 1)) + it("drops block-level whitespace", + open("