Skip to content

Commit

Permalink
Merge pull request #523 from ampproject/enhance/518-add-amp-audio-ssr…
Browse files Browse the repository at this point in the history
…-support

Implement SSR for amp-audio
  • Loading branch information
ediamin authored May 19, 2022
2 parents 517f67b + ead1ba6 commit 8fa1588
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 30 deletions.
13 changes: 0 additions & 13 deletions src/Optimizer/Error/CannotRemoveBoilerplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ final class CannotRemoveBoilerplate implements Error
. 'attribute produced an error: ';
const RENDER_DELAYING_SCRIPT_STRING = 'Cannot remove boilerplate because the document contains a render-delaying '
. 'extension: ';
const AMP_AUDIO_STRING = 'Cannot remove boilerplate because the document contains an extension that '
. 'needs to know the dimensions of the browser: ';
const UNSUPPORTED_LAYOUT_STRING = 'Cannot remove boilerplate because of an unsupported layout: ';

/**
Expand Down Expand Up @@ -59,17 +57,6 @@ public static function fromAmpExperiment(Element $element)
return new self(self::RENDER_DELAYING_SCRIPT_STRING . $element->tagName);
}

/**
* Instantiate a CannotRemoveBoilerplate object for an amp-audio element.
*
* @param Element $element amp-audio element.
* @return self
*/
public static function fromAmpAudio(Element $element)
{
return new self(self::AMP_AUDIO_STRING . new ElementDump($element));
}

/**
* Instantiate a CannotRemoveBoilerplate object for an element with an unsupported layout.
*
Expand Down
40 changes: 31 additions & 9 deletions src/Optimizer/Transformer/ServerSideRendering.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,18 @@ public function transform(Document $document, ErrorCollection $errors)
}

/*
* amp-experiment is a render delaying extension iff the tag is used in the doc. We check for that here
* rather than checking for the existence of the amp-experiment script in IsRenderDelayingExtension below.
* Server-side rendering of an amp-audio element.
*/
if ($ampElement->tagName === Extension::EXPERIMENT && $this->isAmpExperimentUsed($ampElement)) {
$errors->add(Error\CannotRemoveBoilerplate::fromAmpExperiment($ampElement));
$canRemoveBoilerplate = false;
if ($ampElement->tagName === Extension::AUDIO) {
$this->ssrAmpAudio($document, $ampElement);
}

/*
* amp-audio requires knowing the dimensions of the browser. Do not remove the boilerplate or apply layout
* if amp-audio is present in the document.
* amp-experiment is a render delaying extension iff the tag is used in the doc. We check for that here
* rather than checking for the existence of the amp-experiment script in IsRenderDelayingExtension below.
*/
if ($ampElement->tagName === Extension::AUDIO) {
$errors->add(Error\CannotRemoveBoilerplate::fromAmpAudio($ampElement));
if ($ampElement->tagName === Extension::EXPERIMENT && $this->isAmpExperimentUsed($ampElement)) {
$errors->add(Error\CannotRemoveBoilerplate::fromAmpExperiment($ampElement));
$canRemoveBoilerplate = false;
}

Expand Down Expand Up @@ -1060,4 +1058,28 @@ private function isZero($number)

return abs($number) < self::FLOATING_POINT_EPSILON;
}

/**
* Server-side rendering of an amp-audio element.
*
* @param Document $document DOM document to apply the transformations to.
* @param Element $element Element to adapt.
*/
private function ssrAmpAudio(Document $document, Element $element)
{
// Check if we already have a SSR-ed audio element.
if ($element->hasChildNodes()) {
foreach ($element->childNodes as $childNode) {
if ($childNode instanceof Element && $childNode->tagName === Tag::AUDIO) {
return;
}
}
}

$audio = $document->createElement(Tag::AUDIO);
$controls = $document->createAttribute(Attribute::CONTROLS);

$audio->setAttributeNode($controls);
$element->appendChild($audio);
}
}
2 changes: 2 additions & 0 deletions tests/Optimizer/SpecTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ final class SpecTest extends TestCase
'ReorderHead - preserves_amp_custom_style_order' => 'see https://github.com/ampproject/amp-toolbox/issues/604',

'MinifyHtml - minifies_inline_amp-script' => 'see https://github.com/ampproject/amp-toolbox-php/issues/260',

'ServerSideRendering - does_not_transform_amp_audio' => 'The amp-toolbox needs to implement SSR amp-audio',
];

const CLASS_SKIP_TEST = '__SKIP__';
Expand Down
43 changes: 35 additions & 8 deletions tests/Optimizer/Transformer/ServerSideRenderingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,7 @@ public function dataTransform()

'amp-audio' => [
$input('<amp-audio></amp-audio>'),
$expectWithBoilerplate('<amp-audio></amp-audio>'),
[
Error\CannotRemoveBoilerplate::fromAmpAudio(
Document::fromHtmlFragment(
'<amp-audio></amp-audio>'
)->body->firstChild
),
],
$expectWithoutBoilerplate('<amp-audio><audio controls></audio></amp-audio>'),
],

'amp-experiment is non-empty' => [
Expand Down Expand Up @@ -326,6 +319,40 @@ public function dataTransform()
$input('<amp-ad type="doubleclick" data-slot="/6355419/Travel" layout="fluid" height="fluid" width="300"></amp-ad>'),
$expectWithoutBoilerplate('<amp-ad class="i-amphtml-layout-fluid i-amphtml-layout-awaiting-size" data-slot="/6355419/Travel" height="fluid" width="300" i-amphtml-layout="fluid" layout="fluid" style="width:100%;height:0;" type="doubleclick"></amp-ad>'),
],

'server side render amp-audio' => [
$input('<amp-audio src="http://example.com/audio.mp3" width="300"></amp-audio>'),
$expectWithoutBoilerplate('<amp-audio src="http://example.com/audio.mp3" width="300"><audio controls></audio></amp-audio>'),
],

'ssr amp-audio appends audio element' => [
$input(
'<amp-audio src="http://example.com/audio.mp3" width="300">'
. '<div fallback="">Your browser doesn’t support HTML5 audio</div>'
. '</amp-audio>'
),
$expectWithoutBoilerplate(
'<amp-audio src="http://example.com/audio.mp3" width="300">'
. '<div fallback="">Your browser doesn’t support HTML5 audio</div>'
. '<audio controls></audio>'
. '</amp-audio>'
),
],

'skip ssr amp-audio if audio child node is present' => [
$input(
'<amp-audio src="http://example.com/audio.mp3" width="300">'
. '<div fallback="">Your browser doesn’t support HTML5 audio</div>'
. '<audio controls src="http://example.com/audio.mp3"></audio>'
. '</amp-audio>'
),
$expectWithoutBoilerplate(
'<amp-audio src="http://example.com/audio.mp3" width="300">'
. '<div fallback="">Your browser doesn’t support HTML5 audio</div>'
. '<audio controls src="http://example.com/audio.mp3"></audio>'
. '</amp-audio>'
),
]
];
}

Expand Down

0 comments on commit 8fa1588

Please sign in to comment.