diff --git a/src/Optimizer/Transformer/AutoExtensions.php b/src/Optimizer/Transformer/AutoExtensions.php index 4b55f20dc..4ca276bee 100644 --- a/src/Optimizer/Transformer/AutoExtensions.php +++ b/src/Optimizer/Transformer/AutoExtensions.php @@ -207,19 +207,7 @@ private function removeUnneededExtensions(Document $document, $extensionScripts) */ private function renderExtensionScripts(Document $document, array $extensionScripts) { - $referenceNode = $document->viewport; - - if (!$referenceNode) { - $referenceNode = $document->charset; - } - - if ( - $referenceNode - && $referenceNode->nextSibling instanceof Element - && $referenceNode->nextSibling->hasAttribute(Attribute::AMP_BOILERPLATE) - ) { - $referenceNode = $referenceNode->nextSibling; - } + $referenceNode = $this->getExtensionScriptsReferenceNode($document); foreach ($extensionScripts as $extensionScript) { if ($referenceNode && $referenceNode->nextSibling) { @@ -235,6 +223,52 @@ private function renderExtensionScripts(Document $document, array $extensionScri } } + /** + * Get the reference node to attach extension scripts to. + * + * @param Document $document Document to look for the reference node in. + * @return Element|null Reference node to use, or null if not found. + */ + private function getExtensionScriptsReferenceNode(Document $document) + { + $referenceNode = $document->viewport ?: $document->charset; + + if (! $referenceNode instanceof Element) { + $referenceNode = $document->head->firstChild; + } + + if (! $referenceNode instanceof Element) { + return null; + } + + // Try to detect the boilerplate style so we can append the scripts after that. + $remainingNode = $referenceNode->nextSibling; + while ($remainingNode) { + if (! $remainingNode instanceof Element) { + $remainingNode = $remainingNode->nextSibling; + continue; + } + + if ( + $remainingNode->tagName === Tag::STYLE + && $remainingNode->hasAttribute(Attribute::AMP_BOILERPLATE) + ) { + $referenceNode = $remainingNode; + } elseif ( + $remainingNode->tagName === Tag::NOSCRIPT + && $remainingNode->firstChild instanceof Element + && $remainingNode->firstChild->tagName === Tag::STYLE + && $remainingNode->firstChild->hasAttribute(Attribute::AMP_BOILERPLATE) + ) { + $referenceNode = $remainingNode; + } + + $remainingNode = $remainingNode->nextSibling; + } + + return $referenceNode; + } + /** * Maybe add a required extension to the list of extension scripts. *