Anomie has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/393284 )

Change subject: ParserOutput: Add 'deduplicateStyles' post-cache transformation
......................................................................

ParserOutput: Add 'deduplicateStyles' post-cache transformation

This transformation will find <style> tag with a "mw-deduplicate"
attribute. For each value of the attribute, the first instance will be
kept as-is, while any subsequent tags with the same value will have all
contents removed and will have "mw-deduplicate" replaced with
"mw-deduplicated".

This also adds an $attribs parameter to Html::inlineStyle() so the
mw-deduplicate attribute can be added.

Note this doesn't actually depend on Ib931e25c, but action=mobileview
will break if it starts being used without that patch.

Bug: T160563
Change-Id: I055abdf4d73ec65771eaa4fe0999ec907c831568
Depends-On: Ib931e25ce85072000e62c486bbe5907f03372494
---
M RELEASE-NOTES-1.31
M includes/Html.php
M includes/parser/ParserOutput.php
M tests/phpunit/includes/parser/ParserOutputTest.php
4 files changed, 72 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/84/393284/1

diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31
index 4fd3f20..e997dfb 100644
--- a/RELEASE-NOTES-1.31
+++ b/RELEASE-NOTES-1.31
@@ -24,6 +24,9 @@
   warningBox generation.
 * Added a hook, ParserOutputPostCacheTransform, to allow extensions to affect
   the ParserOutput::getText() post-cache transformations.
+* Style tags with an 'mw-deduplicate' attribute will be deduplicated as a
+  ParserOutput::getText() post-cache transformation. This may be disabled by
+  passing 'deduplicateStyles' => false to that method.
 
 === External library changes in 1.31 ===
 
diff --git a/includes/Html.php b/includes/Html.php
index dfd80a8..3bcf131 100644
--- a/includes/Html.php
+++ b/includes/Html.php
@@ -589,9 +589,12 @@
         *
         * @param string $contents CSS
         * @param string $media A media type string, like 'screen'
+        * @param array $attribs (since 1.31) Associative array of attributes, 
e.g., [
+        *   'href' => 'https://www.mediawiki.org/' ]. See expandAttributes() 
for
+        *   further documentation.
         * @return string Raw HTML
         */
-       public static function inlineStyle( $contents, $media = 'all' ) {
+       public static function inlineStyle( $contents, $media = 'all', $attribs 
= [] ) {
                // Don't escape '>' since that is used
                // as direct child selector.
                // Remember, in css, there is no "x" for hexadecimal escapes, 
and
@@ -609,7 +612,7 @@
 
                return self::rawElement( 'style', [
                        'media' => $media,
-               ], $contents );
+               ] + $attribs, $contents );
        }
 
        /**
diff --git a/includes/parser/ParserOutput.php b/includes/parser/ParserOutput.php
index fb4a169..d1b6203 100644
--- a/includes/parser/ParserOutput.php
+++ b/includes/parser/ParserOutput.php
@@ -21,6 +21,9 @@
  * @file
  * @ingroup Parser
  */
+
+use HtmlFormatter\HtmlFormatter;
+
 class ParserOutput extends CacheTime {
        /**
         * Feature flag to indicate to extensions that MediaWiki core supports 
and
@@ -268,6 +271,11 @@
         *  - enableSectionEditLinks: (bool) Include section edit links, 
assuming
         *    section edit link tokens are present in the HTML. Default is true,
         *     but might be statefully overridden.
+        *  - deduplicateStyles: (bool) When true, which is the default, <style>
+        *    tags with the `mw-deduplicate` attribute set are deduplicated by
+        *    value of the attribute: all but the first will have the attribute
+        *    replaced with a `mw-deduplicated` attribute and will have all 
child
+        *    nodes removed.
         * @return string HTML
         */
        public function getText( $options = [] ) {
@@ -282,6 +290,7 @@
                $options += [
                        'allowTOC' => !empty( $this->mTOCEnabled ),
                        'enableSectionEditLinks' => $this->mEditSectionTokens,
+                       'deduplicateStyles' => true,
                ];
                $text = $this->mText;
 
@@ -323,6 +332,31 @@
                        );
                }
 
+               if ( $options['deduplicateStyles'] ) {
+                       // Hide newlines from HtmlFormatter, it sometimes 
strips them
+                       $text = str_replace( "\n<", '&#10;<', $text );
+
+                       $formatter = new HtmlFormatter( $text );
+                       $doc = $formatter->getDoc();
+                       $xpath = new DOMXPath( $doc );
+
+                       $seen = [];
+                       $nodes = $xpath->query( '//style[@mw-deduplicate]' );
+                       foreach ( $nodes as $node ) {
+                               $key = $node->getAttribute( 'mw-deduplicate' );
+                               if ( isset( $seen[$key] ) ) {
+                                       $node->removeAttribute( 
'mw-deduplicate' );
+                                       $node->setAttribute( 'mw-deduplicated', 
$key );
+                                       while ( $node->firstChild !== null ) {
+                                               $node->removeChild( 
$node->firstChild );
+                                       }
+                               }
+                               $seen[$key] = true;
+                       }
+
+                       $text = $formatter->getText();
+               }
+
                return $text;
        }
 
diff --git a/tests/phpunit/includes/parser/ParserOutputTest.php 
b/tests/phpunit/includes/parser/ParserOutputTest.php
index ef35363b..ddb79cd 100644
--- a/tests/phpunit/includes/parser/ParserOutputTest.php
+++ b/tests/phpunit/includes/parser/ParserOutputTest.php
@@ -147,6 +147,19 @@
 </p>
 EOF;
 
+               $dedupText = <<<EOF
+<p>This is a test document.</p>
+<style mw-deduplicate="duplicate1">.Duplicate1 {}</style>
+<style mw-deduplicate="duplicate1">.Duplicate1 {}</style>
+<style mw-deduplicate="duplicate2">.Duplicate2 {}</style>
+<style mw-deduplicate="duplicate1">.Duplicate1 {}</style>
+<style mw-deduplicate="duplicate2">.Duplicate2 {}</style>
+<style mw-not-deduplicate="duplicate1">.Duplicate1 {}</style>
+<style mw-deduplicate="duplicate1">.Same-attribute-different-content {}</style>
+<style mw-deduplicate="duplicate3">.Duplicate1 {}</style>
+<style>.Duplicate1 {}</style>
+EOF;
+
                return [
                        'No stateless options, default state' => [
                                [], [], $text, <<<EOF
@@ -308,6 +321,23 @@
 </p>
 EOF
                        ],
+                       'Style deduplication' => [
+                               [], [], $dedupText, <<<EOF
+<p>This is a test document.</p>
+<style mw-deduplicate="duplicate1">.Duplicate1 {}</style>
+<style mw-deduplicated="duplicate1"></style>
+<style mw-deduplicate="duplicate2">.Duplicate2 {}</style>
+<style mw-deduplicated="duplicate1"></style>
+<style mw-deduplicated="duplicate2"></style>
+<style mw-not-deduplicate="duplicate1">.Duplicate1 {}</style>
+<style mw-deduplicated="duplicate1"></style>
+<style mw-deduplicate="duplicate3">.Duplicate1 {}</style>
+<style>.Duplicate1 {}</style>
+EOF
+                       ],
+                       'Style deduplication disabled' => [
+                               [ 'deduplicateStyles' => false ], [], 
$dedupText, $dedupText
+                       ],
                ];
                // @codingStandardsIgnoreEnd
        }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I055abdf4d73ec65771eaa4fe0999ec907c831568
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>

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

Reply via email to