Input rules (schema-basic) firing inconsistently

Hello there. A million thanks to @marijn for creating ProseMirror, I’m having a blast implementing things with it :slight_smile:

I’m using schema-basic with some additions of my own and everything works greatly. But, I can’t get the input rules for things like the ordered/unordered list to fire consistently.

For example, if I start with some existing HTML, I’m able to trigger the input rules by just typing -<space> . However, if I start with a blank document (whatever DOMParser returns if you give it an empty string) it doesn’t fire.

I can work around this by starting all my empty documents as <p></p> but I’d like to understand what’s going on.

Pointers to documentation are welcome :slight_smile: Thanks again!

What does state.doc.toString() look like when the rule isn’t working?

OK, I’ve figured out what is breaking, but I don’t know what I’m doing wrong.

I’ve added an “aligned paragraph” node, before the basic-schema “paragraph” node. Definition is like so (excuse the ClojureScript syntax):

(def aligned-paragraph
  #js {:content "inline*"
       :group "block"
       :attrs #js {:align #js {:default nil}}
       :toDOM (fn [node]
                #js ["p"
                     #js {"data-align" (-> node .-attrs .-align)}
                     0])
       :parseDOM #js [#js{:tag "p"
                          :getAttrs (fn [dom]
                                      (let [style (.-style dom)
                                            align (.getPropertyValue style "text-align")
                                            attrs-count (.-length style)]
                                        (if (and align (= attrs-count 1))
                                          #js {:align (string/trim align)}
                                          false)))}]})

What I want to do is detect if an incoming p node has a style of text-align: something and if so, make the node “aligned-paragraph” instead of plain paragraph, sticking the something into the node attires so I can style it accordingly.

It actually does all that, but for some reason it breaks input rules. I suspect that it’s the “default” node that gets created and somehow things break, but I’m not sure.

Yes, the order in which nodes are listed in the schema determines which ones are created by default when multiple types fit a context. You’ll want to use the parse rule’s priority field to specify the parsing rule order.

When it’s breaking it shows:

doc(paragraph("hello"), paragraph_aligned("- what!"))

Which I think aligns in what I wrote above. The first paragraph is what I pass in as initial state, the second is what happens I press enter.

Thanks for confirming.

I’m trying to set the priority field in the schema, and I’m printing the parse rules from the parser (I construct one via DOMParser.fromSchema) but still no change. No matter what number I put as priority, I am seeing the initial order of the OrderedMap…

According to the docs items without a priority are counted as if the priority is 50, but it seems like it doesn’t have any effect.

Are you putting the priority on the parse rule object or on the node spec?

D’oh! I misread the docs and was indeed putting the priority on the node. When I put it under parseDom it works perfectly. Thanks for the help!

I would still like to understand better why the original behaviour was observed. What makes the paragraph node special so that the input rules only work within it?

AFAICT my paragraph_aligned node is equivalent, so I’m curious to know what I was doing wrong.

Also, I think it’s probably a better idea to mutate the basic-schema paragraph node and add this “align” attribute there, right?

I suspect your lists are still defined as requiring a regular paragraph as first child, so wrapping an aligned paragraph in a list won’t work, which is what that input rule tries to do.

You really don’t want to mutate nodes from a schema, but you could define your own paragraph node spec based on the default one with something like Object.assign or object spread syntax.