From 1bc62c548c120d79f6a3ff9c14c19037aee40122 Mon Sep 17 00:00:00 2001 From: jdlrobson Date: Fri, 20 Apr 2018 11:42:41 -0700 Subject: [PATCH] Introduce ResourceLoaderLessVarFileModule This ResourceLoader module provides a way to ship messages to CSS variables. We will need this going forward to deal with flash of unstyled content in various JavaScript based UIs that are subject to i18n such as table sorting and collapsible elements. To avoid overhead of hitting the database to fetch and transform localisation messages we make use of the MessageBlobStore making use of `messages` definition already inside ResourceLoaderFileModule. Given this resource is only intended for render blocking styles without JavaScript this should be okay (although if requested in JavaScript will also ship associated messages) Bug: T42812 Change-Id: I2bf12cdc848478889acbe9a7a970e46f8aefa287 --- autoload.php | 1 + .../ResourceLoaderLessVarFileModule.php | 69 +++++++++++++++++++ .../ResourceLoaderLessVarFileModuleTest.php | 43 ++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 includes/resourceloader/ResourceLoaderLessVarFileModule.php create mode 100644 tests/phpunit/includes/resourceloader/ResourceLoaderLessVarFileModuleTest.php diff --git a/autoload.php b/autoload.php index 881d0ddf9b..12958ca089 100644 --- a/autoload.php +++ b/autoload.php @@ -1284,6 +1284,7 @@ $wgAutoloadLocalClasses = [ 'ResourceLoaderJqueryMsgModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderJqueryMsgModule.php', 'ResourceLoaderLanguageDataModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageDataModule.php', 'ResourceLoaderLanguageNamesModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageNamesModule.php', + 'ResourceLoaderLessVarFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLessVarFileModule.php', 'ResourceLoaderMediaWikiUtilModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderMediaWikiUtilModule.php', 'ResourceLoaderModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderModule.php', 'ResourceLoaderOOUIFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIFileModule.php', diff --git a/includes/resourceloader/ResourceLoaderLessVarFileModule.php b/includes/resourceloader/ResourceLoaderLessVarFileModule.php new file mode 100644 index 0000000000..17d00e0fab --- /dev/null +++ b/includes/resourceloader/ResourceLoaderLessVarFileModule.php @@ -0,0 +1,69 @@ +messages, $this->lessVariables ); + } + + /** + * Exclude a set of messages from a JSON string representation + * @param string $blob + * @param array $exclusions + * @return array $blob + */ + protected function excludeMessagesFromBlob( $blob, $exclusions ) { + $data = json_decode( $blob, true ); + // unset the LESS variables so that they are not forwarded to JavaScript + foreach ( $exclusions as $key ) { + unset( $data[$key] ); + } + return $data; + } + + /** + * @inheritDoc + */ + protected function getMessageBlob( ResourceLoaderContext $context ) { + $blob = parent::getMessageBlob( $context ); + return json_encode( $this->excludeMessagesFromBlob( $blob, $this->lessVariables ) ); + } + + /** + * Takes a message and wraps it in quotes for compatibility with LESS parser + * (ModifyVars) method so that the variable can be loaded and made available to stylesheets. + * Note this does not take care of CSS escaping. That will be taken care of as part + * of CSS Janus. + * @param string $msg + * @return string wrapped LESS variable definition + */ + private static function wrapAndEscapeMessage( $msg ) { + return str_replace( "'", "\'", CSSMin::serializeStringValue( $msg ) ); + } + + /** + * @param \ResourceLoaderContext $context + * @return array LESS variables + */ + protected function getLessVars( \ResourceLoaderContext $context ) { + $blob = parent::getMessageBlob( $context ); + $lessMessages = $this->excludeMessagesFromBlob( $blob, $this->messages ); + + $vars = []; + foreach ( $lessMessages as $msgKey => $value ) { + $vars['msg-' . $msgKey] = self::wrapAndEscapeMessage( $value ); + } + return $vars; + } +} diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderLessVarFileModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderLessVarFileModuleTest.php new file mode 100644 index 0000000000..a42e4bed25 --- /dev/null +++ b/tests/phpunit/includes/resourceloader/ResourceLoaderLessVarFileModuleTest.php @@ -0,0 +1,43 @@ +setAccessible( true ); + $this->assertEquals( $expected, $method->invoke( ResourceLoaderLessVarFileModule::class, $msg ) ); + } +} -- 2.20.1