@@ -68,6 +68,12 @@ import {Mark} from "./mark"
6868// property is only meaningful in a schema—when directly
6969// constructing a parser, the order of the rule array is used.
7070//
71+ // consuming:: ?boolean
72+ // By default, when a rule matches an element or style, no further
73+ // rules get a chance to match it. By setting this to `false`, you
74+ // indicate that even when this rule matches, other rules that come
75+ // after it should also run.
76+ //
7177// context:: ?string
7278// When given, restricts this rule to only match when the current
7379// context—the parent nodes into which the content is being
@@ -189,8 +195,8 @@ export class DOMParser {
189195 return Slice . maxOpen ( context . finish ( ) )
190196 }
191197
192- matchTag ( dom , context ) {
193- for ( let i = 0 ; i < this . tags . length ; i ++ ) {
198+ matchTag ( dom , context , after ) {
199+ for ( let i = after ? this . tags . indexOf ( after ) + 1 : 0 ; i < this . tags . length ; i ++ ) {
194200 let rule = this . tags [ i ]
195201 if ( matches ( dom , rule . tag ) &&
196202 ( rule . namespace === undefined || dom . namespaceURI == rule . namespace ) &&
@@ -205,8 +211,8 @@ export class DOMParser {
205211 }
206212 }
207213
208- matchStyle ( prop , value , context ) {
209- for ( let i = 0 ; i < this . styles . length ; i ++ ) {
214+ matchStyle ( prop , value , context , after ) {
215+ for ( let i = after ? this . styles . indexOf ( after ) + 1 : 0 ; i < this . styles . length ; i ++ ) {
210216 let rule = this . styles [ i ]
211217 if ( rule . style . indexOf ( prop ) != 0 ||
212218 rule . context && ! context . matchesContext ( rule . context ) ||
@@ -429,13 +435,14 @@ class ParseContext {
429435 }
430436 }
431437
432- // : (dom.Element)
438+ // : (dom.Element, ?ParseRule )
433439 // Try to find a handler for the given tag and use that to parse. If
434440 // none is found, the element's content nodes are added directly.
435- addElement ( dom ) {
436- let name = dom . nodeName . toLowerCase ( )
441+ addElement ( dom , matchAfter ) {
442+ let name = dom . nodeName . toLowerCase ( ) , ruleID
437443 if ( listTags . hasOwnProperty ( name ) && this . parser . normalizeLists ) normalizeList ( dom )
438- let rule = ( this . options . ruleFromNode && this . options . ruleFromNode ( dom ) ) || this . parser . matchTag ( dom , this )
444+ let rule = ( this . options . ruleFromNode && this . options . ruleFromNode ( dom ) ) ||
445+ ( ruleID = this . parser . matchTag ( dom , this , matchAfter ) )
439446 if ( rule ? rule . ignore : ignoreTags . hasOwnProperty ( name ) ) {
440447 this . findInside ( dom )
441448 } else if ( ! rule || rule . skip || rule . closeParent ) {
@@ -453,7 +460,7 @@ class ParseContext {
453460 if ( sync ) this . sync ( top )
454461 this . needsBlock = oldNeedsBlock
455462 } else {
456- this . addElementByRule ( dom , rule )
463+ this . addElementByRule ( dom , rule , rule . consuming === false ? ruleID : null )
457464 }
458465 }
459466
@@ -468,11 +475,15 @@ class ParseContext {
468475 // had a rule with `ignore` set.
469476 readStyles ( styles ) {
470477 let marks = Mark . none
471- for ( let i = 0 ; i < styles . length ; i += 2 ) {
472- let rule = this . parser . matchStyle ( styles [ i ] , styles [ i + 1 ] , this )
473- if ( ! rule ) continue
474- if ( rule . ignore ) return null
475- marks = this . parser . schema . marks [ rule . mark ] . create ( rule . attrs ) . addToSet ( marks )
478+ style: for ( let i = 0 ; i < styles . length ; i += 2 ) {
479+ for ( let after = null ; ; ) {
480+ let rule = this . parser . matchStyle ( styles [ i ] , styles [ i + 1 ] , this , after )
481+ if ( ! rule ) continue style
482+ if ( rule . ignore ) return null
483+ marks = this . parser . schema . marks [ rule . mark ] . create ( rule . attrs ) . addToSet ( marks )
484+ if ( rule . consuming === false ) after = rule
485+ else break
486+ }
476487 }
477488 return marks
478489 }
@@ -481,7 +492,7 @@ class ParseContext {
481492 // Look up a handler for the given node. If none are found, return
482493 // false. Otherwise, apply it, use its return value to drive the way
483494 // the node's content is wrapped, and return true.
484- addElementByRule ( dom , rule ) {
495+ addElementByRule ( dom , rule , continueAfter ) {
485496 let sync , nodeType , markType , mark
486497 if ( rule . node ) {
487498 nodeType = this . parser . schema . nodes [ rule . node ]
@@ -499,6 +510,8 @@ class ParseContext {
499510
500511 if ( nodeType && nodeType . isLeaf ) {
501512 this . findInside ( dom )
513+ } else if ( continueAfter ) {
514+ this . addElement ( dom , continueAfter )
502515 } else if ( rule . getContent ) {
503516 this . findInside ( dom )
504517 rule . getContent ( dom , this . parser . schema ) . forEach ( node => this . insertNode ( node ) )
0 commit comments