Skip to content

Commit

Permalink
Merge pull request #74 from Lullabot/62-amp-audio-conversion
Browse files Browse the repository at this point in the history
62 amp audio conversion
  • Loading branch information
sidkshatriya committed May 26, 2016
2 parents bcc392c + df2195e commit b228cf9
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 24 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The AMP PHP Library is an open source and pure PHP Library that:
- Converts some non-amp elements to their AMP equivalents automatically
- An `<img>` tag is automatically converted to an `<amp-img>` tag
- An `<iframe>` tag is converted to an `<amp-iframe>`
- An [`<audio>`](https://github.com/Lullabot/amp-library/blob/master/tests/test-data/fragment-html/audio-to-amp-audio-conversion-fragment.html) tag is converted to an `<amp-audio>` tag
- [Standard Twitter embed code](https://github.com/Lullabot/amp-library/blob/master/tests/test-data/fragment-html/twitter-fragment.html) is converted to an `<amp-twitter>` tag.
- [Standard Instagram embed code](https://github.com/Lullabot/amp-library/blob/master/tests/test-data/fragment-html/instagram-fragment.html) is converted to an `<amp-instagram>` tag.
- [Standard Youtube embed code](https://github.com/Lullabot/amp-library/blob/master/tests/test-data/fragment-html/youtube-fragment.html) is converted to an `<amp-youtube>` tag
Expand All @@ -26,8 +27,9 @@ The AMP PHP Library is an open source and pure PHP Library that:
- [Standard Vimeo embed code](https://github.com/Lullabot/amp-library/blob/master/tests/test-data/fragment-html/vimeo-fragment.html) is converted to an `<amp-vimeo>` tag
- [Standard Vine embed code](https://github.com/Lullabot/amp-library/blob/master/tests/test-data/fragment-html/vine-fragment.html) is converted to an `<amp-vine>` tag
- _Notes_:
- Some of these embed code conversions may not have the advanced features you may require. File an issue if you need enhancements to the functionality already provided or new embed code conversions.
- Some of the embed codes have an associated `<script>` tag. These conversions will work even if no `<script>` tag was provided after the embed code.
- Some of these embed code conversions may not have the advanced features you may require. File an issue if you need enhancements to the functionality already provided or new embed code conversions
- Some of the embed codes have an associated `<script>` tag. These conversions will work even if no `<script>` tag was provided after the embed code
- You may experiment with the command line utility `amp-console` on the above HTML fragments to see how the converted HTML looks
- Provides both a console and programmatic interface with which to call the library. It works like this: the programmer/user provides some HTML and we return (1) The AMPized HTML (2) A list of warnings reported by the Validator (3) A list of fixes/tag conversions made by the library

### Use Cases
Expand Down
1 change: 1 addition & 0 deletions src/AMP.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class AMP
public $passes = [
'Lullabot\AMP\Pass\ImgTagTransformPass', // Transform pass
'Lullabot\AMP\Pass\IframeSoundCloudTagTransformPass', // Transform Pass
'Lullabot\AMP\Pass\AudioTagTransformPass', // Transform Pass
'Lullabot\AMP\Pass\IframeVimeoTagTransformPass', // Transform Pass
'Lullabot\AMP\Pass\IframeVineTagTransformPass', // Transform Pass
'Lullabot\AMP\Pass\IframeDailymotionTagTransformPass', // Transform Pass
Expand Down
73 changes: 73 additions & 0 deletions src/Pass/AudioTagTransformPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/*
* Copyright 2016 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


namespace Lullabot\AMP\Pass;

use QueryPath\DOMQuery;
use Lullabot\AMP\Utility\ActionTakenLine;
use Lullabot\AMP\Utility\ActionTakenType;

/**
* Class AudioTagTransformPass
* @package Lullabot\AMP\Pass
*
* @see https://github.com/ampproject/amphtml/blob/master/extensions/amp-audio/amp-audio.md
* @see https://developer.mozilla.org/en/docs/Web/HTML/Element/audio
*/
class AudioTagTransformPass extends BasePass
{
function pass()
{
$audio_tags = $this->q->find('audio:not(noscript audio)');
/** @var DOMQuery $el */
foreach ($audio_tags as $el) {
/** @var \DOMElement $dom_el */
$dom_el = $el->get(0);

$lineno = $this->getLineNo($dom_el);
$context_string = $this->getContextString($dom_el);

$new_dom_el = $this->cloneAndRenameDomElement($dom_el, 'amp-audio');
$new_el = $el->prev();
$el->remove();

$this->addFallbackAndPlaceholder($new_el);
$this->addActionTaken(new ActionTakenLine('audio', ActionTakenType::AUDIO_CONVERTED, $lineno, $context_string));
$this->context->addLineAssociation($new_dom_el, $lineno);
}

return $this->transformations;
}

/**
* @param DOMQuery $el
*/
function addFallbackAndPlaceholder(DOMQuery $el)
{
/** @var DOMQuery $wrap_this */
$wrap_this = $el->children()->not('source')->not('track');

if ($wrap_this->count()) {
$wrap_this->wrapAll('<div fallback=""></div>');
}

if (isset($this->options['audio_placeholder_html'])) {
$el->prepend('<div placeholder="">' . $this->options['audio_placeholder_html'] . '</div>');
}
}
}
8 changes: 4 additions & 4 deletions src/Pass/BasePass.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,21 @@ protected function getContextString(\DOMElement $dom_el)
}

/**
* Rename $el to $tagname. Returns the renamed DOMElement.
* clone $el and then rename tag to $tagname. Returns the cloned DOMElement.
*
* @param \DOMElement $el
* @param $tagname
* @return \DOMElement
*/
protected function renameDomElement(\DOMElement $el, $tagname)
protected function cloneAndRenameDomElement(\DOMElement $el, $tagname)
{
$new_el = $el->ownerDocument->createElement($tagname);

// Renamed DOMElement should have the same children as original
/** @var \DOMElement $child */
foreach ($el->childNodes as $child) {
$new_el->appendChild($child);
// @TODO must we cloneNode(true) ?
$new_el->appendChild($child->cloneNode(true));
}

// Renamed DOMElement should have the same attributes as original
Expand All @@ -143,7 +144,6 @@ protected function renameDomElement(\DOMElement $el, $tagname)

// Replace the old element with new element
$el->parentNode->insertBefore($new_el, $el);
$el->parentNode->removeChild($el);

return $new_el;
}
Expand Down
16 changes: 10 additions & 6 deletions src/Pass/ImgTagTransformPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,21 @@ function pass()
}

$all_a = $this->q->top()->find('img:not(noscript img)');
/** @var \DOMElement $dom_el */
foreach ($all_a->get() as $dom_el) {
/** @var DOMQuery $el */
foreach ($all_a as $el) {
/** @var \DOMElement $dom_el */
$dom_el = $el->get(0);
$lineno = $this->getLineNo($dom_el);
if ($this->isSvg($dom_el)) {
// This should be marked as a validation warning later
// @TODO This should be marked as a validation warning later?
continue;
}
$context_string = $this->getContextString($dom_el);
$new_el = $this->renameDomElement($dom_el, 'amp-img');
$this->setAmpImgAttributes($new_el);
$this->context->addLineAssociation($new_el, $lineno);
$new_dom_el = $this->cloneAndRenameDomElement($dom_el, 'amp-img');
$el->remove(); // remove the old img tag

$this->setAmpImgAttributes($new_dom_el);
$this->context->addLineAssociation($new_dom_el, $lineno);
$this->addActionTaken(new ActionTakenLine('img', ActionTakenType::IMG_CONVERTED, $lineno, $context_string));
}

Expand Down
8 changes: 4 additions & 4 deletions src/Spec/validator-generated.php
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ public static function createValidationRules() {
$o_99->attrs[] = $o_100;
$o_99->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup';
$o_101 = new CdataSpec();
$o_101->cdata_regex = 'body{-webkit-animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both;-moz-animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both;-ms-animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both;animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both}@-webkit-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}';
$o_101->cdata_regex = '\\s*body{-webkit-animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both;-moz-animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both;-ms-animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both;animation:-amp-start\\s+8s\\s+steps\\(1,end\\)\\s+0s\\s+1\\s+normal\\s+both}@-webkit-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes\\s+-amp-start{from{visibility:hidden}to{visibility:visible}}\\s*';
$o_99->cdata = $o_101;
$o_99->also_requires_tag = ['noscript > style : boilerplate'];
$o_0->tags[] = $o_99;
Expand All @@ -773,7 +773,7 @@ public static function createValidationRules() {
$o_102->attrs[] = $o_103;
$o_102->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup';
$o_104 = new CdataSpec();
$o_104->mandatory_cdata = 'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}';
$o_104->cdata_regex = '\\s*body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}\\s*';
$o_102->cdata = $o_104;
$o_102->also_requires_tag = ['head > style : boilerplate'];
$o_0->tags[] = $o_102;
Expand Down Expand Up @@ -4076,7 +4076,7 @@ public static function createValidationRules() {
$o_938 = new AttrSpec();
$o_938->name = 'data-share-endpoint';
$o_939 = new UrlSpec();
$o_939->allowed_protocol = ['ftp', 'http', 'https', 'mailto', 'snapchat', 'sms', 'tel', 'viber', 'whatsapp'];
$o_939->allowed_protocol = ['ftp', 'http', 'https', 'mailto', 'fb-messenger', 'snapchat', 'sms', 'tel', 'viber', 'whatsapp'];
$o_939->allow_relative = false;
$o_938->value_url = $o_939;
$o_936->attrs[] = $o_938;
Expand Down Expand Up @@ -4462,7 +4462,7 @@ public static function createValidationRules() {
$o_1016->also_requires_tag = ['amp-youtube extension .js script'];
$o_0->tags[] = $o_1016;
$o_0->min_validator_revision_required = 135;
$o_0->spec_file_revision = 219;
$o_0->spec_file_revision = 220;
$o_1022 = new AttrList();
$o_1022->name = 'common-link-attrs';
$o_1023 = new AttrSpec();
Expand Down
1 change: 1 addition & 0 deletions src/Utility/ActionTakenType.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ class ActionTakenType
const YOUTUBE_IFRAME_CONVERTED = 'tag was converted to the amp-youtube tag.';
const SOUNDCLOUD_IFRAME_CONVERTED = 'tag was converted to the amp-soundcloud tag.';
const COMPONENT_SCRIPT_TAG_ADDED = 'custom component script tag added to head';
const AUDIO_CONVERTED = 'tag was converted to the amp-audio tag.';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<audio controls autoplay>
<div>Your browser does not support the <strong>audio</strong> tag</div>
<p>Try using recent versions of Google Chrome or Firefox</p>
<source src="//example.dd:8088/sites/default/files/drums.mp3" type="audio/mpeg">
<source src="http://example.dd:8088/sites/default/files/drums.ogg" type="audio/ogg">
<source src="https://example.dd:8088/sites/default/files/drums.wav" type="audio/wav">
<track kind="captions" src="//example.dd:8088/sites/default/files/drums.en.vtt" srclang="en" label="English">
<track kind="captions" src="https://example.dd:8088/sites/default/files/drums.hi.vtt" srclang="hi" label="Hindi">
</audio>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<amp-audio controls autoplay>
<div fallback><div>Your browser does not support the <strong>audio</strong> tag</div><p>Try using recent versions of Google Chrome or Firefox</p></div>

<source src="//example.dd:8088/sites/default/files/drums.mp3" type="audio/mpeg">
<source type="audio/ogg">
<source src="https://example.dd:8088/sites/default/files/drums.wav" type="audio/wav">
<track kind="captions" src="//example.dd:8088/sites/default/files/drums.en.vtt" srclang="en" label="English">
<track kind="captions" src="https://example.dd:8088/sites/default/files/drums.hi.vtt" srclang="hi" label="Hindi">
</amp-audio>


ORIGINAL HTML
---------------
Line 1: <audio controls autoplay>
Line 2: <div>Your browser does not support the <strong>audio</strong> tag</div>
Line 3: <p>Try using recent versions of Google Chrome or Firefox</p>
Line 4: <source src="//example.dd:8088/sites/default/files/drums.mp3" type="audio/mpeg">
Line 5: <source src="http://example.dd:8088/sites/default/files/drums.ogg" type="audio/ogg">
Line 6: <source src="https://example.dd:8088/sites/default/files/drums.wav" type="audio/wav">
Line 7: <track kind="captions" src="//example.dd:8088/sites/default/files/drums.en.vtt" srclang="en" label="English">
Line 8: <track kind="captions" src="https://example.dd:8088/sites/default/files/drums.hi.vtt" srclang="hi" label="Hindi">
Line 9: </audio>
Line 10:


Transformations made from HTML tags to AMP custom tags
-------------------------------------------------------

<audio controls autoplay> at line 1
ACTION TAKEN: audio tag was converted to the amp-audio tag.


AMP-HTML Validation Issues and Fixes
-------------------------------------
FAIL

<source src="http://example.dd:8088/sites/default/files/drums.ogg" type="audio/ogg"> on line 5
- Invalid URL protocol 'http:' for attribute 'src' in tag 'amp-audio > source'.
[code: INVALID_URL_PROTOCOL category: AMP_TAG_PROBLEM see: https://www.ampproject.org/docs/reference/extended/amp-audio.html]
ACTION TAKEN: source.src attribute was removed due to validation issues.

<track kind="captions" src="//example.dd:8088/sites/default/files/drums.en.vtt" srclang="en" label="English"> on line 7
- The relative URL '//example.dd:8088/sites/default/files/drums.en.vtt' for attribute 'src' in tag 'amp-audio > track' is disallowed.
[code: DISALLOWED_RELATIVE_URL category: AMP_TAG_PROBLEM]


COMPONENT NAMES WITH JS PATH
------------------------------
'amp-audio', include path 'https://cdn.ampproject.org/v0/amp-audio-0.1.js'

21 changes: 13 additions & 8 deletions tests/test-data/full-html/noscript.html.out
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<meta name="viewport" content="width=device-width,minimum-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<script async custom-element="amp-audio" src="https://cdn.ampproject.org/v0/amp-audio-0.1.js"></script></head>
<body>
<!-- Example of a valid noscript -->
<noscript>
Expand All @@ -45,9 +45,9 @@
<img alt="Iconic Lemurs">
</noscript>
<!-- Invalid: audio must be in a noscript tag -->
<audio controls>
<amp-audio controls>
<source src="https://example.com/howl-of-the-lemur.mp3" type="audio/mpeg">
</audio>
</amp-audio>
<!-- Invalid: img must be in a noscript tag -->
<amp-img alt="Iconic Lemurs" height="200" src="https://example.com/lemurs.png" width="80" layout="responsive"></amp-img>
<!-- Invalid: video must be in a noscript tag -->
Expand Down Expand Up @@ -132,6 +132,9 @@ Line 64:
Transformations made from HTML tags to AMP custom tags
-------------------------------------------------------

<audio controls> at line 51
ACTION TAKEN: audio tag was converted to the amp-audio tag.

<img alt="Iconic Lemurs" height="200" src="https://example.com/lemurs.png" width="80"> at line 55
ACTION TAKEN: img tag was converted to the amp-img tag.

Expand All @@ -149,10 +152,6 @@ FAIL
- The mandatory attribute 'src' is missing in tag 'img'.
[code: MANDATORY_ATTR_MISSING category: DISALLOWED_HTML see: https://www.ampproject.org/docs/reference/amp-img.html]

<audio controls> on line 51
- The tag 'audio' may only appear as a descendant of tag 'noscript'. Did you mean 'amp-audio'?
[code: MANDATORY_TAG_ANCESTOR_WITH_HINT category: DISALLOWED_HTML_WITH_AMP_EQUIVALENT see: https://www.ampproject.org/docs/reference/extended/amp-audio.html]

<video controls height="480" width="640"> on line 57
- The tag 'video' may only appear as a descendant of tag 'noscript'. Did you mean 'amp-video'?
[code: MANDATORY_TAG_ANCESTOR_WITH_HINT category: DISALLOWED_HTML_WITH_AMP_EQUIVALENT see: https://www.ampproject.org/docs/reference/amp-video.html]
Expand All @@ -161,7 +160,13 @@ FAIL
- The tag 'noscript' may not appear as a descendant of tag 'noscript'.
[code: DISALLOWED_TAG_ANCESTOR category: GENERIC]

GLOBAL WARNING
- The tag 'amp-audio extension .js script' is missing or incorrect, but required by 'amp-audio'.
[code: TAG_REQUIRED_BY_MISSING category: AMP_TAG_PROBLEM see: https://www.ampproject.org/docs/reference/extended/amp-audio.html]
ACTION TAKEN: amp-audio custom component script tag added to head


COMPONENT NAMES WITH JS PATH
------------------------------
No custom amp script includes required
'amp-audio', include path 'https://cdn.ampproject.org/v0/amp-audio-0.1.js'

0 comments on commit b228cf9

Please sign in to comment.