Skip to content

Instantly share code, notes, and snippets.

@marcus-at-localhost
Last active November 12, 2020 06:26
Show Gist options
  • Save marcus-at-localhost/d6f17b84406b3c8e0409c80c57656740 to your computer and use it in GitHub Desktop.
Save marcus-at-localhost/d6f17b84406b3c8e0409c80c57656740 to your computer and use it in GitHub Desktop.
[Move inline scripts in HTML DOM to the bottom of the document] Sandbox: http://ideone.com/pDCedR
<?php
// test code
// http://ideone.com/pDCedR
$html = <<<HTML
<html>
<head>
</head>
<body>
<script class="keep">
// will noit be moved
console.log('I stay');
</script>
<script>
// will be moved at the end of the document
$('h1').addClass('header');
</script>
<h1>DOMDocument</h1>
<p>Text<p>
<script src="jquery.js"></script>
<!-- inline php should appear below -->
</body>
</html>
HTML;
echo move_script($html);
function move_script($html)
{
// in case we have some mangled special chars in the output,
// use this. <https://davidwalsh.name/domdocument-utf8-problem>
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
$dom = new DOMDocument();
$dom->recover = true;
//$dom->substituteEntities = true;
$dom->formatOutput = true;
$dom->preserveWhiteSpace = true;
// set error level
// uncomment to suspress warnings that happen with embedded SVG, duplicate ids
// and raw entities like & instead of &amp;
//$internalErrors = libxml_use_internal_errors(true);
// load HTML
// LIBXML_HTML_NODEFDTD
// keeps linebreaks after <script> tags being rearranged
// http://stackoverflow.com/a/32028596/814031
// http://stackoverflow.com/a/29499398/814031
$dom->loadHTML($html, LIBXML_HTML_NODEFDTD);
// collect the suspressed warnings/errors and print them out
//$errors = libxml_get_errors();
//var_dump($errors);
// Restore error level
//libxml_use_internal_errors($internalErrors);
$xpath = new DOMXPath($dom);
// grab all inline script tags in <body> that not referencing a file or have the class="keep" attached
$script_tags = $xpath->query('//body//script[not(@src)][not(@class="keep")]');
$mainBody = @$dom->getElementsByTagName('body')->item(0);
foreach ($script_tags as $tag) {
$mainBody->appendChild($tag->cloneNode(true));
$tag->parentNode->removeChild($tag);
}
return $dom->saveHTML();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment