Cache processed stylesheets during the parse

If we've already processed a stylesheet once, there's no point in
processing it again.

Change-Id: I83f7aab82cc7674037974b0de43ccae6c77ff39f
This commit is contained in:
Brad Jorsch 2017-11-30 13:52:30 -05:00
parent 5e29310bf1
commit 9964009346
2 changed files with 37 additions and 4 deletions

View file

@ -126,6 +126,7 @@ class TemplateStylesHooks {
*/ */
public static function onParserFirstCallInit( &$parser ) { public static function onParserFirstCallInit( &$parser ) {
$parser->setHook( 'templatestyles', 'TemplateStylesHooks::handleTag' ); $parser->setHook( 'templatestyles', 'TemplateStylesHooks::handleTag' );
$parser->extTemplateStylesCache = new MapCacheLRU( 100 ); // 100 is arbitrary
return true; return true;
} }
@ -178,6 +179,14 @@ class TemplateStylesHooks {
return true; return true;
} }
/**
* Clear our cache when the parser is reset
* @param Parser $parser
*/
public static function onParserClearState( Parser $parser ) {
$parser->extTemplateStylesCache->clear();
}
/** /**
* Parser hook for `<templatestyles>` * Parser hook for `<templatestyles>`
* @param string $text Contents of the tag (ignored). * @param string $text Contents of the tag (ignored).
@ -235,13 +244,32 @@ class TemplateStylesHooks {
'</strong>'; '</strong>';
} }
// For the moment just output the styles inline. // If the revision actually has an ID, cache based on that.
// @todo: If T160563 happens, it would be good to convert this to use that. // Otherwise, cache by hash.
if ( $rev->getId() ) {
$cacheKey = 'r' . $rev->getId();
} else {
$cacheKey = sha1( $content->getNativeData() );
}
// Include any non-default wrapper class in the cache key too
$wrapClass = $parser->getOptions()->getWrapOutputClass();
if ( $wrapClass === false ) {
$wrapClass = 'mw-parser-output';
}
if ( $wrapClass !== 'mw-parser-output' ) {
$cacheKey .= '/' . $wrapClass;
}
// Already cached?
if ( $parser->extTemplateStylesCache->has( $cacheKey ) ) {
return $parser->extTemplateStylesCache->get( $cacheKey );
}
$status = $content->sanitize( [ $status = $content->sanitize( [
'flip' => $parser->getTargetLanguage()->getDir() !== $wgContLang->getDir(), 'flip' => $parser->getTargetLanguage()->getDir() !== $wgContLang->getDir(),
'minify' => !ResourceLoader::inDebugMode(), 'minify' => !ResourceLoader::inDebugMode(),
'class' => $parser->getOptions()->getWrapOutputClass(), 'class' => $wrapClass,
] ); ] );
$style = $status->isOk() ? $status->getValue() : '/* Fatal error, no CSS will be output */'; $style = $status->isOk() ? $status->getValue() : '/* Fatal error, no CSS will be output */';
@ -270,7 +298,9 @@ class TemplateStylesHooks {
// Return the inline <style>, which the Parser will wrap in a 'general' // Return the inline <style>, which the Parser will wrap in a 'general'
// strip marker. // strip marker.
return Html::inlineStyle( $marker ); $ret = Html::inlineStyle( $marker );
$parser->extTemplateStylesCache->set( $cacheKey, $ret );
return $ret;
} }
} }

View file

@ -35,6 +35,9 @@
"ParserFirstCallInit": [ "ParserFirstCallInit": [
"TemplateStylesHooks::onParserFirstCallInit" "TemplateStylesHooks::onParserFirstCallInit"
], ],
"ParserClearState": [
"TemplateStylesHooks::onParserClearState"
],
"ParserAfterTidy": [ "ParserAfterTidy": [
"TemplateStylesHooks::onParserAfterTidy" "TemplateStylesHooks::onParserAfterTidy"
], ],