jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/403977 )

Change subject: Flatten DOM anchors if no attributes kept
......................................................................


Flatten DOM anchors if no attributes kept

The flattenElements method previously did not really flatten in a DOM
sense because it changed the <a> tags to another element (<span>).
This patch proposes to really flatten the <a> tags to plain text,
but only if there is no (class) attribute to be retained.

Bug: T177007
Change-Id: Ib2e63e665d62e8a80215c456c7832a8e965caad1
---
M lib/transformations/flattenElements.js
A test/lib/transformations/flattenElements.test.js
M test/lib/transformations/summarize.js
3 files changed, 62 insertions(+), 19 deletions(-)

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



diff --git a/lib/transformations/flattenElements.js 
b/lib/transformations/flattenElements.js
index 42f9ea9..f3d917f 100644
--- a/lib/transformations/flattenElements.js
+++ b/lib/transformations/flattenElements.js
@@ -1,21 +1,45 @@
 'use strict';
 
+const KEEP_ATTRIBUTE = 'class';
+
 /**
- * Replace all elements in Document `content` that match the
- * css selector, replacing them with span tags.
- * @param {!Document} content
+ * Copies only select attributes from one DOM element to another.
+ * @param {!Element} oldElement the element to copy attributes from
+ * @param {!Element} newElement the element to copy attributes to
+ * @param {!String} name the name of the attribute
+ */
+function copyAttribute(oldElement, newElement, name) {
+    if (oldElement.getAttribute(name)) {
+        newElement.setAttribute(name, oldElement.getAttribute(name));
+    }
+}
+
+function createReplacementNode(oldElement, document) {
+    if (oldElement.getAttribute(KEEP_ATTRIBUTE)) {
+        const spanElement = document.createElement('span');
+        spanElement.innerHTML = oldElement.innerHTML;
+        copyAttribute(oldElement, spanElement, KEEP_ATTRIBUTE);
+        return spanElement;
+    } else {
+        return document.createTextNode(oldElement.innerHTML);
+    }
+}
+
+/**
+ * Replaces all elements in the given Document which match the
+ * CSS selector, replacing them with span tags or text.
+ * If the resulting span tag doesn't have any attributes then
+ * the element is replaced with a TextNode of the same content.
+ * The main purpose of this is to disable certain <a> tags.
+ * @param {!Document} document
  * @param {string} selector
  */
-function flattenElements(content, selector) {
-    const elements = content.querySelectorAll(selector);
+function flattenElements(document, selector) {
+    const elements = document.querySelectorAll(selector);
     for (let i = 0; i < elements.length; i++) {
-        const element = elements[i];
-        const replacementSpan = content.createElement('span');
-        replacementSpan.innerHTML = element.innerHTML;
-        if (element.getAttribute('class')) {
-            replacementSpan.setAttribute('class', 
element.getAttribute('class'));
-        }
-        element.parentNode.replaceChild(replacementSpan, element);
+        const oldElement = elements[i];
+        const newNode = createReplacementNode(oldElement, document);
+        oldElement.parentNode.replaceChild(newNode, oldElement);
     }
 }
 
diff --git a/test/lib/transformations/flattenElements.test.js 
b/test/lib/transformations/flattenElements.test.js
new file mode 100644
index 0000000..4bd1726
--- /dev/null
+++ b/test/lib/transformations/flattenElements.test.js
@@ -0,0 +1,19 @@
+"use strict";
+
+const domino = require('domino');
+const assert = require('./../../utils/assert.js');
+const flattenElements = 
require('./../../../lib/transformations/flattenElements');
+
+describe('lib:flattenElements', () => {
+    it('replaces a with span, keeps class attribute', () => {
+        const document = domino.createDocument('<a class="bar" 
href="#">foo</a>');
+        flattenElements(document, 'a');
+        assert.deepEqual(document.body.innerHTML, '<span 
class="bar">foo</span>');
+    });
+
+    it('replaces a tag with plain text if no attributes to keep', () => {
+        const document = domino.createDocument('<a href="#">foo</a>');
+        flattenElements(document, 'a');
+        assert.deepEqual(document.body.innerHTML, 'foo');
+    });
+});
diff --git a/test/lib/transformations/summarize.js 
b/test/lib/transformations/summarize.js
index fe90123..ec25458 100644
--- a/test/lib/transformations/summarize.js
+++ b/test/lib/transformations/summarize.js
@@ -36,7 +36,7 @@
             // Should flatten links
             [
                 'This is some content with <a href="#"">a link</a>.',
-                'This is some content with <span>a link</span>.'
+                'This is some content with a link.'
             ],
             // Should strip .noexcerpt
             [
@@ -125,22 +125,22 @@
             // Content inside Cantonese parentheticals are also stripped
             [
                 '<p><b>蔡英文</b>(<b>Tsai 
Ing-wen</b>,<a>1956年</a><a>8月31號</a>—)係現任<a>中華民國總統</a>,<a>臺灣</a>學者同埋<a>政治</a>人,<a>民主進步黨</a><a>主席</a>。</p>',
-                '<p><b>蔡英文</b> 
係現任<span>中華民國總統</span>,<span>臺灣</span>學者同埋<span>政治</span>人,<span>民主進步黨</span><span>主席</span>。</p>'
+                '<p><b>蔡英文</b> 係現任中華民國總統,臺灣學者同埋政治人,民主進步黨主席。</p>'
             ],
             // Content inside parentheticals written in `wuu` language variant 
are also stripped
             [
                 '<p><b>东亚</b>(日文:東アジア ‧ 東亜,韩文:東아시아,西文:Asia 
Oriental)是一个比较笼统个地理概念,立在弗同个语境当中有弗一样个含义。东亚个概念来自<a>欧洲</a>人对东方个定位,拿<a>博斯普鲁斯海峡</a>、<a
 class="new">乌拉尔山脉</a>东面个广大欧亚大陆地区侪通称亚洲,拿西太平洋沿岸、欧亚大陆东端个地区就叫做<a 
class="mw-selflink selflink">东亚</a>。</p>',
-                '<p><b>东亚</b> 
是一个比较笼统个地理概念,立在弗同个语境当中有弗一样个含义。东亚个概念来自<span>欧洲</span>人对东方个定位,拿<span>博斯普鲁斯海峡</span>、<span
 class="new">乌拉尔山脉</span>东面个广大欧亚大陆地区侪通称亚洲,拿西太平洋沿岸、欧亚大陆东端个地区就叫做<span 
class="mw-selflink selflink">东亚</span>。</p>'
+                '<p><b>东亚</b> 
是一个比较笼统个地理概念,立在弗同个语境当中有弗一样个含义。东亚个概念来自欧洲人对东方个定位,拿博斯普鲁斯海峡、<span 
class="new">乌拉尔山脉</span>东面个广大欧亚大陆地区侪通称亚洲,拿西太平洋沿岸、欧亚大陆东端个地区就叫做<span 
class="mw-selflink selflink">东亚</span>。</p>'
             ],
             // Content inside parentheticals written in `gan` language variant 
are also stripped
             [
                 
'<p><b>亞細亞洲</b>(古希臘文:Ασία),又簡稱<b>亞洲</b>,絕大部分都位到北半球,係全世界上最大,最多人嗰一隻<a 
class="mw-redirect">洲</a>。佢東頭一徑到白令海峽嗰傑日尼奧夫角(西經169度40分,北緯60度5分),南頭一徑到努沙登加拉群島(東經103度30分,南緯11度7分),西頭一徑到巴巴角(東經26度3分,北緯39度27分),北頭一徑到切柳斯金角(東經104度18分,北緯77度43分),最高嗰山係<a>珠穆朗瑪峰</a>。亞洲東西嗰時差係11小時。佢西首連到<a>歐洲</a>,箇就係世界上最大嗰大陸-<a
 class="new">歐亞大陸</a>。</p>',
-                '<p><b>亞細亞洲</b>,又簡稱<b>亞洲</b>,絕大部分都位到北半球,係全世界上最大,最多人嗰一隻<span 
class="mw-redirect">洲</span>。佢東頭一徑到白令海峽嗰傑日尼奧夫角,南頭一徑到努沙登加拉群島,西頭一徑到巴巴角,北頭一徑到切柳斯金角,最高嗰山係<span>珠穆朗瑪峰</span>。亞洲東西嗰時差係11小時。佢西首連到<span>歐洲</span>,箇就係世界上最大嗰大陸-<span
 class="new">歐亞大陸</span>。</p>'
+                '<p><b>亞細亞洲</b>,又簡稱<b>亞洲</b>,絕大部分都位到北半球,係全世界上最大,最多人嗰一隻<span 
class="mw-redirect">洲</span>。佢東頭一徑到白令海峽嗰傑日尼奧夫角,南頭一徑到努沙登加拉群島,西頭一徑到巴巴角,北頭一徑到切柳斯金角,最高嗰山係珠穆朗瑪峰。亞洲東西嗰時差係11小時。佢西首連到歐洲,箇就係世界上最大嗰大陸-<span
 class="new">歐亞大陸</span>。</p>'
             ],
             // Content inside parentheticals is not stripped if it doesn't 
include any spaces
             [
                 '<p>Der <b>Deutsche Orden</b>, auch <b>Deutschherrenorden</b> 
oder <b>Deutschritterorden</b> genannt, ist eine römisch-katholische 
<a>Ordensgemeinschaft</a>. Mit dem <a>Johanniter-</a> und dem 
<a>Malteserorden</a> steht er in der (Rechts-)Nachfolge der <a>Ritterorden</a> 
aus der Zeit der <a>Kreuzzüge</a>. Die Mitglieder des Ordens sind seit der 
Reform der Ordensregel 1929 <a>regulierte Chorherren</a>. Der Orden hat 
gegenwärtig 1100 Mitglieder, darunter 100 <a>Priester</a> und 200 
Ordensschwestern, die sich vorwiegend karitativen Aufgaben widmen. Der 
Hauptsitz befindet sich heute in <a>Wien</a>.</p>',
-                '<p>Der <b>Deutsche Orden</b>, auch <b>Deutschherrenorden</b> 
oder <b>Deutschritterorden</b> genannt, ist eine römisch-katholische 
<span>Ordensgemeinschaft</span>. Mit dem <span>Johanniter-</span> und dem 
<span>Malteserorden</span> steht er in der (Rechts-)Nachfolge der 
<span>Ritterorden</span> aus der Zeit der <span>Kreuzzüge</span>. Die 
Mitglieder des Ordens sind seit der Reform der Ordensregel 1929 
<span>regulierte Chorherren</span>. Der Orden hat gegenwärtig 1100 Mitglieder, 
darunter 100 <span>Priester</span> und 200 Ordensschwestern, die sich 
vorwiegend karitativen Aufgaben widmen. Der Hauptsitz befindet sich heute in 
<span>Wien</span>.</p>'
+                '<p>Der <b>Deutsche Orden</b>, auch <b>Deutschherrenorden</b> 
oder <b>Deutschritterorden</b> genannt, ist eine römisch-katholische 
Ordensgemeinschaft. Mit dem Johanniter- und dem Malteserorden steht er in der 
(Rechts-)Nachfolge der Ritterorden aus der Zeit der Kreuzzüge. Die Mitglieder 
des Ordens sind seit der Reform der Ordensregel 1929 regulierte Chorherren. Der 
Orden hat gegenwärtig 1100 Mitglieder, darunter 100 Priester und 200 
Ordensschwestern, die sich vorwiegend karitativen Aufgaben widmen. Der 
Hauptsitz befindet sich heute in Wien.</p>'
             ],
             // Content inside parentheticals with single word and leading 
space is not stripped
             [
@@ -160,12 +160,12 @@
             // Full stops do not impact the summary length (T173640)
             [
                 '<p><a href="./Armádní_generál" title="Armádní generál">Arm. 
gen.</a> <a href="./Inženýr" title="Inženýr">Ing.</a> <b>Petr Pavel</b>, <span 
class="new">M.A.</span>, (*<span>&nbsp;</span><a href="./1._listopad" title="1. 
listopad">1.<span>&nbsp;</span>listopadu</a> <a href="./1961" 
title="1961">1961</a> <a href="./Planá" title="Planá">Planá</a>) je <a 
href="./Česko" title="Česko">český</a> <a href="./Voják" 
title="Voják">voják</a>, <a href="./Generál" title="Generál">generál</a> <a 
href="./Armáda_České_republiky" title="Armáda České republiky">Armády České 
republiky</a> a<span>&nbsp;</span>od června 2015 <a 
href="./Předseda_vojenského_výboru_NATO" title="Předseda vojenského výboru 
NATO">předseda vojenského výboru NATO</a>. Jako první zástupce zemí bývalé <a 
href="./Varšavská_smlouva" title="Varšavská smlouva">Varšavské smlouvy</a> tak 
nastoupil do nejvyšší vojenské funkce <a href="./Severoatlantická_aliance" 
title="Severoatlantická aliance">Severoatlantické aliance</a>.<span 
class="mw-ref" id="cite_ref-nastup_NATO_1-0"><a 
href="./Petr_Pavel#cite_note-nastup_NATO-1" style="counter-reset: mw-Ref 
1;"><span class="mw-reflink-text">[1]</span></a></span><span class="mw-ref" 
id="cite_ref-ihned_2-0"><a href="./Petr_Pavel#cite_note-ihned-2" 
style="counter-reset: mw-Ref 2;"><span 
class="mw-reflink-text">[2]</span></a></span></p>',
-                '<p><span>Arm. gen.</span> <span>Ing.</span> <b>Petr 
Pavel</b>, <span class="new">M.A.</span>, je <span>český</span> 
<span>voják</span>, <span>generál</span> <span>Armády České republiky</span> 
a<span>&nbsp;</span>od června 2015 <span>předseda vojenského výboru 
NATO</span>. Jako první zástupce zemí bývalé <span>Varšavské smlouvy</span> tak 
nastoupil do nejvyšší vojenské funkce <span>Severoatlantické 
aliance</span>.</p>'
+                '<p>Arm. gen. Ing. <b>Petr Pavel</b>, <span 
class="new">M.A.</span>, je český voják, generál Armády České republiky 
a<span>&nbsp;</span>od června 2015 předseda vojenského výboru NATO. Jako první 
zástupce zemí bývalé Varšavské smlouvy tak nastoupil do nejvyšší vojenské 
funkce Severoatlantické aliance.</p>'
             ],
             // Bold tags are retained
             [
                 '<p><b>Vladimír Dlouhý</b> (*<span>&nbsp;</span><a 
href="./31._červenec" title="31. červenec">31. července</a> <a href="./1953" 
title="1953">1953</a> <a href="./Praha" title="Praha">Praha</a>) je <a 
href="./Češi" title="Češi">český</a> <a href="./Ekonom" 
title="Ekonom">ekonom</a> a <a href="./Politik" title="Politik">politik</a>, 
bývalý místopředseda strany <a href="./Občanská_demokratická_aliance" 
title="Občanská demokratická aliance">ODA</a> a ministr průmyslu a obchodu v 
letech <a href="./1992" title="1992">1992</a>–<a href="./1997" 
title="1997">1997</a> ve <a href="./První_vláda_Václava_Klause" title="První 
vláda Václava Klause">vládě Václava Klause</a>. V<span>&nbsp;</span>letech <a 
href="./1989" title="1989">1989</a>–<a href="./1992" title="1992">1992</a> byl 
ministrem hospodářství <a href="./Česká_a_Slovenská_Federativní_Republika" 
title="Česká a Slovenská Federativní Republika">ČSFR</a>. Nyní působí 
v&nbsp;soukromé sféře a věnuje se poradenské a pedagogické činnosti, v <a 
href="./Květen" title="Květen">květnu</a> <a href="./2014" 
title="2014">2014</a> byl zvolen prezidentem <a 
href="./Hospodářská_komora_České_republiky" title="Hospodářská komora České 
republiky">Hospodářské komory ČR</a>.</p>',
-                '<p><b>Vladimír Dlouhý</b> je <span>český</span> 
<span>ekonom</span> a <span>politik</span>, bývalý místopředseda strany 
<span>ODA</span> a ministr průmyslu a obchodu v letech 
<span>1992</span>–<span>1997</span> ve <span>vládě Václava Klause</span>. 
V<span>&nbsp;</span>letech <span>1989</span>–<span>1992</span> byl ministrem 
hospodářství <span>ČSFR</span>. Nyní působí v&nbsp;soukromé sféře a věnuje se 
poradenské a pedagogické činnosti, v <span>květnu</span> <span>2014</span> byl 
zvolen prezidentem <span>Hospodářské komory ČR</span>.</p>'
+                '<p><b>Vladimír Dlouhý</b> je český ekonom a politik, bývalý 
místopředseda strany ODA a ministr průmyslu a obchodu v letech 1992–1997 ve 
vládě Václava Klause. V<span>&nbsp;</span>letech 1989–1992 byl ministrem 
hospodářství ČSFR. Nyní působí v&nbsp;soukromé sféře a věnuje se poradenské a 
pedagogické činnosti, v květnu 2014 byl zvolen prezidentem Hospodářské komory 
ČR.</p>'
             ]
         ];
         testCases.forEach((test) => {

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ib2e63e665d62e8a80215c456c7832a8e965caad1
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/services/mobileapps
Gerrit-Branch: master
Gerrit-Owner: BearND <bsitzm...@wikimedia.org>
Gerrit-Reviewer: BearND <bsitzm...@wikimedia.org>
Gerrit-Reviewer: Fjalapeno <cfl...@wikimedia.org>
Gerrit-Reviewer: Jdlrobson <jrob...@wikimedia.org>
Gerrit-Reviewer: Mholloway <mhollo...@wikimedia.org>
Gerrit-Reviewer: Mhurd <mh...@wikimedia.org>
Gerrit-Reviewer: Ppchelko <ppche...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to