jenkins-bot has submitted this change and it was merged.

Change subject: Bug 46027, bug 49484: Drop mw:ExtLink/URL
......................................................................


Bug 46027, bug 49484: Drop mw:ExtLink/URL

* Changes to the content of URL links in VE were not properly handled, as the
  VE never changed the type to mw:ExtLink on such change.

* Instead of requiring clients to implement such a type change, abstract
  syntactical detail about URL link vs. bracketed external link in Parsoid.
  Automatically switch between formats as required, but preserve non-minimal
  links of the form [http://example.com http://example.com].

* Serializer support for mw:ExtLink/URL remains, so cached HTML will continue
  to work for now. This can be dropped after cache clearing.

* The VE handles mw:ExtLink content well, and will also do so for links that
  were formerly marked as mw:ExtLink/URL. Once cached HTML is cleared the VE
  can also drop mw:ExtLink/URL handling.

Change-Id: Ibb4c27b799016c7a41efb23c03978794c1d2f012
---
M js/lib/ext.core.LinkHandler.js
M js/lib/mediawiki.DOMPostProcessor.js
M js/lib/mediawiki.Util.js
M js/lib/mediawiki.WikitextSerializer.js
M js/lib/pegTokenizer.pegjs.txt
5 files changed, 55 insertions(+), 30 deletions(-)

Approvals:
  Subramanya Sastry: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/js/lib/ext.core.LinkHandler.js b/js/lib/ext.core.LinkHandler.js
index 86dff08..71db862 100644
--- a/js/lib/ext.core.LinkHandler.js
+++ b/js/lib/ext.core.LinkHandler.js
@@ -789,7 +789,8 @@
                                                // Reset the optInfo since 
we're changing the nature of it
                                                optInfo = undefined;
                                                // Figure out the proper string 
to put here and break.
-                                               if ( tokenType === 
'mw:ExtLink/URL' ) {
+                                               if ( tokenType === 'mw:ExtLink' 
&&
+                                                               
currentToken.dataAttribs.stx === 'url' ) {
                                                        // Add the URL
                                                        resultStr += tkHref;
                                                        // Tell our loop to 
skip to the end of this tag
@@ -1261,13 +1262,14 @@
                cb( { tokens: [ new SelfclosingTagTk('img', tagAttrs, 
dataAttribs) ] } );
        } else {
                tagAttrs = [
-                       new KV( 'rel', 'mw:ExtLink/URL' )
+                       new KV( 'rel', 'mw:ExtLink' )
                        // href is set explicitly below
                ];
 
                // combine with existing rdfa attrs
                tagAttrs = buildLinkAttrs(token.attribs, false, null, 
tagAttrs).attribs;
                builtTag = new TagTk( 'a', tagAttrs, dataAttribs );
+               dataAttribs.stx = 'url';
 
                if (origTxt) {
                        // origTxt will be null for content from templates
@@ -1283,7 +1285,7 @@
                        tokens: [
                                builtTag,
                                txt,
-                               new EndTagTk( 'a' )
+                               new EndTagTk( 'a', [], {tsr: 
[dataAttribs.tsr[1], dataAttribs.tsr[1]]} )
                        ]
                } );
        }
diff --git a/js/lib/mediawiki.DOMPostProcessor.js 
b/js/lib/mediawiki.DOMPostProcessor.js
index dd534f3..1a66490 100644
--- a/js/lib/mediawiki.DOMPostProcessor.js
+++ b/js/lib/mediawiki.DOMPostProcessor.js
@@ -1995,7 +1995,7 @@
                                } else {
                                        return [2, 2];
                                }
-                       } else if (aType === "mw:ExtLink" && dp.tsr) {
+                       } else if (aType === "mw:ExtLink" && dp.tsr && dp.stx 
!== 'url') {
                                return [dp.targetOff - dp.tsr[0], 1];
                        } else {
                                return null;
diff --git a/js/lib/mediawiki.Util.js b/js/lib/mediawiki.Util.js
index 8c22ce6..0e4fe18 100644
--- a/js/lib/mediawiki.Util.js
+++ b/js/lib/mediawiki.Util.js
@@ -1539,6 +1539,20 @@
                html_old_names[name] === true;
 };
 
+/**
+ * Determine whether the protocol of a link is potentially valid. Use the
+ * environment's per-wiki config to do so.
+ */
+Util.isProtocolValid = function ( linkTarget, env ) {
+       var wikiConf = env.conf.wiki;
+       if ( typeof linkTarget === 'string' ) {
+               return wikiConf.hasValidProtocol( linkTarget );
+       } else {
+               return true;
+       }
+};
+
+
 if (typeof module === "object") {
        module.exports.Util = Util;
 }
diff --git a/js/lib/mediawiki.WikitextSerializer.js 
b/js/lib/mediawiki.WikitextSerializer.js
index 168fb18..1d3c760 100644
--- a/js/lib/mediawiki.WikitextSerializer.js
+++ b/js/lib/mediawiki.WikitextSerializer.js
@@ -809,7 +809,7 @@
                                        console.warn("Toks: " + 
JSON.stringify(tokens));
                                }
                                var tkSrc = arg.substring(da.tsr[0], da.tsr[1]);
-                               // Replace pipe by an entity
+                               // Replace pipe by an entity. This is not 
completely safe.
                                if (t.name === 'extlink' || t.name === 
'urllink') {
                                        tkSrc = tkSrc.replace(/\|/g, '|');
                                }
@@ -1643,7 +1643,7 @@
                                        // Protect empty link content from PST 
pipe trick
                                        contentSrc = '<nowiki/>';
                                }
-                               linkTarget = linkData.target.value;
+                               linkTarget = target.value;
                                linkTarget = this._addColonEscape(linkTarget, 
linkData);
 
                                cb( escapes.prefix + linkData.prefix +
@@ -1652,20 +1652,37 @@
                                return;
                        }
                } else if ( rel === 'mw:ExtLink' ) {
-                       // We expect modified hrefs to be percent-encoded 
already, so
-                       // don't need to encode them here any more. Unmodified 
hrefs are
-                       // just using the original encoding anyway.
-                       cb( '[' + target.value + ' ' +
-                               state.serializeChildrenToString(node, 
this.wteHandlers.aHandler, false) +
-                               ']', node );
+                       // Get plain text content, if any
+                       var contentStr = node.childNodes.length === 1 &&
+                                                               
node.firstChild.nodeType === node.TEXT_NODE &&
+                                                               
node.firstChild.nodeValue;
+                       if ( contentStr &&
+                                       // Can we minimize this?
+                                       ( target.value === contentStr  ||
+                                       node.getAttribute('href') === 
contentStr) &&
+                                       // But preserve non-minimal encoding
+                                       (target.modified || 
linkData.contentModified || dp.stx === 'url'))
+                       {
+                               // Serialize as URL link
+                               cb(target.value, node);
+                       } else {
+                               // Fully serialize the content
+                               contentStr = 
state.serializeChildrenToString(node,
+                                               this.wteHandlers.aHandler, 
false);
+
+                               // We expect modified hrefs to be 
percent-encoded already, so
+                               // don't need to encode them here any more. 
Unmodified hrefs are
+                               // just using the original encoding anyway.
+                               cb( '[' + target.value + ' ' + contentStr + 
']', node );
+                       }
+               } else if ( rel === 'mw:ExtLink/URL' ) {
+                       cb( target.value, node );
                } else if ( rel.match( /mw:ExtLink\/(?:ISBN|RFC|PMID)/ ) ) {
                        cb( node.firstChild.nodeValue, node );
-               } else if ( rel === 'mw:ExtLink/URL' ) {
-                       cb( linkData.target.value, node );
                } else if ( rel === 'mw:ExtLink/Numbered' ) {
                        // XXX: Use shadowed href? Storing serialized tokens in
                        // data-parsoid seems to be... wrong.
-                       cb( '[' + Util.tokensToString(linkData.target.value) + 
']', node);
+                       cb( '[' + Util.tokensToString(target.value) + ']', 
node);
                } else if ( rel.match( /\bmw:Image/ ) ) {
                        this.handleImage( node, state, cb );
                } else {
diff --git a/js/lib/pegTokenizer.pegjs.txt b/js/lib/pegTokenizer.pegjs.txt
index 105087f..7a1f6c3 100644
--- a/js/lib/pegTokenizer.pegjs.txt
+++ b/js/lib/pegTokenizer.pegjs.txt
@@ -162,19 +162,6 @@
         return false;
     };
 
-    /**
-     * Determine whether the protocol of a link is potentially valid. Use the 
environment's per-wiki config to do so.
-     */
-    function isProtocolValid( linkTarget ) {
-        var env = pegArgs.env,
-            wikiConf = env.conf.wiki;
-
-        if ( typeof linkTarget === 'string' ) {
-            return wikiConf.hasValidProtocol( linkTarget );
-        } else {
-            return true;
-        }
-    }
 
     /**
     * Get an attribute value and source, given a start and end position.  
Returned object will have a 'value' property
@@ -806,7 +793,7 @@
         & { return stops.push('extlink', true); }
         //target:urllink
         target:extlink_preprocessor_text
-        & { return isProtocolValid( target ); }
+        & { return Util.isProtocolValid( target, pegArgs.env ); }
         sp:( space / [\u00A0\u1680\u180E\u2000-\u200A\u202F\u205F\u3000] )*
         targetOff:({ return pos; })
         content:(
@@ -895,7 +882,12 @@
 /* Default URL protocols in MediaWiki (see DefaultSettings). Normally
  * these can be configured dynamically. */
 
-url_protocol = & { return isProtocolValid( input.substr( pos ) ); } 
h:[a-zA-Z\/]+ c:':'? s:'//'? { return h.join( '' ) + c + s; }
+url_protocol = 
+    & { return Util.isProtocolValid( input.substr( pos ), pegArgs.env ); } 
+    h:[a-zA-Z\/]+ c:':'? s:'//'? 
+{ 
+    return h.join( '' ) + c + s; 
+}
 
 // javascript does not support unicode features..
 unicode_separator_space = [ \u00A0\u1680\u180E\u2000-\u200A\u202F\u205F\u3000]

-- 
To view, visit https://gerrit.wikimedia.org/r/71162
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ibb4c27b799016c7a41efb23c03978794c1d2f012
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/Parsoid
Gerrit-Branch: master
Gerrit-Owner: GWicke <[email protected]>
Gerrit-Reviewer: Subramanya Sastry <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to