Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/lib/html2wt/DOMHandlers.js b/lib/html2wt/DOMHandlers.js
index 2738c2d87..56816fb72 100644
--- a/lib/html2wt/DOMHandlers.js
+++ b/lib/html2wt/DOMHandlers.js
@@ -1,1559 +1,1562 @@
'use strict';
require('../../core-upgrade.js');
var Consts = require('../config/WikitextConstants.js').WikitextConstants;
var DU = require('../utils/DOMUtils.js').DOMUtils;
var JSUtils = require('../utils/jsutils.js').JSUtils;
var Promise = require('../utils/promise.js');
var Util = require('../utils/Util.js').Util;
var WTSUtils = require('./WTSUtils.js').WTSUtils;
/**
* Definitions of what's loosely defined as the `domHandler` interface.
*
* FIXME: Solidify the interface in code.
*
* var domHandler = {
* handle: Promise.method(function(node, state, wrapperUnmodified) { ... }),
* sepnls: {
* before: (node, otherNode, state) => { min: 1, max: 2 },
* after: (node, otherNode, state) => { ... },
* firstChild: (node, otherNode, state) => { ... },
* lastChild: (node, otherNode, state) => { ... },
* },
* };
*/
// Forward declarations
var _htmlElementHandler;
var htmlElementHandler;
function id(v) {
return function() { return v; };
}
var genContentSpanTypes = new Set([
'mw:Nowiki',
'mw:Image',
'mw:Image/Frameless',
'mw:Image/Frame',
'mw:Image/Thumb',
'mw:Entity',
'mw:DiffMarker',
'mw:Placeholder',
]);
function isRecognizedSpanWrapper(type) {
return type && type.split(/\s+/).find(function(t) {
return genContentSpanTypes.has(t);
}) !== undefined;
}
function buildHeadingHandler(headingWT) {
return {
forceSOL: true,
handle: Promise.method(function(node, state, wrapperUnmodified) {
// For new elements, for prettier wikitext serialization,
// emit a space after the last '=' char.
var space = '';
if (DU.isNewElt(node)) {
var fc = node.firstChild;
if (fc && (!DU.isText(fc) || !fc.nodeValue.match(/^\s/))) {
space = ' ';
}
}
state.emitChunk(headingWT + space, node);
state.singleLineContext.enforce();
var p;
if (node.childNodes.length) {
p = state.serializeChildren(node);
} else {
// Deal with empty headings
state.emitChunk('<nowiki/>', node);
p = Promise.resolve();
}
return p.then(function() {
// For new elements, for prettier wikitext serialization,
// emit a space before the first '=' char.
space = '';
if (DU.isNewElt(node)) {
var lc = node.lastChild;
if (lc && (!DU.isText(lc) || !lc.nodeValue.match(/\s$/))) {
space = ' ';
}
}
state.emitChunk(space + headingWT, node);
state.singleLineContext.pop();
});
}),
sepnls: {
before: function(node, otherNode) {
if (DU.isNewElt(node) && DU.previousNonSepSibling(node)) {
// Default to two preceding newlines for new content
return { min: 2, max: 2 };
} else if (DU.isNewElt(otherNode) &&
DU.previousNonSepSibling(node) === otherNode) {
// T72791: The previous node was newly inserted, separate
// them for readability
return { min: 2, max: 2 };
} else {
return { min: 1, max: 2 };
}
},
after: id({ min: 1, max: 2 }),
},
};
}
/**
* List helper: DOM-based list bullet construction
*/
function getListBullets(state, node) {
var parentTypes = {
ul: '*',
ol: '#',
};
var listTypes = {
ul: '',
ol: '',
dl: '',
li: '',
dt: ';',
dd: ':',
};
// For new elements, for prettier wikitext serialization,
// emit a space after the last bullet (if required)
var space = '';
if (DU.isNewElt(node)) {
var fc = node.firstChild;
if (fc && (!DU.isText(fc) || !fc.nodeValue.match(/^\s/))) {
space = ' ';
}
}
var dp, nodeName, parentName;
var res = '';
while (node) {
nodeName = node.nodeName.toLowerCase();
dp = DU.getDataParsoid(node);
if (dp.stx !== 'html' && nodeName in listTypes) {
if (nodeName === 'li') {
var parentNode = node.parentNode;
while (parentNode && !(parentNode.nodeName.toLowerCase() in parentTypes)) {
parentNode = parentNode.parentNode;
}
if (parentNode) {
parentName = parentNode.nodeName.toLowerCase();
res = parentTypes[parentName] + res;
} else {
state.env.log("error/html2wt", "Input DOM is not well-formed.",
"Top-level <li> found that is not nested in <ol>/<ul>\n LI-node:",
node.outerHTML);
}
} else {
res = listTypes[nodeName] + res;
}
} else if (dp.stx !== 'html' || !dp.autoInsertedStart || !dp.autoInsertedEnd) {
break;
}
node = node.parentNode;
}
// Don't emit a space if we aren't returning any bullets.
return res.length ? res + space : '';
}
function wtListEOL(node, otherNode) {
if (!DU.isElt(otherNode) || DU.isBody(otherNode) ||
DU.isFirstEncapsulationWrapperNode(otherNode)) {
return { min: 0, max: 2 };
}
var nextSibling = DU.nextNonSepSibling(node);
var dp = DU.getDataParsoid(otherNode);
if (nextSibling === otherNode && dp.stx === 'html' || dp.src !== undefined) {
return { min: 0, max: 2 };
} else if (nextSibling === otherNode && DU.isListOrListItem(otherNode)) {
if (DU.isList(node) && otherNode.nodeName === node.nodeName) {
// Adjacent lists of same type need extra newline
return { min: 2, max: 2 };
} else if (DU.isListItem(node) || node.parentNode.nodeName in { LI: 1, DD: 1 }) {
// Top-level list
return { min: 1, max: 1 };
} else {
return { min: 1, max: 2 };
}
} else if (DU.isList(otherNode) ||
(DU.isElt(otherNode) && dp.stx === 'html')) {
// last child in ul/ol (the list element is our parent), defer
// separator constraints to the list.
return {};
} else {
return { min: 1, max: 2 };
}
}
// Normally we wait until hitting the deepest nested list element before
// emitting bullets. However, if one of those list elements is about-id
// marked, the tag handler will serialize content from data-mw parts or src.
// This is a problem when a list wasn't assigned the shared prefix of bullets.
// For example,
//
// ** a
// ** b
//
// Will assign bullets as,
//
// <ul><li-*>
// <ul>
// <li-*> a</li> <!-- no shared prefix -->
// <li-**> b</li> <!-- gets both bullets -->
// </ul>
// </li></ul>
//
// For the b-li, getListsBullets will walk up and emit the two bullets it was
// assigned. If it was about-id marked, the parts would contain the two bullet
// start tag it was assigned. However, for the a-li, only one bullet is
// associated. When it's about-id marked, serializing the data-mw parts or
// src would miss the bullet assigned to the container li.
function isTplListWithoutSharedPrefix(node) {
if (!DU.isEncapsulationWrapper(node)) {
return false;
}
var typeOf = node.getAttribute("typeof") || '';
if (/(?:^|\s)mw:Transclusion(?=$|\s)/.test(typeOf)) {
// If the first part is a string, template ranges were expanded to
// include this list element. That may be trouble. Otherwise,
// containers aren't part of the template source and we should emit
// them.
var dataMw = DU.getDataMw(node);
if (!dataMw.parts || typeof dataMw.parts[0] !== "string") {
return true;
}
// Less than two bullets indicates that a shared prefix was not
// assigned to this element. A safe indication that we should call
// getListsBullets on the containing list element.
return !/^[*#:;]{2,}$/.test(dataMw.parts[0]);
} else if (/(?:^|\s)mw:(Extension|Param)/.test(typeOf)) {
// Containers won't ever be part of the src here, so emit them.
return true;
} else {
return false;
}
}
function isBuilderInsertedElt(node) {
var dp = DU.getDataParsoid(node);
return dp && dp.autoInsertedStart && dp.autoInsertedEnd;
}
function buildListHandler(firstChildNames) {
return {
forceSOL: true,
handle: Promise.method(function(node, state, wrapperUnmodified) {
// Disable single-line context here so that separators aren't
// suppressed between nested list elements.
state.singleLineContext.disable();
var firstChildElt = DU.firstNonSepChildNode(node);
// Skip builder-inserted wrappers
// Ex: <ul><s auto-inserted-start-and-end-><li>..</li><li>..</li></s>...</ul>
// output from: <s>\n*a\n*b\n*c</s>
while (firstChildElt && isBuilderInsertedElt(firstChildElt)) {
firstChildElt = DU.firstNonSepChildNode(firstChildElt);
}
if (!firstChildElt || !(firstChildElt.nodeName in firstChildNames) ||
DU.isLiteralHTMLNode(firstChildElt)) {
state.emitChunk(getListBullets(state, node), node);
}
var liHandler = state.serializer.wteHandlers.liHandler
.bind(state.serializer.wteHandlers, node);
return state.serializeChildren(node, liHandler).then(function() {
state.singleLineContext.pop();
});
}),
sepnls: {
before: function(node, otherNode) {
// SSS FIXME: Thoughts about a fix (abandoned in this patch)
//
// Checking for DU.isBody(otherNode) and returning
// {min:0, max:0} should eliminate the annoying leading newline
// bug in parser tests, but it seems to cause other niggling issues
// <ul> <li>foo</li></ul> serializes to " *foo" which is buggy.
// So, we may need another constraint/flag/test in makeSeparator
// about the node and its context so that leading pre-inducing WS
// can be stripped
if (DU.isBody(otherNode)) {
return { min: 0, max: 0 };
} else if (DU.isText(otherNode) && DU.isListItem(node.parentNode)) {
// A list nested inside a list item
// <li> foo <dl> .. </dl></li>
return { min: 1, max: 1 };
} else {
return { min: 1, max: 2 };
}
},
after: wtListEOL,
},
};
}
function buildDDHandler(stx) {
return {
forceSOL: stx !== 'row',
handle: Promise.method(function(node, state, wrapperUnmodified) {
var firstChildElement = DU.firstNonSepChildNode(node);
var chunk = (stx === 'row') ? ':' : getListBullets(state, node);
if (!DU.isList(firstChildElement) ||
DU.isLiteralHTMLNode(firstChildElement)) {
state.emitChunk(chunk, node);
}
var liHandler = state.serializer.wteHandlers.liHandler
.bind(state.serializer.wteHandlers, node);
state.singleLineContext.enforce();
return state.serializeChildren(node, liHandler).then(function() {
state.singleLineContext.pop();
});
}),
sepnls: {
before: function(node, othernode) {
if (stx === 'row') {
return { min: 0, max: 0 };
} else {
return { min: 1, max: 2 };
}
},
after: wtListEOL,
firstChild: function(node, otherNode) {
if (!DU.isList(otherNode)) {
return { min: 0, max: 0 };
} else {
return {};
}
},
},
};
}
// IMPORTANT: Do not start walking from line.firstNode forward. Always
// walk backward from node. This is because in selser mode, it looks like
// line.firstNode doesn't always correspond to the wikitext line that is
// being processed since the previous emitted node might have been an unmodified
// DOM node that generated multiple wikitext lines.
function currWikitextLineHasBlockNode(line, node, skipNode) {
var parentNode = node.parentNode;
if (!skipNode) {
// If this node could break this wikitext line and emit
// non-ws content on a new line, the P-tag will be on that new line
// with text content that needs P-wrapping.
if (/\n[^\s]/.test(node.textContent)) {
return false;
}
}
node = DU.previousNonDeletedSibling(node);
while (!node || !DU.atTheTop(node)) {
while (node) {
// If we hit a block node that will render on the same line, we are done!
if (DU.isBlockNodeWithVisibleWT(node)) {
return true;
}
// If this node could break this wikitext line, we are done.
// This is conservative because textContent could be looking at descendents
// of 'node' that may not have been serialized yet. But this is safe.
if (/\n/.test(node.textContent)) {
return false;
}
node = DU.previousNonDeletedSibling(node);
// Don't go past the current line in any case.
if (line.firstNode && DU.isAncestorOf(node, line.firstNode)) {
return false;
}
}
node = parentNode;
parentNode = node.parentNode;
}
return false;
}
function newWikitextLineMightHaveBlockNode(node) {
node = DU.nextNonDeletedSibling(node);
while (node) {
if (DU.isText(node)) {
// If this node will break this wikitext line, we are done!
if (node.nodeValue.match(/\n/)) {
return false;
}
} else if (DU.isElt(node)) {
// These tags will always serialize onto a new line
if (Consts.HTMLTagsRequiringSOLContext.has(node.nodeName) &&
!DU.isLiteralHTMLNode(node)) {
return false;
}
// We hit a block node that will render on the same line
if (DU.isBlockNodeWithVisibleWT(node)) {
return true;
}
// Go conservative
return false;
}
node = DU.nextNonDeletedSibling(node);
}
return false;
}
function precedingQuoteEltRequiresEscape(node) {
// * <i> and <b> siblings don't need a <nowiki/> separation
// as long as quote chars in text nodes are always
// properly escaped -- which they are right now.
//
// * Adjacent quote siblings need a <nowiki/> separation
// between them if either of them will individually
// generate a sequence of quotes 4 or longer. That can
// only happen when either prev or node is of the form:
// <i><b>...</b></i>
//
// For new/edited DOMs, this can never happen because
// wts.minimizeQuoteTags.js does quote tag minimization.
//
// For DOMs from existing wikitext, this can only happen
// because of auto-inserted end/start tags. (Ex: ''a''' b ''c''')
var prev = DU.previousNonDeletedSibling(node);
return prev && DU.isQuoteElt(prev) && (
DU.isQuoteElt(DU.lastNonDeletedChildNode(prev)) ||
DU.isQuoteElt(DU.firstNonDeletedChildNode(node)));
}
function buildQuoteHandler(quotes) {
return {
handle: Promise.method(function(node, state, wrapperUnmodified) {
if (precedingQuoteEltRequiresEscape(node)) {
WTSUtils.emitStartTag('<nowiki/>', node, state);
}
WTSUtils.emitStartTag(quotes, node, state);
if (node.childNodes.length === 0) {
// Empty nodes like <i></i> or <b></b> need
// a <nowiki/> in place of the empty content so that
// they parse back identically.
if (WTSUtils.emitEndTag(quotes, node, state, true)) {
WTSUtils.emitStartTag('<nowiki/>', node, state);
WTSUtils.emitEndTag(quotes, node, state);
}
return;
} else {
return state.serializeChildren(node).then(function() {
WTSUtils.emitEndTag(quotes, node, state);
});
}
}),
};
}
var serializeTableElement = Promise.method(function(symbol, endSymbol, state, node) {
var token = DU.mkTagTk(node);
return state.serializer._serializeAttributes(node, token)
.then(function(sAttribs) {
if (sAttribs.length > 0) {
// IMPORTANT: 'endSymbol !== null' NOT 'endSymbol' since the
// '' string is a falsy value and we want to treat it as a
// truthy value.
return symbol + ' ' + sAttribs +
(endSymbol !== null ? endSymbol : ' |');
} else {
return symbol + (endSymbol || '');
}
});
});
var serializeTableTag = Promise.method(function(symbol, endSymbol, state,
node, wrapperUnmodified) {
if (wrapperUnmodified) {
var dsr = DU.getDataParsoid(node).dsr;
return state.getOrigSrc(dsr[0], dsr[0] + dsr[2]);
} else {
return serializeTableElement(symbol, endSymbol, state, node);
}
});
// Just serialize the children, ignore the (implicit) tag
var justChildren = {
handle: Promise.method(function(node, state, wrapperUnmodified) {
return state.serializeChildren(node);
}),
};
function stxInfoValidForTableCell(state, node) {
// If there is no syntax info, nothing to worry about
if (!DU.getDataParsoid(node).stx_v) {
return true;
}
// If we have an identical previous sibling, nothing to worry about
var prev = DU.previousNonDeletedSibling(node);
return prev !== null && prev.nodeName === node.nodeName;
}
// node is being serialized before/after a P-tag.
// While computing newline constraints, this function tests
// if node should be treated as a P-wrapped node
function treatAsPPTransition(node) {
// Treat text/p similar to p/p transition
// If an element, it should not be a:
// * block node or literal HTML node
// * template wrapper
// * mw:Includes meta or a SOL-transparent link
return DU.isText(node) || (
!DU.isBlockNode(node) &&
!DU.isLiteralHTMLNode(node) &&
!DU.isEncapsulationWrapper(node) &&
!DU.isSolTransparentLink(node) &&
!(/^mw:Includes\//.test(node.getAttribute('typeof'))));
}
// Uneditable forms wrapped with mw:Placeholder tags OR unedited nowikis
// N.B. We no longer emit self-closed nowikis as placeholders, so remove this
// once all our stored content is updated.
function emitPlaceholderSrc(node, state) {
var dp = DU.getDataParsoid(node);
if (/<nowiki\s*\/>/.test(dp.src)) {
state.hasSelfClosingNowikis = true;
}
// FIXME: Should this also check for tabs and plain space
// chars interspersed with newlines?
if (dp.src.match(/^\n+$/)) {
state.setSep((state.sep.src || '') + dp.src);
} else {
state.serializer.emitWikitext(dp.src, node);
}
}
function trWikitextNeeded(node, dp) {
// If the token has 'startTagSrc' set, it means that the tr
// was present in the source wikitext and we emit it -- if not,
// we ignore it.
// ignore comments and ws
if (dp.startTagSrc || DU.previousNonSepSibling(node)) {
return true;
} else {
// If parent has a thead/tbody previous sibling, then
// we need the |- separation. But, a caption preceded
// this node's parent, all is good.
var parentSibling = DU.previousNonSepSibling(node.parentNode);
// thead/tbody/tfoot is always present around tr tags in the DOM.
return parentSibling && parentSibling.nodeName !== 'CAPTION';
}
}
function maxNLsInTable(node, origNode) {
return DU.isNewElt(node) || DU.isNewElt(origNode) ? 1 : 2;
}
/**
* A map of `domHandler`s keyed on nodeNames.
*
* Includes specialized keys of the form: nodeName + '_' + dp.stx
*/
var tagHandlers = JSUtils.mapObject({
b: buildQuoteHandler("'''"),
i: buildQuoteHandler("''"),
dl: buildListHandler({ DT: 1, DD: 1 }),
ul: buildListHandler({ LI: 1 }),
ol: buildListHandler({ LI: 1 }),
li: {
forceSOL: true,
handle: Promise.method(function(node, state, wrapperUnmodified) {
var firstChildElement = DU.firstNonSepChildNode(node);
if (!DU.isList(firstChildElement) ||
DU.isLiteralHTMLNode(firstChildElement)) {
state.emitChunk(getListBullets(state, node), node);
}
var liHandler = state.serializer.wteHandlers.liHandler
.bind(state.serializer.wteHandlers, node);
state.singleLineContext.enforce();
return state.serializeChildren(node, liHandler).then(function() {
state.singleLineContext.pop();
});
}),
sepnls: {
before: function(node, otherNode) {
if ((otherNode === node.parentNode && otherNode.nodeName in {UL: 1, OL: 1}) ||
(DU.isElt(otherNode) && DU.getDataParsoid(otherNode).stx === 'html')) {
return {};
} else {
return { min: 1, max: 2 };
}
},
after: wtListEOL,
firstChild: function(node, otherNode) {
if (!DU.isList(otherNode)) {
return { min: 0, max: 0 };
} else {
return {};
}
},
},
},
dt: {
forceSOL: true,
handle: Promise.method(function(node, state, wrapperUnmodified) {
var firstChildElement = DU.firstNonSepChildNode(node);
if (!DU.isList(firstChildElement) ||
DU.isLiteralHTMLNode(firstChildElement)) {
state.emitChunk(getListBullets(state, node), node);
}
var liHandler = state.serializer.wteHandlers.liHandler
.bind(state.serializer.wteHandlers, node);
state.singleLineContext.enforce();
return state.serializeChildren(node, liHandler).then(function() {
state.singleLineContext.pop();
});
}),
sepnls: {
before: id({ min: 1, max: 2 }),
after: function(node, otherNode) {
if (otherNode.nodeName === 'DD' &&
DU.getDataParsoid(otherNode).stx === 'row') {
return { min: 0, max: 0 };
} else {
return wtListEOL(node, otherNode);
}
},
firstChild: function(node, otherNode) {
if (!DU.isList(otherNode)) {
return { min: 0, max: 0 };
} else {
return {};
}
},
},
},
dd_row: buildDDHandler('row'), // single-line dt/dd
dd: buildDDHandler(), // multi-line dt/dd
// XXX: handle options
table: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var dp = DU.getDataParsoid(node);
var wt = dp.startTagSrc || "{|";
var indentTable = node.parentNode.nodeName === 'DD' &&
DU.previousNonSepSibling(node) === null;
if (indentTable) {
state.singleLineContext.disable();
}
return serializeTableTag(wt, '', state, node, wrapperUnmodified)
.then(function(tableTag) {
state.emitChunk(tableTag, node);
if (!DU.isLiteralHTMLNode(node)) {
state.wikiTableNesting++;
}
return state.serializeChildren(node);
}).then(function() {
if (!DU.isLiteralHTMLNode(node)) {
state.wikiTableNesting--;
}
if (!state.sep.constraints) {
// Special case hack for "{|\n|}" since state.sep is
// cleared in SSP.pushSep after a separator is emitted.
// However, for {|\n|}, the <table> tag has no element
// children which means lastchild -> parent constraint
// is never computed and set here.
state.sep.constraints = { a: {}, b: {}, min: 1, max: 2 };
}
WTSUtils.emitEndTag(dp.endTagSrc || "|}", node, state);
if (indentTable) {
state.singleLineContext.pop();
}
});
}),
sepnls: {
before: function(node, otherNode) {
// Handle special table indentation case!
if (node.parentNode === otherNode &&
otherNode.nodeName === 'DD') {
return { min: 0, max: 2 };
} else {
return { min: 1, max: 2 };
}
},
after: function(node, otherNode) {
if (DU.isNewElt(node) || DU.isNewElt(otherNode)) {
return { min: 1, max: 2 };
} else {
return { min: 0, max: 2 };
}
},
firstChild: function(node, otherNode) {
return { min: 1, max: maxNLsInTable(node, otherNode) };
},
lastChild: function(node, otherNode) {
return { min: 1, max: maxNLsInTable(node, otherNode) };
},
},
},
tbody: justChildren,
thead: justChildren,
tfoot: justChildren,
tr: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var dp = DU.getDataParsoid(node);
var p;
if (trWikitextNeeded(node, dp)) {
p = serializeTableTag(dp.startTagSrc || "|-", '', state, node,
wrapperUnmodified).then(function(tableTag) {
WTSUtils.emitStartTag(tableTag, node, state);
});
} else {
p = Promise.resolve();
}
return p.then(function() {
return state.serializeChildren(node);
});
}),
sepnls: {
before: function(node, otherNode) {
if (trWikitextNeeded(node, DU.getDataParsoid(node))) {
return { min: 1, max: maxNLsInTable(node, otherNode) };
} else {
return { min: 0, max: maxNLsInTable(node, otherNode) };
}
},
after: function(node, otherNode) {
return { min: 0, max: maxNLsInTable(node, otherNode) };
},
},
},
th: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var dp = DU.getDataParsoid(node);
var usableDP = stxInfoValidForTableCell(state, node);
var attrSepSrc = usableDP ? (dp.attrSepSrc || null) : null;
var startTagSrc = usableDP ? dp.startTagSrc : '';
if (!startTagSrc) {
startTagSrc = (usableDP && dp.stx_v === 'row') ? '!!' : '!';
}
// T149209: Special case to deal with scenarios
// where the previous sibling put us in a SOL state
// (or will put in a SOL state when the separator is emitted)
if (state.onSOL || state.sep.constraints.min > 0) {
// You can use both "!!" and "||" for same-row headings (ugh!)
startTagSrc = startTagSrc.replace(/!!/, '!')
.replace(/\|\|/, '!')
.replace(/{{!}}{{!}}/, '{{!}}');
}
// If the HTML for the first th is not enclosed in a tr-tag,
// we start a new line. If not, tr will have taken care of it.
return serializeTableTag(startTagSrc, attrSepSrc,
state, node, wrapperUnmodified).then(function(tableTag) {
WTSUtils.emitStartTag(tableTag, node, state);
var thHandler = state.serializer.wteHandlers.thHandler
.bind(state.serializer.wteHandlers, node);
return state.serializeChildren(node, thHandler);
});
}),
sepnls: {
before: function(node, otherNode, state) {
if (otherNode.nodeName === 'TH' &&
DU.getDataParsoid(node).stx_v === 'row') {
// force single line
return { min: 0, max: maxNLsInTable(node, otherNode) };
} else {
return { min: 1, max: maxNLsInTable(node, otherNode) };
}
},
after: function(node, otherNode) {
if (otherNode.nodeName === 'TD') {
// Force a newline break
return { min: 1, max: maxNLsInTable(node, otherNode) };
} else {
return { min: 0, max: maxNLsInTable(node, otherNode) };
}
},
},
},
td: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var dp = DU.getDataParsoid(node);
var usableDP = stxInfoValidForTableCell(state, node);
var attrSepSrc = usableDP ? (dp.attrSepSrc || null) : null;
var startTagSrc = usableDP ? dp.startTagSrc : '';
if (!startTagSrc) {
startTagSrc = (usableDP && dp.stx_v === 'row') ? '||' : '|';
}
// T149209: Special case to deal with scenarios
// where the previous sibling put us in a SOL state
// (or will put in a SOL state when the separator is emitted)
if (state.onSOL || state.sep.constraints.min > 0) {
startTagSrc = startTagSrc.replace(/\|\|/, '|')
.replace(/{{!}}{{!}}/, '{{!}}');
}
// If the HTML for the first td is not enclosed in a tr-tag,
// we start a new line. If not, tr will have taken care of it.
return serializeTableTag(startTagSrc, attrSepSrc,
state, node, wrapperUnmodified).then(function(tableTag) {
var inWideTD = (tableTag.length > 1);
WTSUtils.emitStartTag(tableTag, node, state);
var tdHandler = state.serializer.wteHandlers.tdHandler
.bind(state.serializer.wteHandlers, node, inWideTD);
return state.serializeChildren(node, tdHandler);
});
}),
sepnls: {
before: function(node, otherNode, state) {
if (otherNode.nodeName === 'TD' &&
DU.getDataParsoid(node).stx_v === 'row') {
// force single line
return { min: 0, max: maxNLsInTable(node, otherNode) };
} else {
return { min: 1, max: maxNLsInTable(node, otherNode) };
}
},
after: function(node, otherNode) {
return { min: 0, max: maxNLsInTable(node, otherNode) };
},
},
},
caption: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var dp = DU.getDataParsoid(node);
// Serialize the tag itself
return serializeTableTag(dp.startTagSrc || '|+', null, state, node,
wrapperUnmodified).then(function(tableTag) {
WTSUtils.emitStartTag(tableTag, node, state);
return state.serializeChildren(node);
});
}),
sepnls: {
before: function(node, otherNode) {
return otherNode.nodeName !== 'TABLE' ?
{ min: 1, max: maxNLsInTable(node, otherNode) } :
{ min: 0, max: maxNLsInTable(node, otherNode) };
},
after: function(node, otherNode) {
return { min: 1, max: maxNLsInTable(node, otherNode) };
},
},
},
// Insert the text handler here too?
'#text': { },
p: {
// Counterintuitive but seems right.
// Otherwise the generated wikitext will parse as an indent-pre
// escapeWikitext nowiking will deal with leading space for content
// inside the p-tag, but forceSOL suppresses whitespace before the p-tag.
forceSOL: true,
handle: Promise.method(function(node, state, wrapperUnmodified) {
// XXX: Handle single-line mode by switching to HTML handler!
return state.serializeChildren(node);
}),
sepnls: {
before: function(node, otherNode, state) {
var otherNodeName = otherNode.nodeName;
var tableCellOrBody = new Set(['TD', 'TH', 'BODY']);
if (node.parentNode === otherNode &&
(DU.isListItem(otherNode) || tableCellOrBody.has(otherNodeName))) {
if (tableCellOrBody.has(otherNodeName)) {
return { min: 0, max: 1 };
} else {
return { min: 0, max: 0 };
}
} else if (
otherNode === DU.previousNonDeletedSibling(node) &&
// p-p transition
(otherNodeName === 'P' && DU.getDataParsoid(otherNode).stx !== 'html') ||
(
treatAsPPTransition(otherNode) &&
otherNode === DU.previousNonSepSibling(node) &&
// A new wikitext line could start at this P-tag. We have to figure out
// if 'node' needs a separation of 2 newlines from that P-tag. Examine
// previous siblings of 'node' to see if we emitted a block tag
// there => we can make do with 1 newline separator instead of 2
// before the P-tag.
!currWikitextLineHasBlockNode(state.currLine, otherNode)
)
) {
return { min: 2, max: 2 };
} else if (treatAsPPTransition(otherNode) ||
(DU.isBlockNode(otherNode) && node.parentNode === otherNode) ||
// new p-node added after sol-transparent wikitext should always
// get serialized onto a new wikitext line.
(DU.emitsSolTransparentSingleLineWT(state.env, otherNode) && DU.isNewElt(node))
) {
return { min: 1, max: 2 };
} else {
return { min: 0, max: 2 };
}
},
after: function(node, otherNode, state) {
if (!(node.lastChild && node.lastChild.nodeName === 'BR')
&& ((otherNode.nodeName === 'P' && DU.getDataParsoid(otherNode).stx !== 'html')
|| treatAsPPTransition(otherNode))
// A new wikitext line could start at this P-tag. We have to figure out
// if 'node' needs a separation of 2 newlines from that P-tag. Examine
// previous siblings of 'node' to see if we emitted a block tag
// there => we can make do with 1 newline separator instead of 2
// before the P-tag.
&& !currWikitextLineHasBlockNode(state.currLine, node, true)
// Since we are going to emit newlines before the other P-tag, we know it
// is going to start a new wikitext line. We have to figure out if 'node'
// needs a separation of 2 newlines from that P-tag. Examine following
// siblings of 'node' to see if we might emit a block tag there => we can
// make do with 1 newline separator instead of 2 before the P-tag.
&& !newWikitextLineMightHaveBlockNode(otherNode)
) {
return { min: 2, max: 2 };
} else if (treatAsPPTransition(otherNode) ||
(DU.isBlockNode(otherNode) && node.parentNode === otherNode)) {
return { min: 1, max: 2 };
} else {
return { min: 0, max: 2 };
}
},
},
},
// Wikitext indent pre generated with leading space
pre: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
// Handle indent pre
// XXX: Use a pre escaper?
return state.serializeIndentPreChildrenToString(node)
.then(function(content) {
// Strip (only the) trailing newline
var trailingNL = content.match(/\n$/);
content = content.replace(/\n$/, '');
// Insert indentation
var solRE = JSUtils.rejoin(
'(\\n(',
// SSS FIXME: What happened to the includeonly seen
// in wts.separators.js?
Util.COMMENT_REGEXP,
')*)',
{ flags: 'g' }
);
content = ' ' + content.replace(solRE, '$1 ');
// But skip "empty lines" (lines with 1+ comment and
// optional whitespace) since empty-lines sail through all
// handlers without being affected.
//
// See empty_line_with_comments rule in pegTokenizer.pegjs
//
// We could use 'split' to split content into lines and
// selectively add indentation, but the code will get
// unnecessarily complex for questionable benefits. So, going
// this route for now.
var emptyLinesRE = JSUtils.rejoin(
// This space comes from what we inserted earlier
/(^|\n) /,
'((?:',
/[ \t]*/,
Util.COMMENT_REGEXP,
/[ \t]*/,
')+)',
/(?=\n|$)/
);
content = content.replace(emptyLinesRE, '$1$2');
state.emitChunk(content, node);
// Preserve separator source
state.setSep((trailingNL && trailingNL[0]) || '');
});
}),
sepnls: {
before: function(node, otherNode) {
if (otherNode.nodeName === 'PRE' &&
DU.getDataParsoid(otherNode).stx !== 'html') {
return {min: 2};
} else {
return {min: 1};
}
},
after: function(node, otherNode) {
if (otherNode.nodeName === 'PRE' &&
DU.getDataParsoid(otherNode).stx !== 'html') {
return {min: 2};
} else {
return {min: 1};
}
},
firstChild: id({}),
lastChild: id({}),
},
},
// HTML pre
pre_html: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
return _htmlElementHandler(node, state);
}),
sepnls: {
before: id({}),
after: id({}),
firstChild: id({ max: Number.MAX_VALUE }),
lastChild: id({ max: Number.MAX_VALUE }),
},
},
meta: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var type = node.getAttribute('typeof');
var property = node.getAttribute('property');
var dp = DU.getDataParsoid(node);
if (dp.src !== undefined &&
/(^|\s)mw:Placeholder(\/\w*)?$/.test(type)) {
return emitPlaceholderSrc(node, state);
}
// Check for property before type so that page properties with
// templated attrs roundtrip properly.
// Ex: {{DEFAULTSORT:{{echo|foo}} }}
if (property) {
var switchType = property.match(/^mw\:PageProp\/(.*)$/);
if (switchType) {
var cat = switchType[1].match(/^(?:category)?(.*)/);
var p;
if (cat && Util.magicMasqs.has(cat[1])) {
p = state.serializer.serializedAttrVal(node, 'content',
{}).then(function(contentInfo) {
+ if (DU.hasExpandedAttrsType(node)) {
+ return '{{' + contentInfo.value + '}}';
+ }
if (dp.src !== undefined) {
return dp.src.replace(/^([^:]+:)(.*)$/,
"$1" + contentInfo.value + "}}");
} else {
var magicWord = cat[1].toUpperCase();
state.env.log("warn", cat[1] +
' is missing source. Rendering as ' +
magicWord + ' magicword');
return "{{" + magicWord + ":" +
contentInfo.value + "}}";
}
});
} else {
p = Promise.resolve().then(function() {
return state.env.conf.wiki.getMagicWordWT(
switchType[1], dp.magicSrc) || '';
});
}
return p.then(function(out) {
state.emitChunk(out, node);
});
} else {
return _htmlElementHandler(node, state);
}
} else if (type) {
switch (type) {
case 'mw:Includes/IncludeOnly':
state.emitChunk(dp.src || '', node);
break;
case 'mw:Includes/IncludeOnly/End':
// Just ignore.
break;
case 'mw:Includes/NoInclude':
state.emitChunk(dp.src || '<noinclude>', node);
break;
case 'mw:Includes/NoInclude/End':
state.emitChunk(dp.src || '</noinclude>', node);
break;
case 'mw:Includes/OnlyInclude':
state.emitChunk(dp.src || '<onlyinclude>', node);
break;
case 'mw:Includes/OnlyInclude/End':
state.emitChunk(dp.src || '</onlyinclude>', node);
break;
case 'mw:DiffMarker':
case 'mw:Separator':
// just ignore it
break;
default:
return _htmlElementHandler(node, state);
}
} else {
return _htmlElementHandler(node, state);
}
}),
sepnls: {
before: function(node, otherNode) {
var type = node.getAttribute('typeof') || node.getAttribute('property');
if (type && type.match(/mw:PageProp\/categorydefaultsort/)) {
if (otherNode.nodeName === 'P' && DU.getDataParsoid(otherNode).stx !== 'html') {
// Since defaultsort is outside the p-tag, we need 2 newlines
// to ensure that it go back into the p-tag when parsed.
return { min: 2 };
} else {
return { min: 1 };
}
} else if (DU.isNewElt(node) &&
// Placeholder metas don't need to be serialized on their own line
(node.nodeName !== "META" ||
!/(^|\s)mw:Placeholder(\/|$)/.test(node.getAttribute("typeof")))) {
return { min: 1 };
} else {
return {};
}
},
after: function(node, otherNode) {
// No diffs
if (DU.isNewElt(node) &&
// Placeholder metas don't need to be serialized on their own line
(node.nodeName !== "META" ||
!/(^|\s)mw:Placeholder(\/|$)/.test(node.getAttribute("typeof")))) {
return { min: 1 };
} else {
return {};
}
},
},
},
span: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var env = state.env;
var dp = DU.getDataParsoid(node);
var type = node.getAttribute('typeof');
var contentSrc = node.textContent || node.innerHTML;
if (isRecognizedSpanWrapper(type)) {
if (type === 'mw:Nowiki') {
var nativeExt = env.conf.wiki.extensionTags.get('nowiki');
return nativeExt.serialHandler.handle(node, state, wrapperUnmodified);
} else if (/(?:^|\s)mw\:Image(\/(Frame|Frameless|Thumb))?/.test(type)) {
return state.serializer.figureHandler(node);
} else if (/(?:^|\s)mw\:Entity/.test(type) && node.childNodes.length === 1) {
// handle a new mw:Entity (not handled by selser) by
// serializing its children
if (dp.src !== undefined && contentSrc === dp.srcContent) {
state.serializer.emitWikitext(dp.src, node);
} else if (DU.isText(node.firstChild)) {
state.emitChunk(
Util.entityEncodeAll(node.firstChild.nodeValue),
node.firstChild);
return;
} else {
return state.serializeChildren(node);
}
} else if (/(^|\s)mw:Placeholder(\/\w*)?/.test(type)) {
if (dp.src !== undefined) {
return emitPlaceholderSrc(node, state);
} else if (/(^|\s)mw:Placeholder(\s|$)/ &&
node.childNodes.length === 1 &&
DU.isText(node.firstChild) &&
// See the DisplaySpace hack in the urltext rule
// in the tokenizer.
/\u00a0+/.test(node.firstChild.nodeValue)
) {
state.emitChunk(
' '.repeat(node.firstChild.nodeValue.length),
node.firstChild);
return;
} else {
return _htmlElementHandler(node, state);
}
}
} else {
var kvs = DU.getAttributeKVArray(node).filter(function(kv) {
return !/^data-parsoid/.test(kv.k) &&
!(kv.k === 'id' && /^mw[\w-]{2,}$/.test(kv.v));
});
if (!state.rtTestMode && dp.misnested && dp.stx !== 'html' &&
!kvs.length) {
// Discard span wrappers added to flag misnested content.
// Warn since selser should have reused source.
env.log('warn', 'Serializing misnested content: ' + node.outerHTML);
return state.serializeChildren(node);
} else {
// Fall back to plain HTML serialization for spans created
// by the editor.
return _htmlElementHandler(node, state);
}
}
}),
},
figure: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
return state.serializer.figureHandler(node);
}),
sepnls: {
// TODO: Avoid code duplication
before: function(node) {
if (
DU.isNewElt(node) &&
node.parentNode &&
DU.isBody(node.parentNode)
) {
return { min: 1 };
}
return {};
},
after: function(node) {
if (
DU.isNewElt(node) &&
node.parentNode &&
DU.isBody(node.parentNode)
) {
return { min: 1 };
}
return {};
},
},
},
img: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
if (node.getAttribute('rel') === 'mw:externalImage') {
state.serializer.emitWikitext(node.getAttribute('src') || '', node);
} else {
return state.serializer.figureHandler(node);
}
}),
},
hr: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
state.emitChunk('-'.repeat(4 + (DU.getDataParsoid(node).extra_dashes || 0)), node);
}),
sepnls: {
before: id({ min: 1, max: 2 }),
// XXX: Add a newline by default if followed by new/modified content
after: id({ min: 0, max: 2 }),
},
},
h1: buildHeadingHandler("="),
h2: buildHeadingHandler("=="),
h3: buildHeadingHandler("==="),
h4: buildHeadingHandler("===="),
h5: buildHeadingHandler("====="),
h6: buildHeadingHandler("======"),
br: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
if (DU.getDataParsoid(node).stx === 'html' || node.parentNode.nodeName !== 'P') {
state.emitChunk('<br>', node);
} else {
// Trigger separator
if (state.sep.constraints && state.sep.constraints.min === 2 &&
node.parentNode.childNodes.length === 1) {
// p/br pair
// Hackhack ;)
// SSS FIXME: With the change I made, the above check can be simplified
state.sep.constraints.min = 2;
state.sep.constraints.max = 2;
state.emitChunk('', node);
} else {
state.emitChunk('', node);
}
}
}),
sepnls: {
before: function(node, otherNode) {
if (otherNode === node.parentNode && otherNode.nodeName === 'P') {
return { min: 1, max: 2 };
} else {
return {};
}
},
after: function(node, otherNode) {
// List items in wikitext dont like linebreaks.
//
// This seems like the wrong place to make this fix.
// To handle this properly and more generically / robustly,
// * we have to buffer output of list items,
// * on encountering list item close, post-process the buffer
// to eliminate any newlines.
if (DU.isListItem(node.parentNode)) {
return {};
} else {
return id({ min: 1 })();
}
},
},
},
a: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
return state.serializer.linkHandler(node);
}),
// TODO: Implement link tail escaping with nowiki in DOM handler!
},
link: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
return state.serializer.linkHandler(node);
}),
sepnls: {
before: function(node, otherNode) {
// sol-transparent link nodes are the only thing on their line.
// But, don't force separators wrt to its parent (body, p, list, td, etc.)
if (otherNode !== node.parentNode &&
DU.isSolTransparentLink(node) &&
!DU.isEncapsulationWrapper(node)) {
return { min: 1 };
} else {
return {};
}
},
after: function(node, otherNode, state) {
// sol-transparent link nodes are the only thing on their line
// But, don't force separators wrt to its parent (body, p, list, td, etc.)
if (otherNode !== node.parentNode &&
DU.isSolTransparentLink(node) &&
!DU.isEncapsulationWrapper(node)) {
return { min: 1 };
} else {
return {};
}
},
},
},
body: {
handle: Promise.method(function(node, state, wrapperUnmodified) {
// Just serialize the children
return state.serializeChildren(node);
}),
sepnls: {
firstChild: id({ min: 0, max: 1 }),
lastChild: id({ min: 0, max: 1 }),
},
},
});
var parentMap = {
LI: { UL: 1, OL: 1},
DT: { DL: 1 },
DD: { DL: 1 },
};
function parentBulletsHaveBeenEmitted(node) {
if (DU.isLiteralHTMLNode(node)) {
return true;
} else if (DU.isList(node)) {
return !DU.isListItem(node.parentNode);
} else {
console.assert(DU.isListItem(node));
var parentNode = node.parentNode;
// Skip builder-inserted wrappers
while (isBuilderInsertedElt(parentNode)) {
parentNode = parentNode.parentNode;
}
return !(parentNode.nodeName in parentMap[node.nodeName]);
}
}
function handleListPrefix(node, state) {
var bullets = '';
if (DU.isListOrListItem(node) &&
!parentBulletsHaveBeenEmitted(node) &&
!DU.previousNonSepSibling(node) && // Maybe consider parentNode.
isTplListWithoutSharedPrefix(node) &&
// Nothing to do for definition list rows,
// since we're emitting for the parent node.
!(node.nodeName === 'DD' &&
DU.getDataParsoid(node).stx === 'row')) {
bullets = getListBullets(state, node.parentNode);
}
return bullets;
}
function ClientError(message) {
Error.captureStackTrace(this, ClientError);
this.name = 'Bad Request';
this.message = message || 'Bad Request';
this.httpStatus = 400;
}
ClientError.prototype = Error.prototype;
/**
* Function returning `domHandler`s for nodes with encapsulated content.
*/
var _getEncapsulatedContentHandler = function() {
return {
handle: Promise.method(function(node, state, wrapperUnmodified) {
var env = state.env;
var self = state.serializer;
var dp = DU.getDataParsoid(node);
var dataMw = DU.getDataMw(node);
var p;
var typeOf = node.getAttribute('typeof') || '';
if (/(?:^|\s)(?:mw:Transclusion|mw:Param)(?=$|\s)/.test(typeOf)) {
if (dataMw.parts) {
p = self.serializeFromParts(node, dataMw.parts);
} else if (dp.src !== undefined) {
env.log("error", "data-mw missing in: " + node.outerHTML);
p = Promise.resolve(dp.src);
} else {
throw new ClientError("Cannot serialize " + typeOf + " without data-mw.parts or data-parsoid.src");
}
} else if (/(?:^|\s)mw:Extension\//.test(typeOf)) {
if (!dataMw.name && dp.src === undefined) {
// If there was no typeOf name, and no dp.src, try getting
// the name out of the mw:Extension type. This will
// generate an empty extension tag, but it's better than
// just an error.
var extGivenName = typeOf.replace(/(?:^|\s)mw:Extension\/([^\s]+)/, '$1');
if (extGivenName) {
env.log('error', 'no data-mw name for extension in: ', node.outerHTML);
dataMw.name = extGivenName;
}
}
if (dataMw.name) {
var nativeExt = env.conf.wiki.extensionTags.get(dataMw.name.toLowerCase());
if (nativeExt && nativeExt.serialHandler && nativeExt.serialHandler.handle) {
p = nativeExt.serialHandler.handle(node, state, wrapperUnmodified);
} else {
p = self.defaultExtensionHandler(node, state);
}
} else if (dp.src !== undefined) {
env.log('error', 'data-mw missing in: ' + node.outerHTML);
p = Promise.resolve(dp.src);
} else {
throw new ClientError('Cannot serialize extension without data-mw.name or data-parsoid.src.');
}
} else {
throw new Error('Should never reach here');
}
return p.then(function(s) {
state.singleLineContext.disable();
self.emitWikitext(handleListPrefix(node, state) + s, node);
state.singleLineContext.pop();
return DU.skipOverEncapsulatedContent(node);
});
}),
sepnls: {
// XXX: This is questionable, as the template can expand
// to newlines too. Which default should we pick for new
// content? We don't really want to make separator
// newlines in HTML significant for the semantics of the
// template content.
before: function(node, otherNode, state) {
var env = state.env;
var typeOf = node.getAttribute('typeof') || '';
var dataMw = DU.getDataMw(node);
var dp = DU.getDataParsoid(node);
// Handle native extension constraints.
if (/(?:^|\s)mw:Extension\//.test(typeOf) &&
// Only apply to plain extension tags.
!/(?:^|\s)mw:Transclusion(?:\s|$)/.test(typeOf)) {
if (dataMw.name) {
var nativeExt = env.conf.wiki.extensionTags.get(dataMw.name.toLowerCase());
if (nativeExt && nativeExt.serialHandler && nativeExt.serialHandler.before) {
var ret = nativeExt.serialHandler.before(node, otherNode, state);
if (ret !== null) { return ret; }
}
}
}
// If this content came from a multi-part-template-block
// use the first node in that block for determining
// newline constraints.
if (dp.firstWikitextNode) {
var nodeName = dp.firstWikitextNode.toLowerCase();
var h = tagHandlers.get(nodeName);
if (!h && dp.stx === 'html' && nodeName !== 'a') {
h = htmlElementHandler;
}
if (h && h.sepnls && h.sepnls.before) {
return h.sepnls.before(node, otherNode, state);
}
}
// default behavior
return { min: 0, max: 2 };
},
},
};
};
/**
* Just the handle for the htmlElementHandler defined below.
* It's used as a fallback in some of the tagHandlers above.
*/
_htmlElementHandler = Promise.method(function(node, state, wrapperUnmodified) {
var serializer = state.serializer;
// Wikitext supports the following list syntax:
//
// * <li class="a"> hello world
//
// The "LI Hack" gives support for this syntax, and we need to
// specially reconstruct the above from a single <li> tag.
serializer._handleLIHackIfApplicable(node);
return serializer._serializeHTMLTag(node, wrapperUnmodified)
.then(function(tag) {
WTSUtils.emitStartTag(tag, node, state);
var p;
if (node.childNodes.length) {
var inPHPBlock = state.inPHPBlock;
if (Util.tagOpensBlockScope(node.nodeName.toLowerCase())) {
state.inPHPBlock = true;
}
if (node.nodeName === 'PRE') {
// Handle html-pres specially
// 1. If the node has a leading newline, add one like it (logic copied from VE)
// 2. If not, and it has a data-parsoid strippedNL flag, add it back.
// This patched DOM will serialize html-pres correctly.
var lostLine = '';
var fc = node.firstChild;
if (fc && DU.isText(fc)) {
var m = fc.nodeValue.match(/^\n/);
lostLine = m && m[0] || '';
}
if (!lostLine && DU.getDataParsoid(node).strippedNL) {
lostLine = '\n';
}
state.emitChunk(lostLine, node);
}
p = state.serializeChildren(node).then(function() {
state.inPHPBlock = inPHPBlock;
});
} else {
p = Promise.resolve();
}
return p.then(function() {
return serializer._serializeHTMLEndTag(node, wrapperUnmodified);
}).then(function(endTag) {
WTSUtils.emitEndTag(endTag, node, state);
});
});
});
htmlElementHandler = { handle: _htmlElementHandler };
if (typeof module === "object") {
module.exports.tagHandlers = tagHandlers;
module.exports.htmlElementHandler = htmlElementHandler;
module.exports._getEncapsulatedContentHandler =
_getEncapsulatedContentHandler;
}
diff --git a/lib/wt2html/tt/AttributeExpander.js b/lib/wt2html/tt/AttributeExpander.js
index b8b2b515c..4c811eda8 100644
--- a/lib/wt2html/tt/AttributeExpander.js
+++ b/lib/wt2html/tt/AttributeExpander.js
@@ -1,511 +1,528 @@
/*
* Generic attribute expansion handler.
*/
'use strict';
var coreutil = require('util');
var Util = require('../../utils/Util.js').Util;
var TokenHandler = require('./TokenHandler.js');
var AttributeTransformManager = require('../TokenTransformManager.js').AttributeTransformManager;
var PegTokenizer = require('../tokenizer.js').PegTokenizer;
var defines = require('../parser.defines.js');
// define some constructor shortcuts
var NlTk = defines.NlTk;
var TagTk = defines.TagTk;
var SelfclosingTagTk = defines.SelfclosingTagTk;
function nlTkIndex(nlTkOkay, tokens, atTopLevel) {
// Moving this check here since it makes the
// callsite cleaner and simpler.
if (nlTkOkay) {
return -1;
}
// Check if we have a newline token in the attribute key/value token stream.
// However, newlines are acceptable inside a <*include*>..</*include*> directive
// since they are stripped out.
//
// var includeRE = !atTopLevel ? /(?:^|\s)mw:Includes\/NoInclude(\/.*)?(?:\s|$)/ : /(?:^|\s)mw:Includes\/(?:Only)?Include(?:Only)?(\/.*)?(?:\s|$)/;
//
// SSS FIXME: We cannot support this usage for <*include*> directives currently
// since they don't go through template encapsulation and don't have a data-mw
// format with "wt" and "transclusion" parts that we can use to just track bits
// of wikitext that don't have a DOM representation.
//
// So, for now, we just suppress all newlines contained within these directives.
//
var includeRE = /(?:^|\s)mw:Includes\/(?:No|Only)?Include(?:Only)?(\/.*)?(?:\s|$)/;
var inInclude = false;
for (var i = 0, n = tokens.length; i < n; i++) {
var t = tokens[i];
if (t.constructor === SelfclosingTagTk) {
var type = t.getAttribute("typeof");
var typeMatch = type ? type.match(includeRE) : null;
if (typeMatch) {
inInclude = !typeMatch[1] || !typeMatch[1].match(/\/End$/);
}
} else if (!inInclude && t.constructor === NlTk) {
// newline token outside <*include*>
return i;
}
}
return -1;
}
function splitTokens(env, token, nlTkPos, tokens, wrapTemplates) {
// FIXME: It is insufficient to rely merely on wrapTemplates
// because right now, it is always true. Since tsr values are
// stripped from template tokens, we use that as a proxy.
wrapTemplates = wrapTemplates && token.dataAttribs.tsr;
var buf = [];
var postNLBuf, startMeta, metaTokens;
// Split the token array around the first newline token.
for (var i = 0, l = tokens.length; i < l; i++) {
var t = tokens[i];
if (i === nlTkPos) {
// split here!
postNLBuf = tokens.slice(i);
break;
} else {
if (wrapTemplates && t.constructor === SelfclosingTagTk) {
var type = t.getAttribute("typeof");
var typeMatch = type && type.match(/(mw:(Transclusion|Param|Extension|Includes\/)(.*)?$)/);
// Don't trip on transclusion end tags and mw:Extension/ref/Marker tags
if (typeMatch && !typeMatch[1].match(/\/(End|Marker)$/)) {
startMeta = t;
}
}
buf.push(t);
}
}
if (wrapTemplates && startMeta) {
// Support template wrapping with the following steps:
// - Hoist the transclusion start-meta from the first line
// to before the token.
// - Update the start-meta tsr to that of the token.
// - Record the wikitext between the token and the transclusion
// as an unwrappedWT data-parsoid attribute of the start-meta.
var dp = startMeta.dataAttribs;
dp.unwrappedWT = env.page.src.substring(token.dataAttribs.tsr[0], dp.tsr[0]);
// unwrappedWT will be added to the data-mw.parts array which makes
// this a multi-template-content-block.
// Record the first wikitext node of this block (required by html->wt serialization)
dp.firstWikitextNode = token.dataAttribs.stx ? token.name + "_" + token.dataAttribs.stx : token.name;
// Update tsr[0] only. Unless the end-meta token is moved as well,
// updating tsr[1] can introduce bugs in cases like:
//
// {|
// |{{singlechart|Australia|93|artist=Madonna|album=Girls Gone Wild}}|x
// |}
//
// which can then cause dirty diffs (the "|" before the x gets dropped).
dp.tsr[0] = token.dataAttribs.tsr[0];
metaTokens = [startMeta];
return { metaTokens: metaTokens, preNLBuf: buf, postNLBuf: postNLBuf };
} else {
return { metaTokens: [], preNLBuf: tokens, postNLBuf: [] };
}
}
/* ----------------------------------------------------------
* This helper method strips all meta tags introduced by
* transclusions, etc. and returns the content.
* ---------------------------------------------------------- */
function stripMetaTags(tokens, wrapTemplates) {
var buf = [];
var isPushed = false;
var hasGeneratedContent = false;
for (var i = 0, l = tokens.length; i < l; i++) {
var t = tokens[i];
if ([TagTk, SelfclosingTagTk].indexOf(t.constructor) !== -1) {
isPushed = false;
if (wrapTemplates) {
// Strip all meta tags.
var type = t.getAttribute("typeof");
var typeMatch = type && type.match(/(mw:(Transclusion|Param|Extension|Includes\/)(.*)?$)/);
if (typeMatch) {
if (!typeMatch[1].match(/\/End$/)) {
hasGeneratedContent = true;
}
} else {
isPushed = true;
buf.push(t);
}
}
if (!isPushed && t.name !== "meta") {
// Dont strip token if it is not a meta-tag
buf.push(t);
}
} else {
buf.push(t);
}
}
return { hasGeneratedContent: hasGeneratedContent, value: buf };
}
/**
* @class
*
* Generic attribute expansion handler.
*
* @extends TokenHandler
* @constructor
*/
function AttributeExpander() {
TokenHandler.apply(this, arguments);
}
coreutil.inherits(AttributeExpander, TokenHandler);
AttributeExpander.prototype.rank = 1.12;
AttributeExpander.prototype.skipRank = 1.13; // should be higher than all other ranks above
AttributeExpander.prototype.init = function() {
this.tokenizer = new PegTokenizer(this.env);
- // XXX: only register for tag tokens?
- this.manager.addTransform(this.onToken.bind(this),
- 'AttributeExpander:onToken', this.rank, 'any');
+ if (!this.options.standalone) {
+ // XXX: only register for tag tokens?
+ this.manager.addTransform(this.onToken.bind(this),
+ 'AttributeExpander:onToken', this.rank, 'any');
+ }
};
/**
* Token handler
*
* Expands target and arguments (both keys and values) and either directly
* calls or sets up the callback to _expandTemplate, which then fetches and
* processes the template.
*
* @private
* @param {Token} token -- token whose attrs being expanded
* @param {Frame} frame -- unused here, passed in by AsyncTTM to all handlers
* @param {Function} cb -- callback receiving the expanded token
*/
AttributeExpander.prototype.onToken = function(token, frame, cb) {
// console.warn( 'AttributeExpander.onToken: ', JSON.stringify( token ) );
if ((token.constructor === TagTk || token.constructor === SelfclosingTagTk) &&
// Do not process dom-fragment tokens: a separate handler deals with them.
token.attribs && token.attribs.length &&
token.name !== 'mw:dom-fragment-token' &&
(token.name !== 'meta' ||
!/mw:(TSRMarker|Placeholder|Transclusion|Param|Includes|Extension\/ref\/Marker)/.test(token.getAttribute('typeof')))
) {
cb({ async: true });
(new AttributeTransformManager(
this.manager,
{ wrapTemplates: this.options.wrapTemplates },
this._returnAttributes.bind(this, token, cb)
)).process(token.attribs);
} else {
cb({ tokens: [token] });
}
};
/**
* Callback for attribute expansion in AttributeTransformManager
*
* @private
*/
AttributeExpander.prototype._returnAttributes = function(token, cb, expandedAttrs) {
// SSS FIXME: This is mostly useless.
//
// wrapTemplates will always be true for all tokens from the top-level
// as well as tokens coming from template expansions because template
// content only goes through the PEG in a separate pipeline and the
// resulting tokens are merged back into the main top-level pipeline
// which has wrapTemplates set to true. To see this, look at the
// default pipeline type in ext.core.TemplateHandler.js:_startTokenPipeline
// and check the components of that pipeline type in mediawiki.parser.js
//
// Currently, this doesn't matter a whole lot since templates are currently
// fully expanded with the PHP preprocessor and we encounter transclusions
// only from the top-level. However, when T93368 scenarios happen (or when
// we are in the native parsoid pipeline), this could be a more serious issue.
var wrapTemplates = this.options.wrapTemplates;
var env = this.manager.env;
var modified = false;
var metaTokens = [];
var postNLToks = [];
var skipRank = this.skipRank;
var tmpDataMW;
var oldAttrs = token.attribs;
// Build newAttrs lazily (on-demand) to avoid creating
// objects in the common case where nothing of significance
// happens in this code.
var newAttrs = null;
var nlTkPos = -1;
var i, l;
var nlTkOkay = Util.isHTMLTag(token) || !Util.isTableTag(token);
// Identify attributes that were generated in full or in part using templates
for (i = 0, l = oldAttrs.length; i < l; i++) {
var oldA = oldAttrs[i];
var expandedA = expandedAttrs[i];
// Preserve the key and value source, if available.
// But, if 'oldA' wasn't cloned, expandedA will be the same as 'oldA'.
if (oldA !== expandedA) {
expandedA.ksrc = oldA.ksrc;
expandedA.vsrc = oldA.vsrc;
expandedA.srcOffsets = oldA.srcOffsets;
}
// Deal with two template-expansion scenarios for the attribute key (not value)
//
// 1. We have a template that generates multiple attributes of this token
// as well as content after the token.
// Ex: infobox templates from aircraft, ship, and other pages
// See enwiki:Boeing_757
//
// - Split the expanded tokens into multiple lines.
// - Expanded attributes associated with the token are retained in the
// first line before a NlTk.
// - Content tokens after the NlTk are moved to subsequent lines.
// - The meta tags are hoisted before the original token to make sure
// that the entire token and following content is encapsulated as a unit.
//
// 2. We have a template that only generates multiple attributes of this
// token. In that case, we strip all template meta tags from the expanded
// tokens and assign it as mw:ExpandedAttrs type with orig/expanded
// values in data-mw.
//
// Reparse-KV-string scenario with templated attributes:
// -----------------------------------------------------
// In either scenario above, we need additional special handling if the
// template generates one or more k=v style strings:
// <div {{echo|1=style='color:red''}}></div>
// <div {{echo|1=style='color:red' title='boo'}}></div>
//
// Real use case: Template {{ligne grise}} on frwp.
//
// To support this, we utilize the following hack. If we got a string of the
// form "k=v" and our orig-v was "", we convert the token array to a string
// and retokenize it to extract one or more attributes.
//
// But, we won't support scenarios like this:
// {| title={{echo|1='name' style='color:red;'\n|-\n|foo}}\n|}
// Here, part of one attribute and additional complete attribute strings
// need reparsing, and that isn't a use case that is worth more complexity here.
//
// FIXME:
// ------
// 1. It is not possible for multiple instances of scenario 1 to be triggered
// for the same token. So, I am not bothering trying to test and deal with it.
//
// 2. We trigger the Reparse-KV-string scenario only for attribute keys,
// since it isn't possible for attribute values to require this reparsing.
// However, it is possible to come up with scenarios where a template
// returns the value for one attribute and additional k=v strings for newer
// attributes. We don't support that scenario, but don't even test for it.
//
// Reparse-KV-string scenario with non-string attributes:
// ------------------------------------------------------
// This is only going to be the case with table wikitext that has special syntax
// for attribute strings.
//
// {| <div>a</div> style='border:1px solid black;'
// |- <div>b</div> style='border:1px dotted blue;'
// | <div>c</div> style='color:red;'
// |}
//
// In wikitext like the above, the PEG tokenizer doesn't recognize these as
// valid attributes (the templated attribute scenario is a special case) and
// orig-v will be "". So, the same strategy as above is applied here as well.
var origK = expandedA.k;
var origV = expandedA.v;
var updatedK = null;
var updatedV = null;
var expandedK = expandedA.k;
var reparsedKV = false;
if (expandedK) {
// FIXME: We should get rid of these array/string/non-string checks
// and probably use appropriately-named flags to convey type information.
if (Array.isArray(oldA.k)) {
if (!(expandedK.constructor === String && /(^|\s)mw:maybeContent(\s|$)/.test(expandedK))) {
nlTkPos = nlTkIndex(nlTkOkay, expandedK, wrapTemplates);
if (nlTkPos !== -1) {
// Scenario 1 from the documentation comment above.
updatedK = splitTokens(env, token, nlTkPos, expandedK, wrapTemplates);
expandedK = updatedK.preNLBuf;
postNLToks = updatedK.postNLBuf;
metaTokens = updatedK.metaTokens;
} else {
// Scenario 2 from the documentation comment above.
updatedK = stripMetaTags(expandedK, wrapTemplates);
expandedK = updatedK.value;
}
expandedA.k = expandedK;
// Check if we need to deal with the Reparse-KV-string scenario.
// (See documentation comment above)
if (expandedA.v === '') {
// Extract a parsable string from the token array.
// Trim whitespace to ensure tokenizer isn't tripped up
// by the presence of unnecessary whitespace.
var kStr = Util.tokensToString(expandedK).trim();
var rule = nlTkOkay ? 'generic_newline_attributes' : 'table_attributes';
var kvs = /=/.test(kStr) ? this.tokenizer.tokenizeSync(kStr, rule) : null;
if (kvs) {
// SSS FIXME: Collect all keys here, not just the first key
// i.e. in a string like {{echo|1=id='v1' title='foo' style='..'}}
// that string is setting attributes for [id, title, style], not just id.
//
// That requires the ability for the data-mw.attribs[i].txt to be an array.
// However, the spec at [[mw:Parsoid/MediaWiki_DOM_spec]] says:
// "This spec also assumes that a template can only
// generate one attribute rather than multiple attributes."
//
// So, revision of the spec is another FIXME at which point this code can
// be updated to reflect the revised spec.
expandedK = kvs[0].k;
reparsedKV = true;
if (!newAttrs) {
newAttrs = i === 0 ? [] : expandedAttrs.slice(0, i - 1);
}
newAttrs = newAttrs.concat(kvs);
}
}
modified = true;
}
} else if (expandedK !== oldA.k) {
modified = true;
}
// We have a potentially expanded value.
// Check if the value came from a template/extension expansion.
var attrValTokens = origV;
if (expandedK.constructor === String && Array.isArray(oldA.v)) {
if (!expandedK.match(/^mw:/)) {
nlTkPos = nlTkIndex(nlTkOkay, attrValTokens, wrapTemplates);
if (nlTkPos !== -1) {
// Scenario 1 from the documentation comment above.
updatedV = splitTokens(env, token, nlTkPos, attrValTokens, wrapTemplates);
attrValTokens = updatedV.preNLBuf;
postNLToks = updatedV.postNLBuf;
metaTokens = updatedV.metaTokens;
} else {
// Scenario 2 from the documentation comment above.
updatedV = stripMetaTags(attrValTokens, wrapTemplates);
attrValTokens = updatedV.value;
}
expandedA.v = attrValTokens;
}
modified = true;
} else if (attrValTokens !== oldA.v) {
modified = true;
}
// Update data-mw to account for templated attributes.
// For editability, set HTML property.
//
// If we encountered a reparse-KV-string scenario,
// we set the value's HTML to [] since we can edit
// the transclusion either via the key's HTML or the
// value's HTML, but not both.
if ((reparsedKV && (updatedK.hasGeneratedContent || metaTokens.length > 0)) ||
(updatedK && updatedK.hasGeneratedContent) ||
(updatedV && updatedV.hasGeneratedContent)) {
var key = expandedK.constructor === String ? expandedK : Util.tokensToString(expandedK);
if (!tmpDataMW) {
tmpDataMW = new Map();
}
tmpDataMW.set(key, {
k: {
"txt": key,
"html": reparsedKV || (updatedK && updatedK.hasGeneratedContent) ? origK : undefined,
},
v: {
"html": reparsedKV ? [] : origV,
},
});
}
}
// Update newAttrs
if (newAttrs && !reparsedKV) {
newAttrs.push(expandedA);
}
}
if (modified) {
token.attribs = newAttrs || expandedAttrs;
// If the token already has an about, it already has transclusion/extension
// wrapping. No need to record information about templated attributes in addition.
//
// FIXME: If there is a real use case for extension attributes getting
// templated, this check can be relaxed to allow that.
// https://gerrit.wikimedia.org/r/#/c/65575 has some reference code that
// can be used then.
if (!token.getAttribute('about') && tmpDataMW && tmpDataMW.size > 0) {
cb({ async: true });
// Flatten k-v pairs.
var vals = [];
tmpDataMW.forEach(function(obj) {
vals.push(obj.k, obj.v);
});
var manager = this.manager;
// Async-expand all token arrays to DOM.
Util.expandValuesToDOM(manager.env, manager.frame, vals,
wrapTemplates, function(err, eVals) {
// FIXME: Do something with `err`?
// Rebuild flattened k-v pairs.
var expAttrs = [];
for (var j = 0; j < eVals.length; j += 2) {
expAttrs.push([eVals[j], eVals[j + 1]]);
}
- // Mark token as having expanded attrs.
- token.addAttribute("about", manager.env.newAboutId());
- token.addSpaceSeparatedAttribute("typeof", "mw:ExpandedAttrs");
- token.addAttribute("data-mw", JSON.stringify({
- attribs: expAttrs,
- }));
+ if (token.name === 'template') {
+ // Don't add Parsoid about, typeof, data-mw attributes here since
+ // we won't be able to distinguish between Parsoid-added attributes
+ // and actual template attributes in cases like:
+ // {{some-tpl|about=#mwt1|typeof=mw:Transclusion}}
+ // In both cases, we will encounter a template token that looks like:
+ // { ... "attribs":[{"k":"about","v":"#mwt1"},{"k":"typeof","v":"mw:Transclusion"}] .. }
+ // So, record these in the tmp attribute for the template hander
+ // to retrieve and process.
+ if (!token.dataAttribs.tmp) {
+ token.dataAttribs.tmp = {};
+ }
+ token.dataAttribs.tmp.templatedAttribs = expAttrs;
+ } else {
+ // Mark token as having expanded attrs.
+ token.addAttribute("about", manager.env.newAboutId());
+ token.addSpaceSeparatedAttribute("typeof", "mw:ExpandedAttrs");
+ token.addAttribute("data-mw", JSON.stringify({
+ attribs: expAttrs,
+ }));
+ }
var newTokens = metaTokens.concat([token], postNLToks);
if (metaTokens.length === 0) {
// No more attribute expansion required for token after this
newTokens.rank = skipRank;
}
cb({ tokens: newTokens });
});
return;
}
// console.warn("NEW TOK: " + JSON.stringify(token));
}
var newTokens = metaTokens.concat([token], postNLToks);
if (metaTokens.length === 0) {
// No more attribute expansion required for token after this
newTokens.rank = skipRank;
}
cb({ tokens: newTokens });
};
if (typeof module === "object") {
module.exports.AttributeExpander = AttributeExpander;
}
diff --git a/lib/wt2html/tt/TemplateHandler.js b/lib/wt2html/tt/TemplateHandler.js
index d7026ae1c..f4fc0d9cb 100644
--- a/lib/wt2html/tt/TemplateHandler.js
+++ b/lib/wt2html/tt/TemplateHandler.js
@@ -1,1209 +1,1271 @@
/**
* Template and template argument handling, first cut.
*
* AsyncTokenTransformManager objects provide preprocessor-frame-like
* functionality once template args etc are fully expanded, and isolate
* individual transforms from concurrency issues. Template expansion is
* controlled using a tplExpandData structure created independently for each
* handled template tag.
*/
'use strict';
var coreutil = require('util');
var async = require('async');
var ParserFunctions = require('./ParserFunctions.js').ParserFunctions;
var TokenTransformManager = require('../TokenTransformManager.js');
var TokenHandler = require('./TokenHandler.js');
var AttributeTransformManager = TokenTransformManager.AttributeTransformManager;
+var AttributeExpander = require('./AttributeExpander.js').AttributeExpander;
var TokenAccumulator = TokenTransformManager.TokenAccumulator;
var defines = require('../parser.defines.js');
var TemplateRequest = require('../../mw/ApiRequest.js').TemplateRequest;
var Util = require('../../utils/Util.js').Util;
var DU = require('../../utils/DOMUtils.js').DOMUtils;
// define some constructor shortcuts
var KV = defines.KV;
var CommentTk = defines.CommentTk;
var NlTk = defines.NlTk;
var TagTk = defines.TagTk;
var SelfclosingTagTk = defines.SelfclosingTagTk;
var EndTagTk = defines.EndTagTk;
/**
* @class
* @extends TokenHandler
* @constructor
*/
function TemplateHandler() {
TokenHandler.apply(this, arguments);
// Set this here so that it's available in the TokenStreamPatcher,
// which continues to inherit from TemplateHandler.
this.parserFunctions = new ParserFunctions(this.env);
}
coreutil.inherits(TemplateHandler, TokenHandler);
TemplateHandler.prototype.rank = 1.1;
TemplateHandler.prototype.init = function() {
// Register for template and templatearg tag tokens
this.manager.addTransform(this.onTemplate.bind(this),
"TemplateHandler:onTemplate", this.rank, 'tag', 'template');
// Template argument expansion
this.manager.addTransform(this.onTemplateArg.bind(this),
"TemplateHandler:onTemplateArg", this.rank, 'tag', 'templatearg');
+ this.ae = new AttributeExpander(this.manager, { standalone: true, wrapTemplates: true });
};
/**
* Main template token handler
*
* Expands target and arguments (both keys and values) and either directly
* calls or sets up the callback to _expandTemplate, which then fetches and
* processes the template.
*/
TemplateHandler.prototype.onTemplate = function(token, frame, cb) {
var atm, toks;
+
+ function hasTemplateToken(tokens) {
+ return Array.isArray(tokens) &&
+ tokens.some(function(t) { return Util.isTemplateToken(t); });
+ }
+
+ // If the template name is templated, use the attribute transform manager
+ // to process all attributes to tokens, and force reprocessing of the token.
+ if (hasTemplateToken(token.attribs[0].k)) {
+ cb({async: true});
+
+ var th = this;
+ this.ae.onToken(token, frame, function(ret) {
+ if (ret.tokens) {
+ // Force reprocessing of the token by demoting its rank.
+ ret.tokens.rank = th.rank - 0.0001;
+ }
+ cb(ret);
+ });
+ return;
+ }
+
var env = this.env;
var text = token.dataAttribs.src;
var state = {
token: token,
wrapperType: 'mw:Transclusion',
wrappedObjectId: env.newObjectId(),
recordArgDict: this.options.wrapTemplates,
srcCB: this._startTokenPipeline,
// Uncomment to use DOM-based template expansion
// TODO gwicke: Determine when to use this!
// - Collect stats per template and classify templates into
// balanced/unbalanced ones based on it
// - Always force nesting for new templates inserted by the VE
//
// Default to 'safe' token-based template encapsulation for now.
//
// srcCB: this._startDocumentPipeline
};
var tgt = this.resolveTemplateTarget(state, token.attribs[0].k);
if (tgt && tgt.magicWordType) {
toks = this.processSpecialMagicWord(token, tgt);
console.assert(toks !== null);
cb({ tokens: Array.isArray(toks) ? toks : [toks] });
return;
}
if (this.options.wrapTemplates && tgt === null) {
// Target contains tags, convert template braces and pipes back into text
// Re-join attribute tokens with '=' and '|'
this.convertAttribsToString(state, token.attribs, cb);
return;
}
var accumReceiveToksFromSibling;
var accumReceiveToksFromChild;
if (env.conf.parsoid.usePHPPreProcessor) {
if (this.options.wrapTemplates) {
// Use MediaWiki's action=expandtemplates preprocessor
//
// The tokenizer needs to use `text` as the cache key for caching
// expanded tokens from the expanded transclusion text that we get
// from the preprocessor, since parameter substitution will already
// have taken place.
//
// It's sufficient to pass `[]` in place of attribs since they
// won't be used. In `usePHPPreProcessor`, there is no parameter
// substitution coming from the frame.
var templateName = tgt.target;
var attribs = [];
// We still need to check for loops and depth limit violations
// because of the higher precedence of extension tags, which can
// result in nested templates even while using the php preprocessor
// for expansion.
var checkRes = this.checkRes(templateName);
if (Array.isArray(checkRes)) {
cb({ tokens: checkRes });
return;
}
// Check if we have an expansion for this template in the cache
// already
var cachedTransclusion = env.transclusionCache[text];
if (cachedTransclusion) {
// cache hit: reuse the expansion DOM
var opts = { setDSR: true, isForeignContent: true };
toks = DU.encapsulateExpansionHTML(env, token, cachedTransclusion, opts);
cb({ tokens: toks });
} else {
// Use a TokenAccumulator to divide the template processing
// in two parts: The child part will take care of the main
// template element (including parameters) and the sibling
// will process the returned template expansion
state.accum = new TokenAccumulator(this.manager, cb);
accumReceiveToksFromSibling = state.accum.receiveToksFromSibling.bind(state.accum);
accumReceiveToksFromChild = state.accum.receiveToksFromChild.bind(state.accum);
var srcHandler = state.srcCB.bind(
this, state, frame,
accumReceiveToksFromSibling,
{ name: templateName, attribs: attribs, cacheKey: text });
// Process the main template element
this._encapsulateTemplate(state,
accumReceiveToksFromChild);
// Fetch and process the template expansion
this.fetchExpandedTpl(env.page.name || '',
text, accumReceiveToksFromSibling, srcHandler);
}
} else {
// We don't perform recursive template expansion- something
// template-like that the PHP parser did not expand. This is
// encapsulated already, so just return the plain text.
if (Util.isTemplateToken(token)) {
this.convertAttribsToString(state, token.attribs, cb);
return;
} else {
cb({ tokens: [ Util.tokensToString([token]) ] });
}
}
} else {
if (this.options.wrapTemplates) {
// Use a TokenAccumulator to divide the template processing
// in two parts: The child part will take care of the main
// template element (including parameters) and the sibling
// will do the template expansion
state.accum = new TokenAccumulator(this.manager, cb);
// console.warn("onTemplate created TA-" + state.accum.uid);
accumReceiveToksFromSibling = state.accum.receiveToksFromSibling.bind(state.accum);
accumReceiveToksFromChild = state.accum.receiveToksFromChild.bind(state.accum);
// Process the main template element
this._encapsulateTemplate(state,
state.accum.receiveToksFromChild.bind(state.accum));
} else {
// Don't wrap templates, so we don't need to use the
// TokenAccumulator and can return the expansion directly
accumReceiveToksFromSibling = cb;
}
accumReceiveToksFromSibling({tokens: [], async: true});
// expand argument keys, with callback set to next processing step
// XXX: would likely be faster to do this in a tight loop here
atm = new AttributeTransformManager(
this.manager,
{wrapTemplates: false, inTemplate: true},
this._expandTemplate.bind(this, state, frame, tgt,
accumReceiveToksFromSibling)
);
atm.process(token.attribs);
}
};
/**
* Parser functions also need template wrapping
*/
TemplateHandler.prototype._parserFunctionsWrapper = function(state, cb, ret) {
if (ret.tokens) {
// This is only for the Parsoid native expansion pipeline used in
// parser tests. The "" token sometimes changes foster parenting
// behavior and trips up some tests.
var i = 0;
while (i < ret.tokens.length) {
if (ret.tokens[i] === "") {
ret.tokens.splice(i, 1);
} else {
i++;
}
}
this._onChunk(state, cb, ret.tokens);
}
if (!ret.async) {
// Now, ready to finish up
this._onEnd(state, cb);
}
};
/**
* Process the special magic word as specified by resolvedTgt.magicWordType
* magicWordType === '!' => {{!}} is the magic word
* magicWordtype === 'MASQ' => DEFAULTSORT, DISPLAYTITLE are the magic words
* (Util.magicMasqs.has(..))
*/
TemplateHandler.prototype.processSpecialMagicWord = function(tplToken, resolvedTgt) {
var env = this.manager.env;
// special case for {{!}} magic word
if ((resolvedTgt && resolvedTgt.magicWordType === '!') || tplToken.attribs[0].k === "!") {
// If we're not at the top level, return a table cell. This will always
// be the case. Either {{!}} was tokenized as a td, or it is tokenized
// as template but the recursive call to fetch its content returns a
// single | in an ambiguous context which will again be tokenized as td.
if (!this.atTopLevel) {
return [new TagTk("td")];
}
var state = {
token: tplToken,
wrapperType: "mw:Transclusion",
wrappedObjectId: env.newObjectId(),
};
this.resolveTemplateTarget(state, "!");
var toks = this.getEncapsulationInfo(state, ["|"]);
toks.push(this.getEncapsulationInfoEndTag(state));
var argInfo = this.getArgInfo(state);
toks[0].dataAttribs.tmp.tplarginfo = JSON.stringify(argInfo);
return toks;
}
if (!resolvedTgt || resolvedTgt.magicWordType !== 'MASQ') {
// Nothing to do
return null;
}
var magicWord = resolvedTgt.prefix.toLowerCase();
- var key = resolvedTgt.pfArg;
- var keyToks = resolvedTgt.pfArgToks;
- var templatedKey = false;
- if (keyToks) {
- // Check if any part of the key is templated
- for (var i = 0, n = keyToks.length; i < n; i++) {
- if (Util.isTemplateToken(keyToks[i])) {
- templatedKey = true;
- break;
- }
- }
- key = Util.tokensToString(keyToks);
- }
-
var pageProp = 'mw:PageProp/';
if (magicWord === 'defaultsort') {
pageProp += 'category';
}
pageProp += magicWord;
var metaToken = new SelfclosingTagTk('meta',
[ new KV('property', pageProp) ],
Util.clone(tplToken.dataAttribs)
);
- if (templatedKey) {
+ if ((tplToken.dataAttribs.tmp || {}).templatedAttribs) {
// No shadowing if templated
//
// SSS FIXME: post-tpl-expansion, WS won't be trimmed. How do we handle this?
- metaToken.addAttribute("content", keyToks);
+ metaToken.addAttribute("content", resolvedTgt.pfArgToks);
+ metaToken.addAttribute("about", env.newAboutId());
+ metaToken.addSpaceSeparatedAttribute("typeof", "mw:ExpandedAttrs");
+
+ // See [[mw:Specs/HTML/1.3.0#Transclusion-affected_attributes]]
+ //
+ // For every attribute that has a templated name and/or value,
+ // AttributeExpander creates a 2-item array for that attribute.
+ // [ {txt: '..', html: '..'}, { html: '..'} ]
+ // 'txt' is the plain-text name/value
+ // 'html' is the HTML-version of the name/value
+ //
+ // Massage the templated magic-word info into a similar format.
+ // In this case, the attribute name is 'content' (implicit) and
+ // since it is implicit, the name itself cannot be attribute.
+ // Hence 'html' property is empty.
+ //
+ // The attribute value has been templated and is encoded there.
+ //
+ // NOTE: If any part of the 'MAGIC_WORD:value' string is templated,
+ // we consider the magic word as having expanded attributes, rather
+ // than only when the 'value' part of it. This is because of the
+ // limitation of our token representation for templates. This is
+ // an edge case that it is not worth a refactoring right now to
+ // handle this properly and choose mw:Transclusion or mw:ExpandedAttrs
+ // depending on which part is templated.
+ //
+ // FIXME: Is there a simpler / better repn. for templated attrs?
+ var ta = tplToken.dataAttribs.tmp.templatedAttribs;
+ ta[0][0].txt = 'content'; // Magic-word attribute name
+ ta[0][1].html = ta[0][0].html; // HTML repn. of the attribute value
+ ta[0][0].html = undefined;
+ metaToken.addAttribute("data-mw", JSON.stringify({ attribs: ta }));
} else {
// Leading/trailing WS should be stripped
- key = key.trim();
+ var key = resolvedTgt.pfArg.trim();
var src = (tplToken.dataAttribs || {}).src;
if (src) {
// If the token has original wikitext, shadow the sort-key
var origKey = src.replace(/[^:]+:?/, '').replace(/}}$/, '');
metaToken.addNormalizedAttribute("content", key, origKey);
} else {
// If not, this token came from an extension/template
// in which case, dont bother with shadowing since the token
// will never be edited directly.
metaToken.addAttribute("content", key);
}
}
return metaToken;
};
TemplateHandler.prototype.resolveTemplateTarget = function(state, targetToks) {
function toStringOrNull(tokens) {
var maybeTarget = Util.tokensToString(tokens, true);
if (Array.isArray(maybeTarget)) {
var newTarget = maybeTarget[0];
var tgtTokens = maybeTarget[1];
for (var i = 0, l = tgtTokens.length; i < l; i++) {
var ntt = tgtTokens[i];
switch (ntt.constructor) {
case String:
newTarget += ntt;
break;
case SelfclosingTagTk:
// Quotes are valid template targets
if (ntt.name === 'mw-quote') {
newTarget += ntt.value;
} else if (!Util.isEmptyLineMetaToken(ntt)
&& ntt.name !== 'template'
&& ntt.name !== 'templatearg') {
// We are okay with empty (comment-only) lines,
// {{..}} and {{{..}}} in template targets.
return null;
}
break;
case CommentTk:
// Ignore comments as well
break;
case TagTk:
case EndTagTk:
return null;
}
}
return newTarget;
} else {
return maybeTarget;
}
}
// Normalize to an array
targetToks = !Array.isArray(targetToks) ? [targetToks] : targetToks;
var env = this.manager.env;
var wiki = env.conf.wiki;
var isTemplate = true;
var target = toStringOrNull(targetToks);
if (target === null) {
// Retry with a looser attempt to convert tokens to a string.
// This lenience only applies to parser functions.
isTemplate = false;
target = Util.tokensToString(targetToks);
}
// Without a trim(), we get bug T147742 because
- // the prefix === target check below fails!
+ // the prefix === target check further below fails!
target = target.trim().replace(/^(safe)?subst:/, '');
var pieces = target.split(':');
var prefix = pieces[0].trim();
+ // The check for pieces.length > 1 is require to distinguish between
+ // {{lc:FOO}} and {{lc|FOO}}. The latter is a template transclusion
+ // even though the target (=lc) matches a registered parser-function name.
+ var isPF = pieces.length > 1;
var lowerPrefix = prefix.toLowerCase();
var isSpecialMagicWord = (target === '!');
// Check if we have a parser function.
// Unalias to canonical form and look in config.functionHooks
var magicWordAlias = wiki.magicWords[prefix] || wiki.magicWords[lowerPrefix];
// Retry by adding a ":" to prefix if necessary
if (!magicWordAlias && pieces.length > 1) {
magicWordAlias = wiki.magicWords[prefix + ':'] || wiki.magicWords[lowerPrefix + ':'];
}
var translatedPrefix = magicWordAlias || lowerPrefix || '';
-
- // The check for pieces.length > 1 is require to distinguish between
- // {{lc:FOO}} and {{lc|FOO}}. The latter is a template transclusion
- // even though the target (=lc) matches a registered parser-function name.
if ((magicWordAlias && this.parserFunctions && this.parserFunctions['pf_' + magicWordAlias]) ||
- (pieces.length > 1 && (translatedPrefix[0] === '#' || wiki.functionHooks.has(translatedPrefix)))) {
+ (isPF && (translatedPrefix[0] === '#' || wiki.functionHooks.has(translatedPrefix)))) {
+
+ // Extract toks that make up pfArg
+ var pfArgToks;
+ var firstTok = targetToks[0];
+ if (typeof firstTok === 'string') {
+ targetToks = targetToks.slice(1);
+ // Strip parser-func / magic-word prefix
+ firstTok = firstTok.replace(new RegExp("^" + prefix, 'i'), '');
+
+ // Strip ":" after skipping empty tokens, if any
+ if (isPF) {
+ while (firstTok === '') {
+ firstTok = targetToks[0];
+ targetToks = targetToks.slice(1);
+ }
+
+ console.assert(firstTok[0] === ':', 'Expecting : in parser function definiton');
+ firstTok = firstTok.slice(1);
+ }
+ pfArgToks = [firstTok].concat(targetToks);
+ } else {
+ // FIXME: In the scenario where the target itself is
+ // templated / is not a string, protect from crashers by
+ // using the full token -- this is still going to generate
+ // incorrect output, but it won't crash.
+ // Ex: {{<includeonly>safesubst:</includeonly>#invoke:RfD|foo}}
+ pfArgToks = targetToks;
+ }
- // FIXME: In the scenario where the target itself is
- // templated / is not a string, protect from crashers by
- // using the full token -- this is still going to generate
- // incorrect output, but it won't crash.
- // Ex: {{<includeonly>safesubst:</includeonly>#invoke:RfD|foo}}
- var t0Src = typeof targetToks[0] === 'string' ?
- targetToks[0].replace(/^[^:]*:?/, '') : targetToks[0];
state.parserFunctionName = translatedPrefix;
return {
isPF: true,
prefix: prefix,
magicWordType: Util.magicMasqs.has(lowerPrefix) ? 'MASQ' : null,
target: 'pf_' + translatedPrefix,
pfArg: target.substr(prefix.length + 1),
- // Extract toks that make up pfArg
- pfArgToks: [t0Src].concat(targetToks.slice(1)),
+ pfArgToks: pfArgToks,
};
}
if (!isTemplate) {
return null;
}
// FIXME: resolveTitle adds namespace prefix when it resolves
// fragments and relative titles. Maybe we should add a flag to
// have it do in all cases.
if (prefix === target && !/^[#\/\.]/.test(target)) {
var namespaceId = wiki.canonicalNamespaces.template;
target = wiki.namespaceNames[namespaceId] + ':' + target;
}
// Resolve a possibly relative link and
// normalize the target before template processing.
var title;
try {
title = env.resolveTitle(target);
} catch (e) {
// Invalid template target!
return null;
}
// Entities in transclusions aren't decoded in the PHP parser
// So, treat the title as a url-decoded string!
title = env.makeTitleFromURLDecodedStr(title, undefined, true);
if (!title) {
// Invalid template target!
return null;
}
// data-mw.target.href should be a url
state.resolvedTemplateTarget = env.makeLink(title);
return {
isPF: false,
magicWordType: isSpecialMagicWord ? '!' : null,
target: title.getPrefixedDBKey(),
};
};
TemplateHandler.prototype.convertAttribsToString = function(state, attribs, cb) {
var self = this;
cb({tokens: [], async: true});
// Re-join attribute tokens with '=' and '|'
var attribTokens = [];
attribs.forEach(function(kv) {
if (kv.k) {
attribTokens = Util.flattenAndAppendToks(attribTokens, null, kv.k);
}
if (kv.v) {
attribTokens = Util.flattenAndAppendToks(attribTokens,
kv.k ? "=" : '',
kv.v);
}
attribTokens.push('|');
});
// pop last pipe separator
attribTokens.pop();
var tokens = ['{{'].concat(attribTokens, ['}}', new defines.EOFTk()]);
// Process exploded token in a new pipeline
var newTokens = [];
var endCB = function() {
// Assign the correct rank to the tokens
var finalTokens = newTokens;
finalTokens.rank = this.rank;
cb({ tokens: finalTokens });
};
Util.processContentInPipeline(
self.manager.env,
self.manager.frame,
tokens,
{
pipelineType: "tokens/x-mediawiki",
pipelineOpts: {
wrapTemplates: self.options.wrapTemplates,
},
chunkCB: function(chunk) {
// SSS FIXME: This pattern of attempting to strip
// EOFTk from every chunk is a big ugly, but unavoidable
// since EOF token comes with the entire chunk rather
// than coming through the end event callback.
newTokens = newTokens.concat(Util.stripEOFTkfromTokens(chunk));
},
endCB: endCB.bind(this),
}
);
};
/**
* checkRes
*/
TemplateHandler.prototype.checkRes = function(target) {
var checkRes = this.manager.frame.loopAndDepthCheck(target, this.env.conf.parsoid.maxDepth);
if (checkRes) {
// Loop detected or depth limit exceeded, abort!
var res = [
checkRes,
new TagTk('a', [{ k: 'href', v: target }]),
target,
new EndTagTk('a'),
];
res.rank = this.manager.phaseEndRank;
return res;
}
};
/**
* Fetch, tokenize and token-transform a template after all arguments and the
* target were expanded.
*/
TemplateHandler.prototype._expandTemplate = function(state, frame, resolvedTgt, cb, attribs) {
var env = this.manager.env;
var target = attribs[0].k;
if (!target) {
env.log('debug', 'No target! ', attribs);
}
if (!state.resolveTemplateTarget) {
// We couldn't get the proper target before going through the
// AttributeTransformManager, so try again now
resolvedTgt = this.resolveTemplateTarget(state, target);
if (resolvedTgt === null) {
// Target contains tags, convert template braces and pipes back into text
// Re-join attribute tokens with '=' and '|'
this.convertAttribsToString(state, attribs, cb);
return;
}
}
// TODO:
// check for 'subst:'
// check for variable magic names
// check for msg, msgnw, raw magics
// check for parser functions
// XXX: wrap attribs in object with .dict() and .named() methods,
// and each member (key/value) into object with .tokens(), .dom() and
// .wikitext() methods (subclass of Array)
var res;
target = resolvedTgt.target;
if (resolvedTgt.isPF) {
// FIXME: Parsoid may not have implemented the parser function natively
// Emit an error message, but encapsulate it so it roundtrips back.
if (!this.parserFunctions[target]) {
res = [ "Parser function implementation for " + target + " missing in Parsoid." ];
res.rank = this.rank;
if (this.options.wrapTemplates) {
res.push(this.getEncapsulationInfoEndTag(state));
}
cb({ tokens: res });
return;
}
var pfAttribs = new defines.Params(attribs);
pfAttribs[0] = new KV(resolvedTgt.pfArg, []);
env.log('debug', 'entering prefix', target, state.token);
var newCB;
if (this.options.wrapTemplates) {
newCB = this._parserFunctionsWrapper.bind(this, state, cb);
} else {
newCB = cb;
}
this.parserFunctions[target](state.token, frame, newCB, pfAttribs);
return;
}
var checkRes = this.checkRes(target);
if (Array.isArray(checkRes)) {
cb({ tokens: checkRes });
return;
}
// XXX: notes from brion's mediawiki.parser.environment
// resolve template name
// load template w/ canonical name
// load template w/ variant names (language variants)
// strip template target
attribs = attribs.slice(1);
// For now, just fetch the template and pass the callback for further
// processing along.
var srcHandler = state.srcCB.bind(
this, state, frame, cb,
{ name: target, attribs: attribs, cacheKey: target }
);
this._fetchTemplateAndTitle(target, cb, srcHandler, state);
};
/**
* Process a fetched template source to a document, enforcing proper nesting
* along the way.
*/
TemplateHandler.prototype._startDocumentPipeline = function(state, frame, cb, tplArgs, err, src) {
// We have a choice between aborting or keeping going and reporting the
// error inline.
// TODO: report as special error token and format / remove that just
// before the serializer. (something like <mw:error ../> as source)
if (err) {
src = '';
// this.manager.env.errCB(err);
}
this.manager.env.log('debug', 'TemplateHandler._startDocumentPipeline', tplArgs.name, tplArgs.attribs);
Util.processContentInPipeline(
this.manager.env,
this.manager.frame,
src,
{
// Full pipeline all the way to DOM
pipelineType: 'text/x-mediawiki/full',
pipelineOpts: {
isInclude: true,
// we *might* be able to get away without this if we transfer
// more than just the about when unwrapping
wrapTemplates: false,
// (SSS FIXME: but why?? This function is not used currently)
// suppress paragraphs,
// Should this be the default in all cases?
noPWrapping: true,
},
tplArgs: tplArgs,
documentCB: this._onDocument.bind(this, state, cb),
}
);
};
/**
* Process a fetched template source to a token stream
*/
TemplateHandler.prototype._startTokenPipeline = function(state, frame, cb, tplArgs, err, src, type) {
// The type parameter is passed in from the src fetcher. Typically it is
// 'text/x-mediawiki' since we are fetching wikitext (search for it in
// ApiRequest). We can probably remove it even, as it seems unlikely that
// we will ever have other input types here.
// We have a choice between aborting or keeping going and reporting the
// error inline.
// TODO: report as special error token and format / remove that just
// before the serializer. (something like <mw:error ../> as source)
if (err) {
src = '';
// this.manager.env.errCB(err);
}
var pConf = this.manager.env.conf.parsoid;
if (pConf.dumpFlags && pConf.dumpFlags.indexOf("tplsrc") !== -1) {
console.log("=================================");
console.log(tplArgs.name);
console.log("---------------------------------");
console.log(src);
console.log("---------------------------------");
}
this.manager.env.log('debug', 'TemplateHandler._startTokenPipeline', tplArgs.name, tplArgs.attribs);
// Get a nested transformation pipeline for the input type. The input
// pipeline includes the tokenizer, synchronous stage-1 transforms for
// 'text/wiki' input and asynchronous stage-2 transforms).
Util.processContentInPipeline(
this.manager.env,
this.manager.frame,
src,
{
pipelineType: type || 'text/x-mediawiki',
pipelineOpts: {
inTemplate: true,
isInclude: true,
// NOTE: No template wrapping required for nested templates.
wrapTemplates: false,
extTag: this.options.extTag,
},
tplArgs: tplArgs,
chunkCB: this._onChunk.bind(this, state, cb),
endCB: this._onEnd.bind(this, state, cb),
}
);
};
TemplateHandler.prototype.getEncapsulationInfo = function(state, chunk) {
// TODO
// * only add this information for top-level includes, but track parameter
// expansion in lower-level templates
// * ref all tables to this (just add about)
// * ref end token to this, add property="mw:Transclusion/End"
var attrs = [
new KV('typeof', state.wrapperType),
new KV('about', '#' + state.wrappedObjectId),
];
var dataParsoid = {
tsr: Util.clone(state.token.dataAttribs.tsr),
src: state.token.dataAttribs.src,
tmp: {}, // We'll add the arginfo here if necessary
};
var meta = [new SelfclosingTagTk('meta', attrs, dataParsoid)];
chunk = chunk ? meta.concat(chunk) : meta;
chunk.rank = this.rank;
return chunk;
};
TemplateHandler.prototype.getEncapsulationInfoEndTag = function(state) {
var tsr = state.token.dataAttribs.tsr;
return new SelfclosingTagTk('meta',
[
new KV('typeof', state.wrapperType + '/End'),
new KV('about', '#' + state.wrappedObjectId),
], {
tsr: [null, tsr ? tsr[1] : null],
});
};
/**
* Parameter processing helpers
*/
var isSimpleParam = function(tokens) {
var isSimpleToken = function(token) {
return (token.constructor === String ||
token.constructor === CommentTk ||
token.constructor === NlTk);
};
if (!Array.isArray(tokens)) {
return isSimpleToken(tokens);
}
return tokens.every(isSimpleToken);
};
// Add its HTML conversion to a parameter. The eachCb is only
// used to signal an error to async.each
var getParamHTML = function(paramData, eachCb) {
var param = paramData.param;
var srcStart = paramData.info.srcOffsets[2];
var srcEnd = paramData.info.srcOffsets[3];
if (paramData.info.spc) {
srcStart += paramData.info.spc[2].length;
srcEnd -= paramData.info.spc[3].length;
}
Util.processContentInPipeline(
this.manager.env, this.manager.frame,
param.wt,
{
pipelineType: "text/x-mediawiki/full",
pipelineOpts: {
isInclude: false,
wrapTemplates: true,
// No need to do paragraph-wrapping here
noPWrapping: true,
// TODO: This helps in the case of unnamed
// parameters which start with whitespace,
// but it's not be the correct solution
// for cases with significant start-of-line
// chars inserted after "\n".
noPre: true,
},
srcOffsets: [ srcStart, srcEnd ],
documentCB: function(html) {
// FIXME: We're better off setting a pipeline option above
// to skip dsr computation to begin with. Worth revisitting
// if / when `addHTMLTemplateParameters` is enabled.
// Remove DSR from children
DU.visitDOM(html.body, function(node) {
if (!DU.isElt(node)) { return; }
var dp = DU.getDataParsoid(node);
dp.dsr = undefined;
});
param.html = DU.ppToXML(html.body, { innerXML: true });
eachCb(null);
},
}
);
};
/**
* Process the main template element, including the arguments
*/
TemplateHandler.prototype._encapsulateTemplate = function(state, cb) {
var i, n;
var env = this.manager.env;
var chunk = this.getEncapsulationInfo(state);
if (!this.options.inTemplate && state.recordArgDict) {
// Get the arg dict
var argInfo = this.getArgInfo(state);
var argDict = argInfo.dict;
if (env.conf.parsoid.addHTMLTemplateParameters) {
// Collect the parameters that need parsing into HTML, that is,
// those that are not simple strings.
// This optimizes for the common case where all are simple strings,
// in which we don't need to go async.
var params = [];
for (i = 0, n = argInfo.paramInfos.length; i < n; i++) {
var paramInfo = argInfo.paramInfos[i];
var param = argDict.params[paramInfo.k];
var paramTokens;
if (paramInfo.named) {
paramTokens = state.token.getAttribute(paramInfo.k);
} else {
paramTokens = state.token.attribs[paramInfo.k].v;
}
// No need to pass through a whole sub-pipeline to get the
// html if the param is either a single string, or if it's
// just text, comments or newlines.
if (paramTokens &&
(paramTokens.constructor === String ||
isSimpleParam(paramTokens))) {
param.html = param.wt;
} else if (param.wt.match(/^https?:\/\/[^[\]{}\s]*$/)) {
// If the param is just a simple URL, we can process it to
// HTML directly without going through a sub-pipeline.
param.html = "<a rel='mw:ExtLink' href='" + param.wt.replace(/'/g, '&#39;') +
"'>" + param.wt + "</a>";
} else {
// Prepare the data needed to parse to HTML
params.push({
param: param,
info: paramInfo,
tokens: paramTokens,
});
}
}
if (params.length) {
// TODO: We could avoid going async by checking if all params are strings
// and, in that case returning them immediately.
async.each(params, getParamHTML.bind(this), function(err) {
// Use a data-attribute to prevent the sanitizer from stripping this
// attribute before it reaches the DOM pass where it is needed.
chunk[0].dataAttribs.tmp.tplarginfo = JSON.stringify(argInfo);
env.log('debug', 'TemplateHandler._encapsulateTemplate', chunk);
cb({tokens: chunk});
}.bind(this));
cb({tokens: [], async: true});
return;
} else {
chunk[0].dataAttribs.tmp.tplarginfo = JSON.stringify(argInfo);
}
} else {
// Don't add the HTML template parameters, just use their wikitext
chunk[0].dataAttribs.tmp.tplarginfo = JSON.stringify(argInfo);
}
}
env.log('debug', 'TemplateHandler._encapsulateTemplate', chunk);
cb({tokens: chunk});
};
/**
* Handle chunk emitted from the input pipeline after feeding it a template
*/
TemplateHandler.prototype._onChunk = function(state, cb, chunk) {
chunk = Util.stripEOFTkfromTokens(chunk);
var i, n;
for (i = 0, n = chunk.length; i < n; i++) {
if (chunk[i] && chunk[i].dataAttribs && chunk[i].dataAttribs.tsr) {
chunk[i].dataAttribs.tsr = undefined;
}
var t = chunk[i];
if (t.constructor === SelfclosingTagTk &&
t.name.toLowerCase() === 'meta' &&
t.getAttribute('typeof') === 'mw:Placeholder') {
// replace with empty string to avoid metas being foster-parented out
chunk[i] = '';
}
}
if (!this.options.wrapTemplates) {
// Ignore comments in template transclusion mode
var newChunk = [];
for (i = 0, n = chunk.length; i < n; i++) {
if (chunk[i].constructor !== CommentTk) {
newChunk.push(chunk[i]);
}
}
chunk = newChunk;
}
this.manager.env.log('debug', 'TemplateHandler._onChunk', chunk);
chunk.rank = this.rank;
cb({tokens: chunk, async: true});
};
/**
* Handle the end event emitted by the parser pipeline after fully processing
* the template source.
*/
TemplateHandler.prototype._onEnd = function(state, cb) {
this.manager.env.log('debug', 'TemplateHandler._onEnd');
if (this.options.wrapTemplates) {
var endTag = this.getEncapsulationInfoEndTag(state);
var res = { tokens: [endTag] };
res.tokens.rank = this.rank;
cb(res);
} else {
cb({ tokens: [] });
}
};
/**
* Handle the sub-DOM produced by a DOM-based template expansion
*
* This uses the same encapsulation mechanism as we use for template expansion
* recycling.
*/
TemplateHandler.prototype._onDocument = function(state, cb, doc) {
// FIXME: This will only incorporate the wikitext parameters into data-mw,
// not the HTML ones. For that, the code in _onChunk will have to adapted
// here.
var argDict = this.getArgInfo(state).dict;
var addWrapperAttrs = function(firstNode) {
// Adds the wrapper attributes to the first element
firstNode.setAttribute('typeof', state.wrapperType);
// Update data-mw
DU.setDataMw(firstNode,
Object.assign(state.wrapperDataMw || {}, argDict));
// Update data-parsoid
DU.setDataParsoid(firstNode, {
tsr: Util.clone(state.token.dataAttribs.tsr),
src: state.token.dataAttribs.src,
});
};
var toks = DU.buildDOMFragmentTokens(
this.manager.env,
state.token,
doc,
addWrapperAttrs,
{ setDSR: state.token.name === 'extension', isForeignContent: true }
);
// All done for this template, so perform a callback without async: set.
cb({ tokens: toks });
};
/**
* Get the public data-mw structure that exposes the template name and
* parameters ExtensionHandler provides its own getArgInfo function.
*/
TemplateHandler.prototype.getArgInfo = function(state) {
var src = this.manager.env.page.src;
var params = state.token.attribs;
var dict = {};
var paramInfos = [];
var argIndex = 1;
// Use source offsets to extract arg-name and arg-value wikitext
// since the 'k' and 'v' values in params will be expanded tokens
//
// Ignore params[0] -- that is the template name
for (var i = 1, n = params.length; i < n; i++) {
var srcOffsets = params[i].srcOffsets;
var kSrc, vSrc;
if (srcOffsets) {
kSrc = src.substring(srcOffsets[0], srcOffsets[1]);
vSrc = src.substring(srcOffsets[2], srcOffsets[3]);
} else {
kSrc = params[i].k;
vSrc = params[i].v;
}
var kWt = kSrc.trim();
var k = Util.tokensToString(params[i].k, true, true);
if (Array.isArray(k)) {
// The PHP parser only removes comments and whitespace to construct
// the real parameter name, so if there were other tokens, use the
// original text
k = kWt;
} else {
k = k.trim();
}
var v = vSrc;
// Number positional parameters
var isPositional;
// Even if k is empty, we need to check v immediately follows. If not,
// it's a blank parameter name (which is valid) and we shouldn't make it
// positional.
if (k === '' && srcOffsets[1] === srcOffsets[2]) {
isPositional = true;
k = argIndex.toString();
argIndex++;
} else {
isPositional = false;
// strip ws from named parameter values
v = v.trim();
}
if (dict[k] === undefined) {
var paramInfo = {
k: k,
srcOffsets: srcOffsets,
};
var keySpaceMatch = kSrc.match(/^(\s*)[^]*?(\s*)$/);
var valueSpaceMatch;
if (isPositional) {
// PHP parser does not strip whitespace around
// positional params and neither will we.
valueSpaceMatch = [null, '', ''];
} else {
paramInfo.named = true;
valueSpaceMatch = v ? vSrc.match(/^(\s*)[^]*?(\s*)$/) : [null, '', vSrc];
}
// Preserve key and value space prefix / postfix, if any.
// "=" is the default spacing used by the serializer,
if (keySpaceMatch[1] || keySpaceMatch[2] ||
valueSpaceMatch[1] || valueSpaceMatch[2]) {
// Remember non-standard spacing
paramInfo.spc = [
keySpaceMatch[1], keySpaceMatch[2],
valueSpaceMatch[1], valueSpaceMatch[2],
];
}
paramInfos.push(paramInfo);
}
dict[k] = { wt: v };
// Only add the original parameter wikitext if named and different from
// the actual parameter.
if (!isPositional && kWt !== k) {
dict[k].key = {wt: kWt};
}
}
var tplTgtSrcOffsets = params[0].srcOffsets;
if (tplTgtSrcOffsets) {
var tplTgtWT = src.substring(tplTgtSrcOffsets[0], tplTgtSrcOffsets[1]);
return {
dict: {
target: {
wt: tplTgtWT,
// Add in tpl-target/pf-name info
// Only one of these will be set.
'function': state.parserFunctionName,
href: state.resolvedTemplateTarget,
},
params: dict,
},
paramInfos: paramInfos,
};
}
};
/**
* Fetch a template
*/
TemplateHandler.prototype._fetchTemplateAndTitle = function(title, parentCB, cb, state) {
// @fixme normalize name?
var env = this.manager.env;
if (title in env.pageCache) {
// XXX: store type too (and cache tokens/x-mediawiki)
cb(null, env.pageCache[title] /* , type */);
} else if (!env.conf.parsoid.fetchTemplates) {
var tokens = [state.token.dataAttribs.src];
if (this.options.wrapTemplates) {
// FIXME: We've already emitted a start meta to the accumulator in
// `_encapsulateTemplate`. We could reach for that and modify it,
// or refactor to emit it later for all paths, but the pragmatic
// thing to do is just ignore it and wrap this anew.
state.wrappedObjectId = env.newObjectId();
tokens = this.getEncapsulationInfo(state, tokens);
var argInfo = this.getArgInfo(state);
argInfo.dict.errors = [
{
key: 'mw-api-tplfetch-error',
message: 'Page / template fetching disabled, and no cache for ' + title,
},
];
var start = tokens[0];
start.dataAttribs.tmp.tplarginfo = JSON.stringify(argInfo);
var typeOf = start.getAttribute('typeof');
start.setAttribute('typeof', 'mw:Error ' + typeOf);
tokens.push(this.getEncapsulationInfoEndTag(state));
}
parentCB({ tokens: tokens });
} else {
// We are about to start an async request for a template
env.log('debug', 'Note: trying to fetch ', title);
// Start a new request if none is outstanding
if (env.requestQueue[title] === undefined) {
env.requestQueue[title] = new TemplateRequest(env, title);
}
// append request, process in document order
env.requestQueue[title].once('src', function(err, page) {
cb(err, page ? page.revision['*'] : null);
});
parentCB ({tokens: [], async: true});
}
};
/**
* Fetch the preprocessed wikitext for a template-like construct.
*/
TemplateHandler.prototype.fetchExpandedTpl = function(title, text, parentCB, cb) {
var env = this.manager.env;
if (!env.conf.parsoid.fetchTemplates) {
parentCB({ tokens: [ 'Warning: Page/template fetching disabled cannot expand ' + text] });
} else {
// We are about to start an async request for a template
env.log('debug', 'Note: trying to expand ', text);
parentCB({ tokens: [], async: true });
env.batcher.preprocess(title, text).nodify(cb);
}
};
/* ********************** Template argument expansion ****************** */
/**
* Expand template arguments with tokens from the containing frame.
*/
TemplateHandler.prototype.onTemplateArg = function(token, frame, cb) {
var args = frame.args.named();
var attribs = token.attribs;
var newCB;
if (this.options.wrapTemplates) {
// This is a bare use of template arg syntax at the top level
// outside any template use context. Wrap this use with RDF attrs.
// so that this chunk can be RT-ed en-masse.
var tplHandler = this;
newCB = function(res) {
var toks = Util.stripEOFTkfromTokens(res.tokens);
var state = {
token: token,
wrapperType: "mw:Param",
wrappedObjectId: tplHandler.manager.env.newObjectId(),
};
toks = tplHandler.getEncapsulationInfo(state, toks);
toks.push(tplHandler.getEncapsulationInfoEndTag(state));
var argInfo = tplHandler.getArgInfo(state);
toks[0].dataAttribs.tmp.tplarginfo = JSON.stringify(argInfo);
cb({ tokens: toks });
};
} else {
newCB = cb;
}
this.fetchArg(attribs[0].k, this.lookupArg.bind(this, args, attribs, newCB, cb), cb);
};
TemplateHandler.prototype.fetchArg = function(arg, argCB, asyncCB) {
if (arg.constructor === String) {
argCB({tokens: [arg]});
} else {
this.manager.frame.expand(arg, {
wrapTemplates: false,
type: "tokens/x-mediawiki/expanded",
asyncCB: asyncCB,
cb: function(tokens) {
argCB({tokens: Util.stripEOFTkfromTokens(tokens)});
},
});
}
};
TemplateHandler.prototype.lookupArg = function(args, attribs, cb, asyncCB, ret) {
var toks = ret.tokens;
var argName = toks.constructor === String ? toks : Util.tokensToString(toks).trim();
var res = args.dict[argName];
// The 'res.constructor !== Function' protects against references to
// tpl-args named 'prototype' or 'constructor' that haven't been passed in.
if (res !== null && res !== undefined && res.constructor !== Function) {
if (res.constructor === String) {
res = [res];
}
cb({ tokens: args.namedArgs[argName] ? Util.tokenTrim(res) : res });
} else if (attribs.length > 1) {
this.fetchArg(attribs[1].v, cb, asyncCB);
} else {
cb({ tokens: [ '{{{' + argName + '}}}' ] });
}
};
if (typeof module === "object") {
module.exports.TemplateHandler = TemplateHandler;
}
diff --git a/tests/parserTests-blacklist.js b/tests/parserTests-blacklist.js
index e79a1c0f4..f895151f2 100644
--- a/tests/parserTests-blacklist.js
+++ b/tests/parserTests-blacklist.js
@@ -1,2035 +1,2031 @@
/* A map of tests which we know Parsoid currently fails.
*
* New patches which fix previously-broken tests should also patch this
* file to document which tests are now expected to succeed.
*
* This helps clean up 'npm test' output, documents known bugs, and helps
* Jenkins make sense of the parserTest output.
*
* NOTE that the selser blacklist depends on tests/selser.changes.json
* If the selser change list is modified, this blacklist should be refreshed.
*
* This blacklist can be automagically updated by running
* parserTests.js --rewrite-blacklist
* You might want to do this after you fix some bug that makes more tests
* pass. It is still your responsibility to carefully review the blacklist
* diff to ensure there are no unexpected new failures (lines added).
*/
/*
* This should map test titles to an array of test types (wt2html, wt2wt,
* html2html, html2wt, selser) which are known to fail.
* For easier maintenance, we group each test type together, and use a
* helper function to create the array if needed then append the test type.
*/
'use strict';
var testBlackList = {};
var add = function(testtype, title, raw) {
if (typeof (testBlackList[title]) !== 'object') {
testBlackList[title] = {
modes: [],
raw: raw,
};
}
testBlackList[title].modes.push(testtype);
};
// ### DO NOT REMOVE THIS LINE ### (start of automatically-generated section)
// Blacklist for wt2html
add("wt2html", "Extra newlines between heading and content are swallowed", "<h1 id=\"b\" data-parsoid='{\"dsr\":[0,3,1,1]}'>b</h1>\n\n<p data-parsoid='{\"dsr\":[5,5,0,0]}'><br data-parsoid='{\"dsr\":[5,5,0,0]}'/></p>\n\n<p data-parsoid='{\"dsr\":[7,12,0,0]}'><a rel=\"mw:WikiLink\" href=\"./A\" title=\"A\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./A\"},\"sa\":{\"href\":\"a\"},\"dsr\":[7,12,2,2]}'>a</a></p>");
add("wt2html", "Non-word characters don't terminate tag names (T19663, T42670, T54022)", "&lt;blockquote|>a\n\n<p data-parsoid='{\"dsr\":[29,57,0,0]}'>&lt;b→> doesn't terminate &lt;/b→></p>\n\n<p data-parsoid='{\"dsr\":[59,87,0,0]}'>&lt;bä> doesn't terminate &lt;/bä></p>\n\n<p data-parsoid='{\"dsr\":[89,119,0,0]}'>&lt;boo> doesn't terminate &lt;/boo></p>\n\n<p data-parsoid='{\"dsr\":[121,155,0,0]}'>&lt;s.foo> doesn't terminate &lt;/s.foo></p>\n\n<p data-parsoid='{\"dsr\":[157,167,0,0]}'>&lt;sub-ID#1></p>");
add("wt2html", "Non-word characters don't terminate tag names + tidy", "&lt;blockquote|>a\n\n<p data-parsoid='{\"dsr\":[29,57,0,0]}'>&lt;b→> doesn't terminate &lt;/b→></p>\n\n<p data-parsoid='{\"dsr\":[59,87,0,0]}'>&lt;bä> doesn't terminate &lt;/bä></p>\n\n<p data-parsoid='{\"dsr\":[89,119,0,0]}'>&lt;boo> doesn't terminate &lt;/boo></p>\n\n<p data-parsoid='{\"dsr\":[121,155,0,0]}'>&lt;s.foo> doesn't terminate &lt;/s.foo></p>\n\n<p data-parsoid='{\"dsr\":[157,167,0,0]}'>&lt;sub-ID#1></p>");
add("wt2html", "Comment on its own line post-expand", "<p data-parsoid='{\"dsr\":[0,20,0,0]}'>a\n<span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[2,11,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"blank\",\"href\":\"./Template:Blank\"},\"params\":{},\"i\":0}}]}'></span><!---->\nb</p>");
add("wt2html", "Comment on its own line post-expand with non-significant whitespace", "<p data-parsoid='{\"dsr\":[0,23,0,0]}'>a\n <span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[3,12,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"blank\",\"href\":\"./Template:Blank\"},\"params\":{},\"i\":0}}]}'></span> <!----> \nb</p>");
add("wt2html", "Block tag on one line (<blockquote>)", "<p data-parsoid='{\"dsr\":[0,2,0,0]}'>a </p><blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[2,30,12,13]}'>foo</blockquote>\n\n<p data-parsoid='{\"dsr\":[32,33,0,0]}'>b</p>");
add("wt2html", "Block tag on both lines (<blockquote>)", "<p data-parsoid='{\"dsr\":[0,2,0,0]}'>a </p><blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[2,30,12,13]}'>foo</blockquote>\n\n<p data-parsoid='{\"dsr\":[32,34,0,0]}'>b </p><blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[34,62,12,13]}'>foo</blockquote>");
add("wt2html", "T54763: Preformatted in <blockquote>", "<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[0,74,12,13]}'>\n<p data-parsoid='{\"dsr\":[13,18,0,0]}'> Blah</p>\n<table data-parsoid='{\"dsr\":[19,60,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[22,58,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[22,57,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[22,57,1,0]}'>\n<pre data-parsoid='{\"dsr\":[24,57,1,0]}'>indented cell (no pre-wrapping!)</pre></td></tr>\n</tbody></table>\n</blockquote>");
add("wt2html", "T17491: <ins>/<del> in blockquote (2)", "<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[0,64,12,13]}'>Foo <del data-parsoid='{\"stx\":\"html\",\"dsr\":[16,30,5,6]}'>bar</del> <ins data-parsoid='{\"stx\":\"html\",\"dsr\":[31,45,5,6]}'>baz</ins> quux\n</blockquote>");
add("wt2html", "Templates: Indent-Pre: 1f: Wrapping should be based on expanded content", "<pre about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,11,1,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\" \"}},\"i\":0}},\"a\"]}'>a</pre>\n\n<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[13,25,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"\\n \"}},\"i\":0}},\"a\"]}'>\n</span><pre about=\"#mwt2\">a</pre>\n\n<span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[27,39,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"\\n b\"}},\"i\":0}}]}'>\n</span><pre about=\"#mwt3\">b</pre>\n\n<p about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[41,54,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a\\n \"}},\"i\":0}},\"b\"]}'>a</p><span about=\"#mwt4\">\n</span><pre about=\"#mwt4\">b</pre>\n\n<p about=\"#mwt5\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[56,67,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a\\n\"}},\"i\":0}}]}'>a</p><span about=\"#mwt5\">\n</span><pre data-parsoid='{\"dsr\":[67,69,1,0]}'>b</pre>");
add("wt2html", "Templates: Don't strip whitespace from positional-param values", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,11,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a \"}},\"i\":0}}]}'>a </p>\n\n<p about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[13,33,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"{{echo|b}} \"}},\"i\":0}}]}'>b </p>\n\n<pre about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[35,48,null,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\" c \\n\"}},\"i\":0}}]}'>c </pre><span about=\"#mwt4\">\n</span>\n\n<pre about=\"#mwt5\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[50,71,null,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\" {{echo|d}}\\n\"}},\"i\":0}}]}'>d</pre><span about=\"#mwt5\">\n</span>\n\n<span about=\"#mwt7\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[73,85,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"\\n e\"}},\"i\":0}}]}'>\n</span><pre about=\"#mwt7\">e</pre>\n\n<span about=\"#mwt8\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[87,100,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"\\n* f\"}},\"i\":0}}]}'>\n</span><ul about=\"#mwt8\"><li> f</li></ul>\n\n<span about=\"#mwt9\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[102,114,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"\\n \"}},\"i\":0}},\"g\"]}'>\n</span><pre about=\"#mwt9\">g</pre>");
add("wt2html", "Templates: Other wikitext in parameter names (T69657)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,18,0,0],\"pi\":[[{\"k\":\"&#39;&#39;1&#39;&#39;\",\"named\":true}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"&#39;&#39;1&#39;&#39;\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</p>");
add("wt2html", "6. Pre-blocks should extend across lines with leading WS even when there is no wrappable content", "<pre data-parsoid='{\"dsr\":[0,26,1,0]}'>a\n\n <!-- continue -->\nb</pre>\n\n<pre data-parsoid='{\"dsr\":[28,30,1,0]}'>c</pre>\n \n<p data-parsoid='{\"dsr\":[33,34,0,0]}'>d</p>");
add("wt2html", "Definition lists: ignore colons inside tags", "<dl data-parsoid='{\"dsr\":[0,39,0,0]}'><dt data-parsoid='{\"dsr\":[0,39,1,0]}'>one <b data-parsoid='{\"stx\":\"html\",\"dsr\":[5,34,3,4]}'>two<span typeof=\"mw:DisplaySpace mw:Placeholder\" data-parsoid='{\"src\":\" \",\"isDisplayHack\":true,\"dsr\":[11,12,null,0]}'> </span>: tag <i data-parsoid='{\"stx\":\"html\",\"dsr\":[18,29,3,4]}'>fun:</i>:</b>: def</dt></dl>");
add("wt2html", "Definition Lists: colons and tables 1", "<dl data-parsoid='{\"dsr\":[0,21,0,0]}'><dd data-parsoid='{\"dsr\":[0,10,1,0]}'><table data-parsoid='{\"dsr\":[1,10,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[4,8,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[4,7,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[4,7,1,0]}'> x</td></tr>\n</tbody></table></dd>\n<dd data-parsoid='{\"dsr\":[11,21,1,0]}'><table data-parsoid='{\"dsr\":[12,21,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[15,19,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[15,18,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[15,18,1,0]}'> y</td></tr>\n</tbody></table></dd></dl>");
add("wt2html", "T4702: Mismatched <i>, <b> and <a> tags are invalid", "<p data-parsoid='{\"dsr\":[0,204,0,0]}'><i data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[0,29,2,0]}'><a rel=\"mw:ExtLink\" href=\"http://example.com\" data-parsoid='{\"targetOff\":22,\"contentOffsets\":[22,28],\"dsr\":[2,29,20,1]}'>text<i data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[26,28,2,0]}'></i></a></i>\n<a rel=\"mw:ExtLink\" href=\"http://example.com\" data-parsoid='{\"targetOff\":50,\"contentOffsets\":[50,57],\"dsr\":[30,58,20,1]}'><b data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[50,57,3,0]}'>text</b></a><b data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[58,61,3,0]}'></b>\n<i data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[62,106,2,0]}'>Something <a rel=\"mw:ExtLink\" href=\"http://example.com\" data-parsoid='{\"targetOff\":94,\"contentOffsets\":[94,105],\"dsr\":[74,106,20,1]}'>in italic<i data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[103,105,2,0]}'></i></a></i>\n<i data-parsoid='{\"dsr\":[107,164,2,2]}'>Something <a rel=\"mw:ExtLink\" href=\"http://example.com\" data-parsoid='{\"targetOff\":139,\"contentOffsets\":[139,160],\"dsr\":[119,161,20,1]}'>mixed<b data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[144,160,3,0]}'><i data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[147,160,2,0]}'>, even bold</i></b></a>'</i>\n<b data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[165,204,3,0]}'><i data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[168,204,2,0]}'>Now <a rel=\"mw:ExtLink\" href=\"http://example.com\" data-parsoid='{\"targetOff\":194,\"contentOffsets\":[194,203],\"dsr\":[174,204,20,1]}'>both<b data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[198,203,3,0]}'><i data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[201,203,2,0]}'></i></b></a></i></b></p>");
add("wt2html", "External link containing double-single-quotes in text embedded in italics (T6598 sanity check)", "<p data-parsoid='{\"dsr\":[0,60,0,0]}'><i data-parsoid='{\"dsr\":[0,60,2,2]}'>Some <a rel=\"mw:ExtLink\" href=\"http://example.com/\" data-parsoid='{\"targetOff\":28,\"contentOffsets\":[28,56],\"dsr\":[7,57,21,1]}'>pretty <i data-parsoid='{\"dsr\":[35,46,2,2]}'>italics</i> and stuff</a>!</i></p>");
add("wt2html", "Self-link to numeric title", "<p data-parsoid='{\"dsr\":[0,5,0,0]}'><a rel=\"mw:WikiLink\" href=\"./0\" title=\"0\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./0\"},\"sa\":{\"href\":\"0\"},\"dsr\":[0,5,2,2]}'>0</a></p>");
add("wt2html", "<nowiki> inside a link", "<p data-parsoid='{\"dsr\":[0,96,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main&lt;nowiki> Page&lt;/nowiki>\"},\"dsr\":[0,30,2,2]}'>Main Page</a> <a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[31,96,12,2]}'>the main page <span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[57,94,8,9]}'>[it's not very good]</span></a></p>");
add("wt2html", "Interlanguage link with spacing", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'>Blah blah blah</p>\n<link rel=\"mw:PageProp/Language\" href=\"http://zh.wikipedia.org/wiki/%20%20%20%20Chinese%20%20%20%20%20\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"http://zh.wikipedia.org/wiki/%20%20%20%20Chinese%20%20%20%20%20\"},\"sa\":{\"href\":\" zh : Chinese \"},\"dsr\":[15,43,null,null]}'/>");
add("wt2html", "Escaping of interlanguage links (T129218, T156308)", "<p data-parsoid='{\"dsr\":[0,51,0,0]}'>Blah blah blah\n<a rel=\"mw:ExtLink\" href=\"http://es.wikipedia.org/wiki/Spanish\" title=\"es:Spanish\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"http://es.wikipedia.org/wiki/Spanish\"},\"sa\":{\"href\":\":es:Spanish\"},\"isIW\":true,\"dsr\":[15,30,2,2]}'>es:Spanish</a>\n<a rel=\"mw:WikiLink\" href=\"./Zh_:_Chinese\" title=\"Zh : Chinese\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Zh_:_Chinese\"},\"sa\":{\"href\":\" : zh : Chinese \"},\"dsr\":[31,51,2,2]}'> : zh : Chinese </a></p>");
add("wt2html", "Space and question mark encoding in interlanguage links (T95473)", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'>Blah blah blah</p>\n<link rel=\"mw:PageProp/Language\" href=\"http://es.wikipedia.org/wiki/Foo%20bar?\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"http://es.wikipedia.org/wiki/Foo%20bar?\"},\"sa\":{\"href\":\"es:Foo bar?\"},\"dsr\":[15,30,null,null]}'/>");
add("wt2html", "2. Lists with start-of-line-transparent tokens before bullets: Template close", "<ul about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,18,0,0],\"firstWikitextNode\":\"UL\",\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[\"*foo \",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"bar\\n\"}},\"i\":0}}]}'><li>foo bar</li></ul><span about=\"#mwt1\">\n</span><p data-parsoid='{\"dsr\":[18,22,0,0]}'>*baz</p>");
add("wt2html", "Multiple list tags generated by templates", "<li about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[0,44,null,null],\"pi\":[[{\"k\":\"1\"}],[{\"k\":\"1\"}],[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;li>\"}},\"i\":0}},\"a\\n\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;li>\"}},\"i\":1}},\"b\\n\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;li>\"}},\"i\":2}},\"c\"]}'>a\n</li><li about=\"#mwt1\">b\n</li><li about=\"#mwt1\" data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[null,44,null,0]}'>c</li>");
add("wt2html", "Test the li-hack\n(The PHP parser relies on Tidy for the hack)", "<ul data-parsoid='{\"dsr\":[0,114,0,0]}'><li data-parsoid='{\"dsr\":[0,5,1,0]}'> foo</li>\n<li data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[6,19,6,0],\"liHackSrc\":\"* \"}'>li-hack</li>\n<li about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[20,52,2,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[\"* \",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;li>templated li-hack\"}},\"i\":0}}]}'>templated li-hack</li>\n<li data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[53,66,1,0]}'> <!--foo--> </li><li data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[66,114,4,0]}'> unsupported li-hack with preceding comments</li></ul>\n\n<ul data-parsoid='{\"stx\":\"html\",\"dsr\":[116,154,4,5]}'>\n<li data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[121,125,4,0]}'></li><li data-parsoid='{\"stx\":\"html\",\"dsr\":[125,148,4,5]}'>not a li-hack\n</li>\n</ul>");
add("wt2html", "Unbalanced closing non-block tags don't break a list\n(php parser relies on Tidy to fix up)", "<p data-parsoid='{\"dsr\":[0,6,0,0]}'><span data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[0,6,6,0]}'></span></p>\n<ul data-parsoid='{\"dsr\":[7,32,0,0]}'><li data-parsoid='{\"dsr\":[7,22,1,0]}'>a<span data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[16,22,6,0]}'></span></li>\n<li data-parsoid='{\"dsr\":[23,32,1,0]}'>b</li></ul>");
add("wt2html", "Magic Word: {{CURRENTMONTH1}}", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,17,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"CURRENTMONTH1\",\"href\":\"./Template:CURRENTMONTH1\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:CURRENTMONTH1\"}],\"i\":0}}]}'>{{CURRENTMONTH1}}</span></p>");
add("wt2html", "Magic Words LOCAL (UTC)", "<ul data-parsoid='{\"dsr\":[0,252,0,0]}'><li data-parsoid='{\"dsr\":[0,16,1,0]}'> <span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[2,16,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALMONTH\",\"function\":\"localmonth\"},\"params\":{},\"i\":0}}]}'>01</span></li>\n<li data-parsoid='{\"dsr\":[17,34,1,0]}'> <span about=\"#mwt3\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[19,34,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALMONTH1\",\"href\":\"./Template:LOCALMONTH1\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:LOCALMONTH1\"}],\"i\":0}}]}'>{{LOCALMONTH1}}</span></li>\n<li data-parsoid='{\"dsr\":[35,55,1,0]}'> <span about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[37,55,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALMONTHNAME\",\"function\":\"localmonthname\"},\"params\":{},\"i\":0}}]}'>January</span></li>\n<li data-parsoid='{\"dsr\":[56,79,1,0]}'> <span about=\"#mwt5\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[58,79,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALMONTHNAMEGEN\",\"function\":\"localmonthnamegen\"},\"params\":{},\"i\":0}}]}'>January</span></li>\n<li data-parsoid='{\"dsr\":[80,102,1,0]}'> <span about=\"#mwt6\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[82,102,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALMONTHABBREV\",\"function\":\"localmonthabbrev\"},\"params\":{},\"i\":0}}]}'>Jan</span></li>\n<li data-parsoid='{\"dsr\":[103,117,1,0]}'> <span about=\"#mwt7\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[105,117,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALDAY\",\"function\":\"localday\"},\"params\":{},\"i\":0}}]}'>1</span></li>\n<li data-parsoid='{\"dsr\":[118,133,1,0]}'> <span about=\"#mwt8\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[120,133,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALDAY2\",\"function\":\"localday2\"},\"params\":{},\"i\":0}}]}'>01</span></li>\n<li data-parsoid='{\"dsr\":[134,152,1,0]}'> <span about=\"#mwt9\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[136,152,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALDAYNAME\",\"function\":\"localdayname\"},\"params\":{},\"i\":0}}]}'>Thursday</span></li>\n<li data-parsoid='{\"dsr\":[153,168,1,0]}'> <span about=\"#mwt10\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[155,168,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALYEAR\",\"function\":\"localyear\"},\"params\":{},\"i\":0}}]}'>1970</span></li>\n<li data-parsoid='{\"dsr\":[169,184,1,0]}'> <span about=\"#mwt11\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[171,184,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALTIME\",\"function\":\"localtime\"},\"params\":{},\"i\":0}}]}'>00:02</span></li>\n<li data-parsoid='{\"dsr\":[185,200,1,0]}'> <span about=\"#mwt12\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[187,200,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALHOUR\",\"function\":\"localhour\"},\"params\":{},\"i\":0}}]}'>00</span></li>\n<li data-parsoid='{\"dsr\":[201,216,1,0]}'> <span about=\"#mwt13\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[203,216,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALWEEK\",\"function\":\"localweek\"},\"params\":{},\"i\":0}}]}'>1</span></li>\n<li data-parsoid='{\"dsr\":[217,231,1,0]}'> <span about=\"#mwt14\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[219,231,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALDOW\",\"function\":\"localdow\"},\"params\":{},\"i\":0}}]}'>4</span></li>\n<li data-parsoid='{\"dsr\":[232,252,1,0]}'> <span about=\"#mwt15\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[234,252,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"LOCALTIMESTAMP\",\"function\":\"localtimestamp\"},\"params\":{},\"i\":0}}]}'>19700101000203</span></li></ul>");
add("wt2html", "Magic Word: {{FULLPAGENAMEE}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,17,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"FULLPAGENAMEE\",\"function\":\"fullpagenamee\"},\"params\":{},\"i\":0}}]}'>User:Ævar Arnfjörð Bjarmason</p>");
add("wt2html", "Magic Word: {{TALKSPACE}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKSPACE\",\"function\":\"talkspace\"},\"params\":{},\"i\":0}}]}'>Talk</p>");
add("wt2html", "Magic Word: {{TALKSPACE}}, same namespace", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKSPACE\",\"function\":\"talkspace\"},\"params\":{},\"i\":0}}]}'>Talk</p>");
add("wt2html", "Magic Word: {{TALKSPACEE}}", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,14,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKSPACEE\",\"href\":\"./Template:TALKSPACEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:TALKSPACEE\"}],\"i\":0}}]}'>{{TALKSPACEE}}</span></p>");
add("wt2html", "Magic Word: {{SUBJECTSPACE}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,16,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTSPACE\",\"function\":\"subjectspace\"},\"params\":{},\"i\":0}}]}'>Main</p>");
add("wt2html", "Magic Word: {{SUBJECTSPACE}}, same namespace", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,16,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTSPACE\",\"function\":\"subjectspace\"},\"params\":{},\"i\":0}}]}'>Main</p>");
add("wt2html", "Magic Word: {{SUBJECTSPACE}}, main namespace", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,16,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTSPACE\",\"function\":\"subjectspace\"},\"params\":{},\"i\":0}}]}'>Main</p>");
add("wt2html", "Magic Word: {{SUBJECTSPACEE}}", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,17,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTSPACEE\",\"href\":\"./Template:SUBJECTSPACEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBJECTSPACEE\"}],\"i\":0}}]}'>{{SUBJECTSPACEE}}</span></p>");
add("wt2html", "Magic Word: {{NAMESPACE}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"NAMESPACE\",\"function\":\"namespace\"},\"params\":{},\"i\":0}}]}'>Main</p>");
add("wt2html", "Magic Word: {{NAMESPACEE}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,14,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"NAMESPACEE\",\"function\":\"namespacee\"},\"params\":{},\"i\":0}}]}'>Main</p>");
add("wt2html", "Magic Word: {{NAMESPACENUMBER}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,19,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"NAMESPACENUMBER\",\"function\":\"namespacenumber\"},\"params\":{},\"i\":0}}]}'>0</p>");
add("wt2html", "Magic Word: {{SUBPAGENAME}}", "<p data-parsoid='{\"dsr\":[0,15,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,15,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBPAGENAME\",\"href\":\"./Template:SUBPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBPAGENAME\"}],\"i\":0}}]}'>{{SUBPAGENAME}}</span></p>");
add("wt2html", "Magic Word: {{SUBPAGENAMEE}}", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,16,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBPAGENAMEE\",\"href\":\"./Template:SUBPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBPAGENAMEE\"}],\"i\":0}}]}'>{{SUBPAGENAMEE}}</span></p>");
add("wt2html", "Magic Word: {{ROOTPAGENAME}}", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,16,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ROOTPAGENAME\",\"href\":\"./Template:ROOTPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:ROOTPAGENAME\"}],\"i\":0}}]}'>{{ROOTPAGENAME}}</span></p>");
add("wt2html", "Magic Word: {{ROOTPAGENAMEE}}", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,17,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ROOTPAGENAMEE\",\"href\":\"./Template:ROOTPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:ROOTPAGENAMEE\"}],\"i\":0}}]}'>{{ROOTPAGENAMEE}}</span></p>");
add("wt2html", "Magic Word: {{BASEPAGENAME}}", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,16,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"BASEPAGENAME\",\"href\":\"./Template:BASEPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:BASEPAGENAME\"}],\"i\":0}}]}'>{{BASEPAGENAME}}</span></p>");
add("wt2html", "Magic Word: {{BASEPAGENAMEE}}", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,17,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"BASEPAGENAMEE\",\"href\":\"./Template:BASEPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:BASEPAGENAMEE\"}],\"i\":0}}]}'>{{BASEPAGENAMEE}}</span></p>");
add("wt2html", "Magic Word: {{TALKPAGENAME}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,16,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKPAGENAME\",\"function\":\"talkpagename\"},\"params\":{},\"i\":0}}]}'>User:Ævar Arnfjörð Bjarmason</p>");
add("wt2html", "Magic Word: {{TALKPAGENAMEE}}", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,17,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKPAGENAMEE\",\"href\":\"./Template:TALKPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:TALKPAGENAMEE\"}],\"i\":0}}]}'>{{TALKPAGENAMEE}}</span></p>");
add("wt2html", "Magic Word: {{SUBJECTPAGENAME}}", "<p data-parsoid='{\"dsr\":[0,19,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,19,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTPAGENAME\",\"href\":\"./Template:SUBJECTPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBJECTPAGENAME\"}],\"i\":0}}]}'>{{SUBJECTPAGENAME}}</span></p>");
add("wt2html", "Magic Word: {{SUBJECTPAGENAMEE}}", "<p data-parsoid='{\"dsr\":[0,20,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,20,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTPAGENAMEE\",\"href\":\"./Template:SUBJECTPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBJECTPAGENAMEE\"}],\"i\":0}}]}'>{{SUBJECTPAGENAMEE}}</span></p>");
add("wt2html", "Magic Word: {{NUMBEROFFILES}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,17,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"NUMBEROFFILES\",\"function\":\"numberoffiles\"},\"params\":{},\"i\":0}}]}'>2</p>");
add("wt2html", "Magic Word: {{PAGENAME}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,12,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAME\",\"function\":\"pagename\"},\"params\":{},\"i\":0}}]}'>User:Ævar Arnfjörð Bjarmason</p>");
add("wt2html", "Magic Word: {{PAGENAMEE}}", "<span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAMEE\",\"function\":\"pagenamee\"},\"params\":{},\"i\":0}}]}'></span>");
add("wt2html", "Magic Word: {{PAGENAMEE}} with metacharacters (T28781)", "<span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAMEE\",\"function\":\"pagenamee\"},\"params\":{},\"i\":0}}]}'></span>");
add("wt2html", "Magic Word: {{REVISIONID}}", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,14,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"REVISIONID\",\"href\":\"./Template:REVISIONID\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:REVISIONID\"}],\"i\":0}}]}'>{{REVISIONID}}</span></p>");
add("wt2html", "Magic Word: {{SCRIPTPATH}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,14,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SCRIPTPATH\",\"function\":\"scriptpath\"},\"params\":{},\"i\":0}}]}'>/</p>");
add("wt2html", "Magic Word: {{STYLEPATH}}", "<p data-parsoid='{\"dsr\":[0,13,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,13,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"STYLEPATH\",\"href\":\"./Template:STYLEPATH\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:STYLEPATH\"}],\"i\":0}}]}'>{{STYLEPATH}}</span></p>");
add("wt2html", "Case-sensitive magic words, when cased differently, should just be template transclusions", "<p data-parsoid='{\"dsr\":[0,63,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,16,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"CurrentMonth\",\"href\":\"./Template:CurrentMonth\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:CurrentMonth\"}],\"i\":0}}]}'>{{CurrentMonth}}</span>\n<span about=\"#mwt4\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[17,31,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"currentday\",\"href\":\"./Template:Currentday\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:Currentday\"}],\"i\":0}}]}'>{{currentday}}</span>\n<span about=\"#mwt6\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[32,47,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"cURreNTweEK\",\"href\":\"./Template:CURreNTweEK\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:CURreNTweEK\"}],\"i\":0}}]}'>{{cURreNTweEK}}</span>\n<span about=\"#mwt8\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[48,63,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"currentHour\",\"href\":\"./Template:CurrentHour\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:CurrentHour\"}],\"i\":0}}]}'>{{currentHour}}</span></p>");
-add("wt2html", "Parsoid: Template-generated DISPLAYTITLE", "<meta property=\"mw:PageProp/displaytitle\" content=\"Foo\" about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,29,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"{{echo|DISPLAYTITLE}}:Foo\",\"href\":\"./Foo\"},\"params\":{},\"i\":0}}]}'/>");
add("wt2html", "Namespace 1 {{ns:1}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,8,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ns:1\",\"function\":\"ns\"},\"params\":{},\"i\":0}}]}'>1</p>");
add("wt2html", "Namespace 1 {{ns:01}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,9,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ns:01\",\"function\":\"ns\"},\"params\":{},\"i\":0}}]}'>01</p>");
add("wt2html", "Namespace 0 {{ns:0}} (T6783)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,8,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ns:0\",\"function\":\"ns\"},\"params\":{},\"i\":0}}]}'>0</p>");
add("wt2html", "Namespace 0 {{ns:00}} (T6783)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,9,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ns:00\",\"function\":\"ns\"},\"params\":{},\"i\":0}}]}'>00</p>");
add("wt2html", "Namespace -1 {{ns:-1}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,9,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ns:-1\",\"function\":\"ns\"},\"params\":{},\"i\":0}}]}'>-1</p>");
add("wt2html", "Namespace (lang=de) Benutzer Diskussion {{ns:3}}", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,8,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ns:3\",\"function\":\"ns\"},\"params\":{},\"i\":0}}]}'>3</p>");
add("wt2html", "Nonexistent template", "<p data-parsoid='{\"dsr\":[0,28,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,28,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"thistemplatedoesnotexist\",\"href\":\"./Template:Thistemplatedoesnotexist\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:Thistemplatedoesnotexist\"}],\"i\":0}}]}'>{{thistemplatedoesnotexist}}</span></p>");
add("wt2html", "Template with invalid target containing tags", "<p data-parsoid='{\"dsr\":[0,54,0,0]}'>{{a<b data-parsoid='{\"stx\":\"html\",\"dsr\":[3,11,3,4]}'>b</b>|<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[12,24,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</span>|<span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[25,35,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a\"}},\"i\":0}}]}'>a</span>=<span about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[36,46,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"b\"}},\"i\":0}}]}'>b</span>|a =b}}</p>");
add("wt2html", "Template with invalid target containing unclosed tag", "<p data-parsoid='{\"dsr\":[0,49,0,0]}'>{{a<b data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[3,49,3,0]}'>|<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[7,19,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</span>|<span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[20,30,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a\"}},\"i\":0}}]}'>a</span>=<span about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[31,41,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"b\"}},\"i\":0}}]}'>b</span>|a =b}}</b></p>");
add("wt2html", "Template with invalid target containing wikilink", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'>{{<a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[2,15,2,2]}'>Main Page</a>}}</p>");
add("wt2html", "Template with complex arguments", "<p data-parsoid='{\"dsr\":[0,106,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Template:Complextemplate\" title=\"Template:Complextemplate\" about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Template:Complextemplate\"},\"sa\":{\"href\":\"Template:complextemplate\"},\"dsr\":[0,106,null,null],\"pi\":[[{\"k\":\"param\",\"named\":true,\"spc\":[\"\\n \",\" \",\"\",\"\"]},{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"complextemplate\",\"href\":\"./Template:Complextemplate\"},\"params\":{\"1\":{\"wt\":\"[[Template:complextemplate|link]]\"},\"param\":{\"wt\":\"{{ templateasargtest |\\n templ = simple }}\"}},\"i\":0}}]}'>link</a><span about=\"#mwt1\"> This is a test template with parameter (test)</span></p>");
add("wt2html", "Template infinite loop", "<span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,9,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"loop1\",\"href\":\"./Template:Loop1\"},\"params\":{},\"i\":0}}]}'></span>");
-add("wt2html", "Template with targets containing wikilinks", "<p data-parsoid='{\"dsr\":[0,11,0,0]}'>{{<a rel=\"mw:WikiLink\" href=\"./Foo\" title=\"Foo\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Foo\"},\"sa\":{\"href\":\"foo\"},\"dsr\":[2,9,2,2]}'>foo</a>}}</p>\n\n<p data-parsoid='{\"dsr\":[13,33,0,0]}'>{{<a typeof=\"mw:ExpandedAttrs\" about=\"#mwt6\" rel=\"mw:WikiLink\" href=\"./Foo\" title=\"Foo\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Foo\"},\"sa\":{\"href\":\"{{echo|foo}}\"},\"dsr\":[15,31,null,null]}' data-mw='{\"attribs\":[[{\"txt\":\"href\"},{\"html\":\"&lt;span about=\\\"#mwt3\\\" typeof=\\\"mw:Transclusion\\\" data-parsoid=&#39;{\\\"pi\\\":[[{\\\"k\\\":\\\"1\\\"}]],\\\"dsr\\\":[17,29,null,null]}&#39; data-mw=&#39;{\\\"parts\\\":[{\\\"template\\\":{\\\"target\\\":{\\\"wt\\\":\\\"echo\\\",\\\"href\\\":\\\"./Template:Echo\\\"},\\\"params\\\":{\\\"1\\\":{\\\"wt\\\":\\\"foo\\\"}},\\\"i\\\":0}}]}&#39;>foo&lt;/span>\"}]]}'>foo</a>}}</p>\n\n<p data-parsoid='{\"dsr\":[35,55,0,0]}'>{{<span about=\"#mwt5\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[37,51,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"[[foo\"}},\"i\":0}}]}'>[[foo</span>]]}}</p>");
+add("wt2html", "Template with targets containing wikilinks", "<p data-parsoid='{\"dsr\":[0,11,0,0]}'>{{<a rel=\"mw:WikiLink\" href=\"./Foo\" title=\"Foo\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Foo\"},\"sa\":{\"href\":\"foo\"},\"dsr\":[2,9,2,2]}'>foo</a>}}</p>\n\n<p data-parsoid='{\"dsr\":[13,42,0,0]}'>{{<a typeof=\"mw:ExpandedAttrs\" about=\"#mwt5\" rel=\"mw:WikiLink\" href=\"./Foo\" title=\"Foo\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Foo\"},\"sa\":{\"href\":\"{{echo|foo}}\"},\"dsr\":[15,40,null,null]}' data-mw='{\"attribs\":[[{\"txt\":\"href\"},{\"html\":\"&lt;span about=\\\"#mwt3\\\" typeof=\\\"mw:Transclusion\\\" data-parsoid=&#39;{\\\"pi\\\":[[{\\\"k\\\":\\\"1\\\"}]],\\\"dsr\\\":[17,29,null,null]}&#39; data-mw=&#39;{\\\"parts\\\":[{\\\"template\\\":{\\\"target\\\":{\\\"wt\\\":\\\"echo\\\",\\\"href\\\":\\\"./Template:Echo\\\"},\\\"params\\\":{\\\"1\\\":{\\\"wt\\\":\\\"foo\\\"}},\\\"i\\\":0}}]}&#39;>foo&lt;/span>\"}]]}'>foo</a>}}</p>\n\n<p data-parsoid='{\"dsr\":[44,55,0,0]}'>{{[[foo]]}}</p>");
add("wt2html", "int keyword", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,45,0,0],\"pi\":[[{\"k\":\"1\"},{\"k\":\"2\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"int:youhavenewmessages\",\"function\":\"int\"},\"params\":{\"1\":{\"wt\":\"lots of money\"},\"2\":{\"wt\":\"not!\"}},\"i\":0}}]}'>Parser function implementation for pf_int missing in Parsoid.</p>");
add("wt2html", "int keyword - non-existing message", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,11,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"int:var\",\"function\":\"int\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_int missing in Parsoid.</p>");
add("wt2html", "Self-closed noinclude, includeonly, onlyinclude tags", "<meta typeof=\"mw:Includes/NoInclude\" data-parsoid='{\"src\":\"&lt;noinclude />\",\"dsr\":[0,13,null,null]}'/>\n<meta typeof=\"mw:Includes/IncludeOnly\" data-parsoid='{\"src\":\"&lt;includeonly />\",\"dsr\":[14,29,null,null]}'/>\n<meta typeof=\"mw:Includes/OnlyInclude\" data-parsoid='{\"src\":\"&lt;onlyinclude />\",\"dsr\":[30,45,null,null]}'/>");
add("wt2html", "T8563: Section extraction for section shown by <includeonly>", "<meta typeof=\"mw:Includes/IncludeOnly\" data-parsoid='{\"src\":\"&lt;includeonly>\\n==Includeonly section==\\n&lt;/includeonly>\",\"dsr\":[0,52,null,null]}'/><meta typeof=\"mw:Includes/IncludeOnly/End\" data-parsoid='{\"src\":\"\",\"dsr\":[52,52,null,null]}'/>\n<h2 id=\"Section_T-2\" data-parsoid='{\"dsr\":[53,68,2,2]}'>Section T-2</h2>");
add("wt2html", "T8563: Section extraction for section suppressed by <includeonly>", "<meta typeof=\"mw:Includes/IncludeOnly\" data-parsoid='{\"src\":\"&lt;includeonly>\\n==Includeonly section==\\n&lt;/includeonly>\",\"dsr\":[0,52,null,null]}'/><meta typeof=\"mw:Includes/IncludeOnly/End\" data-parsoid='{\"src\":\"\",\"dsr\":[52,52,null,null]}'/>\n<h2 id=\"Section_1\" data-parsoid='{\"dsr\":[53,66,2,2]}'>Section 1</h2>");
add("wt2html", "2. includeonly in html attr value", "<p data-parsoid='{\"dsr\":[0,155,0,0]}'><span id=\"v1\" about=\"#mwt1\" typeof=\"mw:ExpandedAttrs\" data-parsoid='{\"stx\":\"html\",\"a\":{\"id\":\"v1\"},\"sa\":{\"id\":\"&lt;noinclude>v1&lt;/noinclude>&lt;includeonly>v2&lt;/includeonly>\"},\"dsr\":[0,76,66,7]}' data-mw='{\"attribs\":[[{\"txt\":\"id\"},{\"html\":\"&lt;meta typeof=\\\"mw:Includes/NoInclude\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;noinclude>\\\",\\\"dsr\\\":[10,21,null,null]}&#39;/>v1&lt;meta typeof=\\\"mw:Includes/NoInclude/End\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;/noinclude>\\\",\\\"dsr\\\":[23,35,null,null]}&#39;/>&lt;meta typeof=\\\"mw:Includes/IncludeOnly\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;includeonly>v2&amp;lt;/includeonly>\\\",\\\"dsr\\\":[35,64,null,null]}&#39;/>&lt;meta typeof=\\\"mw:Includes/IncludeOnly/End\\\" data-parsoid=&#39;{\\\"src\\\":\\\"\\\",\\\"dsr\\\":[64,64,null,null]}&#39;/>\"}]]}'>bar</span>\n<span id=\".22v1.22\" about=\"#mwt2\" typeof=\"mw:ExpandedAttrs\" data-parsoid='{\"stx\":\"html\",\"a\":{\"id\":\".22v1.22\"},\"sa\":{\"id\":\"&lt;noinclude>\\\"v1\\\"&lt;/noinclude>&lt;includeonly>\\\"v2\\\"&lt;/includeonly>\"},\"dsr\":[77,155,68,7]}' data-mw='{\"attribs\":[[{\"txt\":\"id\"},{\"html\":\"&lt;meta typeof=\\\"mw:Includes/NoInclude\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;noinclude>\\\",\\\"dsr\\\":[86,97,null,null]}&#39;/>\\\"v1\\\"&lt;meta typeof=\\\"mw:Includes/NoInclude/End\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;/noinclude>\\\",\\\"dsr\\\":[101,113,null,null]}&#39;/>&lt;meta typeof=\\\"mw:Includes/IncludeOnly\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;includeonly>\\\\\\\"v2\\\\\\\"&amp;lt;/includeonly>\\\",\\\"dsr\\\":[113,144,null,null]}&#39;/>&lt;meta typeof=\\\"mw:Includes/IncludeOnly/End\\\" data-parsoid=&#39;{\\\"src\\\":\\\"\\\",\\\"dsr\\\":[144,144,null,null]}&#39;/>\"}]]}'>bar</span></p>");
add("wt2html", "4. includeonly in table attributes", "<table data-parsoid='{\"dsr\":[0,77,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[3,75,0,0]}'><tr about=\"#mwt1\" typeof=\"mw:ExpandedAttrs\" data-parsoid='{\"startTagSrc\":\"|-\",\"a\":{\"&lt;noinclude>\\n|-\\n|a\\n&lt;/noinclude>\":null},\"sa\":{\"&lt;noinclude>\\n|-\\n|a\\n&lt;/noinclude>\":\"\"},\"autoInsertedEnd\":true,\"dsr\":[3,36,33,0]}' data-mw='{\"attribs\":[[{\"txt\":\"a\",\"html\":\"&lt;meta typeof=\\\"mw:Includes/NoInclude\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;noinclude>\\\",\\\"dsr\\\":[6,17,null,null]}&#39;/>\\n|-\\n|a\\n&lt;meta typeof=\\\"mw:Includes/NoInclude/End\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;/noinclude>\\\",\\\"dsr\\\":[24,36,null,null]}&#39;/>\"},{\"html\":\"\"}]]}'></tr>\n<tr about=\"#mwt2\" typeof=\"mw:ExpandedAttrs\" data-parsoid='{\"startTagSrc\":\"|-\",\"a\":{\"&lt;includeonly>\\n|-\\n|b\\n&lt;/includeonly>\":null},\"sa\":{\"&lt;includeonly>\\n|-\\n|b\\n&lt;/includeonly>\":\"\"},\"autoInsertedEnd\":true,\"dsr\":[37,74,37,0]}' data-mw='{\"attribs\":[[{\"txt\":\"\",\"html\":\"&lt;meta typeof=\\\"mw:Includes/IncludeOnly\\\" data-parsoid=&#39;{\\\"src\\\":\\\"&amp;lt;includeonly>\\\\n|-\\\\n|b\\\\n&amp;lt;/includeonly>\\\",\\\"dsr\\\":[40,74,null,null]}&#39;/>&lt;meta typeof=\\\"mw:Includes/IncludeOnly/End\\\" data-parsoid=&#39;{\\\"src\\\":\\\"\\\",\\\"dsr\\\":[74,74,null,null]}&#39;/>\"},{\"html\":\"\"}]]}'></tr>\n</tbody></table>");
add("wt2html", "Templates: 2. Inside a block tag", "<div data-parsoid='{\"stx\":\"html\",\"dsr\":[0,23,5,6]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[5,17,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"Foo\"}},\"i\":0}}]}'>Foo</span></div>\n<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[24,61,12,13]}'><span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[36,48,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"Foo\"}},\"i\":0}}]}'>Foo</span></blockquote>");
add("wt2html", "Templates: HTML Tag: 2. Generation of HTML attr. value", "<div style=\"'color:red;'\" about=\"#mwt2\" typeof=\"mw:ExpandedAttrs\" data-parsoid='{\"stx\":\"html\",\"a\":{\"style\":\"&#39;color:red;&#39;\"},\"sa\":{\"style\":\"{{echo|&#39;color:red;&#39;}}\"},\"dsr\":[0,42,33,6]}' data-mw='{\"attribs\":[[{\"txt\":\"style\"},{\"html\":\"&lt;span about=\\\"#mwt1\\\" typeof=\\\"mw:Transclusion\\\" data-parsoid=&#39;{\\\"pi\\\":[[{\\\"k\\\":\\\"1\\\"}]],\\\"dsr\\\":[11,32,null,null]}&#39; data-mw=&#39;{\\\"parts\\\":[{\\\"template\\\":{\\\"target\\\":{\\\"wt\\\":\\\"echo\\\",\\\"href\\\":\\\"./Template:Echo\\\"},\\\"params\\\":{\\\"1\\\":{\\\"wt\\\":\\\"&amp;#39;color:red;&amp;#39;\\\"}},\\\"i\\\":0}}]}&#39;>&#39;color:red;&#39;&lt;/span>\"}]]}'>foo</div>");
add("wt2html", "Templates: HTML Tag: 3. Generation of HTML attr key and value", "<div style=\"'color:red;'\" about=\"#mwt3\" typeof=\"mw:ExpandedAttrs\" data-parsoid='{\"stx\":\"html\",\"a\":{\"style\":\"&#39;color:red;&#39;\"},\"sa\":{\"style\":\"{{echo|&#39;color:red;&#39;}}\"},\"dsr\":[0,51,42,6]}' data-mw='{\"attribs\":[[{\"txt\":\"style\",\"html\":\"&lt;span about=\\\"#mwt2\\\" typeof=\\\"mw:Transclusion\\\" data-parsoid=&#39;{\\\"pi\\\":[[{\\\"k\\\":\\\"1\\\"}]],\\\"dsr\\\":[5,19,null,null]}&#39; data-mw=&#39;{\\\"parts\\\":[{\\\"template\\\":{\\\"target\\\":{\\\"wt\\\":\\\"echo\\\",\\\"href\\\":\\\"./Template:Echo\\\"},\\\"params\\\":{\\\"1\\\":{\\\"wt\\\":\\\"style\\\"}},\\\"i\\\":0}}]}&#39;>style&lt;/span>\"},{\"html\":\"&lt;span about=\\\"#mwt1\\\" typeof=\\\"mw:Transclusion\\\" data-parsoid=&#39;{\\\"pi\\\":[[{\\\"k\\\":\\\"1\\\"}]],\\\"dsr\\\":[20,41,null,null]}&#39; data-mw=&#39;{\\\"parts\\\":[{\\\"template\\\":{\\\"target\\\":{\\\"wt\\\":\\\"echo\\\",\\\"href\\\":\\\"./Template:Echo\\\"},\\\"params\\\":{\\\"1\\\":{\\\"wt\\\":\\\"&amp;#39;color:red;&amp;#39;\\\"}},\\\"i\\\":0}}]}&#39;>&#39;color:red;&#39;&lt;/span>\"}]]}'>foo</div>");
add("wt2html", "Templates: Wiki Tables: 1a. Fostering of entire template content", "<p about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"fostered\":true,\"autoInsertedEnd\":true,\"dsr\":[0,16,null,null],\"firstWikitextNode\":\"TABLE\",\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[\"{|\\n\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a\"}},\"i\":0}},\"\\n|}\"]}'>a</p><table about=\"#mwt2\">\n\n</table>");
add("wt2html", "Templates: Wiki Tables: 1b. Fostering of entire template content", "<div about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"fostered\":true,\"autoInsertedEnd\":true,\"dsr\":[0,40,null,null],\"firstWikitextNode\":\"TABLE\",\"pi\":[[{\"k\":\"1\"}],[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[\"{|\\n\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;div>\"}},\"i\":0}},\"\\nfoo\\n\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;/div>\"}},\"i\":1}},\"\\n|}\"]}'>\n<p>foo</p>\n</div><table about=\"#mwt3\">\n\n</table>");
add("wt2html", "Templates: Wiki Tables: 2. Fostering of partial template content", "<p about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"fostered\":true,\"autoInsertedEnd\":true,\"dsr\":[0,29,null,null],\"firstWikitextNode\":\"TABLE\",\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[\"{|\\n\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a\\n&lt;div>b&lt;/div>\"}},\"i\":0}},\"\\n|}\"]}'>a</p><div about=\"#mwt2\">b</div><table about=\"#mwt2\">\n\n\n</table>");
add("wt2html", "Templates: Wiki Tables: 4. Templated tags, no content", "<table about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,25,null,null],\"pi\":[[],[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"tbl-start\",\"href\":\"./Template:Tbl-start\"},\"params\":{},\"i\":0}},\"\\n\",{\"template\":{\"target\":{\"wt\":\"tbl-end\",\"href\":\"./Template:Tbl-end\"},\"params\":{},\"i\":1}}]}'>\n</table>");
add("wt2html", "Templates: Lists: Multi-line list-items via templates", "<ul data-parsoid='{\"dsr\":[0,71,0,0]}'><li data-parsoid='{\"dsr\":[0,35,1,0]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[1,35,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"a {{nonexistent|\\nunused}}\"}},\"i\":0}}]}'>a {{nonexistent|\nunused}}</span></li>\n<li data-parsoid='{\"dsr\":[36,71,1,0]}'><span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[37,71,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"b {{nonexistent|\\nunused}}\"}},\"i\":0}}]}'>b {{nonexistent|\nunused}}</span></li></ul>");
add("wt2html", "Templates: Ugly nesting: 1. Quotes opened/closed across templates (echo)", "<p data-parsoid='{\"dsr\":[0,40,0,0]}'><i about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,40,null,null],\"pi\":[[{\"k\":\"1\"}],[{\"k\":\"1\"}],[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&#39;&#39;a\"}},\"i\":0}},{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"b&#39;&#39;c&#39;&#39;d\"}},\"i\":1}},{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&#39;&#39;e\"}},\"i\":2}}]}'>ab</i><span about=\"#mwt1\">c</span><i about=\"#mwt1\">d</i><span about=\"#mwt1\">e</span></p>");
add("wt2html", "Templates: Ugly templates: 1. Navbox template parses badly leading to table misnesting\n(Parsoid-centric)", "<table about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,32,2,null],\"firstWikitextNode\":\"TABLE_html\",\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[\"{|\\n|\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo&lt;/table>\"}},\"i\":0}},\"\\n|bar\\n|}\"]}'>\n<tbody><tr><td>foo</td></tr></tbody></table><span about=\"#mwt1\">\n|bar\n</span>");
add("wt2html", "Templates: Ugly templates: 4. newline-only template parameter inconsistency", "<span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[0,10,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"\\n\"}},\"i\":0}}]}'>\n</span>");
add("wt2html", "subst: does not work during normal parse", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SubstTest\",\"href\":\"./Template:SubstTest\"},\"params\":{},\"i\":0}}]}'>Foobar</p>");
add("wt2html", "message transform: magic variables", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,12,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SITENAME\",\"function\":\"sitename\"},\"params\":{},\"i\":0}}]}'>MediaWiki</p>");
add("wt2html", "message transform: should not transform wiki markup", "<p data-parsoid='{\"dsr\":[0,8,0,0]}'><i data-parsoid='{\"dsr\":[0,8,2,2]}'>test</i></p>");
add("wt2html", "message transform: <noinclude> in transcluded template (T6926)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,12,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Includes\",\"href\":\"./Template:Includes\"},\"params\":{},\"i\":0}}]}'>Foobar</p>");
add("wt2html", "message transform: <onlyinclude> in transcluded template (T6926)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Includes2\",\"href\":\"./Template:Includes2\"},\"params\":{},\"i\":0}}]}'>Foo<meta typeof=\"mw:Includes/OnlyInclude/End\"/></p>");
add("wt2html", "{{#special:}} page name, known", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,26,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#special:Recentchanges\",\"function\":\"#special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#special missing in Parsoid.</p>");
add("wt2html", "{{#special:}} page name with subpage, known", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,32,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#special:Recentchanges/param\",\"function\":\"#special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#special missing in Parsoid.</p>");
add("wt2html", "{{#special:}} page name, unknown", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,31,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#special:foobar nonexistent\",\"function\":\"#special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#special missing in Parsoid.</p>");
add("wt2html", "{{#speciale:}} page name, known", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,27,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#speciale:Recentchanges\",\"function\":\"#speciale\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#speciale missing in Parsoid.</p>");
add("wt2html", "{{#speciale:}} page name with subpage, known", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,33,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#speciale:Recentchanges/param\",\"function\":\"#speciale\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#speciale missing in Parsoid.</p>");
add("wt2html", "{{#speciale:}} page name, unknown", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,32,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#speciale:foobar nonexistent\",\"function\":\"#speciale\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#speciale missing in Parsoid.</p>");
add("wt2html", "Image with link parameter, wgNoFollowLinks set to false", "<p data-parsoid='{\"dsr\":[0,45,0,0]}'><span class=\"mw-default-size\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"link\",\"ak\":\"link=http://example.com/\"}],\"dsr\":[0,45,null,null]}'><a href=\"http://example.com/\" data-parsoid=\"{}\"><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></span></p>");
add("wt2html", "Image with link parameter, wgNoFollowDomainExceptions", "<p data-parsoid='{\"dsr\":[0,45,0,0]}'><span class=\"mw-default-size\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"link\",\"ak\":\"link=http://example.com/\"}],\"dsr\":[0,45,null,null]}'><a href=\"http://example.com/\" data-parsoid=\"{}\"><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></span></p>");
add("wt2html", "SVG thumbnails with invalid language code", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"caption\",\"ak\":\"caption\"},{\"ck\":\"lang\",\"ak\":\"lang=invalid.language.code\"}],\"dsr\":[0,60,2,2]}'><a href=\"./File:Foobar.svg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.svg\"},\"sa\":{\"href\":\"File:Foobar.svg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./File:Foobar.svg\" src=\"//example.com/images/thumb/f/ff/Foobar.svg/220px-Foobar.svg\" lang=\"invalid.language.code\" data-file-width=\"240\" data-file-height=\"180\" data-file-type=\"drawing\" height=\"165\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.svg\",\"lang\":\"invalid.language.code\",\"height\":\"165\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.svg\",\"lang\":\"lang=invalid.language.code\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,58,null,null]}'>caption</figcaption></figure>");
add("wt2html", "T2561: {{/Subpage}}", "<p data-parsoid='{\"dsr\":[0,12,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,12,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"/Subpage\",\"href\":\"./Page/Subpage\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Page/Subpage\"}],\"i\":0}}]}'>{{/Subpage}}</span></p>");
add("wt2html", "PAGESINCATEGORY invalid title fatal (r33546 fix)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,27,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGESINCATEGORY:&lt;bogus>\",\"function\":\"pagesincategory\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_pagesincategory missing in Parsoid.</p>");
-add("wt2html", "Parsoid: Defaultsort (template-generated)", "<meta property=\"mw:PageProp/categorydefaultsort\" content=\"Foo\" about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,28,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"{{echo|DEFAULTSORT}}:Foo\",\"href\":\"./Foo\"},\"params\":{},\"i\":0}}]}'/>");
add("wt2html", "Short headings with trailing space should match behavior of Parser::doHeadings (T21910)", "<p data-parsoid='{\"dsr\":[0,100,0,0]}'>=== \nThe line above must have a trailing space!\n=== <!--\n--> <!-- -->\nBut just in case it doesn't...</p>");
add("wt2html", "Header with space, plus and underscore as entity", "<p data-parsoid='{\"dsr\":[0,34,0,0]}'>Id should not contain + for spaces</p>\n\n<h2 id=\"Space_between_Text\" data-parsoid='{\"dsr\":[36,60,2,2]}'> Space between Text </h2>\n<p data-parsoid='{\"dsr\":[61,70,0,0]}'>section 1</p>\n\n<h2 id=\"Space-Entity_between_Text\" data-parsoid='{\"dsr\":[72,111,2,2]}'> Space-Entity<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#32;\",\"srcContent\":\" \",\"dsr\":[87,92,null,null]}'> </span>between<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#32;\",\"srcContent\":\" \",\"dsr\":[99,104,null,null]}'> </span>Text </h2>\n<p data-parsoid='{\"dsr\":[112,121,0,0]}'>section 2</p>\n\n<h2 id=\"Plus.2Bbetween.2BText\" data-parsoid='{\"dsr\":[123,146,2,2]}'> Plus+between+Text </h2>\n<p data-parsoid='{\"dsr\":[147,156,0,0]}'>section 3</p>\n\n<h2 id=\"Plus-Entity.2Bbetween.2BText\" data-parsoid='{\"dsr\":[158,196,2,2]}'> Plus-Entity<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#43;\",\"srcContent\":\"+\",\"dsr\":[172,177,null,null]}'>+</span>between<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#43;\",\"srcContent\":\"+\",\"dsr\":[184,189,null,null]}'>+</span>Text </h2>\n<p data-parsoid='{\"dsr\":[197,206,0,0]}'>section 4</p>\n\n<h2 id=\"Underscore_between_Text\" data-parsoid='{\"dsr\":[208,237,2,2]}'> Underscore_between_Text </h2>\n<p data-parsoid='{\"dsr\":[238,247,0,0]}'>section 5</p>\n\n<h2 id=\"Underscore-Entity_between_Text\" data-parsoid='{\"dsr\":[249,293,2,2]}'> Underscore-Entity<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#95;\",\"srcContent\":\"_\",\"dsr\":[269,274,null,null]}'>_</span>between<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#95;\",\"srcContent\":\"_\",\"dsr\":[281,286,null,null]}'>_</span>Text </h2>\n<p data-parsoid='{\"dsr\":[294,303,0,0]}'>section 6</p>\n\n<p data-parsoid='{\"dsr\":[305,501,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Main_Page#Space_between_Text\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page#Space_between_Text\"},\"sa\":{\"href\":\"#Space between Text\"},\"dsr\":[305,328,2,2]}'>#Space between Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Space-Entity_between_Text\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page#Space-Entity_between_Text\"},\"sa\":{\"href\":\"#Space-Entity&amp;#32;between&amp;#32;Text\"},\"dsr\":[329,367,2,2]}'>#Space-Entity between Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Plus.2Bbetween.2BText\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page#Plus.2Bbetween.2BText\"},\"sa\":{\"href\":\"#Plus+between+Text\"},\"dsr\":[368,390,2,2]}'>#Plus+between+Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Plus-Entity.2Bbetween.2BText\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page#Plus-Entity.2Bbetween.2BText\"},\"sa\":{\"href\":\"#Plus-Entity&amp;#43;between&amp;#43;Text\"},\"dsr\":[391,428,2,2]}'>#Plus-Entity+between+Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Underscore_between_Text\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page#Underscore_between_Text\"},\"sa\":{\"href\":\"#Underscore_between_Text\"},\"dsr\":[429,457,2,2]}'>#Underscore_between_Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Underscore-Entity_between_Text\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page#Underscore-Entity_between_Text\"},\"sa\":{\"href\":\"#Underscore-Entity&amp;#95;between&amp;#95;Text\"},\"dsr\":[458,501,2,2]}'>#Underscore-Entity_between_Text</a></p>");
add("wt2html", "Single-line or multiline-comments can follow headings", "<h2 id=\"foo\" data-parsoid='{\"dsr\":[0,7,2,2]}'>foo</h2><!---->\n<h2 id=\"bar\" data-parsoid='{\"dsr\":[15,22,2,2]}'>bar</h2><!--c1-->\n<h2 id=\"baz\" data-parsoid='{\"dsr\":[32,39,2,2]}'>baz</h2><!--\nc2\nc3-->");
add("wt2html", "Media link", "<p data-parsoid='{\"dsr\":[0,20,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Media:Foobar.jpg\" title=\"Media:Foobar.jpg\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Media:Foobar.jpg\"},\"sa\":{\"href\":\"Media:Foobar.jpg\"},\"dsr\":[0,20,2,2]}'>Media:Foobar.jpg</a></p>");
add("wt2html", "Media link with text", "<p data-parsoid='{\"dsr\":[0,43,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Media:Foobar.jpg\" title=\"Media:Foobar.jpg\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Media:Foobar.jpg\"},\"sa\":{\"href\":\"Media:Foobar.jpg\"},\"dsr\":[0,43,19,2]}'>A neat file to look at</a></p>");
add("wt2html", "Media link with nasty text", "<p data-parsoid='{\"dsr\":[0,106,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Media:Foobar.jpg\" title=\"Media:Foobar.jpg\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Media:Foobar.jpg\"},\"sa\":{\"href\":\"Media:Foobar.jpg\"},\"dsr\":[0,106,19,2]}'>Safe Link<div style=\"display:none\" data-parsoid='{\"stx\":\"html\",\"dsr\":[28,104,24,6]}'>\" onmouseover=\"alert(document.cookie)\" onfoo=\"</div></a></p>");
add("wt2html", "Media link to nonexistent file (T3702)", "<p data-parsoid='{\"dsr\":[0,21,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Media:No_such.jpg\" title=\"Media:No such.jpg\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Media:No_such.jpg\"},\"sa\":{\"href\":\"Media:No such.jpg\"},\"dsr\":[0,21,2,2]}'>Media:No such.jpg</a></p>");
add("wt2html", "(T21451) Links should refer to the normalized form.", "<p data-parsoid='{\"dsr\":[0,64,0,0]}'><a rel=\"mw:WikiLink\" href=\"./אַ\" title=\"אַ\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./אַ\"},\"sa\":{\"href\":\"&amp;#xFB2E;\"},\"dsr\":[0,12,2,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./אַ\" title=\"אַ\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./אַ\"},\"sa\":{\"href\":\"&amp;#x5d0;&amp;#x5b7;\"},\"dsr\":[13,31,2,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./אַ\" title=\"אַ\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./אַ\"},\"sa\":{\"href\":\"&amp;#x5d0;ַ\"},\"dsr\":[32,44,2,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./אַ\" title=\"אַ\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./אַ\"},\"sa\":{\"href\":\"א&amp;#x5b7;\"},\"dsr\":[45,57,2,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./אַ\" title=\"אַ\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./אַ\"},\"sa\":{\"href\":\"אַ\"},\"dsr\":[58,64,2,2]}'>אַ</a></p>");
add("wt2html", "T4304: HTML attribute safety (unsafe breakout parameter; 2309)", "<div style=\"float: right; >alert(document.cookie)\" about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"a\":{\"style\":\"float: right; >alert(document.cookie)\"},\"sa\":{\"style\":\"float: right; {{{1}}}\"},\"dsr\":[0,55,null,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"div style\",\"href\":\"./Template:Div_style\"},\"params\":{\"1\":{\"wt\":\"\\\">&lt;script>alert(document.cookie)&lt;/script>\"}},\"i\":0}}]}'>Magic div</div>");
add("wt2html", "T4304: HTML attribute safety (unsafe breakout parameter 2; 2309)", "<div style=\"float: right; >alert(document.cookie)\" about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"a\":{\"style\":\"float: right; >alert(document.cookie)\"},\"sa\":{\"style\":\"float: right; {{{1}}}\"},\"dsr\":[0,56,null,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"div style\",\"href\":\"./Template:Div_style\"},\"params\":{\"1\":{\"wt\":\"\\\" >&lt;script>alert(document.cookie)&lt;/script>\"}},\"i\":0}}]}'>Magic div</div>");
add("wt2html", "CSS line continuation 2", "<div style=\"/* insecure input */\" data-parsoid='{\"stx\":\"html\",\"a\":{\"style\":\"/* insecure input */\"},\"sa\":{\"style\":\"background-image: u\\\\&amp;#13;rl(test.jpg); \"},\"dsr\":[0,59,53,6]}'></div>");
add("wt2html", "Sanitizer: Closing of closed but not open table tags", "Table not started");
add("wt2html", "Sanitizer: Validating that <meta> and <link> work, but only for Microdata", "<div itemscope=\"\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,308,15,6]}'>\n\t<p data-parsoid='{\"dsr\":[17,301,0,0]}'>&lt;meta itemprop=\"hello\" content=\"world\">\n\t&lt;meta http-equiv=\"refresh\" content=\"5\">\n\t&lt;meta itemprop=\"hello\" http-equiv=\"refresh\" content=\"5\">\n\t&lt;link itemprop=\"hello\" href=\"{{SERVER}}\">\n\t&lt;link rel=\"stylesheet\" href=\"{{SERVER}}\">\n\t&lt;link rel=\"stylesheet\" itemprop=\"hello\" href=\"{{SERVER}}\"></p>\n</div>");
add("wt2html", "Language converter: output gets cut off unexpectedly (T7757)", "<p data-parsoid='{\"dsr\":[0,20,0,0]}'>this bit is safe: }-</p>\n\n<p data-parsoid='{\"dsr\":[22,82,0,0]}'>but if we add a conversion instance: -{zh-cn:xxx;zh-tw:yyy}-</p>\n\n<p data-parsoid='{\"dsr\":[84,112,0,0]}'>then we get cut off here: }-</p>\n\n<p data-parsoid='{\"dsr\":[114,145,0,0]}'>all additional text is vanished</p>");
add("wt2html", "Self closed html pairs (T7487)", "<center data-parsoid='{\"stx\":\"html\",\"dsr\":[0,47,8,9]}'><font id=\"bug\" data-parsoid='{\"stx\":\"html\",\"selfClose\":true,\"dsr\":[8,25,17,0]}'></font>Centered text</center>\n<div data-parsoid='{\"stx\":\"html\",\"dsr\":[48,88,5,6]}'><font id=\"bug2\" data-parsoid='{\"stx\":\"html\",\"selfClose\":true,\"dsr\":[53,71,18,0]}'></font>In div text</div>");
add("wt2html", "Fuzz testing: Parser14", "<h2 id=\"onmouseover.3D\" data-parsoid='{\"dsr\":[0,18,2,2]}'> onmouseover= </h2>\n<p data-parsoid='{\"dsr\":[19,33,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://__TOC__\" data-parsoid='{\"stx\":\"url\",\"dsr\":[19,33,0,0]}'>http://__TOC__</a></p>");
add("wt2html", "Inline HTML vs wiki block nesting", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'><b data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[0,17,3,0]}'>Bold paragraph</b></p><b data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[17,37,0,0]}'>\n\n<p data-parsoid='{\"dsr\":[19,37,0,0]}'>New wiki paragraph</p></b>");
add("wt2html", "Special page transclusion", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,30,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Special:Prefixindex/Xyzzyx\",\"function\":\"special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_special missing in Parsoid.</p>");
add("wt2html", "Special page transclusion twice (T7021)", "<p data-parsoid='{\"dsr\":[0,61,0,0]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,30,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Special:Prefixindex/Xyzzyx\",\"function\":\"special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_special missing in Parsoid.</span>\n<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[31,61,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Special:Prefixindex/Xyzzyx\",\"function\":\"special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_special missing in Parsoid.</span></p>");
add("wt2html", "Transclusion of default MediaWiki message", "<p data-parsoid='{\"dsr\":[0,22,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,22,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"MediaWiki:Mainpage\",\"href\":\"./MediaWiki:Mainpage\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for MediaWiki:Mainpage\"}],\"i\":0}}]}'>{{MediaWiki:Mainpage}}</span></p>");
add("wt2html", "Transclusion of nonexistent MediaWiki message", "<p data-parsoid='{\"dsr\":[0,25,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,25,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"MediaWiki:Mainpagexxx\",\"href\":\"./MediaWiki:Mainpagexxx\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for MediaWiki:Mainpagexxx\"}],\"i\":0}}]}'>{{MediaWiki:Mainpagexxx}}</span></p>");
add("wt2html", "Transclusion of MediaWiki message with underscore", "<p data-parsoid='{\"dsr\":[0,27,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,27,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"MediaWiki:history_short\",\"href\":\"./MediaWiki:History_short\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for MediaWiki:History_short\"}],\"i\":0}}]}'>{{MediaWiki:history_short}}</span></p>");
add("wt2html", "Transclusion of MediaWiki message with space", "<p data-parsoid='{\"dsr\":[0,27,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,27,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"MediaWiki:history short\",\"href\":\"./MediaWiki:History_short\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for MediaWiki:History_short\"}],\"i\":0}}]}'>{{MediaWiki:history short}}</span></p>");
add("wt2html", "Special:Search page linking.", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,18,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Special:search\",\"function\":\"special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_special missing in Parsoid.</p>");
add("wt2html", "Say the magic word", "<ul data-parsoid='{\"dsr\":[0,544,0,0]}'><li data-parsoid='{\"dsr\":[0,14,1,0]}'> <span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[2,14,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAME\",\"function\":\"pagename\"},\"params\":{},\"i\":0}}]}'>Parser test</span></li>\n<li data-parsoid='{\"dsr\":[15,30,1,0]}'> <span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[17,30,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAMEE\",\"function\":\"pagenamee\"},\"params\":{},\"i\":0}}]}'></span></li>\n<li data-parsoid='{\"dsr\":[31,49,1,0]}'> <span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[33,49,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"FULLPAGENAME\",\"function\":\"fullpagename\"},\"params\":{},\"i\":0}}]}'>Parser test</span></li>\n<li data-parsoid='{\"dsr\":[50,69,1,0]}'> <span about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[52,69,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"FULLPAGENAMEE\",\"function\":\"fullpagenamee\"},\"params\":{},\"i\":0}}]}'>Parser test</span></li>\n<li data-parsoid='{\"dsr\":[70,88,1,0]}'> <span about=\"#mwt6\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[72,88,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"BASEPAGENAME\",\"href\":\"./Template:BASEPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:BASEPAGENAME\"}],\"i\":0}}]}'>{{BASEPAGENAME}}</span></li>\n<li data-parsoid='{\"dsr\":[89,108,1,0]}'> <span about=\"#mwt8\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[91,108,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"BASEPAGENAMEE\",\"href\":\"./Template:BASEPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:BASEPAGENAMEE\"}],\"i\":0}}]}'>{{BASEPAGENAMEE}}</span></li>\n<li data-parsoid='{\"dsr\":[109,126,1,0]}'> <span about=\"#mwt10\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[111,126,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBPAGENAME\",\"href\":\"./Template:SUBPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBPAGENAME\"}],\"i\":0}}]}'>{{SUBPAGENAME}}</span></li>\n<li data-parsoid='{\"dsr\":[127,145,1,0]}'> <span about=\"#mwt12\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[129,145,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBPAGENAMEE\",\"href\":\"./Template:SUBPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBPAGENAMEE\"}],\"i\":0}}]}'>{{SUBPAGENAMEE}}</span></li>\n<li data-parsoid='{\"dsr\":[146,164,1,0]}'> <span about=\"#mwt14\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[148,164,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ROOTPAGENAME\",\"href\":\"./Template:ROOTPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:ROOTPAGENAME\"}],\"i\":0}}]}'>{{ROOTPAGENAME}}</span></li>\n<li data-parsoid='{\"dsr\":[165,184,1,0]}'> <span about=\"#mwt16\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[167,184,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ROOTPAGENAMEE\",\"href\":\"./Template:ROOTPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:ROOTPAGENAMEE\"}],\"i\":0}}]}'>{{ROOTPAGENAMEE}}</span></li>\n<li data-parsoid='{\"dsr\":[185,203,1,0]}'> <span about=\"#mwt17\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[187,203,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKPAGENAME\",\"function\":\"talkpagename\"},\"params\":{},\"i\":0}}]}'>Parser test</span></li>\n<li data-parsoid='{\"dsr\":[204,223,1,0]}'> <span about=\"#mwt19\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[206,223,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKPAGENAMEE\",\"href\":\"./Template:TALKPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:TALKPAGENAMEE\"}],\"i\":0}}]}'>{{TALKPAGENAMEE}}</span></li>\n<li data-parsoid='{\"dsr\":[224,245,1,0]}'> <span about=\"#mwt21\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[226,245,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTPAGENAME\",\"href\":\"./Template:SUBJECTPAGENAME\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBJECTPAGENAME\"}],\"i\":0}}]}'>{{SUBJECTPAGENAME}}</span></li>\n<li data-parsoid='{\"dsr\":[246,268,1,0]}'> <span about=\"#mwt23\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[248,268,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTPAGENAMEE\",\"href\":\"./Template:SUBJECTPAGENAMEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBJECTPAGENAMEE\"}],\"i\":0}}]}'>{{SUBJECTPAGENAMEE}}</span></li>\n<li data-parsoid='{\"dsr\":[269,285,1,0]}'> <span about=\"#mwt24\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[271,285,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"NAMESPACEE\",\"function\":\"namespacee\"},\"params\":{},\"i\":0}}]}'>Main</span></li>\n<li data-parsoid='{\"dsr\":[286,301,1,0]}'> <span about=\"#mwt25\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[288,301,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"NAMESPACE\",\"function\":\"namespace\"},\"params\":{},\"i\":0}}]}'>Main</span></li>\n<li data-parsoid='{\"dsr\":[302,323,1,0]}'> <span about=\"#mwt26\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[304,323,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"NAMESPACENUMBER\",\"function\":\"namespacenumber\"},\"params\":{},\"i\":0}}]}'>0</span></li>\n<li data-parsoid='{\"dsr\":[324,339,1,0]}'> <span about=\"#mwt27\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[326,339,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKSPACE\",\"function\":\"talkspace\"},\"params\":{},\"i\":0}}]}'>Talk</span></li>\n<li data-parsoid='{\"dsr\":[340,356,1,0]}'> <span about=\"#mwt29\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[342,356,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"TALKSPACEE\",\"href\":\"./Template:TALKSPACEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:TALKSPACEE\"}],\"i\":0}}]}'>{{TALKSPACEE}}</span></li>\n<li data-parsoid='{\"dsr\":[357,375,1,0]}'> <span about=\"#mwt30\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[359,375,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTSPACE\",\"function\":\"subjectspace\"},\"params\":{},\"i\":0}}]}'>Main</span></li>\n<li data-parsoid='{\"dsr\":[376,395,1,0]}'> <span about=\"#mwt32\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[378,395,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"SUBJECTSPACEE\",\"href\":\"./Template:SUBJECTSPACEE\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:SUBJECTSPACEE\"}],\"i\":0}}]}'>{{SUBJECTSPACEE}}</span></li>\n<li data-parsoid='{\"dsr\":[396,544,1,0]}'> <span about=\"#mwt41\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"},{\"k\":\"2\"},{\"k\":\"3\"},{\"k\":\"4\"},{\"k\":\"5\"},{\"k\":\"6\"},{\"k\":\"7\"}]],\"dsr\":[398,544,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Dynamic\",\"href\":\"./Template:Dynamic\"},\"params\":{\"1\":{\"wt\":\"{{NUMBEROFUSERS}}\"},\"2\":{\"wt\":\"{{NUMBEROFPAGES}}\"},\"3\":{\"wt\":\"{{CURRENTVERSION}}\"},\"4\":{\"wt\":\"{{CONTENTLANGUAGE}}\"},\"5\":{\"wt\":\"{{DIRECTIONMARK}}\"},\"6\":{\"wt\":\"{{CURRENTTIMESTAMP}}\"},\"7\":{\"wt\":\"{{NUMBEROFARTICLES}}\"}},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Template:Dynamic\"}],\"i\":0}}]}'>{{Dynamic|{{NUMBEROFUSERS}}|{{NUMBEROFPAGES}}|{{CURRENTVERSION}}|{{CONTENTLANGUAGE}}|{{DIRECTIONMARK}}|{{CURRENTTIMESTAMP}}|{{NUMBEROFARTICLES}}}}</span></li></ul>");
add("wt2html", "Gallery override link with absolute external link with LanguageConverter", "<ul class=\"gallery mw-gallery-traditional\" typeof=\"mw:Extension/gallery\" about=\"#mwt2\" data-parsoid='{\"dsr\":[0,87,2,2]}' data-mw='{\"name\":\"gallery\",\"attrs\":{},\"body\":{\"extsrc\":\"\\nFile:foobar.jpg|caption|alt=galleryalt|link=http://www.example.org\\n\"}}'>\n<li class=\"gallerybox\" style=\"width: 155px;\"><div class=\"thumb\" style=\"width: 150px; height: 150px;\"><span style=\"display: inline-block; height: 100%; vertical-align: middle;\"></span><span typeof=\"mw:Image\" style=\"vertical-align: middle; display: inline-block;\"><a href=\"http://www.example.org\"><img alt=\"galleryalt\" resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"14\" width=\"120\"/></a></span></div><div class=\"gallerytext\">caption</div></li>\n</ul>");
add("wt2html", "Illegal character references (T106578)", "<dl data-parsoid='{\"dsr\":[0,167,0,0]}'><dt data-parsoid='{\"dsr\":[0,6,1,0]}'> Null</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[6,13,1,0]}'> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#00;\",\"srcContent\":\"�\",\"dsr\":[8,13,null,null]}'>�</span></dd>\n<dt data-parsoid='{\"dsr\":[14,18,1,0]}'> FF</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[18,25,1,0]}'> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#xC;\",\"srcContent\":\"\\f\",\"dsr\":[20,25,null,null]}'>\f</span></dd>\n<dt data-parsoid='{\"dsr\":[26,30,1,0]}'> CR</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[30,37,1,0]}'> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#xD;\",\"srcContent\":\"\\r\",\"dsr\":[32,37,null,null]}'>\r</span></dd>\n<dt data-parsoid='{\"dsr\":[38,53,1,0]}'> Control (low)</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[53,59,1,0]}'> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#8;\",\"srcContent\":\"\\b\",\"dsr\":[55,59,null,null]}'>\b</span></dd>\n<dt data-parsoid='{\"dsr\":[60,76,1,0]}'> Control (high)</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[76,91,1,0]}'> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#x7F;\",\"srcContent\":\"\",\"dsr\":[78,84,null,null]}'></span> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#x9F;\",\"srcContent\":\"Ÿ\",\"dsr\":[85,91,null,null]}'>Ÿ</span></dd>\n<dt data-parsoid='{\"dsr\":[92,103,1,0]}'> Surrogate</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[103,121,1,0]}'> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#xD83D;\",\"srcContent\":\"�\",\"dsr\":[105,113,null,null]}'>�</span><span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#xDCA9;\",\"srcContent\":\"�\",\"dsr\":[113,121,null,null]}'>�</span></dd>\n<dt data-parsoid='{\"dsr\":[122,156,1,0]}'> This is an okay astral character</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[156,167,1,0]}'> <span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;#x1F4A9;\",\"srcContent\":\"💩\",\"dsr\":[158,167,null,null]}'>💩</span></dd></dl>");
add("wt2html", "Centre-aligned image", "<figure class=\"mw-default-size mw-halign-center\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"center\",\"ak\":\"centre\"}],\"dsr\":[0,27,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:foobar.jpg\"},\"dsr\":[2,25,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></figure>");
add("wt2html", "None-aligned image", "<figure class=\"mw-default-size mw-halign-none\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"none\",\"ak\":\"none\"}],\"dsr\":[0,25,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:foobar.jpg\"},\"dsr\":[2,23,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></figure>");
add("wt2html", "Width + Height sized image (using px) (height is ignored)", "<p data-parsoid='{\"dsr\":[0,30,0,0]}'><span typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"width\",\"ak\":\"640x480px\"}],\"dsr\":[0,30,null,null]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:foobar.jpg\"}}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"73\" width=\"640\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"73\",\"width\":\"640\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></span></p>");
add("wt2html", "Width-sized image (using px, no following whitespace)", "<p data-parsoid='{\"dsr\":[0,26,0,0]}'><span typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"width\",\"ak\":\"640px\"}],\"dsr\":[0,26,null,null]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:foobar.jpg\"}}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"73\" width=\"640\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"73\",\"width\":\"640\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></span></p>");
add("wt2html", "Width-sized image (using px, with following whitespace - test regression from r39467)", "<p data-parsoid='{\"dsr\":[0,27,0,0]}'><span typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"width\",\"ak\":\"640px \"}],\"dsr\":[0,27,null,null]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:foobar.jpg\"}}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"73\" width=\"640\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"73\",\"width\":\"640\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></span></p>");
add("wt2html", "Width-sized image (using px, with preceding whitespace - test regression from r39467)", "<p data-parsoid='{\"dsr\":[0,27,0,0]}'><span typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"width\",\"ak\":\" 640px\"}],\"dsr\":[0,27,null,null]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:foobar.jpg\"}}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"73\" width=\"640\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"73\",\"width\":\"640\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></span></p>");
add("wt2html", "HTML with raw HTML ($wgRawHtml==true)", "<p data-parsoid='{\"dsr\":[0,39,0,0]}'>&lt;html>&lt;script>alert(1);&lt;/script>&lt;/html></p>");
add("wt2html", "Parents of subpages, one level up, not named", "<p data-parsoid='{\"dsr\":[0,7,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Subpage_test/L1/L2\" title=\"Subpage test/L1/L2\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Subpage_test/L1/L2\"},\"sa\":{\"href\":\"../\"},\"dsr\":[0,7,2,2]}'>Subpage_test/L1/L2</a></p>");
add("wt2html", "Parents of subpages, two levels up, with lots of extra trailing slashes.", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Subpage_test/L1\" title=\"Subpage test/L1\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Subpage_test/L1\"},\"sa\":{\"href\":\"../../////\"},\"dsr\":[0,14,2,2]}'>Subpage_test/L1</a></p>");
add("wt2html", "RAW magic word", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,14,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"RAW:QUERTY\",\"href\":\"./RAW:QUERTY\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for RAW:QUERTY\"}],\"i\":0}}]}'>{{RAW:QUERTY}}</span></p>");
add("wt2html", "anchorencode", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,28,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode:foo bar©#%n\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>foo bar©#%n</p>");
add("wt2html", "anchorencode trims spaces", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,36,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode: __pretty__please__\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>__pretty__please__</p>");
add("wt2html", "anchorencode deals with links", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,40,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode: [[hello|world]] [[hi]]\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>world hi</p>");
add("wt2html", "anchorencode encodes like the TOC generator: (T20431)", "<h3 id=\".2B:.3A.253A.26.26.5D.5D\" data-parsoid='{\"dsr\":[0,26,3,3]}'> _ +:.3A%3A&amp;<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;amp;\",\"srcContent\":\"&amp;\",\"dsr\":[15,20,null,null]}'>&amp;</span>]] </h3>\n<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[27,64,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode: _ +:.3A%3A&amp;&amp;amp;]] \",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>_ +:.3A%3A&amp;&amp;]]</p>\n<meta property=\"mw:PageProp/noeditsection\" data-parsoid='{\"src\":\"__NOEDITSECTION__\",\"magicSrc\":\"__NOEDITSECTION__\",\"dsr\":[65,82,null,null]}'/>");
add("wt2html", "Self-link in language variants", "<p data-parsoid='{\"dsr\":[0,54,0,0]}'>Both <a rel=\"mw:WikiLink\" href=\"./Dunav\" title=\"Dunav\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Dunav\"},\"sa\":{\"href\":\"Dunav\"},\"dsr\":[5,14,2,2]}'>Dunav</a> and <a rel=\"mw:WikiLink\" href=\"./Дунав\" title=\"Дунав\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Дунав\"},\"sa\":{\"href\":\"Дунав\"},\"dsr\":[19,28,2,2]}'>Дунав</a> are names for this river.</p>");
add("wt2html", "Link to another existing title shouldn't be parsed as self-link even if it's a variant of this title", "<p data-parsoid='{\"dsr\":[0,77,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Дуна\" title=\"Дуна\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Дуна\"},\"sa\":{\"href\":\"Дуна\"},\"dsr\":[0,8,2,2]}'>Дуна</a> is not a self-link while <a rel=\"mw:WikiLink\" href=\"./Duna\" title=\"Duna\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Duna\"},\"sa\":{\"href\":\"Duna\"},\"dsr\":[34,42,2,2]}'>Duna</a> and <a rel=\"mw:WikiLink\" href=\"./Dуна\" title=\"Dуна\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Dуна\"},\"sa\":{\"href\":\"Dуна\"},\"dsr\":[47,55,2,2]}'>Dуна</a> are still self-links.</p>");
add("wt2html", "Link to a section of a variant of this title shouldn't be parsed as self-link", "<p data-parsoid='{\"dsr\":[0,79,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Dуна\" title=\"Dуна\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Dуна\"},\"sa\":{\"href\":\"Dуна\"},\"dsr\":[0,8,2,2]}'>Dуна</a> is a self-link while <a rel=\"mw:WikiLink\" href=\"./Dunа#Foo\" title=\"Dunа\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Dunа#Foo\"},\"sa\":{\"href\":\"Dunа#Foo\"},\"dsr\":[30,42,2,2]}'>Dunа#Foo</a> and <a rel=\"mw:WikiLink\" href=\"./Dуна#Foo\" title=\"Dуна\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Dуна#Foo\"},\"sa\":{\"href\":\"Dуна#Foo\"},\"dsr\":[47,59,2,2]}'>Dуна#Foo</a> are not self-links.</p>");
add("wt2html", "Link to pages in language variants", "<p data-parsoid='{\"dsr\":[0,41,0,0]}'>Main Page can be written as <a rel=\"mw:WikiLink\" href=\"./Маин_Паге\" title=\"Маин Паге\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Маин_Паге\"},\"sa\":{\"href\":\"Маин Паге\"},\"dsr\":[28,41,2,2]}'>Маин Паге</a></p>");
add("wt2html", "Multiple links to pages in language variants", "<p data-parsoid='{\"dsr\":[0,68,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[0,13,2,2]}'>Main Page</a> can be written as <a rel=\"mw:WikiLink\" href=\"./Маин_Паге\" title=\"Маин Паге\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Маин_Паге\"},\"sa\":{\"href\":\"Маин Паге\"},\"dsr\":[32,45,2,2]}'>Маин Паге</a> same as <a rel=\"mw:WikiLink\" href=\"./Маин_Паге\" title=\"Маин Паге\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Маин_Паге\"},\"sa\":{\"href\":\"Маин Паге\"},\"dsr\":[54,67,2,2]}'>Маин Паге</a>.</p>");
add("wt2html", "Simple template in language variants", "<p data-parsoid='{\"dsr\":[0,8,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,8,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"тест\",\"href\":\"./Шаблон:Тест\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Шаблон:Тест\"}],\"i\":0}}]}'>{{тест}}</span></p>");
add("wt2html", "Template with explicit namespace in language variants", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,17,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Template:тест\",\"href\":\"./Шаблон:Тест\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Шаблон:Тест\"}],\"i\":0}}]}'>{{Template:тест}}</span></p>");
add("wt2html", "Basic test for template parameter in language variants", "<p data-parsoid='{\"dsr\":[0,23,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"param\",\"named\":true}]],\"dsr\":[0,23,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"парамтест\",\"href\":\"./Шаблон:Парамтест\"},\"params\":{\"param\":{\"wt\":\"foo\"}},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Шаблон:Парамтест\"}],\"i\":0}}]}'>{{парамтест|param=foo}}</span></p>");
add("wt2html", "Stripping -{}- tags (language variants)", "<p data-parsoid='{\"dsr\":[0,36,0,0]}'>Latin proverb: -{Ne nuntium necare}-</p>");
add("wt2html", "Prevent conversion with -{}- tags (language variants)", "<p data-parsoid='{\"dsr\":[0,31,0,0]}'>Latinski: -{Ne nuntium necare}-</p>");
add("wt2html", "Prevent conversion of text with -{}- tags (language variants)", "<p data-parsoid='{\"dsr\":[0,31,0,0]}'>Latinski: -{Ne nuntium necare}-</p>");
add("wt2html", "Prevent conversion of links with -{}- tags (language variants)", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'>-{<a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[2,15,2,2]}'>Main Page</a>}-</p>");
add("wt2html", "-{}- tags within headlines (within html for parserConvert())", "<h2 id=\"-.7BNaslov.7D-\" data-parsoid='{\"dsr\":[0,16,2,2]}'> -{Naslov}- </h2>");
add("wt2html", "Explicit definition of language variant alternatives", "<p data-parsoid='{\"dsr\":[0,36,0,0]}'>-{zh:China;zh-tw:Taiwan}-, not China</p>");
add("wt2html", "Conversion around HTML tags", "<p data-parsoid='{\"dsr\":[0,93,0,0]}'>-{H|span=>sr-ec:script;title=>sr-ec:src;}-\n<span title=\"La-{sr-el:L;sr-ec:C;}-tin\" data-parsoid='{\"stx\":\"html\",\"dsr\":[43,93,40,7]}'>ski</span></p>");
add("wt2html", "Explicit session-wise language variant mapping (A flag and - flag)", "<p data-parsoid='{\"dsr\":[0,140,0,0]}'>Taiwan is not China.\nBut -{A|zh:China;zh-tw:Taiwan}- is China,\n(This-{-|zh:China;zh-tw:Taiwan}- should be stripped!)\nand -{China}- is China.</p>");
add("wt2html", "Explicit session-wise language variant mapping (H flag for hide)", "<p data-parsoid='{\"dsr\":[0,70,0,0]}'>(This-{H|zh:China;zh-tw:Taiwan}- should be stripped!)\nTaiwan is China.</p>");
add("wt2html", "Adding explicit conversion rule for title (T flag)", "<p data-parsoid='{\"dsr\":[0,46,0,0]}'>Should be stripped-{T|zh:China;zh-tw:Taiwan}-!</p>");
add("wt2html", "Testing that changing the language variant here in the tests actually works", "<p data-parsoid='{\"dsr\":[0,46,0,0]}'>Should be stripped-{T|zh:China;zh-tw:Taiwan}-!</p>");
add("wt2html", "Recursive conversion of alt and title attrs shouldn't clear converter state", "<p data-parsoid='{\"dsr\":[0,125,0,0]}'>-{H|zh-cn:Exclamation;zh-tw:exclamation;}-\nShould be stripped-{T|zh-cn:China;zh-tw:Taiwan}-<span title=\"exclamation\" data-parsoid='{\"stx\":\"html\",\"dsr\":[91,125,26,7]}'>!</span></p>");
add("wt2html", "T26072: more test on conversion rule for title", "<p data-parsoid='{\"dsr\":[0,128,0,0]}'>This should be stripped-{T|zh:China;zh-tw:Taiwan}-!\nThis won't take interferes with the title rule-{H|zh:Beijing;zh-tw:Taipei}-.</p>");
add("wt2html", "Partly disable title conversion if variant == main language code", "<p data-parsoid='{\"dsr\":[0,23,0,0]}'>-{T|zh-cn:CN;zh-tw:TW}-</p>");
add("wt2html", "Partly disable title conversion if variant == main language code, more", "<p data-parsoid='{\"dsr\":[0,8,0,0]}'>-{T|TW}-</p>");
add("wt2html", "Raw output of variant escape tags (R flag)", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'>Raw: -{R|zh:China;zh-tw:Taiwan}-</p>");
add("wt2html", "Strings evaluating false shouldn't be ignored by Language converter (T51072)", "<p data-parsoid='{\"dsr\":[0,35,0,0]}'>-{zh-cn:0;zh-sg:1;zh-tw:2;zh-hk:3}-</p>");
add("wt2html", "Conversion rules from [numeric-only string] to [something else] (T48634)", "<p data-parsoid='{\"dsr\":[0,95,0,0]}'>-{H|0=>zh-cn:B}--{H|0=>zh-cn:C;0=>zh-cn:D}--{H|0=>zh-hans:A}-012345-{A|zh-tw:0;zh-cn:E;}-012345</p>");
add("wt2html", "Bidirectional converter rule entries with an empty value should be ignored (T53551)", "<p data-parsoid='{\"dsr\":[0,29,0,0]}'>-{H|zh-cn:foo;zh-tw:;}-foobar</p>");
add("wt2html", "Unidirectional converter rule entries with an empty \"from\" string should be ignored (T53551)", "<p data-parsoid='{\"dsr\":[0,24,0,0]}'>-{H|=>zh-cn:foo;}-foobar</p>");
add("wt2html", "Empty converter rule entries shouldn't be inserted into the conversion table (T53551)", "<p data-parsoid='{\"dsr\":[0,12,0,0]}'>-{H|}-foobar</p>");
add("wt2html", "Nested using of manual convert syntax", "<p data-parsoid='{\"dsr\":[0,113,0,0]}'>Nested: -{zh-hans:Hi -{zh-cn:China;zh-sg:Singapore;}-;zh-hant:Hello -{zh-tw:Taiwan;zh-hk:H-{ong}- K-{}-ong;}-;}-!</p>");
add("wt2html", "HTML markups with conversion syntax in attribs, nested in other conversion blocks", "<p data-parsoid='{\"dsr\":[0,51,0,0]}'>-{zh;zh-hans;zh-hant|<span title=\"-{X}-\" data-parsoid='{\"stx\":\"html\",\"dsr\":[21,49,20,7]}'>A</span>}-</p>");
add("wt2html", "Proper conversion of text in external links", "<p data-parsoid='{\"dsr\":[0,269,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://www.google.com\" data-parsoid='{\"stx\":\"url\",\"dsr\":[0,21,0,0]}'>http://www.google.com</a>\n<a rel=\"mw:ExtLink\" href=\"gopher://www.google.com\" data-parsoid='{\"stx\":\"url\",\"dsr\":[22,45,0,0]}'>gopher://www.google.com</a>\n<a rel=\"mw:ExtLink\" href=\"http://www.google.com\" data-parsoid='{\"targetOff\":69,\"contentOffsets\":[69,90],\"dsr\":[46,91,23,1]}'>http://www.google.com</a>\n<a rel=\"mw:ExtLink\" href=\"gopher://www.google.com\" data-parsoid='{\"targetOff\":117,\"contentOffsets\":[117,140],\"dsr\":[92,141,25,1]}'>gopher://www.google.com</a>\n<a rel=\"mw:ExtLink\" href=\"https://www.google.com\" data-parsoid='{\"targetOff\":166,\"contentOffsets\":[166,186],\"dsr\":[142,187,24,1]}'>irc://www.google.com</a>\n<a rel=\"mw:ExtLink\" href=\"ftp://www.google.com\" data-parsoid='{\"targetOff\":210,\"contentOffsets\":[210,234],\"dsr\":[188,235,22,1]}'>www.google.com/ftp://dir</a>\n<a rel=\"mw:ExtLink\" href=\"//www.google.com\" data-parsoid='{\"targetOff\":254,\"contentOffsets\":[254,268],\"dsr\":[236,269,18,1]}'>www.google.com</a></p>");
add("wt2html", "Do not convert roman numbers to language variants", "<p data-parsoid='{\"dsr\":[0,18,0,0]}'>Fridrih IV je car.</p>");
add("wt2html", "Don't convert raw rule \"-{R|=&gt;}-\" to \"=>\"", "<p data-parsoid='{\"dsr\":[0,11,0,0]}'>-{R|=<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;gt;\",\"srcContent\":\">\",\"dsr\":[5,9,null,null]}'>></span>}-</p>");
add("wt2html", "Don't break link parsing if language converter markup is in the caption.", "<p data-parsoid='{\"dsr\":[0,29,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[0,29,12,2]}'>-{R|main page}-</a></p>");
add("wt2html", "T146305: Don't break image parsing if language converter markup is in the caption.", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"bogus\",\"ak\":\"-{R\"},{\"ck\":\"caption\",\"ak\":\"caption:}-\"}],\"dsr\":[0,40,2,2]}'><a href=\"./Датотека:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./Датотека:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./Датотека:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./Датотека:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,38,null,null]}'>caption:}-</figcaption></figure>");
add("wt2html", "T146305: Don't break image parsing if nested language converter markup is in the caption.", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"bogus\",\"ak\":\"-{zh-cn:blog (hk: -{zh-hans\"},{\"ck\":\"bogus\",\"ak\":\"WEBJOURNAL}-, tw: -{zh-hans\"},{\"ck\":\"caption\",\"ak\":\"WEBLOG}-)}-\"}],\"dsr\":[0,93,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,91,null,null]}'>WEBLOG}-)}-</figcaption></figure>");
add("wt2html", "Don't break gallery if language converter markup is inside.", "<ul class=\"gallery mw-gallery-traditional\" typeof=\"mw:Extension/gallery\" about=\"#mwt5\" data-parsoid='{\"dsr\":[0,172,2,2]}' data-mw='{\"name\":\"gallery\",\"attrs\":{},\"body\":{\"extsrc\":\"\\nFile:foobar.jpg|[[File:foobar.jpg|20px|desc|alt=-{R|foo}-|-{R|bar}-]]|alt=-{R|bat}-\\nFile:foobar.jpg|{{Test|unamedParam|alt=-{R|param}-}}|alt=galleryalt\\n\"}}'>\n<li class=\"gallerybox\" style=\"width: 155px;\"><div class=\"thumb\" style=\"width: 150px; height: 150px;\"><span style=\"display: inline-block; height: 100%; vertical-align: middle;\"></span><span typeof=\"mw:Image\" style=\"vertical-align: middle; display: inline-block;\"><a href=\"./File:Foobar.jpg\"><img alt=\"-{R\" resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"14\" width=\"120\"/></a></span></div><div class=\"gallerytext\">bat}-</div></li>\n<li class=\"gallerybox\" style=\"width: 155px;\"><div class=\"thumb\" style=\"width: 150px; height: 150px;\"><span style=\"display: inline-block; height: 100%; vertical-align: middle;\"></span><span typeof=\"mw:Image\" style=\"vertical-align: middle; display: inline-block;\"><a href=\"./File:Foobar.jpg\"><img alt=\"galleryalt\" resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"14\" width=\"120\"/></a></span></div><div class=\"gallerytext\"><span about=\"#mwt4\" typeof=\"mw:Transclusion\" data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Test\",\"href\":\"./Template:Test\"},\"params\":{\"1\":{\"wt\":\"unamedParam\"},\"2\":{\"wt\":\"param}-\"},\"alt\":{\"wt\":\"-{R\"}},\"i\":0}}]}'>This is a test template</span></div></li>\n</ul>");
add("wt2html", "T153135: Don't break list handling if language converter markup is in the item.", "<dl data-parsoid='{\"dsr\":[0,39,0,0]}'><dt data-parsoid='{\"dsr\":[0,8,1,0]}'>-{zh-cn</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[8,24,1,0]}'>AAA;zh-tw:BBB}-</dd>\n<dt data-parsoid='{\"dsr\":[25,33,1,0]}'>-{R|foo</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[33,39,1,0]}'>bar}-</dd></dl>");
add("wt2html", "T153135: Nested language converter markup in definition list (code coverage)", "<dl data-parsoid='{\"dsr\":[0,52,0,0]}'><dt data-parsoid='{\"dsr\":[0,8,1,0]}'>-{zh-cn</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[8,52,1,0]}'>AAA -{zh-hans|foo:bar}- -{R|bat:baz}-}-:def</dd></dl>");
add("wt2html", "T153140: Don't break table handling if language converter markup is in the cell.", "<table data-parsoid='{\"dsr\":[0,18,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[3,16,0,0]}'><tr data-parsoid='{\"startTagSrc\":\"|-\",\"autoInsertedEnd\":true,\"dsr\":[3,15,2,0]}'>\n<td data-parsoid='{\"a\":{\"-{R\":null},\"sa\":{\"-{R\":\"\"},\"autoInsertedEnd\":true,\"dsr\":[6,15,6,0]}'>B}-</td></tr>\n</tbody></table>");
-add("wt2html", "T2529: Uncovered bullet in parser function result", "<ul data-parsoid='{\"dsr\":[0,24,0,0]}'><li data-parsoid='{\"dsr\":[0,24,1,0]}'> Foo <span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[6,24,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"lc:{{bullet}} \",\"function\":\"lc\"},\"params\":{},\"i\":0}}]}'> bar</span></li></ul>");
-add("wt2html", "T7678: Double-parsed template invocation", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,42,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"lc:{{paramtest {{!}} param = hello }} \",\"function\":\"lc\"},\"params\":{},\"i\":0}}]}'>{{paramtest param = hello }}</p>");
+add("wt2html", "T2529: Uncovered bullet in parser function result", "<ul data-parsoid='{\"dsr\":[0,24,0,0]}'><li data-parsoid='{\"dsr\":[0,24,1,0]}'> Foo <span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[6,24,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"lc:{{bullet}} \",\"function\":\"lc\"},\"params\":{},\"i\":0}}]}'> bar</span></li></ul>");
+add("wt2html", "T7678: Double-parsed template invocation", "<p about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,42,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"lc:{{paramtest {{!}} param = hello }} \",\"function\":\"lc\"},\"params\":{},\"i\":0}}]}'>this is a test template with parameter hello</p>");
add("wt2html", "Nesting tags, paragraphs on lines which begin with <div>", "<div data-parsoid='{\"stx\":\"html\",\"dsr\":[0,11,5,6]}'></div><p data-parsoid='{\"dsr\":[11,20,0,0]}'><strong data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[11,20,8,0]}'>A</strong></p>\n<p data-parsoid='{\"dsr\":[21,31,0,0]}'><strong data-parsoid='{\"stx\":\"html\",\"autoInsertedStart\":true,\"dsr\":[21,31,0,9]}'>B</strong></p>");
add("wt2html", "T8200: paragraphs inside blockquotes (no extra line breaks)", "<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[0,43,12,13]}'>Line one\n\nLine two</blockquote>");
add("wt2html", "T8200: paragraphs inside blockquotes (extra line break on close)", "<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[0,44,12,13]}'>Line one\n\n<p data-parsoid='{\"dsr\":[22,30,0,0]}'>Line two</p>\n</blockquote>");
add("wt2html", "Free external link invading image caption", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"bogus\",\"ak\":\"http://x\"},{\"ck\":\"caption\",\"ak\":\"hello\"}],\"dsr\":[0,41,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"Image:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,39,null,null]}'>hello</figcaption></figure>");
add("wt2html", "formatdate parser function", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,26,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#formatdate:2009-03-24\",\"function\":\"#formatdate\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#formatdate missing in Parsoid.</p>");
add("wt2html", "formatdate parser function, with default format", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,30,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#formatdate:2009-03-24\",\"function\":\"#formatdate\"},\"params\":{\"1\":{\"wt\":\"mdy\"}},\"i\":0}}]}'>Parser function implementation for pf_#formatdate missing in Parsoid.</p>");
add("wt2html", "Spacing of numbers in formatted dates", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,26,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#formatdate:January 15\",\"function\":\"#formatdate\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#formatdate missing in Parsoid.</p>");
add("wt2html", "formatdate parser function, with default format and on a page of which the content language is always English and different from the wiki content language", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,30,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#formatdate:2009-03-24\",\"function\":\"#formatdate\"},\"params\":{\"1\":{\"wt\":\"dmy\"}},\"i\":0}}]}'>Parser function implementation for pf_#formatdate missing in Parsoid.</p>");
add("wt2html", "Bad images - basic functionality", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><span class=\"mw-default-size\" typeof=\"mw:Error mw:Image\" data-parsoid='{\"optList\":[],\"dsr\":[0,16,null,null]}' data-mw='{\"errors\":[{\"key\":\"apierror-filedoesnotexist\",\"message\":\"This image does not exist.\"}]}'><a href=\"./File:Bad.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Bad.jpg\"},\"sa\":{\"href\":\"File:Bad.jpg\"}}'><img resource=\"./File:Bad.jpg\" src=\"./Special:FilePath/Bad.jpg\" height=\"220\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Bad.jpg\",\"height\":\"220\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Bad.jpg\"}}'/></a></span></p>");
add("wt2html", "Bad images - T18039: text after bad image disappears", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'>Foo bar\n<span class=\"mw-default-size\" typeof=\"mw:Error mw:Image\" data-parsoid='{\"optList\":[],\"dsr\":[8,24,null,null]}' data-mw='{\"errors\":[{\"key\":\"apierror-filedoesnotexist\",\"message\":\"This image does not exist.\"}]}'><a href=\"./File:Bad.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Bad.jpg\"},\"sa\":{\"href\":\"File:Bad.jpg\"}}'><img resource=\"./File:Bad.jpg\" src=\"./Special:FilePath/Bad.jpg\" height=\"220\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Bad.jpg\",\"height\":\"220\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Bad.jpg\"}}'/></a></span>\nBar foo</p>");
add("wt2html", "T33098 Template which includes system messages which includes the template", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,13,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"Identical\",\"href\":\"./Template:Identical\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_int missing in Parsoid.\nParser function implementation for pf_int missing in Parsoid.</p>");
add("wt2html", "T33490 Turkish: ucfirst 'ix'", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,14,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ucfirst:ix\",\"function\":\"ucfirst\"},\"params\":{},\"i\":0}}]}'>Ix</p>");
add("wt2html", "T33490 Turkish: ucfırst (with a dotless i)", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,16,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ucfırst:blah\",\"href\":\"./Ucfırst:blah\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Ucfırst:blah\"}],\"i\":0}}]}'>{{ucfırst:blah}}</span></p>");
add("wt2html", "T33490 ucfırst (with a dotless i) with English language", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><span about=\"#mwt2\" typeof=\"mw:Error mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,16,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"ucfırst:blah\",\"href\":\"./Ucfırst:blah\"},\"params\":{},\"errors\":[{\"key\":\"mw-api-tplfetch-error\",\"message\":\"Page / template fetching disabled, and no cache for Ucfırst:blah\"}],\"i\":0}}]}'>{{ucfırst:blah}}</span></p>");
add("wt2html", "T35845: Headings become cursive in TOC when they contain an image", "<meta property=\"mw:PageProp/toc\" data-parsoid='{\"src\":\"__TOC__\",\"magicSrc\":\"__TOC__\",\"dsr\":[0,7,null,null]}'/>\n<h2 id=\"Image\" data-parsoid='{\"dsr\":[8,40,2,2]}'> Image <span class=\"mw-default-size\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[],\"dsr\":[17,37,null,null]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"Image:foobar.jpg\"}}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"Image:foobar.jpg\"}}'/></a></span> </h2>");
add("wt2html", "T35845 (2): Headings become bold in TOC when they contain a blockquote", "<meta property=\"mw:PageProp/toc\" data-parsoid='{\"src\":\"__TOC__\",\"magicSrc\":\"__TOC__\",\"dsr\":[0,7,null,null]}'/>\n<h2 id=\"Quote\" data-parsoid='{\"dsr\":[8,44,2,2]}'> <blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[11,41,12,13]}'>Quote</blockquote> </h2>");
add("wt2html", "Multiple tags in TOC", "<meta property=\"mw:PageProp/toc\" data-parsoid='{\"src\":\"__TOC__\",\"magicSrc\":\"__TOC__\",\"dsr\":[0,7,null,null]}'/>\n<h2 id=\"Foo_Bar\" data-parsoid='{\"dsr\":[8,35,2,2]}'> <i data-parsoid='{\"stx\":\"html\",\"dsr\":[11,21,3,4]}'>Foo</i> <b data-parsoid='{\"stx\":\"html\",\"dsr\":[22,32,3,4]}'>Bar</b> </h2>\n\n<h2 id=\"Foo_Bar_2\" data-parsoid='{\"dsr\":[37,82,2,2]}'> <i data-parsoid='{\"stx\":\"html\",\"dsr\":[40,50,3,4]}'>Foo</i> <blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[51,79,12,13]}'>Bar</blockquote> </h2>");
add("wt2html", "span tags with directionality in TOC", "<meta property=\"mw:PageProp/toc\" data-parsoid='{\"src\":\"__TOC__\",\"magicSrc\":\"__TOC__\",\"dsr\":[0,7,null,null]}'/>\n<h2 id=\"C.2B.2B\" data-parsoid='{\"dsr\":[8,40,2,2]}'> <span dir=\"ltr\" data-parsoid='{\"stx\":\"html\",\"dsr\":[11,37,16,7]}'>C++</span> </h2>\n\n<h2 id=\".D7.96.D7.91.D7.A0.D7.92.21\" data-parsoid='{\"dsr\":[42,76,2,2]}'> <span dir=\"rtl\" data-parsoid='{\"stx\":\"html\",\"dsr\":[45,73,16,7]}'>זבנג!</span> </h2>\n\n<h2 id=\"The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\" data-parsoid='{\"dsr\":[78,186,2,2]}'> <span style=\"font-style: italic\" data-parsoid='{\"stx\":\"html\",\"dsr\":[81,183,33,7]}'>The attributes on these span tags must be deleted from the TOC</span> </h2>\n\n<h2 id=\"All_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\" data-parsoid='{\"dsr\":[188,306,2,2]}'> <span style=\"font-style: italic\" dir=\"ltr\" data-parsoid='{\"stx\":\"html\",\"dsr\":[191,303,43,7]}'>All attributes on these span tags must be deleted from the TOC</span> </h2>\n\n<h2 id=\"Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC\" data-parsoid='{\"dsr\":[308,432,2,2]}'> <span dir=\"ltr\" style=\"font-style: italic\" data-parsoid='{\"stx\":\"html\",\"dsr\":[311,429,43,7]}'>Attributes after dir on these span tags must be deleted from the TOC</span> </h2>");
add("wt2html", "Empty <p> tag in TOC, removed by Sanitizer (T92892)", "<meta property=\"mw:PageProp/toc\" data-parsoid='{\"src\":\"__TOC__\",\"magicSrc\":\"__TOC__\",\"dsr\":[0,7,null,null]}'/>\n<h2 id=\"x\" data-parsoid='{\"dsr\":[8,15,2,2]}'> x </h2>");
add("wt2html", "T34057: Title needed when expanding <h> nodes.", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,14,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"int:T34057\",\"function\":\"int\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_int missing in Parsoid.</p>");
add("wt2html", "Check noCommafy in formatNum", "<p data-parsoid='{\"dsr\":[0,53,0,0]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,23,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"formatnum:123456.78\",\"function\":\"formatnum\"},\"params\":{},\"i\":0}}]}'>123456.78</span>\n<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[24,53,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"formatnum:123456.78\",\"function\":\"formatnum\"},\"params\":{\"1\":{\"wt\":\"NOSEP\"}},\"i\":0}}]}'>123456.78</span></p>");
add("wt2html", "Wrong option for formatNum (T58199)", "<p data-parsoid='{\"dsr\":[0,126,0,0]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[0,29,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"formatnum:1,234.56\",\"function\":\"formatnum\"},\"params\":{\"1\":{\"wt\":\"Random\"}},\"i\":0}}]}'>1,234.56</span>\n<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[30,63,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"formatnum:1,234.56\",\"function\":\"formatnum\"},\"params\":{\"1\":{\"wt\":\"EVERYTHING\"}},\"i\":0}}]}'>1,234.56</span>\n<span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[64,126,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"formatnum:1234.56\",\"function\":\"formatnum\"},\"params\":{\"1\":{\"wt\":\"any argument that has the string &#39;NOSEP&#39;\"}},\"i\":0}}]}'>1234.56</span></p>");
add("wt2html", "Strip marker in grammar", "<p about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,35,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"grammar:elative\",\"function\":\"grammar\"},\"params\":{\"1\":{\"wt\":\"foo&lt;nowiki/>bar\"}},\"i\":0}}]}'>Parser function implementation for pf_grammar missing in Parsoid.</p>");
add("wt2html", "Language parser function", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,16,0,0],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#language:ar\",\"function\":\"language\"},\"params\":{},\"i\":0}}]}'>ar</p>");
add("wt2html", "Special parser function", "<p data-parsoid='{\"dsr\":[0,65,0,0]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[0,23,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#special:RandomPage\",\"function\":\"#special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#special missing in Parsoid.</span>\n<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[24,45,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#special:BaDtItLe\",\"function\":\"#special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#special missing in Parsoid.</span>\n<span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[46,65,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"#special:Foobar\",\"function\":\"#special\"},\"params\":{},\"i\":0}}]}'>Parser function implementation for pf_#special missing in Parsoid.</span></p>");
add("wt2html", "1. SOL-sensitive wikitext tokens as template-args", "<p data-parsoid='{\"dsr\":[0,35,0,0]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[0,11,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"*a\"}},\"i\":0}}]}'>*a</span>\n<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[12,23,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"#a\"}},\"i\":0}}]}'>#a</span>\n<span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[24,35,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\":a\"}},\"i\":0}}]}'>:a</span></p>");
add("wt2html", "Empty table rows go away", "<table data-parsoid='{\"dsr\":[0,39,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[3,37,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[3,18,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[3,10,1,0]}'> Hello</td>\n<td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[11,18,1,0]}'> there</td></tr>\n<tr class=\"foo\" data-parsoid='{\"startTagSrc\":\"|-\",\"autoInsertedEnd\":true,\"dsr\":[19,33,14,0]}'></tr>\n<tr data-parsoid='{\"startTagSrc\":\"|-\",\"autoInsertedEnd\":true,\"dsr\":[34,36,2,0]}'></tr>\n</tbody></table>");
// Blacklist for wt2wt
add("wt2wt", "Parsoid only: Quote balancing context should be restricted to td/th cells on the same wikitext line\n(Requires tidy for PHP parser output to be fixed up)", "{|\n!''a''!!''b''\n|''a''||''b''\n|}");
add("wt2wt", "Non-word characters don't terminate tag names (T19663, T42670, T54022)", "<blockquote|>a\n\n<b→> doesn't terminate </b→>\n\n<bä> doesn't terminate </bä>\n\n<boo> doesn't terminate </boo>\n\n<s.foo> doesn't terminate </s.foo>\n\n<sub-ID#1>\n");
add("wt2wt", "Non-word characters don't terminate tag names + tidy", "<blockquote|>a\n\n<b→> doesn't terminate </b→>\n\n<bä> doesn't terminate </bä>\n\n<boo> doesn't terminate </boo>\n\n<s.foo> doesn't terminate </s.foo>\n\n<sub-ID#1>\n");
add("wt2wt", "Templates: Indent-Pre: 1f: Wrapping should be based on expanded content", "{{echo| }}a\n\n{{echo|\n }}a\n\n{{echo|\n b}}\n\n{{echo|a\n }}b\n\n{{echo|a\n}}\n b\n");
add("wt2wt", "Templates: Handle comments in the target", "{{echo\n<!-- should be ignored -->\n|foo}}\n\n{{echo\n<!-- should be ignored and spaces on next line should not trip us up (T147742) -->\n |foo}}\n\n{{echo<!-- should be ignored -->\n|foo}}\n\n{{echo<!-- should be ignored -->|foo}}\n\n{{echo|foo}}");
add("wt2wt", "4. Indent-Pre and extension tags", "<nowiki> </nowiki>a <tag />");
add("wt2wt", "Definition lists: self-closed tag", ";one<br />two : two-line fun");
add("wt2wt", "Definition lists: ignore colons inside tags", ";one <b>two : tag <i>fun:</i>:</b><nowiki>: def</nowiki>");
add("wt2wt", "Definition lists: excess closed tags", ";onetwo : bad tag fun");
add("wt2wt", "Definition Lists: colons occurring in tags", ";a:b\n;'''a:b'''\n;<i>a:b</i>\n;<span>a:b</span>\n;<div>a:b</div>\n;<div>a\n:b\n;{{echo|a:b}}\n;{{echo|''a:b''}}\n;;;''a:b''\n");
add("wt2wt", "T2289: \">\"-token in bracketed URL", "[http://www.example.com/ <hello> stuff]\n");
add("wt2wt", "T2289: literal \">\"-token in bracketed URL", "[http://www.example.com/ <b>html</b> stuff]\n");
add("wt2wt", "T2289: literal double quote in bracketed URL", "[http://www.example.com/ \"hello\" stuff]\n");
add("wt2wt", "External links: multiple legal whitespace is fine, Magnus. Don't break it please. (T7081)", "[http://www.example.com test]\n");
add("wt2wt", "T4702: Mismatched <i>, <b> and <a> tags are invalid", "''[http://example.com text''<nowiki/>'']''\n[http://example.com '''text''']'''<nowiki/>'''\n''Something [http://example.com in italic''<nowiki/>'']''\n''Something [http://example.com mixed''''', even bold''''']'''\n'''''Now [http://example.com both'''''<nowiki/>''''']'''''\n");
add("wt2wt", "External link containing double-single-quotes with no space separating the url from text in italics", "[http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm ''La muerte de Casagemas'' (1901) en el sitio de ][[Museo Picasso (París)|Museo Picasso]].\n");
add("wt2wt", "Unclosed and unmatched quotes", "'''''Bold italic text '''with bold deactivated''' in between.'''''\n\n'''''Bold italic text ''with italic deactivated'' in between.'''''\n\n'''Bold text..'''\n\n..spanning two paragraphs (should not work).'''<nowiki/>'''\n\n'''Bold tag left open'''\n\n''Italic tag left open''\n\nNormal text.\n\n<!-- Unmatching number of opening, closing tags: -->\n'''This year'<nowiki/>'''s election ''should'' beat '''last year''''s.\n\n''Tom'''s car is bigger than '''''<nowiki/>'''Susan'''s.\n\nPlain ''italic'''s plain\n");
add("wt2wt", "A table with captions with non-default spaced attributes and a table row", "{|\n|+ style=\"color: red;\" |caption2\n|+ style=\"color: red;\" | caption3\n|-\n| foo\n|}");
add("wt2wt", "Table td-cell syntax variations", "{|\n| foo bar | baz\n| foo bar foo || baz\n| style=\"color:red;\" | baz\n| style='color:red;' || baz\n|}");
add("wt2wt", "Allow +/- in 2nd and later cells in a row, in 1st cell when td-attrs are present, or in 1st cell when there is a space between \"|\" and +/- ", "{|\n|-\n| style=\"color:red;\" |+1\n| style=\"color:blue;\" |-1\n|-\n| 1 || 2 || 3\n| 1 ||+2 ||-3\n|-\n| +1\n| -1\n|}");
add("wt2wt", "Table rowspan", "{| border=\"1\"\n| Cell 1, row 1\n| rowspan=\"2\" | Cell 2, row 1 (and 2)\n| Cell 3, row 1\n|-\n| Cell 1, row 2\n| Cell 3, row 2\n|}");
add("wt2wt", "Nested table", "{| border=\"1\"\n| &alpha;\n|\n{| bgcolor=\"#ABCDEF\" border=\"2\"\n|nested\n|-\n|table\n|}\n|the original table again\n|}");
add("wt2wt", "Invalid attributes in table cell (T3830)", "{|\n| Cell: |broken\n|}");
add("wt2wt", "Build table with {{!}}", "{{{!}} class=\"wikitable\"\n! header\n! second header\n{{!}}- style=\"color:red;\"\n{{!}} data {{!}}{{!}} style=\"color:red;\"{{!}} second data\n{{!}}}");
add("wt2wt", "Build table with pipe as data", "{| class=\"wikitable\"\n! header\n! second header\n|- style=\"color:red;\"\n| data || style=\"color:red;\" | second data\n|-\n| style=\"color:red;\" |<nowiki> data with | </nowiki>|| style=\"color:red;\" | second data with |\n|-\n||<nowiki> data with | </nowiki>||| second data with |\n|}");
add("wt2wt", "Piped link with multiple pipe characters in link text", "[[Main Page|<nowiki>|The|Main|Page|</nowiki>]]\n");
add("wt2wt", "Link containing \"#<\" and \"#>\" % as a hex sequences- these are valid section anchors", "[[%23%3c|#<]][[%23%3e|#>]]\n");
add("wt2wt", "Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved", "[[Foo| bar]]\n\n[[Foo| ''bar'']]\n\n[http://wp.org foo]\n\n[http://wp.org ''foo'']\n");
add("wt2wt", "Handling html with a div self-closing tag", "<div title=\"\" />\n<div title=\"\" />\n<div title=\"\" />\n<div title=\"bar\" />\n<div title=\"bar\" />\n<div title=\"bar/\">");
add("wt2wt", "Handling html with a br self-closing tag", "<br title=\"\" />\n<br title=\"\" />\n<br title=\"\" />\n<br title=\"bar\" />\n<br title=\"bar\" />\n<br title=\"bar/\">\n");
add("wt2wt", "Horizontal ruler (should it add that extra space?)", "<hr />\n<hr />\nfoo <hr> bar\n");
add("wt2wt", "Nested lists 3 (first element empty)", "\n**bar\n");
add("wt2wt", "Nested lists 6 (both elements empty)", "\n**\n");
add("wt2wt", "Unbalanced closing non-block tags don't break a list\n(php parser relies on Tidy to fix up)", "<span>\n*a<span>\n*b");
add("wt2wt", "Template with invalid target containing tags", "<nowiki>{{a</nowiki><b>b</b>|{{echo|foo}}|{{echo|a}}={{echo|b}}<nowiki>|a =b}}</nowiki>\n");
add("wt2wt", "Template with invalid target containing unclosed tag", "<nowiki>{{a</nowiki><b>|{{echo|foo}}|{{echo|a}}={{echo|b}}<nowiki>|a =b}}</nowiki>\n");
add("wt2wt", "Template with invalid target containing wikilink", "<nowiki>{{</nowiki>[[Main Page]]<nowiki>}}</nowiki>\n");
add("wt2wt", "Template with just whitespace in it, T70421", "{{echo|{{ }<nowiki>}</nowiki>}}");
add("wt2wt", "Template with argument in separate line", "{{templateasargtest |\n templ = simple }}");
add("wt2wt", "T2553: link with two variables in a piped link", "{|\n|[[{{{1}}}<nowiki>|</nowiki>{{{2}}}]]\n|}");
add("wt2wt", "Abort table cell attribute parsing on wikilink", "{|\n| testing [[one|two]]<nowiki> | three </nowiki>|| four\n| testing one two | three || four\n| testing=\"[[one|two]]<nowiki>\" | three </nowiki>|| four\n|}");
-add("wt2wt", "Template with targets containing wikilinks", "<nowiki>{{</nowiki>[[foo]]<nowiki>}}</nowiki>\n\n<nowiki>{{</nowiki>[[{{echo|foo}}]]<nowiki>}}</nowiki>\n\n<nowiki>{{</nowiki>{{echo|<nowiki>[[foo</nowiki>}}<nowiki>]]}}</nowiki>\n");
+add("wt2wt", "Template with targets containing wikilinks", "<nowiki>{{</nowiki>[[foo]]<nowiki>}}</nowiki>\n\n<nowiki>{{</nowiki>[[{{echo|foo}}]]<nowiki>}}</nowiki>\n\n<nowiki>{{[[foo]]}}</nowiki>\n");
add("wt2wt", "2. includeonly in html attr value", "<span id=\"<noinclude>v1</noinclude><includeonly>v2</includeonly>\">bar</span>\n<span id=\"<noinclude>&quot;v1&quot;</noinclude><includeonly>&quot;v2&quot;</includeonly>\">bar</span>\n");
add("wt2wt", "1. Table tag in SOL posn. should get reparsed correctly with valid TSR", "{{echo|}}\n{| width=\"100%\"\n|foo\n|}");
add("wt2wt", "Templates: HTML Tag: 2. Generation of HTML attr. value", "<div style=\"{{echo|'color:red;'}}\">foo</div>");
add("wt2wt", "Templates: HTML Tag: 3. Generation of HTML attr key and value", "<div {{echo|style}}=\"{{echo|'color:red;'}}\">foo</div>");
add("wt2wt", "Templates: HTML Tag: 9. Multiple template-generated attributes", "<div {{echo|1=id=\"v1\" title=\"foo\"}} title=\"foo\">bar</div>");
add("wt2wt", "Templates: HTML Tables: 5. Proper fostering of categories from inside", "[[Category:foo1]]\n<table><tr><td>foo</td></tr></table>\n<!--Two categories (T52330)-->\n[[Category:bar1]]\n[[Category:bar2]]\n<table><tr><td>foo</td></tr></table>");
add("wt2wt", "Allow empty links in image captions (T62753)", "[[File:Foobar.jpg|thumb|Caption [[Link1]]\n<nowiki>[[]]</nowiki>\n[[Link2]]\n]]");
add("wt2wt", "Image with multiple attributes from the same template", "[[File:Foobar.jpg|right|Caption text]]");
add("wt2wt", "Image with multiple widths -- use last", "[[File:Foobar.jpg|300px|caption]]\n");
add("wt2wt", "Render invalid page names as plain text (T53090)", "[[./../foo|bar]]\n[[foo�|bar]]\n[[foo/.|bar]]\n[[foo/..|bar]]\n<nowiki>[[foo~~~bar]]</nowiki>\n[[foo>bar]]\n[[foo[bar]]\n[[.]]\n[[..]]\n[[foo././bar]]\n\n[[{{echo|./../foo}}|bar]]\n[[{{echo|foo/.}}|bar]]\n[[{{echo|foo/..}}|bar]]\n[[{{echo|foo~~~~bar}}]]\n[[{{echo|foo>bar}}]]\n[[{{echo|foo././bar}}]]\n[[{{echo|foo{bar}}]]\n[[{{echo|foo}bar}}]]\n[[{{echo|foo[bar}}]]\n[[{{echo|foo]bar}}]]\n[[{{echo|foo<bar}}]]\n");
add("wt2wt", "Handling of sections up to level 6 and beyond", "= Level 1 Heading=\n== Level 2 Heading==\n=== Level 3 Heading===\n==== Level 4 Heading====\n===== Level 5 Heading=====\n====== Level 6 Heading======\n======<nowiki>= Level 7 Heading=</nowiki>======\n======<nowiki>== Level 8 Heading==</nowiki>======\n======<nowiki>=== Level 9 Heading===</nowiki>======\n======<nowiki>==== Level 10 Heading====</nowiki>======\n");
add("wt2wt", "div with single-quoted attribute", "<div id=\"rock\">HTML rocks</div>");
add("wt2wt", "div with unquoted attribute", "<div id=\"rock\">HTML rocks</div>");
add("wt2wt", "div with illegal double attributes", "<div id=\"b\">HTML rocks</div>");
add("wt2wt", "HTML multiple attributes correction", "<p class=\"awesome\">Awesome!</p>");
add("wt2wt", "Table multiple attributes correction", "{|\n! class=\"awesome\" + | status\n|}");
add("wt2wt", "DIV IN UPPERCASE", "<DIV id=\"x\">HTML ROCKS</DIV>");
add("wt2wt", "Media link with nasty text", "[[Media:Foobar.jpg|Safe Link]]<div style=\"display:none\">[[Media:Foobar.jpg|\" onmouseover=\"alert(document.cookie)\" onfoo=\"]]</div>\n");
add("wt2wt", "Empty attribute crash test single-quotes (T4067)", "<font color=\"\">foo</font>\n");
add("wt2wt", "Attribute test: unquoted but illegal value (hash)", "<font color=\"#x\">foo</font>\n");
add("wt2wt", "T4095: link with pipe and three closing brackets, version 2", "[[Main Page|<nowiki>[http://example.com/]</nowiki>]]\n");
add("wt2wt", "Table attribute legitimate extension", "{|\n! style=\"<nowiki>color:blue</nowiki>\" + | status\n|}");
add("wt2wt", "Table attribute safety", "{|\n! style=\"<nowiki>border-width:expression(0+alert(document.cookie))</nowiki>\" + | status\n|}");
add("wt2wt", "Parser hook: nested tags", "<tag><tag></tag><nowiki></tag></nowiki>");
add("wt2wt", "Sanitizer: Validating that <meta> and <link> work, but only for Microdata", "<div itemscope=\"\">\n\t<nowiki><meta itemprop=\"hello\" content=\"world\"></nowiki>\n\t<nowiki><meta http-equiv=\"refresh\" content=\"5\"></nowiki>\n\t<nowiki><meta itemprop=\"hello\" http-equiv=\"refresh\" content=\"5\"></nowiki>\n\t<nowiki><link itemprop=\"hello\" href=\"{{SERVER}}\"></nowiki>\n\t<nowiki><link rel=\"stylesheet\" href=\"{{SERVER}}\"></nowiki>\n\t<nowiki><link rel=\"stylesheet\" itemprop=\"hello\" href=\"{{SERVER}}\"></nowiki>\n</div>");
add("wt2wt", "Fuzz testing: Parser13", "{| \n| http: / a |\n|}");
add("wt2wt", "Fuzz testing: Parser16", "{|\n!https://||||||\n|}");
add("wt2wt", "Fuzz testing: Parser21", "{|\n! irc://{{ftp://a\" onmouseover=\"alert('hello world');\"\n|\n|}");
add("wt2wt", "Fuzz testing: Parser22", "http://===r:::https://b\n\n{|\n|}");
add("wt2wt", "Inline wiki vs wiki block nesting", "'''Bold paragraph'''\n\nNew wiki paragraph\n");
add("wt2wt", "Mixing markup for italics and bold", "'<nowiki/>''bold'<nowiki/>'''''bold''bolditalics'''''\n");
add("wt2wt", "Illegal character references (T106578)", "; Null: &#00;\n; FF: &#xC;\n; CR: &#x0A;\n; Control (low): &#8;\n; Control (high): &#x7F; &#x9F;\n; Surrogate: &#xD83D;&#xDCA9;\n; This is an okay astral character: &#x1F4A9;");
add("wt2wt", "Image with page parameter", "[[File:LoremIpsum.djvu]]\n");
add("wt2wt", "Don't fall for the self-closing div", "<div>hello world</div>");
add("wt2wt", "Parsing of overlapping (improperly nested) inline html tags", "<span><s>x</span>\n");
add("wt2wt", "T153140: Don't break table handling if language converter markup is in the cell.", "{|\n|-\n| -{R |B}-\n|}");
add("wt2wt", "T2529: Uncovered bullet leaving empty list, normally removed by tidy", "******* Foo \n{{bullet}}");
add("wt2wt", "HHP2.1: Heuristics for headings in preprocessor parenthetical structures", "<nowiki>{{foo|</nowiki>\n=heading=\n");
add("wt2wt", "HHP2.2: Heuristics for headings in preprocessor parenthetical structures", "<nowiki>{{foo|</nowiki>\n==heading==\n");
add("wt2wt", "T21052 U+3000 IDEOGRAPHIC SPACE should terminate bracketed external links", "[http://www.example.org/ ideograms]\n");
add("wt2wt", "Ignore pipe between table row attributes", "{|\n| quux\n|- id=\"foo\" style=\"color: red\" |\n| bar\n|}");
add("wt2wt", "2. Bad treebuilder fixup of formatting elt is cleaned up", "'''foo'''[[File:Foobar.jpg|thumb|'''caption''']]'''bar'''\n\n<small>[[Image:Foobar.jpg|right|300px]]</small>");
add("wt2wt", "3. Bad treebuilder fixup of formatting elt is cleaned up", "<small>'''foo'''[[File:Foobar.jpg|thumb|'''caption''']]'''bar'''</small>\n");
add("wt2wt", "4. Bad treebuilder fixup of formatting elt is cleaned up: formatting tags around captionless images are ignored", "'''<small>'''[[Image:Foobar.jpg|right|300px]]\n");
add("wt2wt", "Trailing newlines in a deep dom-subtree that ends a wikitext line should be migrated out", "{|\n|<small>foo\n\nbar\n|}\n\n{|\n|<small>foo<small>\n|}");
add("wt2wt", "Empty TD followed by TD with tpl-generated attribute", "{|\n|-\n|\n| {{echo|style='color:red'}} |foo\n|}");
add("wt2wt", "Improperly nested inline or quotes tags with whitespace in between", "<span> <s>x</span> </s>\n''' ''x'''''<nowiki/>'' ''\n");
add("wt2wt", "2. Ensure fostered text content is wrapped in element nodes (traps regressions around fostered marker on the element getting lost)", "<nowiki> </nowiki><nowiki>||</nowiki> <nowiki>||</nowiki>\n<table>\n<tr><td> a\n</table>");
add("wt2wt", "8. Encapsulate foster-parented transclusion content", "{{echo|a\n}}\n{|{{echo|style='color:red'}}\n|-\n|b\n|}\n");
add("wt2wt", "T73074: More fostering fun", "[[Category:Two]]\n<table><td></td>{{echo|<tr>}}<!--c-->[[Category:Two]]");
add("wt2wt", "Image: upright option is ignored on inline and frame images (parsoid)", "[[File:Foobar.jpg|500x500px|caption]]\n");
// Blacklist for html2html
add("html2html", "Extra newlines followed by heading", "<p data-parsoid='{\"dsr\":[0,1,0,0]}'>a</p>\n\n<p data-parsoid='{\"dsr\":[3,3,0,0]}'><br data-parsoid='{\"dsr\":[3,3,0,0]}'/></p>\n\n<h1 id=\"b\" data-parsoid='{\"dsr\":[5,10,1,1]}'> b </h1>\n<p data-parsoid='{\"dsr\":[11,55,0,0]}'>[/index.php?title=A&amp;action=edit&amp;redlink=1 a]</p>\n\n<p data-parsoid='{\"dsr\":[57,57,0,0]}'><br data-parsoid='{\"dsr\":[57,57,0,0]}'/></p>\n\n<h1 id=\"b_2\" data-parsoid='{\"dsr\":[59,64,1,1]}'> b </h1>\n");
add("html2html", "Extra newlines between heading and content are swallowed", "<h1 id=\"b\" data-parsoid='{\"dsr\":[0,5,1,1]}'> b </h1>\n<p data-parsoid='{\"dsr\":[6,50,0,0]}'>[/index.php?title=A&amp;action=edit&amp;redlink=1 a]</p>\n");
add("html2html", "Italics and possessives (1)", "<p data-parsoid='{\"dsr\":[0,115,0,0]}'>obtained by <i data-parsoid='{\"dsr\":[12,91,2,2]}'>[/index.php?title=Lunar_Prospector&amp;action=edit&amp;redlink=1 Lunar Prospector]'</i>s gamma-ray spectrometer</p>\n");
add("html2html", "Italics and possessives (3)", "<p data-parsoid='{\"dsr\":[0,421,0,0]}'>The first monolingual dictionary written in a Romance language was <i data-parsoid='{\"dsr\":[67,93,2,2]}'>Sebastián Covarrubias'</i> <i data-parsoid='{\"dsr\":[94,139,2,2]}'>Tesoro de la lengua castellana o española</i>, published in 1611 in Madrid. In 1612 the first edition of the <i data-parsoid='{\"dsr\":[203,310,2,2]}'>Vocabolario dell'[/index.php?title=Accademia_della_Crusca&amp;action=edit&amp;redlink=1 Accademia della Crusca]</i>, for Italian, was published. In 1690 in Rotterdam was published, posthumously, the <i data-parsoid='{\"dsr\":[394,420,2,2]}'>Dictionnaire Universel</i>.</p>\n");
add("html2html", "Preformatted text", "<pre data-parsoid='{\"dsr\":[0,96,1,0]}'>This is some\nPreformatted text\nWith <i data-parsoid='{\"dsr\":[39,49,2,2]}'>italic</i>\nAnd <b data-parsoid='{\"dsr\":[55,65,3,3]}'>bold</b>\nAnd a <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[73,96,17,2]}'>link</a></pre>\n");
add("html2html", "T54763: Preformatted in <blockquote>", "<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[0,75,12,13]}'>\n<p data-parsoid='{\"dsr\":[13,18,0,0]}'> Blah</p>\n\n<table data-parsoid='{\"dsr\":[20,61,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[23,59,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[23,58,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[23,58,1,0]}'>\n<pre data-parsoid='{\"dsr\":[25,58,1,0]}'>indented cell (no pre-wrapping!)</pre></td></tr>\n</tbody></table>\n</blockquote>\n");
add("html2html", "<pre> with attributes (T5202)", "<pre data-parsoid='{\"dsr\":[0,24,1,0]}'>Bluescreen of WikiDeath</pre>\n");
add("html2html", "<pre> with width attribute (T5202)", "<pre data-parsoid='{\"dsr\":[0,22,1,0]}'>Narrow screen goodies</pre>\n");
add("html2html", "<pre> with forbidden attribute (T5202)", "<pre data-parsoid='{\"dsr\":[0,22,1,0]}'>Narrow screen goodies</pre>\n");
add("html2html", "<pre> with forbidden attribute values (T5202)", "<pre data-parsoid='{\"dsr\":[0,22,1,0]}'>Narrow screen goodies</pre>\n");
add("html2html", "<nowiki> inside <pre> (T15238)", "<pre data-parsoid='{\"dsr\":[0,15,1,0]}'><span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;lt;\",\"srcContent\":\"&lt;\",\"dsr\":[1,5,null,null]}'>&lt;</span>nowiki<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;gt;\",\"srcContent\":\">\",\"dsr\":[11,15,null,null]}'>></span></pre>\n\n <p data-parsoid='{\"dsr\":[18,18,0,0]}'><br data-parsoid='{\"dsr\":[18,18,0,0]}'/></p>\n\n<pre data-parsoid='{\"dsr\":[20,53,1,0]}'><span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;lt;\",\"srcContent\":\"&lt;\",\"dsr\":[21,25,null,null]}'>&lt;</span>nowiki<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;gt;\",\"srcContent\":\">\",\"dsr\":[31,35,null,null]}'>></span>Foo<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;lt;\",\"srcContent\":\"&lt;\",\"dsr\":[38,42,null,null]}'>&lt;</span>/nowiki<span typeof=\"mw:Entity\" data-parsoid='{\"src\":\"&amp;gt;\",\"srcContent\":\">\",\"dsr\":[49,53,null,null]}'>></span></pre>\n");
add("html2html", "Templates: Handle comments in the target", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,39,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo &lt;!-- should be ignored -->\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</p>\n\n<p about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[41,136,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo &lt;!-- should be ignored and spaces on next line should not trip us up (T147742) -->\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</p>\n\n<p about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[138,176,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo&lt;!-- should be ignored -->\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</p>\n\n<p about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[178,216,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo&lt;!-- should be ignored -->\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</p>\n\n<p about=\"#mwt5\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[218,230,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</p>");
add("html2html", "Templates: Handle comments in parameter names (T69657)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,41,0,0],\"pi\":[[{\"k\":\"1\",\"named\":true}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\",\"key\":{\"wt\":\"1 &lt;!-- should be ignored -->\"}}},\"i\":0}}]}'>foo</p>\n\n<p about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[43,84,0,0],\"pi\":[[{\"k\":\"1\",\"named\":true}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\",\"key\":{\"wt\":\"&lt;!-- should be ignored --> 1\"}}},\"i\":0}}]}'>foo</p>\n\n<p about=\"#mwt3\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[86,126,0,0],\"pi\":[[{\"k\":\"1\",\"named\":true}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\",\"key\":{\"wt\":\"1&lt;!-- should be ignored -->\"}}},\"i\":0}}]}'>foo</p>\n\n<p about=\"#mwt4\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[128,168,0,0],\"pi\":[[{\"k\":\"1\",\"named\":true}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo\",\"key\":{\"wt\":\"&lt;!-- should be ignored -->1\"}}},\"i\":0}}]}'>foo</p>");
add("html2html", "Templates: Other wikitext in parameter names (T69657)", "<p about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,18,0,0],\"pi\":[[{\"k\":\"&#39;&#39;1&#39;&#39;\",\"named\":true}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"&#39;&#39;1&#39;&#39;\":{\"wt\":\"foo\"}},\"i\":0}}]}'>foo</p>");
add("html2html", "2g. Indented table markup mixed with indented pre content (proposed in T8200)", " <table data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[1,57,2,0]}'> \n <tbody data-parsoid='{\"dsr\":[6,57,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[6,56,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[6,56,1,0]}'>\n<pre data-parsoid='{\"dsr\":[8,56,1,0]}'>Text that should be rendered preformatted \n|}</pre></td></tr>\n</tbody></table>");
add("html2html", "3c. Indent-Pre and block tags (pre-content on separate line)", "\n<p data-parsoid='{\"dsr\":[1,22,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[1,19,8,9]}'> </span>foo</p>\n\n<div data-parsoid='{\"stx\":\"html\",\"dsr\":[24,42,5,6]}'>\n<pre data-parsoid='{\"dsr\":[30,34,1,0]}'>foo</pre>\n\n</div>\n<center data-parsoid='{\"stx\":\"html\",\"dsr\":[43,67,8,9]}'>\n<pre data-parsoid='{\"dsr\":[52,56,1,0]}'>foo</pre>\n\n</center>\n<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[68,100,12,13]}'>\n<p data-parsoid='{\"dsr\":[81,85,0,0]}'> foo</p>\n\n</blockquote>\n<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[101,133,12,13]}'>\n<p data-parsoid='{\"dsr\":[114,118,0,0]}'> foo</p>\n\n</blockquote>\n<table data-parsoid='{\"dsr\":[134,146,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[137,144,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[137,143,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[137,143,1,0]}'>\n<pre data-parsoid='{\"dsr\":[139,143,1,0]}'>foo</pre></td></tr>\n</tbody></table>\n<ul data-parsoid='{\"dsr\":[147,153,0,0]}'><li data-parsoid='{\"dsr\":[147,153,1,0]}'> foo</li></ul>\n");
add("html2html", "5a. White-space in indent-pre", "<pre data-parsoid='{\"dsr\":[0,13,1,0]}'>a<br data-parsoid='{\"stx\":\"html\",\"noClose\":true,\"dsr\":[2,8,4,null]}'/>\n\n\nb</pre>\n");
add("html2html", "Definition list with wikilink containing colon", "<dl data-parsoid='{\"dsr\":[0,95,0,0]}'><dt data-parsoid='{\"dsr\":[0,24,1,0]}'> [/index.php?title=Help</dt><dd data-parsoid='{\"stx\":\"row\",\"dsr\":[24,60,1,0]}'>FAQ&amp;action=edit&amp;redlink=1 Help:FAQ]</dd>\n<dd data-parsoid='{\"dsr\":[61,95,1,0]}'> The least-read page on Wikipedia</dd></dl>\n");
add("html2html", "Definition lists: colon in HTML attribute", "<dl data-parsoid='{\"dsr\":[0,12,0,0]}'><dt data-parsoid='{\"dsr\":[0,12,1,0]}'> <b data-parsoid='{\"dsr\":[2,12,3,3]}'>bold</b></dt></dl>\n");
add("html2html", "Definition Lists: colons and tables 1", "<dl data-parsoid='{\"dsr\":[0,24,0,0]}'><dd data-parsoid='{\"dsr\":[0,11,1,0]}'> <table data-parsoid='{\"dsr\":[2,11,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[5,9,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[5,8,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[5,8,1,0]}'> x</td></tr>\n</tbody></table></dd>\n\n<dd data-parsoid='{\"dsr\":[13,24,1,0]}'> <table data-parsoid='{\"dsr\":[15,24,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[18,22,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[18,21,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[18,21,1,0]}'> y</td></tr>\n</tbody></table></dd></dl>\n");
add("html2html", "Build table with wikilink", "<table class=\"wikitable\" data-parsoid='{\"dsr\":[0,213,20,2]}'>\n<tbody data-parsoid='{\"dsr\":[21,211,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[21,46,0,0]}'><th data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[21,30,1,0]}'> header </th>\n<th data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[31,46,1,0]}'> second header</th></tr>\n<tr style=\"color:red;\" data-parsoid='{\"startTagSrc\":\"|-\",\"autoInsertedEnd\":true,\"dsr\":[47,146,21,0]}'>\n<td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[69,104,1,0]}'> data <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[76,103,17,2]}'>linktext</a> </td>\n<td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[105,146,1,0]}'> second data <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[119,146,17,2]}'>linktext</a></td></tr>\n<tr data-parsoid='{\"startTagSrc\":\"|-\",\"autoInsertedEnd\":true,\"dsr\":[147,210,2,0]}'>\n<td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[150,157,1,0]}'> data </td>\n<td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[158,210,1,0]}'> second data <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[172,210,17,2]}'>link|text with pipe</a></td></tr>\n</tbody></table>\n");
add("html2html", "Plain link, capitalized", "<p data-parsoid='{\"dsr\":[0,28,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,28,17,2]}'>Main Page</a></p>\n");
add("html2html", "Plain link, uncapitalized", "<p data-parsoid='{\"dsr\":[0,28,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,28,17,2]}'>main Page</a></p>\n");
add("html2html", "Piped link", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,32,17,2]}'>The Main Page</a></p>\n");
add("html2html", "Piped link with comment in link text", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,32,17,2]}'>The Main Page</a></p>\n");
add("html2html", "Piped link with multiple pipe characters in link text", "<p data-parsoid='{\"dsr\":[0,46,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[0,46,12,2]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[12,44,8,9]}'>|The|Main|Page|</span></a></p>\n");
add("html2html", "Broken link", "<p data-parsoid='{\"dsr\":[0,72,0,0]}'>[/index.php?title=Zigzagzogzagzig&amp;action=edit&amp;redlink=1 Zigzagzogzagzig]</p>\n");
add("html2html", "Broken link with fragment", "<p data-parsoid='{\"dsr\":[0,76,0,0]}'>[/index.php?title=Zigzagzogzagzig&amp;action=edit&amp;redlink=1 Zigzagzogzagzig#zug]</p>\n");
add("html2html", "Special page link with fragment", "<p data-parsoid='{\"dsr\":[0,54,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Special:Version#anchor\" title=\"Wiki/Special:Version\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Special:Version#anchor\"},\"sa\":{\"href\":\"wiki/Special:Version#anchor\"},\"dsr\":[0,54,30,2]}'>Special:Version#anchor</a></p>\n");
add("html2html", "Nonexistent special page link with fragment", "<p data-parsoid='{\"dsr\":[0,97,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Special:ThisNameWillHopefullyNeverBeUsed\" title=\"Wiki/Special:ThisNameWillHopefullyNeverBeUsed\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Special:ThisNameWillHopefullyNeverBeUsed\"},\"sa\":{\"href\":\"wiki/Special:ThisNameWillHopefullyNeverBeUsed\"},\"dsr\":[0,97,48,2]}'>Special:ThisNameWillHopefullyNeverBeUsed#anchor</a></p>\n");
add("html2html", "Link with prefix", "<p data-parsoid='{\"dsr\":[0,162,0,0]}'>xxx<a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[3,31,17,2]}'>main Page</a>, xxx<a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[36,64,17,2]}'>Main Page</a>, Xxx<a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[69,97,17,2]}'>main Page</a> XXX<a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[101,129,17,2]}'>main Page</a>, XXX<a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[134,162,17,2]}'>Main Page</a></p>\n");
add("html2html", "Link with suffix", "<p data-parsoid='{\"dsr\":[0,97,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,31,17,2]}'>Main Pagexxx</a>, <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[33,61,17,2]}'>Main Page</a>XXX, <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[66,94,17,2]}'>Main Page</a>!!!</p>\n");
add("html2html", "T45661: Piped links with identical prefixes", "<p data-parsoid='{\"dsr\":[0,55,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Prefixed_article\" title=\"Wiki/Prefixed article\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Prefixed_article\"},\"sa\":{\"href\":\"wiki/Prefixed article\"},\"dsr\":[0,55,24,2]}'>prefixed articles with spaces</a></p>\n\n<p data-parsoid='{\"dsr\":[57,104,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Prefixed_article\" title=\"Wiki/Prefixed article\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Prefixed_article\"},\"sa\":{\"href\":\"wiki/Prefixed article\"},\"dsr\":[57,104,24,2]}'>prefixed articlesaoeu</a></p>\n\n<p data-parsoid='{\"dsr\":[106,139,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[106,139,17,2]}'>Main Page test</a></p>\n");
add("html2html", "Link with 4 brackets", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'>[[<a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[2,30,17,2]}'>Main Page</a>]]</p>\n");
add("html2html", "Link with multiple pipes", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,32,17,2]}'>The|Main|Page</a></p>\n");
add("html2html", "Link to namespaces", "<p data-parsoid='{\"dsr\":[0,156,0,0]}'>[/index.php?title=Talk:Parser_testing&amp;action=edit&amp;redlink=1 Talk:Parser testing], [/index.php?title=Meta:Disclaimers&amp;action=edit&amp;redlink=1 Meta:Disclaimers]</p>\n");
add("html2html", "Link with space in namespace", "<p data-parsoid='{\"dsr\":[0,76,0,0]}'>[/index.php?title=User_talk:Foo_bar&amp;action=edit&amp;redlink=1 User talk:Foo bar]</p>\n");
add("html2html", "Namespace takes precedence over interwiki link (T53680)", "<p data-parsoid='{\"dsr\":[0,52,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/MemoryAlpha:AlphaTest\" title=\"Wiki/MemoryAlpha:AlphaTest\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/MemoryAlpha:AlphaTest\"},\"sa\":{\"href\":\"wiki/MemoryAlpha:AlphaTest\"},\"dsr\":[0,52,29,2]}'>MemoryAlpha:AlphaTest</a></p>\n");
add("html2html", "Piped link to namespace", "<p data-parsoid='{\"dsr\":[0,73,0,0]}'>[/index.php?title=Meta:Disclaimers&amp;action=edit&amp;redlink=1 The disclaimers]</p>\n");
add("html2html", "Link containing double-single-quotes '' in text embedded in italics (T6598 sanity check)", "<p data-parsoid='{\"dsr\":[0,84,0,0]}'><i data-parsoid='{\"dsr\":[0,61,2,2]}'>Some [/index.php?title=Link&amp;action=edit&amp;redlink=1 pretty </i>italics<i data-parsoid='{\"dsr\":[68,84,2,2]}'> and stuff]!</i></p>\n");
add("html2html", "Plain link to page with question mark in title", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/A%3Fb\" title=\"Wiki/A?b\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/A%3Fb\"},\"sa\":{\"href\":\"wiki/A?b\"},\"dsr\":[0,16,11,2]}'>A?b</a></p>\n\n<p data-parsoid='{\"dsr\":[18,34,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/A%3Fb\" title=\"Wiki/A?b\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/A%3Fb\"},\"sa\":{\"href\":\"wiki/A?b\"},\"dsr\":[18,34,11,2]}'>Baz</a></p>\n");
add("html2html", "Self-link to section should not be bold", "<p data-parsoid='{\"dsr\":[0,44,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page#section\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page#section\"},\"sa\":{\"href\":\"wiki/Main Page#section\"},\"dsr\":[0,44,25,2]}'>Main Page#section</a></p>\n");
add("html2html", "Self-link to numeric title", "<p data-parsoid='{\"dsr\":[0,1,0,0]}'>0</p>\n");
add("html2html", "Link to numeric-equivalent title", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/00\" title=\"Wiki/00\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/00\"},\"sa\":{\"href\":\"wiki/00\"},\"dsr\":[0,14,10,2]}'>00</a></p>\n");
add("html2html", "<nowiki> inside a link", "<p data-parsoid='{\"dsr\":[0,84,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[0,30,8,9]}'>[[Main Page]]</span> <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[31,83,17,2]}'>the main page [it's not very good</a>]</p>\n");
add("html2html", "Non-breaking spaces in title", "<p data-parsoid='{\"dsr\":[0,34,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,34,17,2]}'>  Main   Page  </a></p>\n");
add("html2html", "Internal link with ca linktrail, surrounded by bold apostrophes (T29473 primary issue)", "<p data-parsoid='{\"dsr\":[0,34,0,0]}'><b data-parsoid='{\"dsr\":[0,34,3,3]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[3,31,17,2]}'>Main Page</a></b></p>\n");
add("html2html", "Internal link with ca linktrail, surrounded by italic apostrophes (T29473 primary issue)", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'><i data-parsoid='{\"dsr\":[0,32,2,2]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[2,30,17,2]}'>Main Page</a></i></p>\n");
add("html2html", "Internal link with en linktrail: no apostrophes (T29473)", "<p data-parsoid='{\"dsr\":[0,65,0,0]}'>[/index.php?title=Something&amp;action=edit&amp;redlink=1 Something]'nice</p>\n");
add("html2html", "Internal link with ca linktrail with apostrophes (T29473)", "<p data-parsoid='{\"dsr\":[0,65,0,0]}'>[/index.php?title=Something&amp;action=edit&amp;redlink=1 Something'nice]</p>\n");
add("html2html", "Internal link with kaa linktrail with apostrophes (T29473)", "<p data-parsoid='{\"dsr\":[0,65,0,0]}'>[/index.php?title=Something&amp;action=edit&amp;redlink=1 Something'nice]</p>\n");
add("html2html", "Internal link with is link prefix", "<p data-parsoid='{\"dsr\":[0,45,0,0]}'>Aðrir <a rel=\"mw:WikiLink\" href=\"./Wiki/Söfnuður\" title=\"Wiki/Söfnuður\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Söfnuður\"},\"sa\":{\"href\":\"wiki/Söfnuður\"},\"dsr\":[6,42,16,2]}'>mótmælendasöfnuðir</a> og</p>\n");
add("html2html", "Internal link with is link trail and link prefix", "<p data-parsoid='{\"dsr\":[0,181,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Mótmælendatrú\" title=\"Wiki/Mótmælendatrú\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Mótmælendatrú\"},\"sa\":{\"href\":\"wiki/Mótmælendatrú\"},\"dsr\":[0,28,21,2]}'>xxxar</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/Mótmælendatrú\" title=\"Wiki/Mótmælendatrú\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Mótmælendatrú\"},\"sa\":{\"href\":\"wiki/Mótmælendatrú\"},\"dsr\":[29,67,21,2]}'>mótmælendatrúar</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/Söfnuður\" title=\"Wiki/Söfnuður\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Söfnuður\"},\"sa\":{\"href\":\"wiki/Söfnuður\"},\"dsr\":[68,104,16,2]}'>mótmælendasöfnuður</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/Söfnuður\" title=\"Wiki/Söfnuður\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Söfnuður\"},\"sa\":{\"href\":\"wiki/Söfnuður\"},\"dsr\":[105,141,16,2]}'>mótmælendasöfnuðir</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/Söfnuður\" title=\"Wiki/Söfnuður\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Söfnuður\"},\"sa\":{\"href\":\"wiki/Söfnuður\"},\"dsr\":[142,181,16,2]}'>mótmælendasöfnuðirxxx</a></p>\n");
add("html2html", "Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved", "<p data-parsoid='{\"dsr\":[0,18,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[0,18,11,2]}'> bar</a></p>\n\n<p data-parsoid='{\"dsr\":[20,42,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[20,42,11,2]}'> <i data-parsoid='{\"dsr\":[33,40,2,2]}'>bar</i></a></p>\n\n<p data-parsoid='{\"dsr\":[44,63,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://wp.org\" data-parsoid='{\"targetOff\":59,\"contentOffsets\":[59,62],\"dsr\":[44,63,15,1]}'>foo</a></p>\n\n<p data-parsoid='{\"dsr\":[65,88,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://wp.org\" data-parsoid='{\"targetOff\":80,\"contentOffsets\":[80,87],\"dsr\":[65,88,15,1]}'><i data-parsoid='{\"dsr\":[80,87,2,2]}'>foo</i></a></p>\n");
add("html2html", "Space and question mark encoding in interlanguage links (T95473)", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'>Blah blah blah</p>\n<link rel=\"mw:PageProp/Language\" href=\"http://es.wikipedia.org/wiki/Foo_bar?\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"http://es.wikipedia.org/wiki/Foo_bar?\"},\"sa\":{\"href\":\"es:Foo_bar?\"},\"dsr\":[15,30,null,null]}'/>");
add("html2html", "Parsoid-specific test: Wikilinks with &nbsp; should RT properly", "<p data-parsoid='{\"dsr\":[0,52,0,0]}'>[/index.php?title=WW_II&amp;action=edit&amp;redlink=1 WW II]</p>\n");
add("html2html", "<br> to <br />", "<p data-parsoid='{\"dsr\":[0,5,0,0]}'>1\n2\n3</p>\n");
add("html2html", "Incorrecly removing closing slashes from correctly formed XHTML", "\n");
add("html2html", "Failing to transform badly formed HTML into correct XHTML", "\n\n<p data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[2,2,0,0]}'><br data-parsoid='{\"dsr\":[2,2,0,0]}'/></p>\n");
add("html2html", "Handling html with a br self-closing tag", "\n\n<p data-parsoid='{\"dsr\":[2,2,0,0]}'><br data-parsoid='{\"dsr\":[2,2,0,0]}'/></p>\n\n\n<p data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[5,5,0,0]}'><br data-parsoid='{\"dsr\":[5,5,0,0]}'/></p>\n");
add("html2html", "Unbalanced closing non-block tags don't break a list\n(php parser relies on Tidy to fix up)", "<p data-parsoid='{\"dsr\":[0,6,0,0]}'><span data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[0,6,6,0]}'></span></p>\n\n<ul data-parsoid='{\"dsr\":[8,28,0,0]}'><li data-parsoid='{\"dsr\":[8,24,1,0]}'> a<span data-parsoid='{\"stx\":\"html\",\"dsr\":[11,24,6,7]}'></span></li>\n<li data-parsoid='{\"dsr\":[25,28,1,0]}'> b</li></ul>\n\n<p data-parsoid='{\"dsr\":[30,37,0,0]}'></p>");
add("html2html", "2. List embedded in a formatting tag", "<p data-parsoid='{\"dsr\":[0,23,0,0]}'><small data-parsoid='{\"stx\":\"html\",\"dsr\":[0,15,7,8]}'></small>\n<small data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[16,23,7,0]}'></small></p><small data-parsoid='{\"stx\":\"html\",\"autoInsertedStart\":true,\"dsr\":[23,36,0,8]}'>\n<ul data-parsoid='{\"dsr\":[24,27,0,0]}'><li data-parsoid='{\"dsr\":[24,27,1,0]}'> a</li></ul>\n</small>\n<ul data-parsoid='{\"dsr\":[37,55,0,0]}'><li data-parsoid='{\"dsr\":[37,55,1,0]}'> <small data-parsoid='{\"stx\":\"html\",\"dsr\":[39,55,7,8]}'>b</small></li></ul>\n");
add("html2html", "Case-sensitive magic words, when cased differently, should just be template transclusions", "<p data-parsoid='{\"dsr\":[0,331,0,0]}'>[/index.php?title=Template:CurrentMonth&amp;action=edit&amp;redlink=1 Template:CurrentMonth]\n[/index.php?title=Template:Currentday&amp;action=edit&amp;redlink=1 Template:Currentday]\n[/index.php?title=Template:CURreNTweEK&amp;action=edit&amp;redlink=1 Template:CURreNTweEK]\n[/index.php?title=Template:CurrentHour&amp;action=edit&amp;redlink=1 Template:CurrentHour]</p>\n");
-add("html2html", "Parsoid: Template-generated DISPLAYTITLE", "<meta property=\"mw:PageProp/displaytitle\" content=\"Foo\" about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,29,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"{{echo|DISPLAYTITLE}}:Foo\",\"href\":\"./Foo\"},\"params\":{},\"i\":0}}]}'/>");
add("html2html", "Nonexistent template", "<p data-parsoid='{\"dsr\":[0,108,0,0]}'>[/index.php?title=Template:Thistemplatedoesnotexist&amp;action=edit&amp;redlink=1 Template:Thistemplatedoesnotexist]</p>\n");
add("html2html", "Template with invalid target containing wikilink", "<p data-parsoid='{\"dsr\":[0,17,0,0]}'>{{<a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[2,15,2,2]}'>Main Page</a>}}</p>\n");
add("html2html", "Template with just whitespace in it, T70421", "<p data-parsoid='{\"dsr\":[1,31,0,0]}'>{{echo|{{}<span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[11,29,8,9]}'>}</span>}}</p>");
add("html2html", "Template unnamed parameter", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,32,17,2]}'>the main page</a></p>\n");
add("html2html", "Template with complex arguments", "<p data-parsoid='{\"dsr\":[0,84,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Template:Complextemplate\" title=\"Wiki/Template:Complextemplate\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Template:Complextemplate\"},\"sa\":{\"href\":\"wiki/Template:Complextemplate\"},\"dsr\":[0,38,32,2]}'>link</a> This is a test template with parameter (test)</p>\n");
add("html2html", "T2553: link with two variables in a piped link", "<table data-parsoid='{\"dsr\":[0,43,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[3,41,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[3,40,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[3,40,1,0]}'>[[<span about=\"#mwt7\" typeof=\"mw:Param\" data-parsoid='{\"pi\":[[]],\"dsr\":[6,13,null,null]}' data-mw='{\"parts\":[{\"templatearg\":{\"target\":{\"wt\":\"1\"},\"params\":{},\"i\":0}}]}'>{{{1}}}</span><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[13,31,8,9]}'>|</span><span about=\"#mwt8\" typeof=\"mw:Param\" data-parsoid='{\"pi\":[[]],\"dsr\":[31,38,null,null]}' data-mw='{\"parts\":[{\"templatearg\":{\"target\":{\"wt\":\"2\"},\"params\":{},\"i\":0}}]}'>{{{2}}}</span>]]</td></tr>\n</tbody></table>\n");
add("html2html", "Abort table cell attribute parsing on wikilink", "<table data-parsoid='{\"dsr\":[0,151,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[3,149,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[3,148,0,0]}'><td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[3,50,1,0]}'> testing <a rel=\"mw:WikiLink\" href=\"./One\" title=\"One\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./One\"},\"sa\":{\"href\":\"one\"},\"dsr\":[13,24,6,2]}'>two</a><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[24,50,8,9]}'> | three </span></td><td data-parsoid='{\"stx_v\":\"row\",\"autoInsertedEnd\":true,\"dsr\":[50,57,2,0]}'> four</td>\n<td data-parsoid='{\"a\":{\"testing\":null,\"one\":null,\"two\":null},\"sa\":{\"testing\":\"\",\"one\":\"\",\"two\":\"\"},\"autoInsertedEnd\":true,\"dsr\":[58,84,19,0]}'> three </td><td data-parsoid='{\"stx_v\":\"row\",\"autoInsertedEnd\":true,\"dsr\":[84,91,2,0]}'> four</td>\n<td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[92,141,1,0]}'> testing=\"<a rel=\"mw:WikiLink\" href=\"./One\" title=\"One\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./One\"},\"sa\":{\"href\":\"one\"},\"dsr\":[103,114,6,2]}'>two</a><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[114,141,8,9]}'>\" | three </span></td><td data-parsoid='{\"stx_v\":\"row\",\"autoInsertedEnd\":true,\"dsr\":[141,148,2,0]}'> four</td></tr>\n</tbody></table>\n");
add("html2html", "Template parameter as link source", "<p data-parsoid='{\"dsr\":[0,23,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,23,17,2]}'>link</a></p>\n");
add("html2html", "Template as link source", "<p data-parsoid='{\"dsr\":[0,28,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,28,17,2]}'>Main Page</a></p>\n\n<p data-parsoid='{\"dsr\":[30,58,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[30,58,17,2]}'>Main Page</a></p>\n\n<p data-parsoid='{\"dsr\":[60,92,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[60,88,17,2]}'>Main Page</a>Page</p>\n");
add("html2html", "Template infinite loop", "<p data-parsoid='{\"dsr\":[0,89,0,0]}'><span class=\"error\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,89,20,7]}'>Template loop detected: <a rel=\"mw:WikiLink\" href=\"./Wiki/Template:Loop1\" title=\"Wiki/Template:Loop1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Template:Loop1\"},\"sa\":{\"href\":\"wiki/Template:Loop1\"},\"dsr\":[44,82,22,2]}'>Template:Loop1</a></span></p>\n");
add("html2html", "Template with targets containing wikilinks", "<p data-parsoid='{\"dsr\":[0,54,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[0,19,8,9]}'>{{</span><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[19,35,11,2]}'>foo</a><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[35,54,8,9]}'>}}</span></p>\n\n<p data-parsoid='{\"dsr\":[56,110,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[56,75,8,9]}'>{{</span><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[75,91,11,2]}'>foo</a><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[91,110,8,9]}'>}}</span></p>\n\n<p data-parsoid='{\"dsr\":[112,140,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[112,138,8,9]}'>{{[[foo}}</span>]]</p>\n");
add("html2html", "Self-closed noinclude, includeonly, onlyinclude tags", "\n");
add("html2html", "T8563: Section extraction for section shown by <includeonly>", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[0,32,8,9]}'>==Section T-2==</span></p>");
add("html2html", "T8563: Section extraction for section suppressed by <includeonly>", "<p data-parsoid='{\"dsr\":[0,30,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[0,30,8,9]}'>==Section 1==</span></p>");
add("html2html", "Templates: Links: 1. Simple example", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[0,16,11,2]}'>bar</a></p>\n");
add("html2html", "Templates: Links: 2. Generation of link href", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[0,16,11,2]}'>bar</a></p>\n");
add("html2html", "Templates: Links: 3. Generation of part of a link href", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[0,16,11,2]}'>bar</a></p>\n\n<p data-parsoid='{\"dsr\":[18,72,0,0]}'>[/index.php?title=Foobar&amp;action=edit&amp;redlink=1 Foobar]</p>\n\n<p data-parsoid='{\"dsr\":[74,134,0,0]}'>[/index.php?title=Foobarbaz&amp;action=edit&amp;redlink=1 Foobarbaz]</p>\n\n<p data-parsoid='{\"dsr\":[136,187,0,0]}'>[/index.php?title=Foobar&amp;action=edit&amp;redlink=1 bar]</p>\n\n<p data-parsoid='{\"dsr\":[189,243,0,0]}'>[/index.php?title=Foobar&amp;action=edit&amp;redlink=1 Foobar]</p>\n\n<p data-parsoid='{\"dsr\":[245,296,0,0]}'>[/index.php?title=Foobar&amp;action=edit&amp;redlink=1 bar]</p>\n");
add("html2html", "Templates: Links: 4. Multiple templates generating link href", "<p data-parsoid='{\"dsr\":[0,54,0,0]}'>[/index.php?title=Foobar&amp;action=edit&amp;redlink=1 Foobar]</p>\n");
add("html2html", "Templates: Links: 5. Generation of link text", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[0,16,11,2]}'>bar</a></p>\n");
add("html2html", "Templates: Links: 5. Nested templates (only outermost template should be marked)", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[0,16,11,2]}'>bar</a></p>\n");
add("html2html", "Templates: Lists: Multi-line list-items via templates", "<ul data-parsoid='{\"dsr\":[0,173,0,0]}'><li data-parsoid='{\"dsr\":[0,86,1,0]}'> a [/index.php?title=Template:Nonexistent&amp;action=edit&amp;redlink=1 Template:Nonexistent]</li>\n<li data-parsoid='{\"dsr\":[87,173,1,0]}'> b [/index.php?title=Template:Nonexistent&amp;action=edit&amp;redlink=1 Template:Nonexistent]</li></ul>\n");
add("html2html", "Templates: Ugly templates: 1. Navbox template parses badly leading to table misnesting\n(Parsoid-centric)", "<table about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,32,2,null],\"firstWikitextNode\":\"TABLE_html\",\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[\"{|\\n|\",{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo&lt;/table>\"}},\"i\":0}},\"\\n|bar\\n|}\"]}'>\n<tbody><tr><td>foo</td></tr></tbody></table><span about=\"#mwt1\">\n|bar\n</span>");
add("html2html", "Templates: Ugly templates: 4. newline-only template parameter inconsistency", "\n");
add("html2html", "message transform: magic variables", "<p data-parsoid='{\"dsr\":[0,9,0,0]}'>MediaWiki</p>");
add("html2html", "message transform: should not transform wiki markup", "<p data-parsoid='{\"dsr\":[0,25,0,0]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[0,25,8,9]}'>''test''</span></p>");
add("html2html", "message transform: <noinclude> in transcluded template (T6926)", "<p data-parsoid='{\"dsr\":[0,6,0,0]}'>Foobar</p>");
add("html2html", "message transform: <onlyinclude> in transcluded template (T6926)", "<p data-parsoid='{\"dsr\":[0,3,0,0]}'>Foo</p>");
add("html2html", "{{#special:}} page name, known", "<p data-parsoid='{\"dsr\":[0,21,0,0]}'>Special:RecentChanges</p>");
add("html2html", "{{#special:}} page name with subpage, known", "<p data-parsoid='{\"dsr\":[0,27,0,0]}'>Special:RecentChanges/param</p>");
add("html2html", "{{#special:}} page name, unknown", "<p data-parsoid='{\"dsr\":[0,26,0,0]}'>Special:Foobar nonexistent</p>");
add("html2html", "{{#speciale:}} page name, known", "<p data-parsoid='{\"dsr\":[0,21,0,0]}'>Special:RecentChanges</p>");
add("html2html", "{{#speciale:}} page name with subpage, known", "<p data-parsoid='{\"dsr\":[0,27,0,0]}'>Special:RecentChanges/param</p>");
add("html2html", "{{#speciale:}} page name, unknown", "<p data-parsoid='{\"dsr\":[0,26,0,0]}'>Special:Foobar_nonexistent</p>");
add("html2html", "Allow empty links in image captions (T62753)", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"caption\",\"ak\":\"Caption [[Link1]]\\n&lt;nowiki>[[]]&lt;/nowiki>\\n[[Link2]]\\n\"}],\"dsr\":[0,76,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,74,null,null]}'>Caption <a rel=\"mw:WikiLink\" href=\"./Link1\" title=\"Link1\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Link1\"},\"sa\":{\"href\":\"Link1\"},\"dsr\":[32,41,2,2]}'>Link1</a>\n<span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[42,63,8,9]}'>[[]]</span>\n<a rel=\"mw:WikiLink\" href=\"./Link2\" title=\"Link2\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Link2\"},\"sa\":{\"href\":\"Link2\"},\"dsr\":[64,73,2,2]}'>Link2</a>\n</figcaption></figure>");
add("html2html", "Image with multiple attributes from the same template", "<figure class=\"mw-default-size mw-halign-right\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"right\",\"ak\":\"right\"},{\"ck\":\"caption\",\"ak\":\"Caption text\"}],\"dsr\":[0,38,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,36,null,null]}'>Caption text</figcaption></figure>\n");
add("html2html", "Image with link tails", "<p data-parsoid='{\"dsr\":[0,29,0,0]}'>123<span class=\"mw-default-size\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[],\"dsr\":[3,22,null,null]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"}}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a></span>456\n123</p>\n<figure class=\"mw-default-size mw-halign-right\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"right\",\"ak\":\"right\"}],\"dsr\":[30,55,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[32,53,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a></figure>\n<p data-parsoid='{\"dsr\":[56,63,0,0]}'>456\n123</p>\n<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"}],\"dsr\":[64,89,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[66,87,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a></figure>\n<p data-parsoid='{\"dsr\":[90,93,0,0]}'>456</p>\n");
add("html2html", "Image with link parameter, wgNoFollowLinks set to false", "<p data-parsoid='{\"dsr\":[0,41,0,0]}'><img src=\"http://example.com/images/3/3a/Foobar.jpg\" alt=\"Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[0,41,null,null]}'/></p>\n");
add("html2html", "Image with link parameter, wgNoFollowDomainExceptions", "<p data-parsoid='{\"dsr\":[0,41,0,0]}'><img src=\"http://example.com/images/3/3a/Foobar.jpg\" alt=\"Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[0,41,null,null]}'/></p>\n");
add("html2html", "Link to image page- image page normally doesn't exists, hence edit link\nAdd test with existing image page\n#<p><a href=\"/wiki/File:Test\" title=\"Image:Test\">Image:test</a>", "<p data-parsoid='{\"dsr\":[0,61,0,0]}'>[/index.php?title=File:Test&amp;action=edit&amp;redlink=1 Image:test]</p>\n");
add("html2html", "T20784 Link to non-existent image page with caption should use caption as link text", "<p data-parsoid='{\"dsr\":[0,58,0,0]}'>[/index.php?title=File:Test&amp;action=edit&amp;redlink=1 caption]</p>\n");
add("html2html", "SVG thumbnails with invalid language code", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"lang\",\"ak\":\"lang=invalid.language.code\"}],\"dsr\":[0,52,2,2]}'><a href=\"./File:Foobar.svg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.svg\"},\"sa\":{\"href\":\"File:Foobar.svg\"},\"dsr\":[2,50,null,null]}'><img resource=\"./File:Foobar.svg\" src=\"//example.com/images/thumb/f/ff/Foobar.svg/220px-Foobar.svg\" lang=\"invalid.language.code\" data-file-width=\"240\" data-file-height=\"180\" data-file-type=\"drawing\" height=\"165\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.svg\",\"lang\":\"invalid.language.code\",\"height\":\"165\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.svg\",\"lang\":\"lang=invalid.language.code\"}}'/></a></figure>\n");
add("html2html", "T93580: 3. Templated <ref> inside inline images", "<p data-parsoid='{\"dsr\":[0,98,0,0]}'><span class=\"mw-default-size\" typeof=\"mw:Image\" data-parsoid='{\"optList\":[{\"ck\":\"caption\",\"ak\":\"Undisplayed caption in inline image with ref: {{echo|&lt;ref>{{echo|foo}}&lt;/ref>}}\"}],\"dsr\":[0,98,null,null]}' data-mw='{\"caption\":\"Undisplayed caption in inline image with ref: &lt;span about=\\\"#mwt3\\\" class=\\\"mw-ref\\\" id=\\\"cite_ref-1\\\" rel=\\\"dc:references\\\" typeof=\\\"mw:Transclusion mw:Extension/ref\\\" data-parsoid=&#39;{\\\"dsr\\\":[64,96,null,null],\\\"pi\\\":[[{\\\"k\\\":\\\"1\\\"}]]}&#39; data-mw=&#39;{\\\"parts\\\":[{\\\"template\\\":{\\\"target\\\":{\\\"wt\\\":\\\"echo\\\",\\\"href\\\":\\\"./Template:Echo\\\"},\\\"params\\\":{\\\"1\\\":{\\\"wt\\\":\\\"&amp;lt;ref>{{echo|foo}}&amp;lt;/ref>\\\"}},\\\"i\\\":0}}]}&#39;>&lt;a href=\\\"./Main_Page#cite_note-1\\\" style=\\\"counter-reset: mw-Ref 1;\\\" data-parsoid=\\\"{}\\\">&lt;span class=\\\"mw-reflink-text\\\" data-parsoid=\\\"{}\\\">[1]&lt;/span>&lt;/a>&lt;/span>&lt;meta typeof=\\\"mw:Transclusion mw:Extension/ref/Marker\\\" about=\\\"#mwt3\\\" data-parsoid=&#39;{\\\"group\\\":\\\"\\\",\\\"name\\\":\\\"\\\",\\\"content\\\":\\\"foo\\\",\\\"hasRefInRef\\\":false,\\\"dsr\\\":[64,96,null,null],\\\"pi\\\":[[{\\\"k\\\":\\\"1\\\"}]]}&#39; data-mw=&#39;{\\\"parts\\\":[{\\\"template\\\":{\\\"target\\\":{\\\"wt\\\":\\\"echo\\\",\\\"href\\\":\\\"./Template:Echo\\\"},\\\"params\\\":{\\\"1\\\":{\\\"wt\\\":\\\"&amp;lt;ref>{{echo|foo}}&amp;lt;/ref>\\\"}},\\\"i\\\":0}}]}&#39;/>\"}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"}}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/3/3a/Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"220\" width=\"1941\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"220\",\"width\":\"1941\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a></span></p>\n\n<ol class=\"mw-references\" typeof=\"mw:Extension/references\" about=\"#mwt7\" data-parsoid='{\"dsr\":[100,114,2,2]}' data-mw='{\"name\":\"references\",\"attrs\":{}}'><li about=\"#cite_note-1\" id=\"cite_note-1\"><a href=\"./Main_Page#cite_ref-1\" rel=\"mw:referencedBy\"><span class=\"mw-linkback-text\">↑ </span></a> <span id=\"mw-reference-text-cite_note-1\" class=\"mw-reference-text\" data-parsoid=\"{}\">foo</span></li></ol>");
add("html2html", "Subpage link", "<p data-parsoid='{\"dsr\":[0,38,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Subpage_test/subpage\" title=\"Wiki/Subpage test/subpage\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Subpage_test/subpage\"},\"sa\":{\"href\":\"wiki/Subpage test/subpage\"},\"dsr\":[0,38,28,2]}'>/subpage</a></p>\n");
add("html2html", "Subpage noslash link", "<p data-parsoid='{\"dsr\":[0,37,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Subpage_test/subpage\" title=\"Wiki/Subpage test/subpage\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Subpage_test/subpage\"},\"sa\":{\"href\":\"wiki/Subpage test/subpage\"},\"dsr\":[0,37,28,2]}'>subpage</a></p>\n");
add("html2html", "Render invalid page names as plain text (T53090)", "<p data-parsoid='{\"dsr\":[0,141,0,0]}'>[[./../foo|bar]]\n[[foo�|bar]]\n[[foo/.|bar]]\n[[foo/..|bar]]\n<span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[59,89,8,9]}'>[[foo~~~bar]]</span>\n[[foo>bar]]\n[[foo[bar]]\n[[.]]\n[[..]]\n[[foo././bar]]</p>\n\n<p data-parsoid='{\"dsr\":[143,389,0,0]}'>[[<span about=\"#mwt35\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[145,162,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"./../foo\"}},\"i\":0}}]}'>./../foo</span>|bar]]\n[[<span about=\"#mwt36\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[171,185,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo/.\"}},\"i\":0}}]}'>foo/.</span>|bar]]\n[[<span about=\"#mwt37\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[194,209,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo/..\"}},\"i\":0}}]}'>foo/..</span>|bar]]\n[[<span about=\"#mwt38\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[218,237,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo~~~~bar\"}},\"i\":0}}]}'>foo~~~~bar</span>]]\n[[<span about=\"#mwt39\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[242,258,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo>bar\"}},\"i\":0}}]}'>foo>bar</span>]]\n[[<span about=\"#mwt40\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[263,282,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo././bar\"}},\"i\":0}}]}'>foo././bar</span>]]\n[[<span about=\"#mwt41\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[287,303,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo{bar\"}},\"i\":0}}]}'>foo{bar</span>]]\n[[<span about=\"#mwt42\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[308,324,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo}bar\"}},\"i\":0}}]}'>foo}bar</span>]]\n[[<span about=\"#mwt43\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[329,345,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo[bar\"}},\"i\":0}}]}'>foo[bar</span>]]\n[[<span about=\"#mwt44\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[350,366,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo]bar\"}},\"i\":0}}]}'>foo]bar</span>]]\n[[<span about=\"#mwt45\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[{\"k\":\"1\"}]],\"dsr\":[371,387,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"foo&lt;bar\"}},\"i\":0}}]}'>foo&lt;bar</span>]]</p>\n");
add("html2html", "Disabled subpages", "<p data-parsoid='{\"dsr\":[0,58,0,0]}'>[/index.php?title=/subpage&amp;action=edit&amp;redlink=1 /subpage]</p>\n");
add("html2html", "T2561: {{/Subpage}}", "<p data-parsoid='{\"dsr\":[0,66,0,0]}'>[/index.php?title=Page/Subpage&amp;action=edit&amp;redlink=1 Page/Subpage]</p>\n");
add("html2html", "Link to category", "<p data-parsoid='{\"dsr\":[0,72,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Category:MediaWiki_User's_Guide\" title=\"Wiki/Category:MediaWiki User's Guide\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Category:MediaWiki_User&#39;s_Guide\"},\"sa\":{\"href\":\"wiki/Category:MediaWiki User&#39;s Guide\"},\"dsr\":[0,72,39,2]}'>Category:MediaWiki User's Guide</a></p>\n");
-add("html2html", "Parsoid: Defaultsort (template-generated)", "<meta property=\"mw:PageProp/categorydefaultsort\" content=\"Foo\" about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[0,28,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"{{echo|DEFAULTSORT}}:Foo\",\"href\":\"./Foo\"},\"params\":{},\"i\":0}}]}'/>");
add("html2html", "Section headings with TOC", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,708,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,176,0,0]}'><li data-parsoid='{\"dsr\":[86,176,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Headline_1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Headline_1\"},\"sa\":{\"href\":\"#Headline_1\"},\"dsr\":[88,176,14,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[102,134,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[135,174,22,7]}'>Headline 1</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[178,277,0,0]}'><li data-parsoid='{\"dsr\":[178,277,1,0]}'><ul data-parsoid='{\"dsr\":[179,277,0,0]}'><li data-parsoid='{\"dsr\":[179,277,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Subheadline_1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Subheadline_1\"},\"sa\":{\"href\":\"#Subheadline_1\"},\"dsr\":[181,277,17,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[198,232,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[233,275,22,7]}'>Subheadline 1</span></a></li></ul></li></ul>\n\n<ul data-parsoid='{\"dsr\":[279,387,0,0]}'><li data-parsoid='{\"dsr\":[279,387,1,0]}'><ul data-parsoid='{\"dsr\":[280,387,0,0]}'><li data-parsoid='{\"dsr\":[280,387,1,0]}'><ul data-parsoid='{\"dsr\":[281,387,0,0]}'><li data-parsoid='{\"dsr\":[281,387,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Skipping_a_level\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Skipping_a_level\"},\"sa\":{\"href\":\"#Skipping_a_level\"},\"dsr\":[283,387,20,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[303,339,24,7]}'>1.1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[340,385,22,7]}'>Skipping a level</span></a></li></ul></li></ul></li></ul>\n\n<ul data-parsoid='{\"dsr\":[389,593,0,0]}'><li data-parsoid='{\"dsr\":[389,502,1,0]}'><ul data-parsoid='{\"dsr\":[390,502,0,0]}'><li data-parsoid='{\"dsr\":[390,502,1,0]}'><ul data-parsoid='{\"dsr\":[391,502,0,0]}'><li data-parsoid='{\"dsr\":[391,502,1,0]}'><ul data-parsoid='{\"dsr\":[392,502,0,0]}'><li data-parsoid='{\"dsr\":[392,502,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Skipping_a_level_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Skipping_a_level_2\"},\"sa\":{\"href\":\"#Skipping_a_level_2\"},\"dsr\":[394,502,22,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[416,454,24,7]}'>1.1.1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[455,500,22,7]}'>Skipping a level</span></a></li></ul></li></ul></li></ul></li>\n<li data-parsoid='{\"dsr\":[503,593,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Headline_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Headline_2\"},\"sa\":{\"href\":\"#Headline_2\"},\"dsr\":[505,593,14,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[519,551,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[552,591,22,7]}'>Headline 2</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[595,700,0,0]}'><li data-parsoid='{\"dsr\":[595,700,1,0]}'><ul data-parsoid='{\"dsr\":[596,700,0,0]}'><li data-parsoid='{\"dsr\":[596,700,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Another_headline\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Another_headline\"},\"sa\":{\"href\":\"#Another_headline\"},\"dsr\":[598,700,20,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[618,652,24,7]}'>2.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[653,698,22,7]}'>Another headline</span></a></li></ul></li></ul>\n\n</div>\n\n<h2 id=\"Headline_1\" data-parsoid='{\"dsr\":[710,726,2,2]}'> Headline 1 </h2>\n\n<h3 id=\"Subheadline_1\" data-parsoid='{\"dsr\":[728,749,3,3]}'> Subheadline 1 </h3>\n\n<h5 id=\"Skipping_a_level\" data-parsoid='{\"dsr\":[751,779,5,5]}'> Skipping a level </h5>\n\n<h6 id=\"Skipping_a_level_2\" data-parsoid='{\"dsr\":[781,811,6,6]}'> Skipping a level </h6>\n\n<h2 id=\"Headline_2\" data-parsoid='{\"dsr\":[813,829,2,2]}'> Headline 2 </h2>\n<p data-parsoid='{\"dsr\":[830,839,0,0]}'>Some text</p>\n\n<h3 id=\"Another_headline\" data-parsoid='{\"dsr\":[841,865,3,3]}'> Another headline </h3>\n");
add("html2html", "Handling of sections up to level 6 and beyond", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,1303,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,186,0,0]}'><li data-parsoid='{\"dsr\":[86,186,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Level_1_Heading\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Level_1_Heading\"},\"sa\":{\"href\":\"#Level_1_Heading\"},\"dsr\":[88,186,19,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[107,139,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[140,184,22,7]}'>Level 1 Heading</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[188,291,0,0]}'><li data-parsoid='{\"dsr\":[188,291,1,0]}'><ul data-parsoid='{\"dsr\":[189,291,0,0]}'><li data-parsoid='{\"dsr\":[189,291,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Level_2_Heading\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Level_2_Heading\"},\"sa\":{\"href\":\"#Level_2_Heading\"},\"dsr\":[191,291,19,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[210,244,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[245,289,22,7]}'>Level 2 Heading</span></a></li></ul></li></ul>\n\n<ul data-parsoid='{\"dsr\":[293,399,0,0]}'><li data-parsoid='{\"dsr\":[293,399,1,0]}'><ul data-parsoid='{\"dsr\":[294,399,0,0]}'><li data-parsoid='{\"dsr\":[294,399,1,0]}'><ul data-parsoid='{\"dsr\":[295,399,0,0]}'><li data-parsoid='{\"dsr\":[295,399,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Level_3_Heading\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Level_3_Heading\"},\"sa\":{\"href\":\"#Level_3_Heading\"},\"dsr\":[297,399,19,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[316,352,24,7]}'>1.1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[353,397,22,7]}'>Level 3 Heading</span></a></li></ul></li></ul></li></ul>\n\n<ul data-parsoid='{\"dsr\":[401,510,0,0]}'><li data-parsoid='{\"dsr\":[401,510,1,0]}'><ul data-parsoid='{\"dsr\":[402,510,0,0]}'><li data-parsoid='{\"dsr\":[402,510,1,0]}'><ul data-parsoid='{\"dsr\":[403,510,0,0]}'><li data-parsoid='{\"dsr\":[403,510,1,0]}'><ul data-parsoid='{\"dsr\":[404,510,0,0]}'><li data-parsoid='{\"dsr\":[404,510,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Level_4_Heading\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Level_4_Heading\"},\"sa\":{\"href\":\"#Level_4_Heading\"},\"dsr\":[406,510,19,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[425,463,24,7]}'>1.1.1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[464,508,22,7]}'>Level 4 Heading</span></a></li></ul></li></ul></li></ul></li></ul>\n\n<ul data-parsoid='{\"dsr\":[512,624,0,0]}'><li data-parsoid='{\"dsr\":[512,624,1,0]}'><ul data-parsoid='{\"dsr\":[513,624,0,0]}'><li data-parsoid='{\"dsr\":[513,624,1,0]}'><ul data-parsoid='{\"dsr\":[514,624,0,0]}'><li data-parsoid='{\"dsr\":[514,624,1,0]}'><ul data-parsoid='{\"dsr\":[515,624,0,0]}'><li data-parsoid='{\"dsr\":[515,624,1,0]}'><ul data-parsoid='{\"dsr\":[516,624,0,0]}'><li data-parsoid='{\"dsr\":[516,624,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Level_5_Heading\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Level_5_Heading\"},\"sa\":{\"href\":\"#Level_5_Heading\"},\"dsr\":[518,624,19,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[537,577,24,7]}'>1.1.1.1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[578,622,22,7]}'>Level 5 Heading</span></a></li></ul></li></ul></li></ul></li></ul></li></ul>\n\n<ul data-parsoid='{\"dsr\":[626,1295,0,0]}'><li data-parsoid='{\"dsr\":[626,1295,1,0]}'><ul data-parsoid='{\"dsr\":[627,1295,0,0]}'><li data-parsoid='{\"dsr\":[627,1295,1,0]}'><ul data-parsoid='{\"dsr\":[628,1295,0,0]}'><li data-parsoid='{\"dsr\":[628,1295,1,0]}'><ul data-parsoid='{\"dsr\":[629,1295,0,0]}'><li data-parsoid='{\"dsr\":[629,1295,1,0]}'><ul data-parsoid='{\"dsr\":[630,1295,0,0]}'><li data-parsoid='{\"dsr\":[630,1295,1,0]}'><ul data-parsoid='{\"dsr\":[631,1295,0,0]}'><li data-parsoid='{\"dsr\":[631,741,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Level_6_Heading\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Level_6_Heading\"},\"sa\":{\"href\":\"#Level_6_Heading\"},\"dsr\":[633,741,19,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[652,694,24,7]}'>1.1.1.1.1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[695,739,22,7]}'>Level 6 Heading</span></a></li>\n<li data-parsoid='{\"dsr\":[742,867,6,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#.3D_Level_7_Heading.3D\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#.3D_Level_7_Heading.3D\"},\"sa\":{\"href\":\"#.3D_Level_7_Heading.3D\"},\"dsr\":[749,867,26,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[775,817,24,7]}'>1.1.1.1.1.2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[818,865,22,7]}'>= Level 7 Heading=</span></a></li>\n<li data-parsoid='{\"dsr\":[868,1001,6,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#.3D.3D_Level_8_Heading.3D.3D\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#.3D.3D_Level_8_Heading.3D.3D\"},\"sa\":{\"href\":\"#.3D.3D_Level_8_Heading.3D.3D\"},\"dsr\":[875,1001,32,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[907,949,24,7]}'>1.1.1.1.1.3</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[950,999,22,7]}'>== Level 8 Heading==</span></a></li>\n<li data-parsoid='{\"dsr\":[1002,1143,6,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#.3D.3D.3D_Level_9_Heading.3D.3D.3D\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#.3D.3D.3D_Level_9_Heading.3D.3D.3D\"},\"sa\":{\"href\":\"#.3D.3D.3D_Level_9_Heading.3D.3D.3D\"},\"dsr\":[1009,1143,38,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1047,1089,24,7]}'>1.1.1.1.1.4</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1090,1141,22,7]}'>=== Level 9 Heading===</span></a></li>\n<li data-parsoid='{\"dsr\":[1144,1295,6,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#.3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#.3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D\"},\"sa\":{\"href\":\"#.3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D\"},\"dsr\":[1151,1295,45,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1196,1238,24,7]}'>1.1.1.1.1.5</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1239,1293,22,7]}'>==== Level 10 Heading====</span></a></li></ul></li></ul></li></ul></li></ul></li></ul></li></ul>\n\n</div>\n\n<h1 id=\"Level_1_Heading\" data-parsoid='{\"dsr\":[1305,1324,1,1]}'> Level 1 Heading </h1>\n\n<h2 id=\"Level_2_Heading\" data-parsoid='{\"dsr\":[1326,1347,2,2]}'> Level 2 Heading </h2>\n\n<h3 id=\"Level_3_Heading\" data-parsoid='{\"dsr\":[1349,1372,3,3]}'> Level 3 Heading </h3>\n\n<h4 id=\"Level_4_Heading\" data-parsoid='{\"dsr\":[1374,1399,4,4]}'> Level 4 Heading </h4>\n\n<h5 id=\"Level_5_Heading\" data-parsoid='{\"dsr\":[1401,1428,5,5]}'> Level 5 Heading </h5>\n\n<h6 id=\"Level_6_Heading\" data-parsoid='{\"dsr\":[1430,1459,6,6]}'> Level 6 Heading </h6>\n\n<h6 id=\".3D_Level_7_Heading.3D\" data-parsoid='{\"dsr\":[1461,1493,6,6]}'> = Level 7 Heading= </h6>\n\n<h6 id=\".3D.3D_Level_8_Heading.3D.3D\" data-parsoid='{\"dsr\":[1495,1529,6,6]}'> == Level 8 Heading== </h6>\n\n<h6 id=\".3D.3D.3D_Level_9_Heading.3D.3D.3D\" data-parsoid='{\"dsr\":[1531,1567,6,6]}'> === Level 9 Heading=== </h6>\n\n<h6 id=\".3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D\" data-parsoid='{\"dsr\":[1569,1608,6,6]}'> ==== Level 10 Heading==== </h6>\n");
add("html2html", "TOC regression (T11764)", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,641,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,170,0,0]}'><li data-parsoid='{\"dsr\":[86,170,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1\"},\"sa\":{\"href\":\"#title_1\"},\"dsr\":[88,170,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[99,131,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[132,168,22,7]}'>title 1</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[172,263,0,0]}'><li data-parsoid='{\"dsr\":[172,263,1,0]}'><ul data-parsoid='{\"dsr\":[173,263,0,0]}'><li data-parsoid='{\"dsr\":[173,263,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1.1\"},\"sa\":{\"href\":\"#title_1.1\"},\"dsr\":[175,263,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[188,222,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[223,261,22,7]}'>title 1.1</span></a></li></ul></li></ul>\n\n<ul data-parsoid='{\"dsr\":[265,540,0,0]}'><li data-parsoid='{\"dsr\":[265,455,1,0]}'><ul data-parsoid='{\"dsr\":[266,455,0,0]}'><li data-parsoid='{\"dsr\":[266,363,1,0]}'><ul data-parsoid='{\"dsr\":[267,363,0,0]}'><li data-parsoid='{\"dsr\":[267,363,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1.1.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1.1.1\"},\"sa\":{\"href\":\"#title_1.1.1\"},\"dsr\":[269,363,15,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[284,320,24,7]}'>1.1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[321,361,22,7]}'>title 1.1.1</span></a></li></ul></li>\n<li data-parsoid='{\"dsr\":[364,455,2,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1.2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1.2\"},\"sa\":{\"href\":\"#title_1.2\"},\"dsr\":[367,455,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[380,414,24,7]}'>1.2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[415,453,22,7]}'>title 1.2</span></a></li></ul></li>\n<li data-parsoid='{\"dsr\":[456,540,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_2\"},\"sa\":{\"href\":\"#title_2\"},\"dsr\":[458,540,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[469,501,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[502,538,22,7]}'>title 2</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[542,633,0,0]}'><li data-parsoid='{\"dsr\":[542,633,1,0]}'><ul data-parsoid='{\"dsr\":[543,633,0,0]}'><li data-parsoid='{\"dsr\":[543,633,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_2.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_2.1\"},\"sa\":{\"href\":\"#title_2.1\"},\"dsr\":[545,633,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[558,592,24,7]}'>2.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[593,631,22,7]}'>title 2.1</span></a></li></ul></li></ul>\n\n</div>\n\n<h2 id=\"title_1\" data-parsoid='{\"dsr\":[643,656,2,2]}'> title 1 </h2>\n\n<h3 id=\"title_1.1\" data-parsoid='{\"dsr\":[658,675,3,3]}'> title 1.1 </h3>\n\n<h4 id=\"title_1.1.1\" data-parsoid='{\"dsr\":[677,698,4,4]}'> title 1.1.1 </h4>\n\n<h3 id=\"title_1.2\" data-parsoid='{\"dsr\":[700,717,3,3]}'> title 1.2 </h3>\n\n<h2 id=\"title_2\" data-parsoid='{\"dsr\":[719,732,2,2]}'> title 2 </h2>\n\n<h3 id=\"title_2.1\" data-parsoid='{\"dsr\":[734,751,3,3]}'> title 2.1 </h3>\n");
add("html2html", "TOC with wgMaxTocLevel=3 (T8204)", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,541,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,170,0,0]}'><li data-parsoid='{\"dsr\":[86,170,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1\"},\"sa\":{\"href\":\"#title_1\"},\"dsr\":[88,170,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[99,131,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[132,168,22,7]}'>title 1</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[172,440,0,0]}'><li data-parsoid='{\"dsr\":[172,355,1,0]}'><ul data-parsoid='{\"dsr\":[173,355,0,0]}'><li data-parsoid='{\"dsr\":[173,263,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1.1\"},\"sa\":{\"href\":\"#title_1.1\"},\"dsr\":[175,263,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[188,222,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[223,261,22,7]}'>title 1.1</span></a></li>\n<li data-parsoid='{\"dsr\":[264,355,2,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1.2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1.2\"},\"sa\":{\"href\":\"#title_1.2\"},\"dsr\":[267,355,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[280,314,24,7]}'>1.2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[315,353,22,7]}'>title 1.2</span></a></li></ul></li>\n<li data-parsoid='{\"dsr\":[356,440,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_2\"},\"sa\":{\"href\":\"#title_2\"},\"dsr\":[358,440,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[369,401,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[402,438,22,7]}'>title 2</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[442,533,0,0]}'><li data-parsoid='{\"dsr\":[442,533,1,0]}'><ul data-parsoid='{\"dsr\":[443,533,0,0]}'><li data-parsoid='{\"dsr\":[443,533,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_2.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_2.1\"},\"sa\":{\"href\":\"#title_2.1\"},\"dsr\":[445,533,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[458,492,24,7]}'>2.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[493,531,22,7]}'>title 2.1</span></a></li></ul></li></ul>\n\n</div>\n\n<h2 id=\"title_1\" data-parsoid='{\"dsr\":[543,556,2,2]}'> title 1 </h2>\n\n<h3 id=\"title_1.1\" data-parsoid='{\"dsr\":[558,575,3,3]}'> title 1.1 </h3>\n\n<h4 id=\"title_1.1.1\" data-parsoid='{\"dsr\":[577,598,4,4]}'> title 1.1.1 </h4>\n\n<h3 id=\"title_1.2\" data-parsoid='{\"dsr\":[600,617,3,3]}'> title 1.2 </h3>\n\n<h2 id=\"title_2\" data-parsoid='{\"dsr\":[619,632,2,2]}'> title 2 </h2>\n\n<h3 id=\"title_2.1\" data-parsoid='{\"dsr\":[634,651,3,3]}'> title 2.1 </h3>\n");
add("html2html", "TOC with wgMaxTocLevel=3 and two level four headings (T8204)", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,368,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,174,0,0]}'><li data-parsoid='{\"dsr\":[86,174,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Section_1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Section_1\"},\"sa\":{\"href\":\"#Section_1\"},\"dsr\":[88,174,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[101,133,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[134,172,22,7]}'>Section 1</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[176,360,0,0]}'><li data-parsoid='{\"dsr\":[176,271,1,0]}'><ul data-parsoid='{\"dsr\":[177,271,0,0]}'><li data-parsoid='{\"dsr\":[177,271,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Section_1.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Section_1.1\"},\"sa\":{\"href\":\"#Section_1.1\"},\"dsr\":[179,271,15,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[194,228,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[229,269,22,7]}'>Section 1.1</span></a></li></ul></li>\n<li data-parsoid='{\"dsr\":[272,360,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Section_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Section_2\"},\"sa\":{\"href\":\"#Section_2\"},\"dsr\":[274,360,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[287,319,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[320,358,22,7]}'>Section 2</span></a></li></ul>\n\n</div>\n\n<h2 id=\"Section_1\" data-parsoid='{\"dsr\":[370,385,2,2]}'> Section 1 </h2>\n\n<h3 id=\"Section_1.1\" data-parsoid='{\"dsr\":[387,406,3,3]}'> Section 1.1 </h3>\n\n<h4 id=\"Section_1.1.1\" data-parsoid='{\"dsr\":[408,431,4,4]}'> Section 1.1.1 </h4>\n\n<h4 id=\"Section_1.1.1.1\" data-parsoid='{\"dsr\":[433,458,4,4]}'> Section 1.1.1.1 </h4>\n\n<h2 id=\"Section_2\" data-parsoid='{\"dsr\":[460,475,2,2]}'> Section 2 </h2>\n");
add("html2html", "Link inside a section heading", "<h2 id=\"Section_with_a_link_in_it\" data-parsoid='{\"dsr\":[0,50,2,2]}'> Section with a <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[18,41,17,2]}'>link</a> in it </h2>\n");
add("html2html", "TOC regression (T14077)", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,356,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,170,0,0]}'><li data-parsoid='{\"dsr\":[86,170,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1\"},\"sa\":{\"href\":\"#title_1\"},\"dsr\":[88,170,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[99,131,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[132,168,22,7]}'>title 1</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[172,348,0,0]}'><li data-parsoid='{\"dsr\":[172,263,1,0]}'><ul data-parsoid='{\"dsr\":[173,263,0,0]}'><li data-parsoid='{\"dsr\":[173,263,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_1.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_1.1\"},\"sa\":{\"href\":\"#title_1.1\"},\"dsr\":[175,263,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[188,222,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[223,261,22,7]}'>title 1.1</span></a></li></ul></li>\n<li data-parsoid='{\"dsr\":[264,348,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#title_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#title_2\"},\"sa\":{\"href\":\"#title_2\"},\"dsr\":[266,348,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[277,309,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[310,346,22,7]}'>title 2</span></a></li></ul>\n\n</div>\n\n<h2 id=\"title_1\" data-parsoid='{\"dsr\":[358,371,2,2]}'> title 1 </h2>\n\n<h3 id=\"title_1.1\" data-parsoid='{\"dsr\":[373,390,3,3]}'> title 1.1 </h3>\n\n<h2 id=\"title_2\" data-parsoid='{\"dsr\":[392,405,2,2]}'> title 2 </h2>\n");
add("html2html", "Header with special characters (T27462)", "<p data-parsoid='{\"dsr\":[0,72,0,0]}'>The tooltips shall not show entities to the user (ie. be double escaped)</p>\n\n<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[74,642,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[100,158,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[137,151,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[160,634,0,0]}'><li data-parsoid='{\"dsr\":[160,254,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#text_.3E_text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#text_.3E_text\"},\"sa\":{\"href\":\"#text_.3E_text\"},\"dsr\":[162,254,17,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[179,211,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[212,252,22,7]}'>text > text</span></a></li>\n<li data-parsoid='{\"dsr\":[255,349,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#text_.3C_text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#text_.3C_text\"},\"sa\":{\"href\":\"#text_.3C_text\"},\"dsr\":[257,349,17,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[274,306,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[307,347,22,7]}'>text &lt; text</span></a></li>\n<li data-parsoid='{\"dsr\":[350,444,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#text_.26_text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#text_.26_text\"},\"sa\":{\"href\":\"#text_.26_text\"},\"dsr\":[352,444,17,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[369,401,24,7]}'>3</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[402,442,22,7]}'>text &amp; text</span></a></li>\n<li data-parsoid='{\"dsr\":[445,539,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#text_.27_text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#text_.27_text\"},\"sa\":{\"href\":\"#text_.27_text\"},\"dsr\":[447,539,17,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[464,496,24,7]}'>4</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[497,537,22,7]}'>text ' text</span></a></li>\n<li data-parsoid='{\"dsr\":[540,634,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#text_.22_text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#text_.22_text\"},\"sa\":{\"href\":\"#text_.22_text\"},\"dsr\":[542,634,17,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[559,591,24,7]}'>5</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[592,632,22,7]}'>text \" text</span></a></li></ul>\n\n</div>\n\n<h2 id=\"text_.3E_text\" data-parsoid='{\"dsr\":[644,661,2,2]}'> text > text </h2>\n<p data-parsoid='{\"dsr\":[662,671,0,0]}'>section 1</p>\n\n<h2 id=\"text_.3C_text\" data-parsoid='{\"dsr\":[673,690,2,2]}'> text &lt; text </h2>\n<p data-parsoid='{\"dsr\":[691,700,0,0]}'>section 2</p>\n\n<h2 id=\"text_.26_text\" data-parsoid='{\"dsr\":[702,719,2,2]}'> text &amp; text </h2>\n<p data-parsoid='{\"dsr\":[720,729,0,0]}'>section 3</p>\n\n<h2 id=\"text_.27_text\" data-parsoid='{\"dsr\":[731,748,2,2]}'> text ' text </h2>\n<p data-parsoid='{\"dsr\":[749,758,0,0]}'>section 4</p>\n\n<h2 id=\"text_.22_text\" data-parsoid='{\"dsr\":[760,777,2,2]}'> text \" text </h2>\n<p data-parsoid='{\"dsr\":[778,787,0,0]}'>section 5</p>\n");
add("html2html", "Header with space, plus and underscore as entity", "<p data-parsoid='{\"dsr\":[0,34,0,0]}'>Id should not contain + for spaces</p>\n\n<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[36,837,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[62,120,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[99,113,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[122,829,0,0]}'><li data-parsoid='{\"dsr\":[122,228,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Space_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Space_between_Text\"},\"sa\":{\"href\":\"#Space_between_Text\"},\"dsr\":[124,228,22,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[146,178,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[179,226,22,7]}'>Space between Text</span></a></li>\n<li data-parsoid='{\"dsr\":[229,349,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Space-Entity_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Space-Entity_between_Text\"},\"sa\":{\"href\":\"#Space-Entity_between_Text\"},\"dsr\":[231,349,29,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[260,292,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[293,347,22,7]}'>Space-Entity between Text</span></a></li>\n<li data-parsoid='{\"dsr\":[350,458,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Plus.2Bbetween.2BText\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Plus.2Bbetween.2BText\"},\"sa\":{\"href\":\"#Plus.2Bbetween.2BText\"},\"dsr\":[352,458,25,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[377,409,24,7]}'>3</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[410,456,22,7]}'>Plus+between+Text</span></a></li>\n<li data-parsoid='{\"dsr\":[459,581,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Plus-Entity.2Bbetween.2BText\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Plus-Entity.2Bbetween.2BText\"},\"sa\":{\"href\":\"#Plus-Entity.2Bbetween.2BText\"},\"dsr\":[461,581,32,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[493,525,24,7]}'>4</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[526,579,22,7]}'>Plus-Entity+between+Text</span></a></li>\n<li data-parsoid='{\"dsr\":[582,698,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Underscore_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Underscore_between_Text\"},\"sa\":{\"href\":\"#Underscore_between_Text\"},\"dsr\":[584,698,27,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[611,643,24,7]}'>5</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[644,696,22,7]}'>Underscore_between_Text</span></a></li>\n<li data-parsoid='{\"dsr\":[699,829,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Underscore-Entity_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Underscore-Entity_between_Text\"},\"sa\":{\"href\":\"#Underscore-Entity_between_Text\"},\"dsr\":[701,829,34,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[735,767,24,7]}'>6</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[768,827,22,7]}'>Underscore-Entity_between_Text</span></a></li></ul>\n\n</div>\n\n<h2 id=\"Space_between_Text\" data-parsoid='{\"dsr\":[839,863,2,2]}'> Space between Text </h2>\n<p data-parsoid='{\"dsr\":[864,873,0,0]}'>section 1</p>\n\n<h2 id=\"Space-Entity_between_Text\" data-parsoid='{\"dsr\":[875,906,2,2]}'> Space-Entity between Text </h2>\n<p data-parsoid='{\"dsr\":[907,916,0,0]}'>section 2</p>\n\n<h2 id=\"Plus.2Bbetween.2BText\" data-parsoid='{\"dsr\":[918,941,2,2]}'> Plus+between+Text </h2>\n<p data-parsoid='{\"dsr\":[942,951,0,0]}'>section 3</p>\n\n<h2 id=\"Plus-Entity.2Bbetween.2BText\" data-parsoid='{\"dsr\":[953,983,2,2]}'> Plus-Entity+between+Text </h2>\n<p data-parsoid='{\"dsr\":[984,993,0,0]}'>section 4</p>\n\n<h2 id=\"Underscore_between_Text\" data-parsoid='{\"dsr\":[995,1024,2,2]}'> Underscore_between_Text </h2>\n<p data-parsoid='{\"dsr\":[1025,1034,0,0]}'>section 5</p>\n\n<h2 id=\"Underscore-Entity_between_Text\" data-parsoid='{\"dsr\":[1036,1072,2,2]}'> Underscore-Entity_between_Text </h2>\n<p data-parsoid='{\"dsr\":[1073,1082,0,0]}'>section 6</p>\n\n<p data-parsoid='{\"dsr\":[1084,1413,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Main_Page#Space_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Space_between_Text\"},\"sa\":{\"href\":\"#Space_between_Text\"},\"dsr\":[1084,1127,22,2]}'>#Space between Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Space-Entity_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Space-Entity_between_Text\"},\"sa\":{\"href\":\"#Space-Entity_between_Text\"},\"dsr\":[1128,1185,29,2]}'>#Space-Entity between Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Plus.2Bbetween.2BText\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Plus.2Bbetween.2BText\"},\"sa\":{\"href\":\"#Plus.2Bbetween.2BText\"},\"dsr\":[1186,1231,25,2]}'>#Plus+between+Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Plus-Entity.2Bbetween.2BText\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Plus-Entity.2Bbetween.2BText\"},\"sa\":{\"href\":\"#Plus-Entity.2Bbetween.2BText\"},\"dsr\":[1232,1291,32,2]}'>#Plus-Entity+between+Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Underscore_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Underscore_between_Text\"},\"sa\":{\"href\":\"#Underscore_between_Text\"},\"dsr\":[1292,1345,27,2]}'>#Underscore_between_Text</a>\n<a rel=\"mw:WikiLink\" href=\"./Main_Page#Underscore-Entity_between_Text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Underscore-Entity_between_Text\"},\"sa\":{\"href\":\"#Underscore-Entity_between_Text\"},\"dsr\":[1346,1413,34,2]}'>#Underscore-Entity_between_Text</a></p>\n");
add("html2html", "Headers with excess '=' characters\n(Are similar tests necessary beyond the 1st level?)", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,469,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,461,0,0]}'><li data-parsoid='{\"dsr\":[86,166,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#foo.3D\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#foo.3D\"},\"sa\":{\"href\":\"#foo.3D\"},\"dsr\":[88,166,10,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[98,130,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[131,164,22,7]}'>foo=</span></a></li>\n<li data-parsoid='{\"dsr\":[167,247,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#.3Dfoo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#.3Dfoo\"},\"sa\":{\"href\":\"#.3Dfoo\"},\"dsr\":[169,247,10,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[179,211,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[212,245,22,7]}'>=foo</span></a></li>\n<li data-parsoid='{\"dsr\":[248,354,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#italic_heading.3D\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#italic_heading.3D\"},\"sa\":{\"href\":\"#italic_heading.3D\"},\"dsr\":[250,354,21,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[271,303,24,7]}'>3</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[304,352,22,7]}'><i data-parsoid='{\"dsr\":[326,336,2,2]}'>italic</i> heading=</span></a></li>\n<li data-parsoid='{\"dsr\":[355,461,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#.3Ditalic_heading\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#.3Ditalic_heading\"},\"sa\":{\"href\":\"#.3Ditalic_heading\"},\"dsr\":[357,461,21,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[378,410,24,7]}'>4</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[411,459,22,7]}'>=<i data-parsoid='{\"dsr\":[434,444,2,2]}'>italic</i> heading</span></a></li></ul>\n\n</div>\n\n<h1 id=\"foo.3D\" data-parsoid='{\"dsr\":[471,479,1,1]}'> foo= </h1>\n\n<h1 id=\".3Dfoo\" data-parsoid='{\"dsr\":[481,489,1,1]}'> =foo </h1>\n\n<h1 id=\"italic_heading.3D\" data-parsoid='{\"dsr\":[491,514,1,1]}'> <i data-parsoid='{\"dsr\":[493,503,2,2]}'>italic</i> heading= </h1>\n\n<h1 id=\".3Ditalic_heading\" data-parsoid='{\"dsr\":[516,539,1,1]}'> =<i data-parsoid='{\"dsr\":[519,529,2,2]}'>italic</i> heading </h1>\n");
add("html2html", "HTML headers vs TOC (T25393)\n(__NOEDITSECTION__ for clearer output, doesn't matter here)", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,645,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,172,0,0]}'><li data-parsoid='{\"dsr\":[86,172,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Header_1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Header_1\"},\"sa\":{\"href\":\"#Header_1\"},\"dsr\":[88,172,12,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[100,132,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[133,170,22,7]}'>Header 1</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[174,448,0,0]}'><li data-parsoid='{\"dsr\":[174,361,1,0]}'><ul data-parsoid='{\"dsr\":[175,361,0,0]}'><li data-parsoid='{\"dsr\":[175,267,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Header_1.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Header_1.1\"},\"sa\":{\"href\":\"#Header_1.1\"},\"dsr\":[177,267,14,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[191,225,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[226,265,22,7]}'>Header 1.1</span></a></li>\n<li data-parsoid='{\"dsr\":[268,361,2,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Header_1.2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Header_1.2\"},\"sa\":{\"href\":\"#Header_1.2\"},\"dsr\":[271,361,14,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[285,319,24,7]}'>1.2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[320,359,22,7]}'>Header 1.2</span></a></li></ul></li>\n<li data-parsoid='{\"dsr\":[362,448,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Header_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Header_2\"},\"sa\":{\"href\":\"#Header_2\"},\"dsr\":[364,448,12,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[376,408,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[409,446,22,7]}'>Header 2</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[450,637,0,0]}'><li data-parsoid='{\"dsr\":[450,637,1,0]}'><ul data-parsoid='{\"dsr\":[451,637,0,0]}'><li data-parsoid='{\"dsr\":[451,543,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Header_2.1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Header_2.1\"},\"sa\":{\"href\":\"#Header_2.1\"},\"dsr\":[453,543,14,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[467,501,24,7]}'>2.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[502,541,22,7]}'>Header 2.1</span></a></li>\n<li data-parsoid='{\"dsr\":[544,637,2,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Header_2.2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Header_2.2\"},\"sa\":{\"href\":\"#Header_2.2\"},\"dsr\":[547,637,14,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[561,595,24,7]}'>2.2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[596,635,22,7]}'>Header 2.2</span></a></li></ul></li></ul>\n\n</div>\n\n<h1 id=\"Header_1\" data-parsoid='{\"dsr\":[647,659,1,1]}'> Header 1 </h1>\n\n<h2 id=\"Header_1.1\" data-parsoid='{\"dsr\":[661,677,2,2]}'> Header 1.1 </h2>\n\n<h2 id=\"Header_1.2\" data-parsoid='{\"dsr\":[679,695,2,2]}'> Header 1.2 </h2>\n\n<h1 id=\"Header_2\" data-parsoid='{\"dsr\":[697,709,1,1]}'> Header 2 </h1>\n\n<h2 id=\"Header_2.1\" data-parsoid='{\"dsr\":[711,727,2,2]}'> Header 2.1 </h2>\n\n<h2 id=\"Header_2.2\" data-parsoid='{\"dsr\":[729,745,2,2]}'> Header 2.2 </h2>\n");
add("html2html", "Media link", "<p data-parsoid='{\"dsr\":[0,60,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://example.com/images/3/3a/Foobar.jpg\" data-parsoid='{\"targetOff\":43,\"contentOffsets\":[43,59],\"dsr\":[0,60,43,1]}'>Media:Foobar.jpg</a></p>\n");
add("html2html", "Media link with text", "<p data-parsoid='{\"dsr\":[0,66,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://example.com/images/3/3a/Foobar.jpg\" data-parsoid='{\"targetOff\":43,\"contentOffsets\":[43,65],\"dsr\":[0,66,43,1]}'>A neat file to look at</a></p>\n");
add("html2html", "Media link with nasty text", "<p data-parsoid='{\"dsr\":[0,53,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://example.com/images/3/3a/Foobar.jpg\" data-parsoid='{\"targetOff\":43,\"contentOffsets\":[43,52],\"dsr\":[0,53,43,1]}'>Safe Link</a></p>\n<div style=\"display:none\" data-parsoid='{\"stx\":\"html\",\"dsr\":[54,132,26,6]}'>\" onmouseover=\"alert(document.cookie)\" onfoo=\"</div>");
add("html2html", "Media link to nonexistent file (T3702)", "<p data-parsoid='{\"dsr\":[0,74,0,0]}'>[/index.php?title=Special:Upload&amp;wpDestFile=No_such.jpg Media:No such.jpg]</p>\n");
add("html2html", "Character reference normalization in link text (T3938)", "<p data-parsoid='{\"dsr\":[0,28,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,28,17,2]}'>this&amp;that</a></p>\n");
add("html2html", "(T21451) Links should refer to the normalized form.", "<p data-parsoid='{\"dsr\":[0,73,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/אַ\" title=\"Wiki/אַ\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/אַ\"},\"sa\":{\"href\":\"wiki/אַ\"},\"dsr\":[0,13,10,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/אַ\" title=\"Wiki/אַ\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/אַ\"},\"sa\":{\"href\":\"wiki/אַ\"},\"dsr\":[14,28,10,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/אַ\" title=\"Wiki/אַ\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/אַ\"},\"sa\":{\"href\":\"wiki/אַ\"},\"dsr\":[29,43,10,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/אַ\" title=\"Wiki/אַ\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/אַ\"},\"sa\":{\"href\":\"wiki/אַ\"},\"dsr\":[44,58,10,2]}'>אַ</a>\n<a rel=\"mw:WikiLink\" href=\"./Wiki/אַ\" title=\"Wiki/אַ\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/אַ\"},\"sa\":{\"href\":\"wiki/אַ\"},\"dsr\":[59,73,10,2]}'>אַ</a></p>\n");
add("html2html", "T4095: link with pipe and three closing brackets, version 2", "<p data-parsoid='{\"dsr\":[0,52,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Main_Page\" title=\"Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page\"},\"sa\":{\"href\":\"Main Page\"},\"dsr\":[0,52,12,2]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[12,50,8,9]}'>[http://example.com/]</span></a></p>\n");
add("html2html", "Table attribute safety", "<table data-parsoid='{\"dsr\":[0,45,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[3,43,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[3,42,0,0]}'><th style=\" \" data-parsoid='{\"a\":{\"style\":\" \"},\"sa\":{\"style\":\"/* insecure input */\"},\"autoInsertedEnd\":true,\"dsr\":[3,42,32,0]}'> status</th></tr>\n</tbody></table>\n");
add("html2html", "CSS line continuation 1", "<div style=\" \" data-parsoid='{\"stx\":\"html\",\"a\":{\"style\":\" \"},\"sa\":{\"style\":\"/* insecure input */\"},\"dsr\":[0,40,34,6]}'></div>\n");
add("html2html", "CSS line continuation 2", "<div style=\" \" data-parsoid='{\"stx\":\"html\",\"a\":{\"style\":\" \"},\"sa\":{\"style\":\"/* invalid control char */\"},\"dsr\":[0,46,40,6]}'></div>\n");
add("html2html", "Parser hook: nested tags", "<pre typeof=\"mw:Extension/tag\" about=\"#mwt3\" data-parsoid='{\"dsr\":[0,16,2,2]}' data-mw='{\"name\":\"tag\",\"attrs\":{},\"body\":{\"extsrc\":\"&lt;tag>\"}}'></pre><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[16,39,8,9]}'>&lt;/tag></span>");
add("html2html", "Sanitizer: Validating that <meta> and <link> work, but only for Microdata", "<div itemscope=\"\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,244,18,6]}'>\n\t<p data-parsoid='{\"dsr\":[20,141,0,0]}'>&lt;meta itemprop=\"hello\" content=\"world\" />\n\t&lt;meta http-equiv=\"refresh\" content=\"5\">\n\t&lt;meta itemprop=\"hello\" content=\"5\" /></p>\n\n\t<p data-parsoid='{\"dsr\":[144,237,0,0]}'><a rel=\"mw:ExtLink\" href=\"http://example.org\" data-parsoid='{\"targetOff\":163,\"contentOffsets\":[163,163],\"dsr\":[144,164,19,1]}'></a>\n\t&lt;link rel=\"stylesheet\" href=\"http://example.org\">\n\t<a rel=\"mw:ExtLink\" href=\"http://example.org\" data-parsoid='{\"targetOff\":236,\"contentOffsets\":[236,236],\"dsr\":[217,237,19,1]}'></a></p>\n</div>\n");
add("html2html", "HTML ordered list item with parameters oddity", "<ol data-parsoid='{\"dsr\":[0,5,0,0]}'><li data-parsoid='{\"dsr\":[0,5,1,0]}'> One</li></ol>\n");
add("html2html", "Fuzz testing: Parser14", "<h2 id=\"onmouseover.3D\" data-parsoid='{\"dsr\":[0,18,2,2]}'> onmouseover= </h2>\n<p data-parsoid='{\"dsr\":[19,26,0,0]}'>http://</p>\n<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[27,218,26,6]}'>\n<div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[54,112,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[91,105,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[114,210,0,0]}'><li data-parsoid='{\"dsr\":[114,210,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#onmouseover.3D\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#onmouseover.3D\"},\"sa\":{\"href\":\"#onmouseover.3D\"},\"dsr\":[116,210,18,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[134,166,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[167,208,22,7]}'>onmouseover=</span></a></li></ul>\n\n</div>\n");
add("html2html", "Special page transclusion", "<ul data-parsoid='{\"dsr\":[0,24,0,0]}'><li data-parsoid='{\"dsr\":[0,24,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Wiki/Xyzzyx\" title=\"Wiki/Xyzzyx\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Xyzzyx\"},\"sa\":{\"href\":\"wiki/Xyzzyx\"},\"dsr\":[2,24,14,2]}'>Xyzzyx</a></li></ul>\n");
add("html2html", "Special page transclusion twice (T7021)", "<ul data-parsoid='{\"dsr\":[0,24,0,0]}'><li data-parsoid='{\"dsr\":[0,24,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Wiki/Xyzzyx\" title=\"Wiki/Xyzzyx\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Xyzzyx\"},\"sa\":{\"href\":\"wiki/Xyzzyx\"},\"dsr\":[2,24,14,2]}'>Xyzzyx</a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[26,50,0,0]}'><li data-parsoid='{\"dsr\":[26,50,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Wiki/Xyzzyx\" title=\"Wiki/Xyzzyx\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Xyzzyx\"},\"sa\":{\"href\":\"wiki/Xyzzyx\"},\"dsr\":[28,50,14,2]}'>Xyzzyx</a></li></ul>\n");
add("html2html", "Transclusion of nonexistent MediaWiki message", "<p data-parsoid='{\"dsr\":[0,84,0,0]}'>[/index.php?title=MediaWiki:Mainpagexxx&amp;action=edit&amp;redlink=1 MediaWiki:Mainpagexxx]</p>\n");
add("html2html", "Special:Search page linking.", "<p data-parsoid='{\"dsr\":[0,38,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Special:Search\" title=\"Wiki/Special:Search\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Special:Search\"},\"sa\":{\"href\":\"wiki/Special:Search\"},\"dsr\":[0,38,22,2]}'>Special:Search</a></p>\n");
add("html2html", "Say the magic word", "<ul data-parsoid='{\"dsr\":[0,312,0,0]}'><li data-parsoid='{\"dsr\":[0,13,1,0]}'> Parser test</li>\n<li data-parsoid='{\"dsr\":[14,27,1,0]}'> Parser_test</li>\n<li data-parsoid='{\"dsr\":[28,41,1,0]}'> Parser test</li>\n<li data-parsoid='{\"dsr\":[42,55,1,0]}'> Parser_test</li>\n<li data-parsoid='{\"dsr\":[56,69,1,0]}'> Parser test</li>\n<li data-parsoid='{\"dsr\":[70,83,1,0]}'> Parser_test</li>\n<li data-parsoid='{\"dsr\":[84,97,1,0]}'> Parser test</li>\n<li data-parsoid='{\"dsr\":[98,111,1,0]}'> Parser_test</li>\n<li data-parsoid='{\"dsr\":[112,125,1,0]}'> Parser test</li>\n<li data-parsoid='{\"dsr\":[126,139,1,0]}'> Parser_test</li>\n<li data-parsoid='{\"dsr\":[140,158,1,0]}'> Talk:Parser test</li>\n<li data-parsoid='{\"dsr\":[159,177,1,0]}'> Talk:Parser_test</li>\n<li data-parsoid='{\"dsr\":[178,191,1,0]}'> Parser test</li>\n<li data-parsoid='{\"dsr\":[192,205,1,0]}'> Parser_test</li>\n<li data-parsoid='{\"dsr\":[206,208,1,0]}'> </li>\n<li data-parsoid='{\"dsr\":[209,211,1,0]}'> </li>\n<li data-parsoid='{\"dsr\":[212,215,1,0]}'> 0</li>\n<li data-parsoid='{\"dsr\":[216,222,1,0]}'> Talk</li>\n<li data-parsoid='{\"dsr\":[223,229,1,0]}'> Talk</li>\n<li data-parsoid='{\"dsr\":[230,232,1,0]}'> </li>\n<li data-parsoid='{\"dsr\":[233,235,1,0]}'> </li>\n<li data-parsoid='{\"dsr\":[236,312,1,0]}'> [/index.php?title=Template:Dynamic&amp;action=edit&amp;redlink=1 Template:Dynamic]</li></ul>\n");
add("html2html", "Gallery override link with absolute external link with LanguageConverter", "<p data-parsoid='{\"dsr\":[0,4,0,0]}'>\t\t* </p><div style=\"width: 155px\" data-parsoid='{\"stx\":\"html\",\"dsr\":[4,239,26,6]}'> \t\t\t<div class=\"thumb\" style=\"width: 150px;\" data-parsoid='{\"stx\":\"html\",\"dsr\":[34,182,41,6]}'><div style=\"margin:68px auto;\" data-parsoid='{\"stx\":\"html\",\"dsr\":[75,176,31,6]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg\" alt=\"120px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[106,170,null,null]}'/></div></div> \t\t\t<div class=\"gallerytext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[186,230,25,6]}'> caption \t\t\t</div> \t\t</div>\n");
add("html2html", "Double RFC with a wiki link", "<p data-parsoid='{\"dsr\":[0,62,0,0]}'>RFC [/index.php?title=RFC_1234&amp;action=edit&amp;redlink=1 <a href=\"//tools.ietf.org/html/rfc1234\" rel=\"mw:ExtLink\" data-parsoid='{\"stx\":\"magiclink\",\"dsr\":[53,61,0,0]}'>RFC 1234</a>]</p>\n");
add("html2html", "Centre-aligned image", "<div class=\"center\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,96,20,6]}'><div class=\"floatnone\" data-parsoid='{\"stx\":\"html\",\"dsr\":[20,90,23,6]}'><img src=\"http://example.com/images/3/3a/Foobar.jpg\" alt=\"Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[43,84,null,null]}'/></div></div>\n");
add("html2html", "None-aligned image", "<div class=\"floatnone\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,70,23,6]}'><img src=\"http://example.com/images/3/3a/Foobar.jpg\" alt=\"Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[23,64,null,null]}'/></div>\n");
add("html2html", "Width + Height sized image (using px) (height is ignored)", "<p data-parsoid='{\"dsr\":[0,64,0,0]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" alt=\"640px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[0,64,null,null]}'/></p>\n");
add("html2html", "Width-sized image (using px, no following whitespace)", "<p data-parsoid='{\"dsr\":[0,64,0,0]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" alt=\"640px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[0,64,null,null]}'/></p>\n");
add("html2html", "Width-sized image (using px, with following whitespace - test regression from r39467)", "<p data-parsoid='{\"dsr\":[0,64,0,0]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" alt=\"640px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[0,64,null,null]}'/></p>\n");
add("html2html", "Width-sized image (using px, with preceding whitespace - test regression from r39467)", "<p data-parsoid='{\"dsr\":[0,64,0,0]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg\" alt=\"640px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[0,64,null,null]}'/></p>\n");
add("html2html", "HTML with raw HTML ($wgRawHtml==true)", "<p data-parsoid='{\"dsr\":[0,26,0,0]}'>&lt;script>alert(1);&lt;/script></p>\n");
add("html2html", "Parents of subpages, one level up", "<p data-parsoid='{\"dsr\":[0,62,0,0]}'>[/index.php?title=Subpage_test/L1/L2&amp;action=edit&amp;redlink=1 L2]</p>\n");
add("html2html", "Parents of subpages, one level up, not named", "<p data-parsoid='{\"dsr\":[0,78,0,0]}'>[/index.php?title=Subpage_test/L1/L2&amp;action=edit&amp;redlink=1 Subpage test/L1/L2]</p>\n");
add("html2html", "Parents of subpages, two levels up", "<p data-parsoid='{\"dsr\":[0,60,0,0]}'>[/index.php?title=Subpage_test/L1&amp;action=edit&amp;redlink=1 L1]2</p>\n\n<p data-parsoid='{\"dsr\":[62,122,0,0]}'>[/index.php?title=Subpage_test/L1&amp;action=edit&amp;redlink=1 L1l]</p>\n");
add("html2html", "Parents of subpages, two levels up, with lots of extra trailing slashes.", "<p data-parsoid='{\"dsr\":[0,72,0,0]}'>[/index.php?title=Subpage_test/L1&amp;action=edit&amp;redlink=1 Subpage test/L1]</p>\n");
add("html2html", "RAW magic word", "<p data-parsoid='{\"dsr\":[0,72,0,0]}'>[/index.php?title=Template:QUERTY&amp;action=edit&amp;redlink=1 Template:QUERTY]</p>\n");
add("html2html", "Out-of-order TOC heading levels", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,547,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,158,0,0]}'><li data-parsoid='{\"dsr\":[86,158,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#2\"},\"sa\":{\"href\":\"#2\"},\"dsr\":[88,158,5,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[93,125,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[126,156,22,7]}'>2</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[160,384,0,0]}'><li data-parsoid='{\"dsr\":[160,311,1,0]}'><ul data-parsoid='{\"dsr\":[161,311,0,0]}'><li data-parsoid='{\"dsr\":[161,235,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#6\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#6\"},\"sa\":{\"href\":\"#6\"},\"dsr\":[163,235,5,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[168,202,24,7]}'>1.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[203,233,22,7]}'>6</span></a></li>\n<li data-parsoid='{\"dsr\":[236,311,2,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#3\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#3\"},\"sa\":{\"href\":\"#3\"},\"dsr\":[239,311,5,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[244,278,24,7]}'>1.2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[279,309,22,7]}'>3</span></a></li></ul></li>\n<li data-parsoid='{\"dsr\":[312,384,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#1\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#1\"},\"sa\":{\"href\":\"#1\"},\"dsr\":[314,384,5,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[319,351,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[352,382,22,7]}'>1</span></a></li></ul>\n\n<ul data-parsoid='{\"dsr\":[386,539,0,0]}'><li data-parsoid='{\"dsr\":[386,539,1,0]}'><ul data-parsoid='{\"dsr\":[387,539,0,0]}'><li data-parsoid='{\"dsr\":[387,461,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#5\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#5\"},\"sa\":{\"href\":\"#5\"},\"dsr\":[389,461,5,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[394,428,24,7]}'>2.1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[429,459,22,7]}'>5</span></a></li>\n<li data-parsoid='{\"dsr\":[462,539,2,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#2_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#2_2\"},\"sa\":{\"href\":\"#2_2\"},\"dsr\":[465,539,7,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[472,506,24,7]}'>2.2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[507,537,22,7]}'>2</span></a></li></ul></li></ul>\n\n</div>\n\n<h2 id=\"2\" data-parsoid='{\"dsr\":[549,556,2,2]}'> 2 </h2>\n\n<h6 id=\"6\" data-parsoid='{\"dsr\":[558,573,6,6]}'> 6 </h6>\n\n<h3 id=\"3\" data-parsoid='{\"dsr\":[575,584,3,3]}'> 3 </h3>\n\n<h1 id=\"1\" data-parsoid='{\"dsr\":[586,591,1,1]}'> 1 </h1>\n\n<h5 id=\"5\" data-parsoid='{\"dsr\":[593,606,5,5]}'> 5 </h5>\n\n<h2 id=\"2_2\" data-parsoid='{\"dsr\":[608,615,2,2]}'> 2 </h2>\n");
add("html2html", "ISBN with space-delimited number", "<p data-parsoid='{\"dsr\":[0,58,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Special:BookSources/9290170328\" title=\"Wiki/Special:BookSources/9290170328\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Special:BookSources/9290170328\"},\"sa\":{\"href\":\"wiki/Special:BookSources/9290170328\"},\"dsr\":[0,58,38,2]}'>ISBN 92 9017 032 8</a></p>\n");
add("html2html", "ISBN length", "<p data-parsoid='{\"dsr\":[0,14,0,0]}'>ISBN 123456789</p>\n\n<p data-parsoid='{\"dsr\":[16,71,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Special:BookSources/1234567890\" title=\"Wiki/Special:BookSources/1234567890\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Special:BookSources/1234567890\"},\"sa\":{\"href\":\"wiki/Special:BookSources/1234567890\"},\"dsr\":[16,71,38,2]}'>ISBN 1234567890</a></p>\n\n<p data-parsoid='{\"dsr\":[73,89,0,0]}'>ISBN 12345678901</p>\n");
add("html2html", "ISBN with trailing year (T9110)", "<p data-parsoid='{\"dsr\":[0,65,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Special:BookSources/1234567890\" title=\"Wiki/Special:BookSources/1234567890\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Special:BookSources/1234567890\"},\"sa\":{\"href\":\"wiki/Special:BookSources/1234567890\"},\"dsr\":[0,58,38,2]}'>ISBN 1-234-56789-0</a> - 2006</p>\n\n<p data-parsoid='{\"dsr\":[67,132,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Special:BookSources/1234567890\" title=\"Wiki/Special:BookSources/1234567890\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Special:BookSources/1234567890\"},\"sa\":{\"href\":\"wiki/Special:BookSources/1234567890\"},\"dsr\":[67,125,38,2]}'>ISBN 1 234 56789 0</a> - 2006</p>\n");
add("html2html", "Self-link in language variants", "<p data-parsoid='{\"dsr\":[0,46,0,0]}'>Both Dunav and Дунав are names for this river.</p>\n");
add("html2html", "Link to another existing title shouldn't be parsed as self-link even if it's a variant of this title", "<p data-parsoid='{\"dsr\":[0,79,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Дуна\" title=\"Wiki/Дуна\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Дуна\"},\"sa\":{\"href\":\"wiki/Дуна\"},\"dsr\":[0,18,12,2]}'>Дуна</a> is not a self-link while Duna and Dуна are still self-links.</p>\n");
add("html2html", "Link to a section of a variant of this title shouldn't be parsed as self-link", "<p data-parsoid='{\"dsr\":[0,95,0,0]}'>Dуна is a self-link while <a rel=\"mw:WikiLink\" href=\"./Wiki/Дуна\" title=\"Wiki/Дуна\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Дуна\"},\"sa\":{\"href\":\"wiki/Дуна\"},\"dsr\":[26,48,12,2]}'>Dunа#Foo</a> and <a rel=\"mw:WikiLink\" href=\"./Wiki/Дуна\" title=\"Wiki/Дуна\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Дуна\"},\"sa\":{\"href\":\"wiki/Дуна\"},\"dsr\":[53,75,12,2]}'>Dуна#Foo</a> are not self-links.</p>\n");
add("html2html", "Link to pages in language variants", "<p data-parsoid='{\"dsr\":[0,56,0,0]}'>Main Page can be written as <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[28,56,17,2]}'>Маин Паге</a></p>\n");
add("html2html", "Multiple links to pages in language variants", "<p data-parsoid='{\"dsr\":[0,113,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,28,17,2]}'>Main Page</a> can be written as <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[47,75,17,2]}'>Маин Паге</a> same as <a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[84,112,17,2]}'>Маин Паге</a>.</p>\n");
add("html2html", "Prevent conversion of links with -{}- tags (language variants)", "<p data-parsoid='{\"dsr\":[0,28,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,28,17,2]}'>Main Page</a></p>\n");
add("html2html", "Adding explicit conversion rule for title (T flag)", "<p data-parsoid='{\"dsr\":[0,6,0,0]}'>Taiwan</p>\n\n<p data-parsoid='{\"dsr\":[8,27,0,0]}'>Should be stripped!</p>\n");
add("html2html", "Testing that changing the language variant here in the tests actually works", "<p data-parsoid='{\"dsr\":[0,5,0,0]}'>China</p>\n\n<p data-parsoid='{\"dsr\":[7,26,0,0]}'>Should be stripped!</p>\n");
add("html2html", "Recursive conversion of alt and title attrs shouldn't clear converter state", "<p data-parsoid='{\"dsr\":[0,5,0,0]}'>China</p>\n\n<p data-parsoid='{\"dsr\":[7,59,0,0]}'>Should be stripped<span title=\"Exclamation\" data-parsoid='{\"stx\":\"html\",\"dsr\":[25,59,26,7]}'>!</span></p>\n");
add("html2html", "T26072: more test on conversion rule for title", "<p data-parsoid='{\"dsr\":[0,6,0,0]}'>Taiwan</p>\n\n<p data-parsoid='{\"dsr\":[8,80,0,0]}'>This should be stripped!\nThis won't take interferes with the title rule.</p>\n");
add("html2html", "Partly disable title conversion if variant == main language code", "<p data-parsoid='{\"dsr\":[0,2,0,0]}'>ZH</p>\n");
add("html2html", "Partly disable title conversion if variant == main language code, more", "<p data-parsoid='{\"dsr\":[0,2,0,0]}'>ZH</p>\n");
add("html2html", "Don't break link parsing if language converter markup is in the caption.", "<p data-parsoid='{\"dsr\":[0,28,0,0]}'><a rel=\"mw:WikiLink\" href=\"./Wiki/Main_Page\" title=\"Wiki/Main Page\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Main_Page\"},\"sa\":{\"href\":\"wiki/Main Page\"},\"dsr\":[0,28,17,2]}'>main page</a></p>\n");
add("html2html", "T146305: Don't break image parsing if language converter markup is in the caption.", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"мини\"},{\"ck\":\"caption\",\"ak\":\"&lt;span>&lt;/span>\"}],\"dsr\":[0,42,2,2]}'><a href=\"./Датотека:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./Датотека:Foobar.jpg\"},\"sa\":{\"href\":\"Датотека:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./Датотека:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./Датотека:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"Датотека:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,40,null,null]}'><span data-parsoid='{\"stx\":\"html\",\"dsr\":[27,40,6,7]}'></span></figcaption></figure>\n");
add("html2html", "T146305: Don't break image parsing if nested language converter markup is in the caption.", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"缩略图\"},{\"ck\":\"caption\",\"ak\":\"&lt;span>&lt;/span>\"}],\"dsr\":[0,37,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,35,null,null]}'><span data-parsoid='{\"stx\":\"html\",\"dsr\":[22,35,6,7]}'></span></figcaption></figure>\n");
add("html2html", "Don't break gallery if language converter markup is inside.", "<p data-parsoid='{\"dsr\":[0,4,0,0]}'>\t\t* </p><div style=\"width: 155px\" data-parsoid='{\"stx\":\"html\",\"dsr\":[4,295,26,6]}'> \t\t\t<div class=\"thumb\" style=\"width: 150px;\" data-parsoid='{\"stx\":\"html\",\"dsr\":[34,182,41,6]}'><div style=\"margin:68px auto;\" data-parsoid='{\"stx\":\"html\",\"dsr\":[75,176,31,6]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg\" alt=\"120px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[106,170,null,null]}'/></div></div> \t\t\t<div class=\"gallerytext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[186,286,25,6]}'> <img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg\" alt=\"20px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[212,275,null,null]}'/> \t\t\t</div> \t\t</div>\n<p data-parsoid='{\"dsr\":[296,300,0,0]}'>\t\t* </p><div style=\"width: 155px\" data-parsoid='{\"stx\":\"html\",\"dsr\":[300,551,26,6]}'> \t\t\t<div class=\"thumb\" style=\"width: 150px;\" data-parsoid='{\"stx\":\"html\",\"dsr\":[330,478,41,6]}'><div style=\"margin:68px auto;\" data-parsoid='{\"stx\":\"html\",\"dsr\":[371,472,31,6]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg\" alt=\"120px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[402,466,null,null]}'/></div></div> \t\t\t<div class=\"gallerytext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[482,542,25,6]}'> This is a test template \t\t\t</div> \t\t</div>\n");
add("html2html", "T153135: Don't break list handling if language converter markup is in the item.", "\n<dl data-parsoid='{\"dsr\":[1,32,0,0]}'><dt data-parsoid='{\"dsr\":[1,16,1,0]}'> <span data-parsoid='{\"stx\":\"html\",\"dsr\":[3,16,6,7]}'></span></dt>\n<dt data-parsoid='{\"dsr\":[17,32,1,0]}'> <span data-parsoid='{\"stx\":\"html\",\"dsr\":[19,32,6,7]}'></span></dt></dl>\n");
add("html2html", "T153135: Unclosed markup in definition list (code coverage)", "\n<dl data-parsoid='{\"dsr\":[1,16,0,0]}'><dt data-parsoid='{\"dsr\":[1,16,1,0]}'> <b data-parsoid='{\"dsr\":[3,16,3,3]}'>foo:bar</b></dt></dl>\n<p data-parsoid='{\"dsr\":[17,20,0,0]}'><b data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[17,20,3,0]}'></b></p>\n<dl data-parsoid='{\"dsr\":[21,36,0,0]}'><dt data-parsoid='{\"dsr\":[21,30,1,0]}'> -{zh-cn</dt>\n<dd data-parsoid='{\"dsr\":[31,36,1,0]}'> AAA</dd></dl>\n<p data-parsoid='{\"dsr\":[37,40,0,0]}'><b data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[37,40,3,0]}'></b></p>");
add("html2html", "T153135: Nested language converter markup in definition list (code coverage)", "\n<dl data-parsoid='{\"dsr\":[1,22,0,0]}'><dt data-parsoid='{\"dsr\":[1,16,1,0]}'> <span data-parsoid='{\"stx\":\"html\",\"dsr\":[3,16,6,7]}'></span></dt>\n<dd data-parsoid='{\"dsr\":[17,22,1,0]}'> def</dd></dl>\n");
add("html2html", "Free external link invading image caption", "<div class=\"thumb tright\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,236,26,6]}'><div class=\"thumbinner\" style=\"width:182px;\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,230,45,6]}'><img src=\"http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg\" alt=\"180px-Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[71,135,null,null]}'/> <div class=\"thumbcaption\" data-parsoid='{\"stx\":\"html\",\"dsr\":[137,224,26,6]}'><div class=\"magnify\" data-parsoid='{\"stx\":\"html\",\"dsr\":[163,213,21,6]}'>[/wiki/File:Foobar.jpg]</div>hello</div></div></div>\n");
add("html2html", "Bad images - basic functionality", "<p data-parsoid='{\"dsr\":[0,16,0,0]}'><span class=\"mw-default-size\" typeof=\"mw:Error mw:Image\" data-parsoid='{\"optList\":[],\"dsr\":[0,16,null,null]}' data-mw='{\"errors\":[{\"key\":\"apierror-filedoesnotexist\",\"message\":\"This image does not exist.\"}]}'><a href=\"./File:Bad.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Bad.jpg\"},\"sa\":{\"href\":\"File:Bad.jpg\"}}'><img resource=\"./File:Bad.jpg\" src=\"./Special:FilePath/Bad.jpg\" height=\"220\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Bad.jpg\",\"height\":\"220\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Bad.jpg\"}}'/></a></span></p>\n");
add("html2html", "Bad images - T18039: text after bad image disappears", "<p data-parsoid='{\"dsr\":[0,32,0,0]}'>Foo bar\n<span class=\"mw-default-size\" typeof=\"mw:Error mw:Image\" data-parsoid='{\"optList\":[],\"dsr\":[8,24,null,null]}' data-mw='{\"errors\":[{\"key\":\"apierror-filedoesnotexist\",\"message\":\"This image does not exist.\"}]}'><a href=\"./File:Bad.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Bad.jpg\"},\"sa\":{\"href\":\"File:Bad.jpg\"}}'><img resource=\"./File:Bad.jpg\" src=\"./Special:FilePath/Bad.jpg\" height=\"220\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Bad.jpg\",\"height\":\"220\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Bad.jpg\"}}'/></a></span>\nBar foo</p>\n");
add("html2html", "T33098 Template which includes system messages which includes the template", "<p data-parsoid='{\"dsr\":[0,195,0,0]}'><span class=\"error\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,97,20,7]}'>Template loop detected: <a rel=\"mw:WikiLink\" href=\"./Wiki/Template:Identical\" title=\"Wiki/Template:Identical\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Template:Identical\"},\"sa\":{\"href\":\"wiki/Template:Identical\"},\"dsr\":[44,90,26,2]}'>Template:Identical</a></span>\n<span class=\"error\" data-parsoid='{\"stx\":\"html\",\"dsr\":[98,195,20,7]}'>Template loop detected: <a rel=\"mw:WikiLink\" href=\"./Wiki/Template:Identical\" title=\"Wiki/Template:Identical\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Template:Identical\"},\"sa\":{\"href\":\"wiki/Template:Identical\"},\"dsr\":[142,188,26,2]}'>Template:Identical</a></span></p>\n");
add("html2html", "T33490 Turkish: ucfırst (with a dotless i)", "<p data-parsoid='{\"dsr\":[0,90,0,0]}'>[/index.php?title=%C5%9Eablon:Ucf%C4%B1rst:blah&amp;action=edit&amp;redlink=1 Şablon:Ucfırst:blah]</p>\n");
add("html2html", "T33490 ucfırst (with a dotless i) with English language", "<p data-parsoid='{\"dsr\":[0,89,0,0]}'>[/index.php?title=Template:Ucf%C4%B1rst:blah&amp;action=edit&amp;redlink=1 Template:Ucfırst:blah]</p>\n");
add("html2html", "T28375: TOC with italics", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,194,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,186,0,0]}'><li data-parsoid='{\"dsr\":[86,186,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Lost_episodes\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Lost_episodes\"},\"sa\":{\"href\":\"#Lost_episodes\"},\"dsr\":[88,186,17,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[105,137,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[138,184,22,7]}'><i data-parsoid='{\"dsr\":[160,168,2,2]}'>Lost</i> episodes</span></a></li></ul>\n\n</div>\n\n<h2 id=\"Lost_episodes\" data-parsoid='{\"dsr\":[196,219,2,2]}'> <i data-parsoid='{\"dsr\":[199,207,2,2]}'>Lost</i> episodes </h2>\n");
add("html2html", "T28375: TOC with bold", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,232,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,224,0,0]}'><li data-parsoid='{\"dsr\":[86,224,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#should_be_bold_then_normal_text\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#should_be_bold_then_normal_text\"},\"sa\":{\"href\":\"#should_be_bold_then_normal_text\"},\"dsr\":[88,224,35,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[123,155,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[156,222,22,7]}'><b data-parsoid='{\"dsr\":[178,198,3,3]}'>should be bold</b> then normal text</span></a></li></ul>\n\n</div>\n\n<h2 id=\"should_be_bold_then_normal_text\" data-parsoid='{\"dsr\":[234,277,2,2]}'> <b data-parsoid='{\"dsr\":[237,257,3,3]}'>should be bold</b> then normal text </h2>\n");
add("html2html", "T35845: Headings become cursive in TOC when they contain an image", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,174,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,166,0,0]}'><li data-parsoid='{\"dsr\":[86,166,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Image\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Image\"},\"sa\":{\"href\":\"#Image\"},\"dsr\":[88,166,9,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[97,129,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[130,164,22,7]}'>Image</span></a></li></ul>\n\n</div>\n\n<h2 id=\"Image\" data-parsoid='{\"dsr\":[176,229,2,2]}'> Image <img src=\"http://example.com/images/3/3a/Foobar.jpg\" alt=\"Foobar.jpg\" rel=\"mw:externalImage\" data-parsoid='{\"dsr\":[185,226,null,null]}'/> </h2>\n");
add("html2html", "T35845 (2): Headings become bold in TOC when they contain a blockquote", "\n<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1,176,26,6]}'>\n<div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[28,86,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[65,79,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[88,168,0,0]}'><li data-parsoid='{\"dsr\":[88,168,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Quote\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Quote\"},\"sa\":{\"href\":\"#Quote\"},\"dsr\":[90,168,9,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[99,131,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[132,166,22,7]}'>Quote</span></a></li></ul>\n\n</div>\n\n<h2 id=\"\" data-parsoid='{\"dsr\":[178,191,2,2]}'><span typeof=\"mw:Nowiki\" data-parsoid='{\"dsr\":[180,189,9,0]}'></span></h2>\n<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[192,224,12,13]}'>\n<p data-parsoid='{\"dsr\":[205,210,0,0]}'>Quote</p>\n</blockquote>\n<p data-parsoid='{\"dsr\":[225,406,0,0]}'><span class=\"mw-editsection\" data-parsoid='{\"stx\":\"html\",\"dsr\":[225,406,29,7]}'><span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[254,299,37,7]}'>[</span>[/index.php?title=Main_Page&amp;action=edit&amp;section=1 edit]<span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[354,399,37,7]}'>]</span></span></p>\n");
add("html2html", "Unclosed tags in TOC", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,190,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,182,0,0]}'><li data-parsoid='{\"dsr\":[86,182,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Proof:_2_.3C_3\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Proof:_2_.3C_3\"},\"sa\":{\"href\":\"#Proof:_2_.3C_3\"},\"dsr\":[88,182,18,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[106,138,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[139,180,22,7]}'>Proof: 2 &lt; 3</span></a></li></ul>\n\n</div>\n\n<h2 id=\"Proof:_2_.3C_3\" data-parsoid='{\"dsr\":[192,210,2,2]}'> Proof: 2 &lt; 3 </h2>\n<p data-parsoid='{\"dsr\":[211,266,0,0]}'><small data-parsoid='{\"stx\":\"html\",\"dsr\":[211,262,7,8]}'>Hanc marginis exiguitas non caperet.</small>\nQED</p>\n");
add("html2html", "Multiple tags in TOC", "\n<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1,281,26,6]}'>\n<div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[28,86,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[65,79,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[88,273,0,0]}'><li data-parsoid='{\"dsr\":[88,182,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Foo_Bar\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Foo_Bar\"},\"sa\":{\"href\":\"#Foo_Bar\"},\"dsr\":[90,182,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[101,133,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[134,180,22,7]}'><i data-parsoid='{\"dsr\":[156,163,2,2]}'>Foo</i> <b data-parsoid='{\"dsr\":[164,173,3,3]}'>Bar</b></span></a></li>\n<li data-parsoid='{\"dsr\":[183,273,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Foo_Bar_2\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Foo_Bar_2\"},\"sa\":{\"href\":\"#Foo_Bar_2\"},\"dsr\":[185,273,13,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[198,230,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[231,271,22,7]}'><i data-parsoid='{\"dsr\":[253,260,2,2]}'>Foo</i> Bar</span></a></li></ul>\n\n</div>\n\n<h2 id=\"Foo_Bar\" data-parsoid='{\"dsr\":[283,306,2,2]}'> <i data-parsoid='{\"dsr\":[286,293,2,2]}'>Foo</i> <b data-parsoid='{\"dsr\":[294,303,3,3]}'>Bar</b> </h2>\n\n<h2 id=\"Foo\" data-parsoid='{\"dsr\":[308,321,2,2]}'> <i data-parsoid='{\"dsr\":[311,318,2,2]}'>Foo</i> </h2>\n<blockquote data-parsoid='{\"stx\":\"html\",\"dsr\":[322,352,12,13]}'>\n<p data-parsoid='{\"dsr\":[335,338,0,0]}'>Bar</p>\n</blockquote>\n<p data-parsoid='{\"dsr\":[353,536,0,0]}'><span class=\"mw-editsection\" data-parsoid='{\"stx\":\"html\",\"dsr\":[353,536,29,7]}'><span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[382,427,37,7]}'>[</span>[/index.php?title=Parser_test&amp;action=edit&amp;section=2 edit]<span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[484,529,37,7]}'>]</span></span></p>\n");
add("html2html", "span tags with directionality in TOC", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,969,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,961,0,0]}'><li data-parsoid='{\"dsr\":[86,189,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#C.2B.2B\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#C.2B.2B\"},\"sa\":{\"href\":\"#C.2B.2B\"},\"dsr\":[88,189,11,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[99,131,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[132,187,22,7]}'><span dir=\"ltr\" data-parsoid='{\"stx\":\"html\",\"dsr\":[154,180,16,7]}'>C++</span></span></a></li>\n<li data-parsoid='{\"dsr\":[190,315,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#.D7.96.D7.91.D7.A0.D7.92.21\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#.D7.96.D7.91.D7.A0.D7.92.21\"},\"sa\":{\"href\":\"#.D7.96.D7.91.D7.A0.D7.92.21\"},\"dsr\":[192,315,31,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[223,255,24,7]}'>2</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[256,313,22,7]}'><span dir=\"rtl\" data-parsoid='{\"stx\":\"html\",\"dsr\":[278,306,16,7]}'>זבנג!</span></span></a></li>\n<li data-parsoid='{\"dsr\":[316,523,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\"},\"sa\":{\"href\":\"#The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\"},\"dsr\":[318,523,66,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[384,416,24,7]}'>3</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[417,521,22,7]}'><span data-parsoid='{\"stx\":\"html\",\"dsr\":[439,514,6,7]}'>The attributes on these span tags must be deleted from the TOC</span></span></a></li>\n<li data-parsoid='{\"dsr\":[524,731,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#All_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#All_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\"},\"sa\":{\"href\":\"#All_attributes_on_these_span_tags_must_be_deleted_from_the_TOC\"},\"dsr\":[526,731,66,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[592,624,24,7]}'>4</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[625,729,22,7]}'><span data-parsoid='{\"stx\":\"html\",\"dsr\":[647,722,6,7]}'>All attributes on these span tags must be deleted from the TOC</span></span></a></li>\n<li data-parsoid='{\"dsr\":[732,961,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC\"},\"sa\":{\"href\":\"#Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC\"},\"dsr\":[734,961,72,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[806,838,24,7]}'>5</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[839,959,22,7]}'><span dir=\"ltr\" data-parsoid='{\"stx\":\"html\",\"dsr\":[861,952,16,7]}'>Attributes after dir on these span tags must be deleted from the TOC</span></span></a></li></ul>\n\n</div>\n\n<h2 id=\"C.2B.2B.5B.5B.2Findex.php.3Ftitle.3DParser_test.26action.3Dedit.26section.3D1_edit.5D.5D\" data-parsoid='{\"dsr\":[971,1186,2,2]}'> <span dir=\"ltr\" data-parsoid='{\"stx\":\"html\",\"dsr\":[974,1000,16,7]}'>C++</span><span class=\"mw-editsection\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1000,1183,29,7]}'><span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1029,1074,37,7]}'>[</span>[/index.php?title=Parser_test&amp;action=edit&amp;section=1 edit]<span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1131,1176,37,7]}'>]</span></span> </h2>\n\n<h2 id=\".D7.96.D7.91.D7.A0.D7.92.21.5B.5B.2Findex.php.3Ftitle.3DParser_test.26action.3Dedit.26section.3D2_edit.5D.5D\" data-parsoid='{\"dsr\":[1188,1405,2,2]}'> <span dir=\"rtl\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1191,1219,16,7]}'>זבנג!</span><span class=\"mw-editsection\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1219,1402,29,7]}'><span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1248,1293,37,7]}'>[</span>[/index.php?title=Parser_test&amp;action=edit&amp;section=2 edit]<span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1350,1395,37,7]}'>]</span></span> </h2>\n\n<h2 id=\"The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC.5B.5B.2Findex.php.3Ftitle.3DParser_test.26action.3Dedit.26section.3D3_edit.5D.5D\" data-parsoid='{\"dsr\":[1407,1698,2,2]}'> <span style=\"font-style: italic\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1410,1512,33,7]}'>The attributes on these span tags must be deleted from the TOC</span><span class=\"mw-editsection\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1512,1695,29,7]}'><span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1541,1586,37,7]}'>[</span>[/index.php?title=Parser_test&amp;action=edit&amp;section=3 edit]<span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1643,1688,37,7]}'>]</span></span> </h2>\n\n<h2 id=\"All_attributes_on_these_span_tags_must_be_deleted_from_the_TOC.5B.5B.2Findex.php.3Ftitle.3DParser_test.26action.3Dedit.26section.3D4_edit.5D.5D\" data-parsoid='{\"dsr\":[1700,2001,2,2]}'> <span style=\"font-style: italic\" dir=\"ltr\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1703,1815,43,7]}'>All attributes on these span tags must be deleted from the TOC</span><span class=\"mw-editsection\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1815,1998,29,7]}'><span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1844,1889,37,7]}'>[</span>[/index.php?title=Parser_test&amp;action=edit&amp;section=4 edit]<span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1946,1991,37,7]}'>]</span></span> </h2>\n\n<h2 id=\"Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC.5B.5B.2Findex.php.3Ftitle.3DParser_test.26action.3Dedit.26section.3D5_edit.5D.5D\" data-parsoid='{\"dsr\":[2003,2310,2,2]}'> <span dir=\"ltr\" style=\"font-style: italic\" data-parsoid='{\"stx\":\"html\",\"dsr\":[2006,2124,43,7]}'>Attributes after dir on these span tags must be deleted from the TOC</span><span class=\"mw-editsection\" data-parsoid='{\"stx\":\"html\",\"dsr\":[2124,2307,29,7]}'><span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[2153,2198,37,7]}'>[</span>[/index.php?title=Parser_test&amp;action=edit&amp;section=5 edit]<span class=\"mw-editsection-bracket\" data-parsoid='{\"stx\":\"html\",\"dsr\":[2255,2300,37,7]}'>]</span></span> </h2>\n");
add("html2html", "T74884: bdi element in ToC", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,183,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,175,0,0]}'><li data-parsoid='{\"dsr\":[86,175,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#test\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#test\"},\"sa\":{\"href\":\"#test\"},\"dsr\":[88,175,8,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[96,128,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[129,173,22,7]}'><bdi data-parsoid='{\"stx\":\"html\",\"dsr\":[151,166,5,6]}'>test</bdi></span></a></li></ul>\n\n</div>\n\n<h2 id=\"test\" data-parsoid='{\"dsr\":[185,206,2,2]}'> <bdi data-parsoid='{\"stx\":\"html\",\"dsr\":[188,203,5,6]}'>test</bdi> </h2>\n");
add("html2html", "T35715: s/strike element in ToC", "<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[0,216,26,6]}'><div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[26,84,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[63,77,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[86,208,0,0]}'><li data-parsoid='{\"dsr\":[86,208,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#test_test_test\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#test_test_test\"},\"sa\":{\"href\":\"#test_test_test\"},\"dsr\":[88,208,18,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[106,138,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[139,206,22,7]}'><s data-parsoid='{\"stx\":\"html\",\"dsr\":[161,172,3,4]}'>test</s> test <strike data-parsoid='{\"stx\":\"html\",\"dsr\":[178,199,8,9]}'>test</strike></span></a></li></ul>\n\n</div>\n\n<h2 id=\"test_test_test\" data-parsoid='{\"dsr\":[218,262,2,2]}'> <s data-parsoid='{\"stx\":\"html\",\"dsr\":[221,232,3,4]}'>test</s> test <strike data-parsoid='{\"stx\":\"html\",\"dsr\":[238,259,8,9]}'>test</strike> </h2>\n");
add("html2html", "Empty <p> tag in TOC, removed by Sanitizer (T92892)", "\n<div id=\"toc\" class=\"toc\" data-parsoid='{\"stx\":\"html\",\"dsr\":[1,168,26,6]}'>\n<div id=\"toctitle\" class=\"toctitle\" data-parsoid='{\"stx\":\"html\",\"dsr\":[28,86,36,6]}'>\n<h2 id=\"Contents\" data-parsoid='{\"dsr\":[65,79,2,2]}'> Contents </h2>\n</div>\n\n<ul data-parsoid='{\"dsr\":[88,160,0,0]}'><li data-parsoid='{\"dsr\":[88,160,1,0]}'> <a rel=\"mw:WikiLink\" href=\"./Main_Page#x\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Main_Page#x\"},\"sa\":{\"href\":\"#x\"},\"dsr\":[90,160,5,2]}'><span class=\"tocnumber\" data-parsoid='{\"stx\":\"html\",\"dsr\":[95,127,24,7]}'>1</span> <span class=\"toctext\" data-parsoid='{\"stx\":\"html\",\"dsr\":[128,158,22,7]}'>x</span></a></li></ul>\n\n</div>\n\n<h2 id=\"x\" data-parsoid='{\"dsr\":[170,177,2,2]}'> x </h2>\n");
add("html2html", "nowiki inside link inside heading (T20295)", "<h2 id=\"xyz\" data-parsoid='{\"dsr\":[0,22,2,2]}'> <a rel=\"mw:WikiLink\" href=\"./Wiki/Foo\" title=\"Wiki/Foo\" data-parsoid='{\"stx\":\"piped\",\"a\":{\"href\":\"./Wiki/Foo\"},\"sa\":{\"href\":\"wiki/Foo\"},\"dsr\":[3,19,11,2]}'>xyz</a> </h2>\n");
add("html2html", "new support for bdi element (T33817)", "<p data-parsoid='{\"dsr\":[0,122,0,0]}'>ולדימיר לנין (ברוסית: <bdi lang=\"ru\" data-parsoid='{\"stx\":\"html\",\"dsr\":[22,57,15,6]}'>Владимир Ленин</bdi>, 24 באפריל 1870–22 בינואר 1924) הוא מנהיג פוליטי קומוניסטי רוסי.</p>\n");
add("html2html", "Empty LI and TR nodes should not be stripped from top-level content", "<ul data-parsoid='{\"dsr\":[0,9,0,0]}'><li data-parsoid='{\"dsr\":[0,3,1,0]}'> a</li>\n<li data-parsoid='{\"dsr\":[4,5,1,0]}'></li>\n<li data-parsoid='{\"dsr\":[6,9,1,0]}'> b</li></ul>\n\n<table data-parsoid='{\"dsr\":[11,24,2,2]}'>\n<tbody data-parsoid='{\"dsr\":[14,22,0,0]}'><tr data-parsoid='{\"startTagSrc\":\"|-\",\"autoInsertedEnd\":true,\"dsr\":[14,21,2,0]}'>\n<td data-parsoid='{\"autoInsertedEnd\":true,\"dsr\":[17,21,1,0]}'>foo</td></tr>\n</tbody></table>\n");
add("html2html", "Empty TR followed by a template-generated TR", "<table data-parsoid='{\"dsr\":[0,36,2,2]}'>\n<tbody about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[3,34,0,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;tr>&lt;td>foo&lt;/td>&lt;/tr>\"}},\"i\":0}},\"\\n\"]}'><tr><td>foo</td></tr>\n</tbody></table>\n");
add("html2html", "Empty TR followed by mixed-ws-comment line should RT correctly", "<table data-parsoid='{\"dsr\":[0,36,2,2]}'>\n\n <!--c--><tbody data-parsoid='{\"dsr\":[13,34,0,0]}'><tr data-parsoid='{\"startTagSrc\":\"|-\",\"autoInsertedEnd\":true,\"dsr\":[13,25,2,0]}'>\n<!--c--> </tr><!--d-->\n</tbody></table>\n");
add("html2html", "T73074: More fostering fun", "<link rel=\"mw:PageProp/Category\" href=\"./Category:Two\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Category:Two\"},\"sa\":{\"href\":\"Category:Two\"},\"dsr\":[0,16,null,null]}'/>\n<link rel=\"mw:PageProp/Category\" href=\"./Category:Two\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Category:Two\"},\"sa\":{\"href\":\"Category:Two\"},\"fostered\":true,\"dsr\":[17,17]}'/><table data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[17,70,7,0]}'><tbody data-parsoid='{\"dsr\":[24,70,0,0]}'><tr data-parsoid='{\"autoInsertedEnd\":true,\"autoInsertedStart\":true,\"dsr\":[24,33,0,0]}'><td data-parsoid='{\"stx\":\"html\",\"dsr\":[24,33,4,5]}'></td></tr><tr about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[33,70,null,0],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;tr>\"}},\"i\":0}},\"&lt;!--c-->[[Category:Two]]\"]}'><!--c--></tr></tbody></table>");
add("html2html", "Image: upright option (parsoid)", "<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"caption\",\"ak\":\"caption\"}],\"dsr\":[0,33,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[2,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,31,null,null]}'>caption</figcaption></figure>\n<figure class=\"mw-default-size\" typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"caption\",\"ak\":\"caption\"}],\"dsr\":[34,67,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[36,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"25\" width=\"220\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"25\",\"width\":\"220\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,65,null,null]}'>caption</figcaption></figure>\n<figure typeof=\"mw:Image/Thumb\" data-parsoid='{\"optList\":[{\"ck\":\"thumbnail\",\"ak\":\"thumb\"},{\"ck\":\"width\",\"ak\":\"500x500px\"},{\"ck\":\"caption\",\"ak\":\"caption\"}],\"dsr\":[68,111,2,2]}'><a href=\"./File:Foobar.jpg\" data-parsoid='{\"a\":{\"href\":\"./File:Foobar.jpg\"},\"sa\":{\"href\":\"File:Foobar.jpg\"},\"dsr\":[70,null,null,null]}'><img resource=\"./File:Foobar.jpg\" src=\"//example.com/images/thumb/3/3a/Foobar.jpg/500px-Foobar.jpg\" data-file-width=\"1941\" data-file-height=\"220\" data-file-type=\"bitmap\" height=\"57\" width=\"500\" data-parsoid='{\"a\":{\"resource\":\"./File:Foobar.jpg\",\"height\":\"57\",\"width\":\"500\"},\"sa\":{\"resource\":\"File:Foobar.jpg\"}}'/></a><figcaption data-parsoid='{\"dsr\":[null,109,null,null]}'>caption</figcaption></figure>\n");
add("html2html", "Consecutive <pre>s should not get merged", "<pre data-parsoid='{\"dsr\":[0,2,1,0]}'>a</pre>\n\n<pre data-parsoid='{\"dsr\":[4,6,1,0]}'>b</pre>\n\n<pre data-parsoid='{\"dsr\":[8,10,1,0]}'>c</pre>\n\n<pre data-parsoid='{\"dsr\":[12,14,1,0]}'>d</pre>\n\n<pre data-parsoid='{\"dsr\":[16,19,1,0]}'>e</pre>\n\n\n <p data-parsoid='{\"dsr\":[23,23,0,0]}'><br data-parsoid='{\"dsr\":[23,23,0,0]}'/></p>\n<pre data-parsoid='{\"dsr\":[24,26,1,0]}'>f</pre>\n");
// Blacklist for html2wt
add("html2wt", "Paragraphs with newline spacing with comment lines in between", "----\na\nb\n\n----\na\nb\n\n---