How to configure an editor

Martin Middel
FontoXML

The problem

Schemata

  • Most are 'like HTML', but different names

    <p />
    <para />
  • Or different attributes:

    <emphasis bold="true" />
    <emphasis type="bold" />

Or other structures

Martin is going to XML Prague Correct! London Incorrect Amsterdam Is that even a thing anymore? to present why Fonto works like it works.

Smart commands

Use schema knowledge to compute actions

(Vertically) insert node

Insert an image, somewhere 'here'

  1. Try to insert at the cursor
  2. Validate
  3. If invalid: discard changes and split the parent
  4. Return to step 1
  • A piece of| Text
  • A piece of<img src="..."/>| Text
  • A piece
  • |
  • of Text
  • A piece
  • <img src="..." />|
  • of Text
  • A piece
    • |
  • of Text
  • A piece
    • <img src="..." />|
  • of Text

Blueprints

'Try' out these changes, and revert them if they were bad

const blueprint = new Blueprint();

const newElement = document.createElement('newElement');
blueprint.appendChild(newParent, newElement);
const newParent = blueprint.getParentNode(newElement);
// newParent is now set the documentElement node.

const isValid = validator.isValidNode(blueprint, newParent);
// The validator is passed the blueprint so it can see
// whether the new structure is valid

if (isValid) {
  // We know it's valid, so we can safely apply these changes to the DOM
  blueprint.realize();
}

Deep schema knowledge

What if the node we split has required children?

<section>
    <title></title>
    <p>before split</p>
</section>
<section>
    <title></title> <--
    <p>after split</p>
</section>

Composable mutations

  • Insert a node vertically
  • , OR append if it can't be
  • Wrap the selection
  • , OR insert if there is no selection

Overlays

  • Blueprints, but layered

Operations

{
  "insert-image": {
    "steps": [
      { "type": "modal/open-image-browser" },
      {
        "type": "command/insert-node",
        "data": {
          "childNodeStructure": [
            "img", { "src": "{{href}}" ]
          ]
        }
      }
    ]
  }
}

Flow properties

More abstract commands
  • Splittable
    • Can we split this element?
  • Closed
    • Can we move our cursor out of this element?
  • Detached
    • Is this element actually 'here'?

JS-based selectors

matchNodeName("emphasis").withAttribute("type", "bold")

Stencils

[
  "figure",
  [
    "title",
    [{
      "bindTo": "titleGap",
      "multiple": true,
     "required": false
    }]
  ],
  ["img", { "href": { "bindTo": "hrefGap"}}]
]

Refinement

matchNodeName("emphasis")
  .withAttribute("type", "bold")
  .requireNodePredicate(
    (node, blueprint) =>
	  matchNodeName("someElement")
        .matches(
           blueprint.getParentNode(node),
           blueprint)

Selectors -> XPath

self::emphasis[@type="bold" and parent::someElement] 

Stencils -> XQuery

<figure>
  <title>{&data("title")}</title>
  <img @href="{href}" />
</figure>

Operations -> Update Facility

(WIP)

  • Open questions:
  • Blueprints / Overlays
  • integrate UI (do we want to?)

Take-aways

  • A lot of XML tools are missing in JavaScript
  • So build your own
  • Building your own APIs is fast
  • But standards are better
  • So implement them yourselves

Questions