Soft validation in an editor environment

Martin Middel, FontoXML

What is FontoXML?

Note: the original presentation contains a demo of the FontoXML docbook editor. A similar editor is available at dita.fontoxml.com

Schematron

A set of queries for nodes

Followed by assertions and tests for them


						
							An example schema
							
								
									A paragraph must have a class
								
							
						
					

Schematron in Fonto


							
							
								
								
											footnote must not occur in the descendants of footnote
										
									
								
							
						

Note: the original presentation contains a demo of the FontoXML docbook editor. A similar editor is available at dita.fontoxml.com. At the moment of writing, this does not contain a schematron implementation though./

Performance

  • 3500+ (generated) Schematron rules
  • Look like this:
    • rule: /chunk[@class="achievement"]/ chunk-body/descendant::ol‍ [@class="achievement-list"]
    • assert: count(child::li[not(@class)]) < 1

Options

Server side

Big Update Button

XPath 3.1 in the browser

How we did it

Parse the XPath expression

  • PegJS parser generator
  • Outputs an ast in JSON:
  • 
    [
    	"absolutePath",
    	[
    		"path",
    		[
    			"descendant-or-self",
    			["kindTest", "node()"]
    		]
    	]
    ]
    							
  • This is saved in 'indexedDB', no parser hit next time

Execute it

  • Parse the ast to JavaScript models
  • Resolve functions
  • Propagate variables on the dynamic context

Instant feedback

  • We need instant feedback
  • Remember: non-technical authors
  • Need to be guided

How to do it live

  • Optimize all the queries
  • Only run affected queries

Dependency tracking


						class DependencyTrackingDomFacade {
							getParentNode (node) {
								addDep('childList', node.parentNode);
								return node.parentNode;
							}
							getNextSibling (node) {
								addDep('childList', node.parentNode);
								return node.nextSibling;
							}
							getAttribute (node, name) {
								addDep('attributes', node);
								return node.getAttribute(name);
							}
						}
					

MutationObserver


{
 type: 'childList' | 'attribute' | 'characterData',
 target: Node,
 addedNodes: Node[],
 removedNodes: Node[],
 nextSibling: Node?,
 previousSibling: Node?,
 attributeName: String?,
 oldValue: String?
}
					

Demo time

/chunk/chunk-body/ol/li


							
								
									

Some text

Some more text

  1. A list item

Done?

  • Not nearly
  • Static analysis / optimization
  • Partial queries / result caching

Conclusion

  • Client is happy
  • Good editing performance
  • Next year: write your paper in Fonto