Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save NOUIY/5029225b3f3c1c807385cd98c62ecdff to your computer and use it in GitHub Desktop.
Save NOUIY/5029225b3f3c1c807385cd98c62ecdff to your computer and use it in GitHub Desktop.
<?php
use Sabberworm\CSS\Parser;
use Sabberworm\CSS\RuleSet\DeclarationBlock;
$dom = new DOMDocument();
$dom->loadHTML(
'
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
img#nod {
aspect-ratio: 1 / 1;
width: 100%;
}
</style>
</head>
<body>
<img id="nod" src="https://media.giphy.com/media/xSM46ernAUN3y/giphy.gif">
</body>
</html>
'
);
$xpath = new DOMXPath( $dom );
$img_query = $xpath->query(
'
//img[
starts-with(
@src,
"https://media.giphy.com/media/"
)
and
contains( @src, ".gif" )
]
'
);
foreach ( $img_query as $img ) {
/** @var DOMElement $img */
$video = $dom->createElement( 'video' );
// Capture and remove ID so it can be added to replacement.
// IMPORTANT: Thus must be done separately from copying the other attributes.
$id = $img->getAttribute( 'id' );
if ( $id ) {
$img->removeAttribute( 'id' );
$video->setAttribute( 'id', $id );
}
foreach ( $img->attributes as $attribute ) {
$video->setAttribute( $attribute->nodeName, $attribute->nodeValue );
}
foreach ( [ 'autoplay', 'loop', 'muted', 'playsinline' ] as $boolean_attribute ) {
$video->setAttributeNode( $dom->createAttribute( $boolean_attribute ) );
}
// Replace gif with mp4.
$video->setAttribute(
'src',
preg_replace(
':/giphy(-.+?)?\.gif:',
'/giphy.mp4',
$img->getAttribute( 'src' )
)
);
// Finally, swap out the img with the video.
$img->parentNode->replaceChild( $video, $img );
}
echo "# The document prior to style processing:\n";
echo $dom->saveHTML() . "\n";
foreach ( $xpath->query( '//style' ) as $style ) {
/** @var DOMElement $style */
$parser = new Parser( $style->textContent );
$parsed = $parser->parse();
foreach ( $parsed->getAllDeclarationBlocks() as $declaration_block ) {
/** @var DeclarationBlock $declaration_block */
$ids = [];
foreach ( $declaration_block->getSelectors() as $selector ) {
// This ID extractor is admittedly rudimentary.
if ( preg_match( '/#([a-z0-9_-]+)/', $selector, $matches ) ) {
$ids[] = $matches[1];
} else {
// If we couldn't parse an ID out, then skip the whole block.
continue 2;
}
}
// Now inline the declaration blocks as style attributes.
foreach ( $ids as $id ) {
$element = $dom->getElementById( $id );
if ( ! $element ) {
continue;
}
$styles = [];
foreach ( $declaration_block->getRules() as $rule ) {
$styles[] = (string) $rule;
}
if ( $element->hasAttribute( 'style' ) ) {
$styles[] = $element->getAttribute( 'style' );
}
$element->setAttribute( 'style', implode( '', $styles ) );
}
$parsed->remove( $declaration_block );
}
// Update the stylesheet to remove the inlined style rules.
$css_text = $parsed->render();
if ( ! $css_text ) {
$style->parentNode->removeChild( $style );
} else {
$style->textContent = $parsed->render();
}
}
echo "# The nod element as returned by getElementById:\n";
$element = $dom->getElementById( 'nod' );
if ( $element ) {
echo $dom->saveHTML( $dom->getElementById( 'nod' ) ) . "\n";
} else {
echo "NULL\n";
}
echo "\n";
echo "# The element with the 'nod' ID as queried by XPath:\n";
echo $dom->saveHTML( $xpath->query( '//*[ @id = "nod" ]' )->item( 0 ) ) . "\n";
echo "\n";
echo "# The entire document:\n";
echo $dom->saveHTML();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment