VisualEditor/Debugging

From mediawiki.org

This page documents some helpful commands you can type into the console to investigate bugs in VisualEditor. Eventually, we should build a kind of debugging utility that makes this less necessary.

Inspecting the linear model[edit]

To inspect the linear model data:

>>> ve.init.target.surface.model.documentModel.data.data
[Object { type="paragraph", internal={...}}, "H", "e", "l", "l", "o", " ", ["w", [0]], ["o", [0]], ["r", [0]], ["l", [0]], ["d", [0]], "!", Object { type="/paragraph"}, Object { type="internalList"}, Object { type="/internalList"}]

To inspect the metadata:

>>> ve.init.target.surface.model.documentModel.metadata.data
[undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, [Object { attributes={...}, type="mwCategory"}]]

To get the interleaved data+metadata:

>>> ve.init.target.surface.model.documentModel.getFullData()
[Object { type="paragraph", internal={...}}, "H", "e", "l", "l", "o", " ", ["w", [0]], ["o", [0]], ["r", [0]], ["l", [0]], ["d", [0]], "!", Object { type="/paragraph"}, Object { type="internalList"}, Object { type="/internalList"}, Object { attributes={...}, type="mwCategory"}, Object { type="/mwCategory"}]

To inspect the store[edit]

Note that annotated characters are represented as ["w", [0]] where 0 is a store index. To get the annotation for a given store index:

>>> ve.init.target.surface.model.documentModel.store.value("hfbe3cfe099b83e1e").element
Object { type="textStyle/bold"}

Other items are represented directly:

>>> ve.init.target.surface.model.documentModel.store.value("hb37b5f09f2873ef3")
Array [p#mwBg]

>>> ve.init.target.surface.model.documentModel.store.value("hb37b5f09f2873ef3")[0].nodeName
"P"

To get the contents of the entire store:

>>> ve.init.target.surface.model.documentModel.store.hashStore
Object {h8788854973ec964c: Array(1), h740d0af80b1c0698: Array(1), h2f86de084f98631e: VeDmBoldAnnotation, h2d984d4ad173adc5: Array(1), h5f73cafcc20ffbc0: Array(1), …}

To inspect HTML[edit]

To look at the raw, unmodified HTML that was retrieved from Parsoid:

>>> ve.init.target.originalHtml

"<!DOCTYPE html>
<html prefix="dc: http://purl.org/dc/terms/ mw: http://mediawiki.org/rdf/" about="http://localhost/w/index.php/Special:Redirect/revision/561376450"><head prefix="mwr: http://localhost/w/index.php/Special:Redirect/"><meta property="mw:articleNamespace" content="0"/><link rel="dc:replaces" resource="mwr:revision/0"/><meta property="dc:modified" content="2013-10-17T18:12:26.000Z"/><meta about="mwr:user/0" property="dc:title" content="127.0.0.1"/><link rel="dc:contributor" resource="mwr:user/0"/><meta property="mw:revisionSHA1" content="f8846a82759cb8a393444422f0643651b9b32cda"/><meta property="dc:description" content="Created page with "Hello '''world'''!""/><meta property="mw:parsoidVersion" content="0"/><link rel="dc:isVersionOf" href="http://localhost/w/index.php/Hello_world"/><title>Hello_world</title><base href="http://localhost/w/index.php/Hello_world"/></head><body data-parsoid='{"dsr":[0,18,0,0]}'><p data-parsoid='{"dsr":[0,18,0,0]}'>Hello <b data-parsoid='{"dsr":[6,17,3,3]}'>world</b>!</p></body></html>"

To look at this HTML parsed into a DOM tree:

>>> d = ve.init.target.doc
Document
>>> d.body
<body data-parsoid="{"dsr":[0,18,0,0]}">
>>> d.body.outerHTML
"<body data-parsoid="{"dsr":[0,18,0,0]}"><p data-parsoid="{"dsr":[0,18,0,0]}">Hello <b data-parsoid="{"dsr":[6,17,3,3]}">world</b>!</p></body>"

To look at the HTML that would be sent back to Parsoid if the user were to save the current document, run:

>>> d2 = ve.init.target.getDocToSave()
Document
>>> ve.init.target.getHtml( d2 )
"<!doctype html><html><head></head><body><p data-parsoid="{"dsr":[0,18,0,0]}">Hello <b data-parsoid="{"dsr":[6,17,3,3]}">world</b>!</p></body></html>"

DOM diffing[edit]

This is done to investigate corruption warnings. Open up the editor without making any changes, then get HTMLDocuments for the ingoing and outgoing HTML:

d = ve.createDocumentFromHtml(ve.init.target.originalHtml)
//> Document
doc = ve.init.target.surface.model.documentModel
//> VeDmDocument { bindings={...}, documentNode={...}, internalList=VeDmInternalList, more...}
d2 = ve.dm.converter.getDomFromData(doc.getFullData(), doc.getStore(), doc.getInternalList())
//> Document

Then confirm that the documents are actually different:

d.body.isEqualNode(d2.body)
//> false

Now dig deeper to find where the diff is:

for ( i = 0; i < d.body.childNodes.length; i++) {
  if ( !d.body.childNodes[i].isEqualNode(d2.body.childNodes[i]) ) { console.log(i); }
}
//> 2
d.body.childNodes[2]
//> <p data-parsoid="{"dsr":[73,139,0,0]}">
d2.body.childNodes[2]
//> <p data-parsoid="{"dsr":[73,139,0,0]}">

And digging even deeper:

for ( i = 0; i < d.body.childNodes[2].childNodes.length; i++) {
  if ( !d.body.childNodes[2].childNodes[i].isEqualNode(d2.body.childNodes[2].childNodes[i]) ) { 
    console.log(i);
  }
}
//> 1

d.body.childNodes[2].childNodes[1]
//> <link data-parsoid="{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"},"dsr":[85,101,null,null]}" href="./Category:Foo" rel="mw:PageProp/Category">

d2.body.childNodes[2].childNodes[1]
//> <link rel="mw:WikiLink/Category" href="./Category:Foo" data-parsoid="{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"},"dsr":[85,101,null,null]}">

There we go.