Create variable feature

I am trying to create variable feature. i cant understand how to do the schema feature.

the outcome i want:
view in the editor:

<div>hello <span style="background:blue;" class="editor-variable" data-value="fullName">fullName</span></div>
<div>this is another row</div>

view on get html string:

 <div>hello {{fullname}} </div>
 <div>this is another row</div>
i want <span style="background:blue;" class="editor-variable" data-value="fullName">fullName</span>
to be translate to {{fullName}}
1 Like

What do you mean by “view on get html string”?

   1.  let domNode = pm.doc.content.toDOM();
   2. let tmp = document.createElement("div");
   3. tmp.appendChild(domNode);
   4, tmp.innerHTML; 

i mean the output on line 4 should be
     <div>hello {{fullname}} </div>
     <div>this is another row</div>

You may be looking for DOMSerializer.renderSpec.

Hey thanks for the help. i want to do something similar to Plugins | Variable

i want to use the prosemirror as email editor and to add support for variables with liquidjs

on the editor view i want to show chip like in the example about and the output should change the chip to plain text {{fullName}}. i looked over the link you sent me. can i create specific Serializer to the variable type.

what would be the best way to go ?

  • create schema
  • create markdown

if would be helpful if you can show me simple code example ? thanks for the help

The variable feature seems very close to the ProseMirror dino example, except you replace dinosaur enums with variable enums. Have you checked that out?

hey, Yes i tried this example. but i don’t understand how i can transform the node to different form on innerHTML

  let fragment = window.PM.model.DOMSerializer.fromSchema(dinoSchema).serializeFragment(window.view.state.doc.content);
  let tmp = document.createElement("div");

i added this code at the end of the dino example and i get same html as on the editor view for example if i change the function toDom to be

toDOM: node => ["div", {"dino-type": node.attrs.type,
                          src: "/img/dino/" + node.attrs.type + ".png",
                          title: node.attrs.type,
                          class: "dinosaur"}],

i want that on editor view it still will render img tag and only when i do the part of the innerHTML it will render div instead of img.

DOMSerializer uses the nodespec’s toDOM to render the PM node into a DOM element, so that’s why you’re getting the same innerHTML as what you see on the editor view.

i want that on editor view it still will render img tag and only when i do the part of the innerHTML it will render div instead of img.

One option to achieve this would be to take that fragment you get from serializeFragment and change it yourself outside of the PM library.

let fragment = DOMSerializer.fromSchema(dinoSchema).serializeFragment(window.view.state.doc.content);

const transform = (fragment) => {
  let dinos = fragment.querySelectorAll("div[dino-type]");
  dinos.forEach(d => d.parentNode.replace(newDiv, d)); // newDiv is how you want dinos to be rendered

hey, thanks for the response. what about creating another schema just for the innerHTML part ?

let fragment = DOMSerializer.fromSchema(dinoSchemaForInnerHTML).serializeFragment(window.view.state.doc.content); it possible to add click,hover event to the dino schema ? 2. on hovering the dino element,i want to show small toolbar above the element. is there built in/ clean way to do it. ?

Look into writing a custom node view, as it’ll allow you to register more granular click and hover events. For making a toolbar, I would recommend looking at tiptap as an example.