Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

prosemirror-model

Package Overview
Dependencies
Maintainers
1
Versions
85
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prosemirror-model - npm Package Compare versions

Comparing version 1.22.2 to 1.22.3

6

CHANGELOG.md

@@ -0,1 +1,7 @@

## 1.22.3 (2024-08-06)
### Bug fixes
Fix some corner cases in the way the DOM parser tracks active marks.
## 1.22.2 (2024-07-18)

@@ -2,0 +8,0 @@

2

dist/index.d.ts

@@ -1113,3 +1113,3 @@ import OrderedMap from 'orderedmap';

A function or type name used to validate values of this
attibute. This will be used when deserializing the attribute
attribute. This will be used when deserializing the attribute
from JSON, and when running [`Node.check`](https://prosemirror.net/docs/ref/#model.Node.check).

@@ -1116,0 +1116,0 @@ When a function, it should raise an exception if the value isn't

{
"name": "prosemirror-model",
"version": "1.22.2",
"version": "1.22.3",
"description": "ProseMirror's document model",

@@ -5,0 +5,0 @@ "type": "module",

@@ -219,3 +219,3 @@ import {Fragment} from "./fragment"

let context = new ParseContext(this, options, false)
context.addAll(dom, options.from, options.to)
context.addAll(dom, Mark.none, options.from, options.to)
return context.finish() as Node

@@ -232,3 +232,3 @@ }

let context = new ParseContext(this, options, true)
context.addAll(dom, options.from, options.to)
context.addAll(dom, Mark.none, options.from, options.to)
return Slice.maxOpen(context.finish() as Fragment)

@@ -344,4 +344,2 @@ }

activeMarks: readonly Mark[] = Mark.none
// Nested Marks with same type
stashMarks: Mark[] = []

@@ -351,6 +349,3 @@ constructor(

readonly attrs: Attrs | null,
// Marks applied to this node itself
readonly marks: readonly Mark[],
// Marks that can't apply here, but will be used in children if possible
public pendingMarks: readonly Mark[],
readonly solid: boolean,

@@ -397,18 +392,2 @@ match: ContentMatch | null,

popFromStashMark(mark: Mark) {
for (let i = this.stashMarks.length - 1; i >= 0; i--)
if (mark.eq(this.stashMarks[i])) return this.stashMarks.splice(i, 1)[0]
}
applyPending(nextType: NodeType) {
for (let i = 0, pending = this.pendingMarks; i < pending.length; i++) {
let mark = pending[i]
if ((this.type ? this.type.allowsMarkType(mark.type) : markMayApply(mark.type, nextType)) &&
!mark.isInSet(this.activeMarks)) {
this.activeMarks = mark.addToSet(this.activeMarks)
this.pendingMarks = mark.removeFromSet(this.pendingMarks)
}
}
}
inlineContext(node: DOMNode) {

@@ -437,8 +416,8 @@ if (this.type) return this.type.inlineContent

if (topNode)
topContext = new NodeContext(topNode.type, topNode.attrs, Mark.none, Mark.none, true,
topContext = new NodeContext(topNode.type, topNode.attrs, Mark.none, true,
options.topMatch || topNode.type.contentMatch, topOptions)
else if (isOpen)
topContext = new NodeContext(null, null, Mark.none, Mark.none, true, null, topOptions)
topContext = new NodeContext(null, null, Mark.none, true, null, topOptions)
else
topContext = new NodeContext(parser.schema.topNodeType, null, Mark.none, Mark.none, true, null, topOptions)
topContext = new NodeContext(parser.schema.topNodeType, null, Mark.none, true, null, topOptions)
this.nodes = [topContext]

@@ -456,21 +435,8 @@ this.find = options.findPositions

// `style` attribute, `addElementWithStyles`.
addDOM(dom: DOMNode) {
if (dom.nodeType == 3) this.addTextNode(dom as Text)
else if (dom.nodeType == 1) this.addElement(dom as HTMLElement)
addDOM(dom: DOMNode, marks: readonly Mark[]) {
if (dom.nodeType == 3) this.addTextNode(dom as Text, marks)
else if (dom.nodeType == 1) this.addElement(dom as HTMLElement, marks)
}
withStyleRules(dom: HTMLElement, f: () => void) {
let style = dom.style
if (!style || !style.length) return f()
let marks = this.readStyles(dom.style)
if (!marks) return // A style with ignore: true
let [addMarks, removeMarks] = marks, top = this.top
for (let i = 0; i < removeMarks.length; i++) this.removePendingMark(removeMarks[i], top)
for (let i = 0; i < addMarks.length; i++) this.addPendingMark(addMarks[i])
f()
for (let i = 0; i < addMarks.length; i++) this.removePendingMark(addMarks[i], top)
for (let i = 0; i < removeMarks.length; i++) this.addPendingMark(removeMarks[i])
}
addTextNode(dom: Text) {
addTextNode(dom: Text, marks: readonly Mark[]) {
let value = dom.nodeValue!

@@ -499,3 +465,3 @@ let top = this.top

}
if (value) this.insertNode(this.parser.schema.text(value))
if (value) this.insertNode(this.parser.schema.text(value), marks)
this.findInText(dom)

@@ -509,3 +475,3 @@ } else {

// none is found, the element's content nodes are added directly.
addElement(dom: HTMLElement, matchAfter?: TagParseRule) {
addElement(dom: HTMLElement, marks: readonly Mark[], matchAfter?: TagParseRule) {
let name = dom.nodeName.toLowerCase(), ruleID: TagParseRule | undefined

@@ -517,3 +483,3 @@ if (listTags.hasOwnProperty(name) && this.parser.normalizeLists) normalizeList(dom)

this.findInside(dom)
this.ignoreFallback(dom)
this.ignoreFallback(dom, marks)
} else if (!rule || rule.skip || rule.closeParent) {

@@ -531,13 +497,13 @@ if (rule && rule.closeParent) this.open = Math.max(0, this.open - 1)

} else if (!dom.firstChild) {
this.leafFallback(dom)
this.leafFallback(dom, marks)
return
}
if (rule && rule.skip) this.addAll(dom)
else this.withStyleRules(dom, () => this.addAll(dom))
let innerMarks = rule && rule.skip ? marks : this.readStyles(dom, marks)
if (innerMarks) this.addAll(dom, innerMarks)
if (sync) this.sync(top)
this.needsBlock = oldNeedsBlock
} else {
this.withStyleRules(dom, () => {
this.addElementByRule(dom, rule as TagParseRule, rule!.consuming === false ? ruleID : undefined)
})
let innerMarks = this.readStyles(dom, marks)
if (innerMarks)
this.addElementByRule(dom, rule as TagParseRule, innerMarks, rule!.consuming === false ? ruleID : undefined)
}

@@ -547,19 +513,19 @@ }

// Called for leaf DOM nodes that would otherwise be ignored
leafFallback(dom: DOMNode) {
leafFallback(dom: DOMNode, marks: readonly Mark[]) {
if (dom.nodeName == "BR" && this.top.type && this.top.type.inlineContent)
this.addTextNode(dom.ownerDocument!.createTextNode("\n"))
this.addTextNode(dom.ownerDocument!.createTextNode("\n"), marks)
}
// Called for ignored nodes
ignoreFallback(dom: DOMNode) {
ignoreFallback(dom: DOMNode, marks: readonly Mark[]) {
// Ignored BR nodes should at least create an inline context
if (dom.nodeName == "BR" && (!this.top.type || !this.top.type.inlineContent))
this.findPlace(this.parser.schema.text("-"))
this.findPlace(this.parser.schema.text("-"), marks)
}
// Run any style parser associated with the node's styles. Either
// return an array of marks, or null to indicate some of the styles
// had a rule with `ignore` set.
readStyles(styles: CSSStyleDeclaration) {
let add = Mark.none, remove = Mark.none
// return an updated array of marks, or null to indicate some of the
// styles had a rule with `ignore` set.
readStyles(dom: HTMLElement, marks: readonly Mark[]) {
let styles = dom.style
// Because many properties will only show up in 'normalized' form

@@ -570,3 +536,3 @@ // in `style.item` (i.e. text-decoration becomes

// over the items.
if (styles.length) for (let i = 0; i < this.parser.matchedStyles.length; i++) {
if (styles && styles.length) for (let i = 0; i < this.parser.matchedStyles.length; i++) {
let name = this.parser.matchedStyles[i], value = styles.getPropertyValue(name)

@@ -577,9 +543,6 @@ if (value) for (let after: StyleParseRule | undefined = undefined;;) {

if (rule.ignore) return null
if (rule.clearMark) {
this.top.pendingMarks.concat(this.top.activeMarks).forEach(m => {
if (rule!.clearMark!(m)) remove = m.addToSet(remove)
})
} else {
add = this.parser.schema.marks[rule.mark!].create(rule.attrs).addToSet(add)
}
if (rule.clearMark)
marks = marks.filter(m => !rule!.clearMark!(m))
else
marks = marks.concat(this.parser.schema.marks[rule.mark!].create(rule.attrs))
if (rule.consuming === false) after = rule

@@ -589,3 +552,3 @@ else break

}
return [add, remove]
return marks
}

@@ -596,15 +559,18 @@

// the node's content is wrapped, and return true.
addElementByRule(dom: HTMLElement, rule: TagParseRule, continueAfter?: TagParseRule) {
let sync, nodeType, mark
addElementByRule(dom: HTMLElement, rule: TagParseRule, marks: readonly Mark[], continueAfter?: TagParseRule) {
let sync, nodeType
if (rule.node) {
nodeType = this.parser.schema.nodes[rule.node]
if (!nodeType.isLeaf) {
sync = this.enter(nodeType, rule.attrs || null, rule.preserveWhitespace)
} else if (!this.insertNode(nodeType.create(rule.attrs))) {
this.leafFallback(dom)
let inner = this.enter(nodeType, rule.attrs || null, marks, rule.preserveWhitespace)
if (inner) {
sync = true
marks = inner
}
} else if (!this.insertNode(nodeType.create(rule.attrs), marks)) {
this.leafFallback(dom, marks)
}
} else {
let markType = this.parser.schema.marks[rule.mark!]
mark = markType.create(rule.attrs)
this.addPendingMark(mark)
marks = marks.concat(markType.create(rule.attrs))
}

@@ -616,6 +582,6 @@ let startIn = this.top

} else if (continueAfter) {
this.addElement(dom, continueAfter)
this.addElement(dom, marks, continueAfter)
} else if (rule.getContent) {
this.findInside(dom)
rule.getContent(dom, this.parser.schema).forEach(node => this.insertNode(node))
rule.getContent(dom, this.parser.schema).forEach(node => this.insertNode(node, marks))
} else {

@@ -627,6 +593,5 @@ let contentDOM = dom

this.findAround(dom, contentDOM, true)
this.addAll(contentDOM)
this.addAll(contentDOM, marks)
}
if (sync && this.sync(startIn)) this.open--
if (mark) this.removePendingMark(mark, startIn)
}

@@ -637,3 +602,3 @@

// synchronize after every block element.
addAll(parent: DOMNode, startIndex?: number, endIndex?: number) {
addAll(parent: DOMNode, marks: readonly Mark[], startIndex?: number, endIndex?: number) {
let index = startIndex || 0

@@ -644,3 +609,3 @@ for (let dom = startIndex ? parent.childNodes[startIndex] : parent.firstChild,

this.findAtPoint(parent, index)
this.addDOM(dom!)
this.addDOM(dom!, marks)
}

@@ -653,3 +618,3 @@ this.findAtPoint(parent, index)

// nodes that we're in.
findPlace(node: Node) {
findPlace(node: Node, marks: readonly Mark[]) {
let route, sync: NodeContext | undefined

@@ -666,25 +631,25 @@ for (let depth = this.open; depth >= 0; depth--) {

}
if (!route) return false
if (!route) return null
this.sync(sync!)
for (let i = 0; i < route.length; i++)
this.enterInner(route[i], null, false)
return true
marks = this.enterInner(route[i], null, marks, false)
return marks
}
// Try to insert the given node, adjusting the context when needed.
insertNode(node: Node) {
insertNode(node: Node, marks: readonly Mark[]) {
if (node.isInline && this.needsBlock && !this.top.type) {
let block = this.textblockFromContext()
if (block) this.enterInner(block)
if (block) marks = this.enterInner(block, null, marks)
}
if (this.findPlace(node)) {
let innerMarks = this.findPlace(node, marks)
if (innerMarks) {
this.closeExtra()
let top = this.top
top.applyPending(node.type)
if (top.match) top.match = top.match.matchType(node.type)
let marks = top.activeMarks
for (let i = 0; i < node.marks.length; i++)
if (!top.type || top.type.allowsMarkType(node.marks[i].type))
marks = node.marks[i].addToSet(marks)
top.content.push(node.mark(marks))
let nodeMarks = Mark.none
for (let m of innerMarks.concat(node.marks))
if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, node.type))
nodeMarks = m.addToSet(nodeMarks)
top.content.push(node.mark(nodeMarks))
return true

@@ -697,18 +662,27 @@ }

// necessary.
enter(type: NodeType, attrs: Attrs | null, preserveWS?: boolean | "full") {
let ok = this.findPlace(type.create(attrs))
if (ok) this.enterInner(type, attrs, true, preserveWS)
return ok
enter(type: NodeType, attrs: Attrs | null, marks: readonly Mark[], preserveWS?: boolean | "full") {
let innerMarks = this.findPlace(type.create(attrs), marks)
if (innerMarks) innerMarks = this.enterInner(type, attrs, marks, true, preserveWS)
return innerMarks
}
// Open a node of the given type
enterInner(type: NodeType, attrs: Attrs | null = null, solid: boolean = false, preserveWS?: boolean | "full") {
enterInner(type: NodeType, attrs: Attrs | null, marks: readonly Mark[],
solid: boolean = false, preserveWS?: boolean | "full") {
this.closeExtra()
let top = this.top
top.applyPending(type)
top.match = top.match && top.match.matchType(type)
let options = wsOptionsFor(type, preserveWS, top.options)
if ((top.options & OPT_OPEN_LEFT) && top.content.length == 0) options |= OPT_OPEN_LEFT
this.nodes.push(new NodeContext(type, attrs, top.activeMarks, top.pendingMarks, solid, null, options))
let applyMarks = Mark.none
marks = marks.filter(m => {
if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, type)) {
applyMarks = m.addToSet(applyMarks)
return false
}
return true
})
this.nodes.push(new NodeContext(type, attrs, applyMarks, solid, null, options))
this.open++
return marks
}

@@ -825,24 +799,2 @@

}
addPendingMark(mark: Mark) {
let found = findSameMarkInSet(mark, this.top.pendingMarks)
if (found) this.top.stashMarks.push(found)
this.top.pendingMarks = mark.addToSet(this.top.pendingMarks)
}
removePendingMark(mark: Mark, upto: NodeContext) {
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)
let stashMark = level.popFromStashMark(mark)
if (stashMark && level.type && level.type.allowsMarkType(stashMark.type))
level.activeMarks = stashMark.addToSet(level.activeMarks)
}
if (level == upto) break
}
}
}

@@ -897,7 +849,1 @@

}
function findSameMarkInSet(mark: Mark, set: readonly Mark[]) {
for (let i = 0; i < set.length; i++) {
if (mark.eq(set[i])) return set[i]
}
}

@@ -545,3 +545,3 @@ import OrderedMap from "orderedmap"

/// A function or type name used to validate values of this
/// attibute. This will be used when deserializing the attribute
/// attribute. This will be used when deserializing the attribute
/// from JSON, and when running [`Node.check`](#model.Node.check).

@@ -548,0 +548,0 @@ /// When a function, it should raise an exception if the value isn't

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc