Subramanya Sastry has uploaded a new change for review.
https://gerrit.wikimedia.org/r/72858
Change subject: (Bug 50841): First pass reducing scope of nowiki tags
......................................................................
(Bug 50841): First pass reducing scope of nowiki tags
* This still feels a little crude, but does the job for now.
* One failing html2html test is because of a quirk of how we
normalize newlines while comparing output.
Additional tests:
------------
[subbu@earth lib] echo "[[foo]] [[bar]] [[baz]] [[foobar]] [[moobar]]" | node
parse --html2wt
<nowiki>[[foo]] [[bar]] [[baz]]</nowiki> <nowiki>[[foobar]] [[moobar]]</nowiki>
------------
[subbu@earth lib] echo "Links in wikitext are written like this: [[foo]] How
magical\!\!" | node parse --html2wt
Links in wikitext are written like this: <nowiki>[[foo]]</nowiki> How magical!!
------------
[subbu@earth lib] echo 'Hello my [[name]]*(see below) is Julian and I live in
the city of Rochester, New York\nwith my friend Sandy; we write [[books]].' |
node parse --html2wt
Hello my <nowiki>[[name]]</nowiki>*(see below) is Julian and I live in the city
of Rochester, New York with my friend Sandy; we write
<nowiki>[[books]]</nowiki>.
------------
[subbu@earth lib] echo 'Hello my [[name]]*(see below) is Julian and I live in
the city of Rochester, New York to \n* escape with my friend Sandy; we write
[[books]].' | node parse --html2wt
Hello my <nowiki>[[name]]</nowiki><nowiki>*(see below) is Julian and I live in
the city of Rochester, New York to
* escape with my friend Sandy; we write </nowiki> <nowiki>[[books]].</nowiki>
------------
Change-Id: Iac2cf7470bb566372fd856250fbbeef2e37e4156
---
M js/lib/mediawiki.WikitextSerializer.js
M js/tests/parserTests-blacklist.js
2 files changed, 87 insertions(+), 11 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Parsoid
refs/changes/58/72858/1
diff --git a/js/lib/mediawiki.WikitextSerializer.js
b/js/lib/mediawiki.WikitextSerializer.js
index 4a56fde..74ee942 100644
--- a/js/lib/mediawiki.WikitextSerializer.js
+++ b/js/lib/mediawiki.WikitextSerializer.js
@@ -539,9 +539,84 @@
// Make sure the initialState is never modified
Util.deepFreeze( WSP.initialState );
-function escapedText(text) {
- var match =
text.match(/^((?:.*?|[\r\n]+[^\r\n]|[~]{3,5})*?)((?:\r?\n)*)$/);
- return ["<nowiki>", match[1], "</nowiki>", match[2]].join('');
+function escapedText(text, fullWrap) {
+ // Full-wrapping is enabled in the following cases:
+ // * text is a "small" string
+ // * text has url triggers (RFC, ISBN, etc.)
+ // * is being escaped within context-specific handlers
+
+ var match =
text.match(/^((?:.*?|[\r\n]+[^\r\n]|[~]{3,5})*?)((?:\r?\n)*)$/),
+ text = match[1],
+ nls = match[2],
+ maxRun = 20;
+
+ if (fullWrap || text.length < maxRun) {
+ return ["<nowiki>", text, "</nowiki>", nls].join('');
+ } else {
+ // For now, only optimize "[[..]]", "{{..}}", "{{{..}}}"
scenarios
+ // Splitting on white-space, "=", ' chars can split html tags
+ // in the middle and create ugly nowiki escaping output.
+ var pieces = text.split(/(\[\[|\]\]|\{\{\{|\{\{|\}\}\}|\}\})/g),
+ n = pieces.length,
+ buf = n === 1 ? ["<nowiki>", text, "</nowiki>"] : [];
+
+ if (n > 1) {
+ var openTag = null,
+ openNowiki = false,
+ currentRun = 0,
+ closingWtTagMap = { "[[" : "]]", "{{" : "}}",
"{{{": "}}}" };
+
+ for (var i = 0; i < n; i++) {
+ var p = pieces[i];
+ if (!openTag) {
+ if (p in closingWtTagMap) {
+ openTag = p;
+ if (!openNowiki) {
+ buf.push("<nowiki>");
+ openNowiki = true;
+ }
+ } else if (!openNowiki &&
+ (
+ // [..], <..>, '', ~~~~
+
p.match(/\[[^\[\]]\]|<[^<>]*>|''|~{3,5}/) ||
+ // If in SOL (previous
piece ended in a \n), or after a \n,
+ // \s+ (indent-pre), =
(headings), *#;: (lists), {| |}, |, ||, |-, |+, ! (tables)
+ p.match(/\n([
\t]+[^\s]+|[=:;#\*]|\s*(\{\||\|\}|\|[\|\-\+]?|!))/) ||
+ ((i === 0 ||
pieces[i-1].match(/\n$/)) && p.match(/^([
\t]+[^\s]+|=:;#\*|\s*(\{\||\|\}|\|[\|\-\+]?|!))/))
+ ))
+ {
+ buf.push("<nowiki>");
+ openNowiki = true;
+ }
+ } else {
+ if (p === closingWtTagMap[openTag]) {
+ openTag = null;
+ }
+ }
+
+ buf.push(p);
+
+ // If:
+ // - we are in the middle of an open <nowiki>,
+ // - we are not in the middle of an open tag,
+ // - and will except max-run length on the next
piece
+ // close the current nowiki.
+ currentRun += p.length;
+ if (!openTag && openNowiki && (i < n-1 &&
pieces[i+1].length + currentRun >= maxRun)) {
+ buf.push("</nowiki>");
+ openNowiki = false;
+ currentRun = 0;
+ }
+ }
+
+ if (openNowiki) {
+ buf.push("</nowiki>");
+ }
+ }
+
+ buf.push(nls);
+ return buf.join('');
+ }
}
WSP.tokenizeStr = function(state, str, sol) {
@@ -587,7 +662,7 @@
var wteHandler = state.wteHandlerStack.last();
if (wteHandler && wteHandler(state, text, opts)) {
// console.warn("---EWT:F2---");
- return escapedText(text);
+ return escapedText(text, true);
}
// Template and template-arg markers are escaped unconditionally!
@@ -595,7 +670,7 @@
// of whether we are in template arg context or not.
if (text.match(/\{\{\{|\{\{|\}\}\}|\}\}/)) {
// console.warn("---EWT:F3---");
- return escapedText(text);
+ return escapedText(text, fullCheckNeeded);
}
// Escape quotes that come after I/B nodes that can be reparsed
@@ -604,7 +679,7 @@
var prev = opts.node && opts.node.previousSibling ?
opts.node.previousSibling.nodeName : '';
if (prev === 'I' || prev === 'B') {
// console.warn("---EWT:F3b---");
- return escapedText(text);
+ return escapedText(text, true);
}
}
@@ -639,7 +714,7 @@
// So, we always conservatively escape text with ' ' in sol posn.
if (sol && text.match(/(^|\n)[ \t]+[^\s]+/)) {
// console.warn("---EWT:F6---");
- return escapedText(text);
+ return escapedText(text, fullCheckNeeded);
}
// escape nowiki tags
@@ -652,11 +727,11 @@
// hasWikitextTokens check
if (this.wteHandlers.hasWikitextTokens(state, sol, text) || hasTildes) {
// console.warn("---EWT:DBG1---");
- return escapedText(text);
+ return escapedText(text, fullCheckNeeded);
} else if (state.onSOL) {
if (text.match(/(^|\n)=+[^\n=]+=+[ \t]*\n/)) {
// console.warn("---EWT:DBG2a---");
- return escapedText(text);
+ return escapedText(text, fullCheckNeeded);
} else if (text.match(/(^|\n)=+[^\n=]+=+[ \t]*$/)) {
/*
---------------------------------------------------------------
* '$' is only specific to 'text' and not the entire
line.
@@ -687,7 +762,7 @@
DU.isText(nonSepSibling) &&
nonSepSibling.nodeValue.match(/^\s*\n/))
{
// console.warn("---EWT:DBG2b---");
- return escapedText(text);
+ return escapedText(text, fullCheckNeeded);
} else {
// console.warn("---EWT:DBG2c---");
return text;
@@ -742,7 +817,7 @@
this.wteHandlers.hasWikitextTokens(state, sol,
cl.text + text, true))
{
// console.warn("---EWT:DBG4---");
- return escapedText(text);
+ return escapedText(text, fullCheckNeeded);
} else {
// console.warn("---EWT:DBG5---");
return text;
diff --git a/js/tests/parserTests-blacklist.js
b/js/tests/parserTests-blacklist.js
index 8d05fe7..6be02af 100644
--- a/js/tests/parserTests-blacklist.js
+++ b/js/tests/parserTests-blacklist.js
@@ -848,6 +848,7 @@
add("html2html", "Template as link source");
add("html2html", "Template infinite loop");
add("html2html", "Template with targets containing wikilinks");
+add("html2html", "msgnw keyword");
add("html2html", "Self-closed noinclude, includeonly, onlyinclude tags");
add("html2html", "Bug 6563: Edit link generation for section shown by
<includeonly>");
add("html2html", "Bug 6563: Section extraction for section shown by
<includeonly>");
--
To view, visit https://gerrit.wikimedia.org/r/72858
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iac2cf7470bb566372fd856250fbbeef2e37e4156
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Parsoid
Gerrit-Branch: master
Gerrit-Owner: Subramanya Sastry <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits