From 49b376e9c8bb5295efdd31378aa22192c60fac46 Mon Sep 17 00:00:00 2001 From: FuzzyTree Date: Thu, 22 Sep 2016 18:10:25 -0700 Subject: [PATCH 01/27] Add fixed layout option by width for images --- src/Pass/ImgTagTransformPass.php | 15 ++++++++++++++- .../fragment-html/img-test-fragment.html | 2 +- .../img-test-fragment.html.options.json | 3 +++ .../fragment-html/img-test-fragment.html.out | 6 +++--- 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 tests/test-data/fragment-html/img-test-fragment.html.options.json diff --git a/src/Pass/ImgTagTransformPass.php b/src/Pass/ImgTagTransformPass.php index 89757773..50b0cfcf 100644 --- a/src/Pass/ImgTagTransformPass.php +++ b/src/Pass/ImgTagTransformPass.php @@ -121,11 +121,24 @@ protected function convertAmpImg($el, $lineno, $context_string) $dom_el = $el->get(0); $new_dom_el = $this->cloneAndRenameDomElement($dom_el, 'amp-img'); $new_el = $el->prev(); - $this->setLayoutIfNoLayout($new_el, 'responsive'); + $this->setLayoutIfNoLayout($new_el, $this->getLayout($el)); $this->addActionTaken(new ActionTakenLine('img', ActionTakenType::IMG_CONVERTED, $lineno, $context_string)); return $new_dom_el; } + /** + * Given an image DOMQuery + * Returns whether the image should have 'fixed' or 'responsive' layout + * + * @param DOMQuery $el + * @return string + */ + protected function getLayout($el) { + return (isset($this->options['img_max_fixed_layout_width']) + && $this->options['img_max_fixed_layout_width'] >= $el->attr('width')) + ? 'fixed' : 'responsive'; + } + /** * Given an image src attribute, try to get its dimensions * Returns false on failure diff --git a/tests/test-data/fragment-html/img-test-fragment.html b/tests/test-data/fragment-html/img-test-fragment.html index 504490de..348842c8 100644 --- a/tests/test-data/fragment-html/img-test-fragment.html +++ b/tests/test-data/fragment-html/img-test-fragment.html @@ -3,7 +3,7 @@ - + diff --git a/tests/test-data/fragment-html/img-test-fragment.html.options.json b/tests/test-data/fragment-html/img-test-fragment.html.options.json new file mode 100644 index 00000000..161df05d --- /dev/null +++ b/tests/test-data/fragment-html/img-test-fragment.html.options.json @@ -0,0 +1,3 @@ +{ + "img_max_fixed_layout_width" : 200 +} \ No newline at end of file diff --git a/tests/test-data/fragment-html/img-test-fragment.html.out b/tests/test-data/fragment-html/img-test-fragment.html.out index 6309a45c..e52f7f55 100644 --- a/tests/test-data/fragment-html/img-test-fragment.html.out +++ b/tests/test-data/fragment-html/img-test-fragment.html.out @@ -3,8 +3,8 @@ - - + + @@ -31,7 +31,7 @@ Line 2: Line 3: Line 4: Line 5: -Line 6: +Line 6: Line 7: Line 8: Line 9: From 0f71259f4359bd947f9b99a4071409c620d437e6 Mon Sep 17 00:00:00 2001 From: FuzzyTree Date: Fri, 23 Sep 2016 22:19:35 -0700 Subject: [PATCH 02/27] Add amp-ad support. Regenerated validator-generated.php file with custom script tags from: https://github.com/ampproject/amphtml/blob/master/extensions/amp-ad/0.1/validator-amp-ad.protoascii Regenerating the validator was necessary to avoid flagging the script tag for in as an error --- src/Pass/StandardFixPass.php | 5 + src/Spec/validator-generated.php | 4344 +++++++++-------- src/Validate/Context.php | 1 + .../full-html/mandatory_dimensions.html.out | 1 + .../full-html/several_errors.html.out | 1 + .../test-data/full-html/spec_example.html.out | 3 +- tests/test-data/full-html/urls.html.out | 1 + .../full-html/validator-amp-sidebar.html.out | 1 + 8 files changed, 2200 insertions(+), 2157 deletions(-) diff --git a/src/Pass/StandardFixPass.php b/src/Pass/StandardFixPass.php index c5771d8d..fc52c4a4 100644 --- a/src/Pass/StandardFixPass.php +++ b/src/Pass/StandardFixPass.php @@ -58,6 +58,11 @@ class StandardFixPass extends BasePass public function pass() { + $all_ampad = $this->q->top()->find('amp-ad'); + if ($all_ampad->length > 0) { + $this->addComponentJsToHead('amp-ad'); + } + /** @var SValidationError $error */ foreach ($this->validation_result->errors as $error) { // If the error was resolved, continue diff --git a/src/Spec/validator-generated.php b/src/Spec/validator-generated.php index 082bb58a..6523ef92 100644 --- a/src/Spec/validator-generated.php +++ b/src/Spec/validator-generated.php @@ -2358,33 +2358,39 @@ public static function createValidationRules() { $o_564->tag_name = 'o:p'; $o_0->tags[] = $o_564; $o_565 = new TagSpec(); - $o_565->tag_name = 'amp-ad'; + $o_565->tag_name = 'script'; + $o_565->spec_name = 'amp-ad extension .js script'; + $o_565->mandatory_parent = 'head'; $o_566 = new AttrSpec(); - $o_566->name = 'alt'; + $o_566->name = 'async'; + $o_566->mandatory = true; + $o_566->value = ''; $o_565->attrs[] = $o_566; $o_567 = new AttrSpec(); - $o_567->name = 'json'; + $o_567->name = 'custom-element'; + $o_567->mandatory = true; + $o_567->value = 'amp-ad'; + $o_567->dispatch_key = true; $o_565->attrs[] = $o_567; $o_568 = new AttrSpec(); $o_568->name = 'src'; - $o_569 = new UrlSpec(); - $o_569->allowed_protocol = ['https']; - $o_569->allow_relative = true; - $o_568->value_url = $o_569; + $o_568->mandatory = true; + $o_568->value_regex = 'https://cdn\\.ampproject\\.org/v0/amp-ad-(latest|0\\.1).js'; $o_565->attrs[] = $o_568; - $o_570 = new AttrSpec(); - $o_570->name = 'type'; - $o_570->mandatory = true; - $o_565->attrs[] = $o_570; - $o_565->attr_lists = ['extended-amp-global']; - $o_565->spec_url = 'https://www.ampproject.org/docs/reference/amp-ad.html'; - $o_571 = new AmpLayout(); - $o_571->supported_layouts = [AmpLayoutLayout::FILL, AmpLayoutLayout::FIXED, AmpLayoutLayout::FIXED_HEIGHT, AmpLayoutLayout::FLEX_ITEM, AmpLayoutLayout::NODISPLAY, AmpLayoutLayout::RESPONSIVE]; - $o_565->amp_layout = $o_571; - $o_565->disallowed_ancestor = ['amp-sidebar']; + $o_569 = new AttrSpec(); + $o_569->name = 'type'; + $o_569->value = 'text/javascript'; + $o_565->attrs[] = $o_569; + $o_565->spec_url = 'https://www.ampproject.org/docs/reference/extended/amp-ad.html'; + $o_570 = new CdataSpec(); + $o_571 = new BlackListedCDataRegex(); + $o_571->regex = '.'; + $o_571->error_message = 'contents'; + $o_570->blacklisted_cdata_regex[] = $o_571; + $o_565->cdata = $o_570; $o_0->tags[] = $o_565; $o_572 = new TagSpec(); - $o_572->tag_name = 'amp-embed'; + $o_572->tag_name = 'amp-ad'; $o_573 = new AttrSpec(); $o_573->name = 'alt'; $o_572->attrs[] = $o_573; @@ -2403,723 +2409,717 @@ public static function createValidationRules() { $o_577->mandatory = true; $o_572->attrs[] = $o_577; $o_572->attr_lists = ['extended-amp-global']; - $o_572->spec_url = 'https://www.ampproject.org/docs/reference/amp-embed.html'; + $o_572->spec_url = 'https://www.ampproject.org/docs/reference/amp-ad.html'; $o_578 = new AmpLayout(); $o_578->supported_layouts = [AmpLayoutLayout::FILL, AmpLayoutLayout::FIXED, AmpLayoutLayout::FIXED_HEIGHT, AmpLayoutLayout::FLEX_ITEM, AmpLayoutLayout::NODISPLAY, AmpLayoutLayout::RESPONSIVE]; $o_572->amp_layout = $o_578; $o_572->disallowed_ancestor = ['amp-sidebar']; $o_0->tags[] = $o_572; $o_579 = new TagSpec(); - $o_579->tag_name = 'amp-img'; + $o_579->tag_name = 'amp-embed'; $o_580 = new AttrSpec(); $o_580->name = 'alt'; $o_579->attrs[] = $o_580; $o_581 = new AttrSpec(); - $o_581->name = 'attribution'; + $o_581->name = 'json'; $o_579->attrs[] = $o_581; $o_582 = new AttrSpec(); - $o_582->name = 'placeholder'; + $o_582->name = 'src'; + $o_583 = new UrlSpec(); + $o_583->allowed_protocol = ['https']; + $o_583->allow_relative = true; + $o_582->value_url = $o_583; $o_579->attrs[] = $o_582; - $o_579->attr_lists = ['extended-amp-global', 'mandatory-src-or-srcset']; - $o_579->spec_url = 'https://www.ampproject.org/docs/reference/amp-img.html'; - $o_583 = new AmpLayout(); - $o_583->supported_layouts = [AmpLayoutLayout::FILL, AmpLayoutLayout::FIXED, AmpLayoutLayout::FIXED_HEIGHT, AmpLayoutLayout::FLEX_ITEM, AmpLayoutLayout::NODISPLAY, AmpLayoutLayout::RESPONSIVE]; - $o_579->amp_layout = $o_583; + $o_584 = new AttrSpec(); + $o_584->name = 'type'; + $o_584->mandatory = true; + $o_579->attrs[] = $o_584; + $o_579->attr_lists = ['extended-amp-global']; + $o_579->spec_url = 'https://www.ampproject.org/docs/reference/amp-embed.html'; + $o_585 = new AmpLayout(); + $o_585->supported_layouts = [AmpLayoutLayout::FILL, AmpLayoutLayout::FIXED, AmpLayoutLayout::FIXED_HEIGHT, AmpLayoutLayout::FLEX_ITEM, AmpLayoutLayout::NODISPLAY, AmpLayoutLayout::RESPONSIVE]; + $o_579->amp_layout = $o_585; + $o_579->disallowed_ancestor = ['amp-sidebar']; $o_0->tags[] = $o_579; - $o_584 = new TagSpec(); - $o_584->tag_name = 'amp-pixel'; - $o_585 = new AttrSpec(); - $o_585->name = 'src'; - $o_585->mandatory = true; - $o_586 = new UrlSpec(); - $o_586->allowed_protocol = ['https']; - $o_586->allow_relative = true; - $o_585->value_url = $o_586; - $o_584->attrs[] = $o_585; - $o_584->attr_lists = ['extended-amp-global']; - $o_584->spec_url = 'https://www.ampproject.org/docs/reference/amp-pixel.html'; - $o_587 = new AmpLayout(); - $o_587->supported_layouts = [AmpLayoutLayout::FIXED, AmpLayoutLayout::NODISPLAY]; - $o_587->defines_default_width = true; - $o_587->defines_default_height = true; - $o_584->amp_layout = $o_587; - $o_584->disallowed_ancestor = ['amp-sidebar']; - $o_0->tags[] = $o_584; - $o_588 = new TagSpec(); - $o_588->tag_name = 'amp-video'; + $o_586 = new TagSpec(); + $o_586->tag_name = 'amp-img'; + $o_587 = new AttrSpec(); + $o_587->name = 'alt'; + $o_586->attrs[] = $o_587; + $o_588 = new AttrSpec(); + $o_588->name = 'attribution'; + $o_586->attrs[] = $o_588; $o_589 = new AttrSpec(); - $o_589->name = 'alt'; - $o_588->attrs[] = $o_589; - $o_590 = new AttrSpec(); - $o_590->name = 'attribution'; - $o_588->attrs[] = $o_590; - $o_591 = new AttrSpec(); - $o_591->name = 'autoplay'; - $o_591->value = ''; - $o_588->attrs[] = $o_591; + $o_589->name = 'placeholder'; + $o_586->attrs[] = $o_589; + $o_586->attr_lists = ['extended-amp-global', 'mandatory-src-or-srcset']; + $o_586->spec_url = 'https://www.ampproject.org/docs/reference/amp-img.html'; + $o_590 = new AmpLayout(); + $o_590->supported_layouts = [AmpLayoutLayout::FILL, AmpLayoutLayout::FIXED, AmpLayoutLayout::FIXED_HEIGHT, AmpLayoutLayout::FLEX_ITEM, AmpLayoutLayout::NODISPLAY, AmpLayoutLayout::RESPONSIVE]; + $o_586->amp_layout = $o_590; + $o_0->tags[] = $o_586; + $o_591 = new TagSpec(); + $o_591->tag_name = 'amp-pixel'; $o_592 = new AttrSpec(); - $o_592->name = 'controls'; - $o_592->value = ''; - $o_588->attrs[] = $o_592; - $o_593 = new AttrSpec(); - $o_593->name = 'loop'; - $o_593->value = ''; - $o_588->attrs[] = $o_593; - $o_594 = new AttrSpec(); - $o_594->name = 'muted'; - $o_594->value = ''; - $o_588->attrs[] = $o_594; - $o_595 = new AttrSpec(); - $o_595->name = 'placeholder'; - $o_588->attrs[] = $o_595; + $o_592->name = 'src'; + $o_592->mandatory = true; + $o_593 = new UrlSpec(); + $o_593->allowed_protocol = ['https']; + $o_593->allow_relative = true; + $o_592->value_url = $o_593; + $o_591->attrs[] = $o_592; + $o_591->attr_lists = ['extended-amp-global']; + $o_591->spec_url = 'https://www.ampproject.org/docs/reference/amp-pixel.html'; + $o_594 = new AmpLayout(); + $o_594->supported_layouts = [AmpLayoutLayout::FIXED, AmpLayoutLayout::NODISPLAY]; + $o_594->defines_default_width = true; + $o_594->defines_default_height = true; + $o_591->amp_layout = $o_594; + $o_591->disallowed_ancestor = ['amp-sidebar']; + $o_0->tags[] = $o_591; + $o_595 = new TagSpec(); + $o_595->tag_name = 'amp-video'; $o_596 = new AttrSpec(); - $o_596->name = 'poster'; - $o_588->attrs[] = $o_596; + $o_596->name = 'alt'; + $o_595->attrs[] = $o_596; $o_597 = new AttrSpec(); - $o_597->name = 'preload'; - $o_597->value_regex = '(none|metadata|auto|)'; - $o_588->attrs[] = $o_597; + $o_597->name = 'attribution'; + $o_595->attrs[] = $o_597; $o_598 = new AttrSpec(); - $o_598->name = 'src'; - $o_599 = new UrlSpec(); - $o_599->allowed_protocol = ['https']; - $o_599->allow_relative = true; - $o_598->value_url = $o_599; - $o_588->attrs[] = $o_598; - $o_588->attr_lists = ['extended-amp-global']; - $o_588->spec_url = 'https://www.ampproject.org/docs/reference/amp-video.html'; - $o_600 = new AmpLayout(); - $o_600->supported_layouts = [AmpLayoutLayout::FILL, AmpLayoutLayout::FIXED, AmpLayoutLayout::FIXED_HEIGHT, AmpLayoutLayout::FLEX_ITEM, AmpLayoutLayout::NODISPLAY, AmpLayoutLayout::RESPONSIVE]; - $o_588->amp_layout = $o_600; - $o_588->disallowed_ancestor = ['amp-sidebar']; - $o_0->tags[] = $o_588; - $o_601 = new TagSpec(); - $o_601->tag_name = 'script'; - $o_601->spec_name = 'amp-access extension .js script'; - $o_601->mandatory_parent = 'head'; + $o_598->name = 'autoplay'; + $o_598->value = ''; + $o_595->attrs[] = $o_598; + $o_599 = new AttrSpec(); + $o_599->name = 'controls'; + $o_599->value = ''; + $o_595->attrs[] = $o_599; + $o_600 = new AttrSpec(); + $o_600->name = 'loop'; + $o_600->value = ''; + $o_595->attrs[] = $o_600; + $o_601 = new AttrSpec(); + $o_601->name = 'muted'; + $o_601->value = ''; + $o_595->attrs[] = $o_601; $o_602 = new AttrSpec(); - $o_602->name = 'async'; - $o_602->mandatory = true; - $o_602->value = ''; - $o_601->attrs[] = $o_602; + $o_602->name = 'placeholder'; + $o_595->attrs[] = $o_602; $o_603 = new AttrSpec(); - $o_603->name = 'custom-element'; - $o_603->mandatory = true; - $o_603->value = 'amp-access'; - $o_603->dispatch_key = true; - $o_601->attrs[] = $o_603; + $o_603->name = 'poster'; + $o_595->attrs[] = $o_603; $o_604 = new AttrSpec(); - $o_604->name = 'src'; - $o_604->mandatory = true; - $o_604->value_regex = 'https://cdn\\.ampproject\\.org/v0/amp-access-(latest|0\\.1).js'; - $o_601->attrs[] = $o_604; + $o_604->name = 'preload'; + $o_604->value_regex = '(none|metadata|auto|)'; + $o_595->attrs[] = $o_604; $o_605 = new AttrSpec(); - $o_605->name = 'type'; - $o_605->value = 'text/javascript'; - $o_601->attrs[] = $o_605; - $o_601->spec_url = 'https://www.ampproject.org/docs/reference/extended/amp-access.html'; - $o_606 = new CdataSpec(); - $o_607 = new BlackListedCDataRegex(); - $o_607->regex = '.'; - $o_607->error_message = 'contents'; - $o_606->blacklisted_cdata_regex[] = $o_607; - $o_601->cdata = $o_606; - $o_0->tags[] = $o_601; + $o_605->name = 'src'; + $o_606 = new UrlSpec(); + $o_606->allowed_protocol = ['https']; + $o_606->allow_relative = true; + $o_605->value_url = $o_606; + $o_595->attrs[] = $o_605; + $o_595->attr_lists = ['extended-amp-global']; + $o_595->spec_url = 'https://www.ampproject.org/docs/reference/amp-video.html'; + $o_607 = new AmpLayout(); + $o_607->supported_layouts = [AmpLayoutLayout::FILL, AmpLayoutLayout::FIXED, AmpLayoutLayout::FIXED_HEIGHT, AmpLayoutLayout::FLEX_ITEM, AmpLayoutLayout::NODISPLAY, AmpLayoutLayout::RESPONSIVE]; + $o_595->amp_layout = $o_607; + $o_595->disallowed_ancestor = ['amp-sidebar']; + $o_0->tags[] = $o_595; $o_608 = new TagSpec(); $o_608->tag_name = 'script'; - $o_608->spec_name = 'amp-access extension .json script'; + $o_608->spec_name = 'amp-access extension .js script'; $o_608->mandatory_parent = 'head'; $o_609 = new AttrSpec(); - $o_609->name = 'id'; + $o_609->name = 'async'; $o_609->mandatory = true; - $o_609->value = 'amp-access'; - $o_609->dispatch_key = true; + $o_609->value = ''; $o_608->attrs[] = $o_609; $o_610 = new AttrSpec(); - $o_610->name = 'type'; + $o_610->name = 'custom-element'; $o_610->mandatory = true; - $o_610->value = 'application/json'; + $o_610->value = 'amp-access'; + $o_610->dispatch_key = true; $o_608->attrs[] = $o_610; - $o_608->spec_url = 'https://www.ampproject.org/docs/reference/extended/amp-access-spec.html'; - $o_611 = new CdataSpec(); - $o_612 = new BlackListedCDataRegex(); - $o_612->regex = ' From ab6eea9ef4e0dbd506d942c97cb8549167e95514 Mon Sep 17 00:00:00 2001 From: FuzzyTree Date: Sun, 25 Sep 2016 01:27:35 -0700 Subject: [PATCH 03/27] Add support for additional Facebook embed url schemas --- src/Pass/BaseFacebookPass.php | 49 +++++++++++++++++++ src/Pass/FacebookNonIframeTransformPass.php | 9 ++-- src/Pass/IframeFacebookTagTransformPass.php | 9 ++-- .../facebook-iframe-fragment.html | 4 ++ .../facebook-iframe-fragment.html.out | 11 ++++- .../facebook-non-iframe-fragment.html | 18 +++++++ .../facebook-non-iframe-fragment.html.out | 42 +++++++++++++--- 7 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 src/Pass/BaseFacebookPass.php diff --git a/src/Pass/BaseFacebookPass.php b/src/Pass/BaseFacebookPass.php new file mode 100644 index 00000000..0947d95f --- /dev/null +++ b/src/Pass/BaseFacebookPass.php @@ -0,0 +1,49 @@ +isValidVideoUrl($src)) { // A facebook video can be embedded as a post. Doing that enables the video "card" to display if ($el->attr('data-show-text') !== "false") { $embed_as = 'post'; @@ -118,8 +117,8 @@ protected function getFacebookEmbedAttrs(DOMQuery $el) } else { $embed_as = 'video'; } - } // e.g. https://www.facebook.com/20531316728/posts/10154009990506729/ - else if (preg_match('&(*UTF8)facebook\.com/.*/posts/\d+/?&i', $src)) { + } + elseif ($this->isValidPostUrl($src)) { $embed_as = 'post'; } else { return false; diff --git a/src/Pass/IframeFacebookTagTransformPass.php b/src/Pass/IframeFacebookTagTransformPass.php index 281aa377..f3883247 100644 --- a/src/Pass/IframeFacebookTagTransformPass.php +++ b/src/Pass/IframeFacebookTagTransformPass.php @@ -54,7 +54,7 @@ * @see https://github.com/ampproject/amphtml/blob/master/extensions/amp-facebook/amp-facebook.md * @see https://github.com/ampproject/amphtml/blob/master/extensions/amp-facebook/0.1/validator-amp-facebook.protoascii */ -class IframeFacebookTagTransformPass extends BasePass +class IframeFacebookTagTransformPass extends BaseFacebookPass { const DEFAULT_ASPECT_RATIO = 1.7778; const DEFAULT_WIDTH = 500; @@ -108,16 +108,15 @@ protected function setStandardFacebookParameters(DOMQuery $el) return false; } - // e.g https://www.facebook.com/facebook/videos/10153231379946729/ - if (preg_match('&(*UTF8)facebook\.com/facebook/videos/\d+/?&i', $query_arr['href'])) { + if ($this->isValidVideoUrl($query_arr['href'])) { // A facebook video can be embedded as a post. Doing that enables the video "card" to display if (isset($query_arr['show_text']) && $query_arr['show_text'] !== "false") { $embed_as = 'post'; } else { $embed_as = 'video'; } - } // e.g. https://www.facebook.com/20531316728/posts/10154009990506729/ - else if (preg_match('&(*UTF8)facebook\.com/.*/posts/\d+/?&i', $query_arr['href'])) { + } + elseif ($this->isValidPostUrl($query_arr['href'])) { $embed_as = 'post'; } else { return false; diff --git a/tests/test-data/fragment-html/facebook-iframe-fragment.html b/tests/test-data/fragment-html/facebook-iframe-fragment.html index b791dd49..0278e42b 100644 --- a/tests/test-data/fragment-html/facebook-iframe-fragment.html +++ b/tests/test-data/fragment-html/facebook-iframe-fragment.html @@ -13,3 +13,7 @@ width="500" height="290" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true"> + + diff --git a/tests/test-data/fragment-html/facebook-iframe-fragment.html.out b/tests/test-data/fragment-html/facebook-iframe-fragment.html.out index 0806b80e..c896abd2 100644 --- a/tests/test-data/fragment-html/facebook-iframe-fragment.html.out +++ b/tests/test-data/fragment-html/facebook-iframe-fragment.html.out @@ -7,6 +7,8 @@ + + ORIGINAL HTML @@ -26,7 +28,11 @@ Line 12: Line 15: -Line 16: +Line 16: +Line 17: +Line 20: Transformations made from HTML tags to AMP custom tags @@ -41,6 +47,9 @@ Transformations made from HTML tags to AMP custom tags \ No newline at end of file diff --git a/tests/test-data/fragment-html/youtube-02-fragment.html.out b/tests/test-data/fragment-html/youtube-02-fragment.html.out new file mode 100644 index 00000000..3a7c33ac --- /dev/null +++ b/tests/test-data/fragment-html/youtube-02-fragment.html.out @@ -0,0 +1,25 @@ + + +ORIGINAL HTML +--------------- +Line 1: + + +Transformations made from HTML tags to AMP custom tags +------------------------------------------------------- + + + * + * @see https://www.ampproject.org/docs/reference/extended/amp-hulu.html + * @see https://ampbyexample.com/components/amp-hulu/ + */ +class IframeHuluTagTransformPass extends BasePass +{ + function pass() + { + $all_iframes = $this->q->find('iframe:not(noscript iframe)'); + /** @var DOMQuery $el */ + foreach ($all_iframes as $el) { + /** @var \DOMElement $dom_el */ + $dom_el = $el->get(0); + $lineno = $this->getLineNo($dom_el); + $query = $this->getQueryArray($el); + // If we can't get the videoid, abort + if (empty($query['eid'])) { + continue; + } + $eid = $query['eid']; + $width = $el->attr('width') ?: 800; + $heigth = $el->attr('height') ?: 600; + + $context_string = $this->getContextString($dom_el); + + // width and height are intended to be aspect ratios here + $el->after(''); + $new_dom_el = $el->next()->get(0); + + $el->removeChildren()->remove(); + $this->addActionTaken(new ActionTakenLine('iframe', ActionTakenType::HULU_CONVERTED, $lineno, $context_string)); + + $this->context->addLineAssociation($new_dom_el, $lineno); + } + + return $this->transformations; + } +} diff --git a/src/Utility/ActionTakenType.php b/src/Utility/ActionTakenType.php index 0a9a8817..dfabc79f 100644 --- a/src/Utility/ActionTakenType.php +++ b/src/Utility/ActionTakenType.php @@ -33,6 +33,7 @@ class ActionTakenType const FACEBOOK_JSDK_CONVERTED = 'facebook javascript sdk embed code was converted to the amp-facebook tag.'; const FACEBOOK_SCRIPT_REMOVED = 'facebook script tag was removed.'; const VIMEO_CONVERTED = 'vimeo embed code was converted to the amp-vimeo tag.'; + const HULU_CONVERTED = 'hulu embed code was converted to the amp-hulu tag.'; const DAILYMOTION_CONVERTED = 'dailymotion embed code was converted to the amp-dailymotion tag.'; const TWITTER_CONVERTED = 'twitter embed code was converted to the amp-twitter tag.'; const IFRAME_CONVERTED = 'tag was converted to the amp-iframe tag.'; diff --git a/tests/test-data/fragment-html/hulu-fragment.html b/tests/test-data/fragment-html/hulu-fragment.html new file mode 100644 index 00000000..4f1c7869 --- /dev/null +++ b/tests/test-data/fragment-html/hulu-fragment.html @@ -0,0 +1 @@ + diff --git a/tests/test-data/fragment-html/hulu-fragment.html.out b/tests/test-data/fragment-html/hulu-fragment.html.out new file mode 100644 index 00000000..8f016137 --- /dev/null +++ b/tests/test-data/fragment-html/hulu-fragment.html.out @@ -0,0 +1,25 @@ + + + + +ORIGINAL HTML +--------------- +Line 1: +Line 2: + + +Transformations made from HTML tags to AMP custom tags +------------------------------------------------------- + + at line 1 + ACTION TAKEN: iframe (with associated script tag) hulu embed code was converted to the amp-hulu tag. + + +AMP-HTML Validation Issues and Fixes +------------------------------------- +PASS + +COMPONENT NAMES WITH JS PATH +------------------------------ +'amp-vine', include path 'https://cdn.ampproject.org/v0/amp-vine-0.1.js' + From c095c0d0f946a1a8a42a0359b410622fb0d8ce2e Mon Sep 17 00:00:00 2001 From: Daniel Wehner Date: Wed, 8 Feb 2017 15:47:04 +0100 Subject: [PATCH 10/27] fix typo --- src/Pass/IframeHuluTagTransformPass.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Pass/IframeHuluTagTransformPass.php b/src/Pass/IframeHuluTagTransformPass.php index cac1e630..09114fc7 100644 --- a/src/Pass/IframeHuluTagTransformPass.php +++ b/src/Pass/IframeHuluTagTransformPass.php @@ -50,12 +50,12 @@ function pass() } $eid = $query['eid']; $width = $el->attr('width') ?: 800; - $heigth = $el->attr('height') ?: 600; + $height = $el->attr('height') ?: 600; $context_string = $this->getContextString($dom_el); // width and height are intended to be aspect ratios here - $el->after(''); + $el->after(''); $new_dom_el = $el->next()->get(0); $el->removeChildren()->remove(); From dda5e38f6708e1bc0435ae86fe903d1a60793ff8 Mon Sep 17 00:00:00 2001 From: Daniel Wehner Date: Wed, 8 Feb 2017 15:59:41 +0100 Subject: [PATCH 11/27] Update the specfile generated by https://github.com/Lullabot/amphtml/pull/1 --- src/Spec/validator-generated.php | 11111 ++++++++++++++++++----------- 1 file changed, 6876 insertions(+), 4235 deletions(-) diff --git a/src/Spec/validator-generated.php b/src/Spec/validator-generated.php index 082bb58a..dd3d7fe8 100644 --- a/src/Spec/validator-generated.php +++ b/src/Spec/validator-generated.php @@ -63,6 +63,7 @@ class AttrSpec { public $mandatory = null; public $mandatory_oneof = null; public $value = null; + public $value_casei = null; public $value_regex = null; public $value_regex_casei = null; public $value_url = null; @@ -100,14 +101,11 @@ class ChildTagSpec { public $child_tag_name_oneof = []; } -class CssRuleSpec { -} - class CssSpec { public $at_rule_spec = []; - public $css_rule = []; public $image_url_spec = null; public $font_url_spec = null; + public $validate_amp4ads = null; } class ErrorCategory { @@ -132,6 +130,11 @@ class ErrorFormat { public $format = null; } +class ErrorSpecificity { + public $code = null; + public $specificity = null; +} + class PropertySpec { public $name = null; public $mandatory = null; @@ -143,31 +146,50 @@ class PropertySpecList { public $properties = []; } +class ReferencePoint { + public $tag_spec_name = null; + public $mandatory = null; + public $unique = null; +} + class TagSpec { + public $html_format = []; public $tag_name = null; public $spec_name = null; public $mandatory = null; public $mandatory_alternatives = null; public $unique = null; + public $unique_warning = null; public $mandatory_parent = null; public $mandatory_ancestor = null; public $mandatory_ancestor_suggested_alternative = null; public $disallowed_ancestor = []; public $also_requires_tag = []; + public $also_requires_tag_warning = []; + public $extension_unused_unless_tag_present = []; + public $satisfies = []; + public $requires = []; public $deprecation = null; public $deprecation_url = null; public $attrs = []; public $attr_lists = []; public $cdata = null; public $child_tags = null; + public $reference_points = []; public $spec_url = null; public $amp_layout = null; } +class TagSpecHtmlFormat { + const AMP = 'AMP'; + const AMP4ADS = 'AMP4ADS'; + +} class UrlSpec { public $allowed_protocol = []; public $allow_relative = null; public $allow_empty = null; + public $disallowed_domain = []; } class ValidationError { @@ -186,6 +208,8 @@ class ValidationErrorCode { const UNKNOWN_CODE = 'UNKNOWN_CODE'; const MANDATORY_TAG_MISSING = 'MANDATORY_TAG_MISSING'; const TAG_REQUIRED_BY_MISSING = 'TAG_REQUIRED_BY_MISSING'; + const WARNING_TAG_REQUIRED_BY_MISSING = 'WARNING_TAG_REQUIRED_BY_MISSING'; + const WARNING_EXTENSION_UNUSED = 'WARNING_EXTENSION_UNUSED'; const ATTR_REQUIRED_BUT_MISSING = 'ATTR_REQUIRED_BUT_MISSING'; const DISALLOWED_TAG = 'DISALLOWED_TAG'; const GENERAL_DISALLOWED_TAG = 'GENERAL_DISALLOWED_TAG'; @@ -198,6 +222,7 @@ class ValidationErrorCode { const MANDATORY_ONEOF_ATTR_MISSING = 'MANDATORY_ONEOF_ATTR_MISSING'; const DUPLICATE_DIMENSION = 'DUPLICATE_DIMENSION'; const DUPLICATE_UNIQUE_TAG = 'DUPLICATE_UNIQUE_TAG'; + const DUPLICATE_UNIQUE_TAG_WARNING = 'DUPLICATE_UNIQUE_TAG_WARNING'; const WRONG_PARENT_TAG = 'WRONG_PARENT_TAG'; const STYLESHEET_TOO_LONG_OLD_VARIANT = 'STYLESHEET_TOO_LONG_OLD_VARIANT'; const STYLESHEET_TOO_LONG = 'STYLESHEET_TOO_LONG'; @@ -211,6 +236,7 @@ class ValidationErrorCode { const MISSING_URL = 'MISSING_URL'; const INVALID_URL = 'INVALID_URL'; const INVALID_URL_PROTOCOL = 'INVALID_URL_PROTOCOL'; + const DISALLOWED_DOMAIN = 'DISALLOWED_DOMAIN'; const DISALLOWED_RELATIVE_URL = 'DISALLOWED_RELATIVE_URL'; const DISALLOWED_PROPERTY_IN_ATTR_VALUE = 'DISALLOWED_PROPERTY_IN_ATTR_VALUE'; const MUTUALLY_EXCLUSIVE_ATTRS = 'MUTUALLY_EXCLUSIVE_ATTRS'; @@ -226,6 +252,13 @@ class ValidationErrorCode { const INCORRECT_NUM_CHILD_TAGS = 'INCORRECT_NUM_CHILD_TAGS'; const DISALLOWED_CHILD_TAG_NAME = 'DISALLOWED_CHILD_TAG_NAME'; const DISALLOWED_FIRST_CHILD_TAG_NAME = 'DISALLOWED_FIRST_CHILD_TAG_NAME'; + const DISALLOWED_MANUFACTURED_BODY = 'DISALLOWED_MANUFACTURED_BODY'; + const CHILD_TAG_DOES_NOT_SATISFY_REFERENCE_POINT = 'CHILD_TAG_DOES_NOT_SATISFY_REFERENCE_POINT'; + const MANDATORY_REFERENCE_POINT_MISSING = 'MANDATORY_REFERENCE_POINT_MISSING'; + const DUPLICATE_REFERENCE_POINT = 'DUPLICATE_REFERENCE_POINT'; + const TAG_REFERENCE_POINT_CONFLICT = 'TAG_REFERENCE_POINT_CONFLICT'; + const CHILD_TAG_DOES_NOT_SATISFY_REFERENCE_POINT_SINGULAR = 'CHILD_TAG_DOES_NOT_SATISFY_REFERENCE_POINT_SINGULAR'; + const BASE_TAG_MUST_PRECEED_ALL_URLS = 'BASE_TAG_MUST_PRECEED_ALL_URLS'; const CSS_SYNTAX = 'CSS_SYNTAX'; const CSS_SYNTAX_INVALID_AT_RULE = 'CSS_SYNTAX_INVALID_AT_RULE'; const CSS_SYNTAX_STRAY_TRAILING_BACKSLASH = 'CSS_SYNTAX_STRAY_TRAILING_BACKSLASH'; @@ -242,16 +275,20 @@ class ValidationErrorCode { const CSS_SYNTAX_MISSING_URL = 'CSS_SYNTAX_MISSING_URL'; const CSS_SYNTAX_INVALID_URL = 'CSS_SYNTAX_INVALID_URL'; const CSS_SYNTAX_INVALID_URL_PROTOCOL = 'CSS_SYNTAX_INVALID_URL_PROTOCOL'; + const CSS_SYNTAX_DISALLOWED_DOMAIN = 'CSS_SYNTAX_DISALLOWED_DOMAIN'; const CSS_SYNTAX_DISALLOWED_RELATIVE_URL = 'CSS_SYNTAX_DISALLOWED_RELATIVE_URL'; const CSS_SYNTAX_INVALID_ATTR_SELECTOR = 'CSS_SYNTAX_INVALID_ATTR_SELECTOR'; + const CSS_SYNTAX_DISALLOWED_PROPERTY_VALUE = 'CSS_SYNTAX_DISALLOWED_PROPERTY_VALUE'; + const CSS_SYNTAX_DISALLOWED_PROPERTY_VALUE_WITH_HINT = 'CSS_SYNTAX_DISALLOWED_PROPERTY_VALUE_WITH_HINT'; + const CSS_SYNTAX_PROPERTY_DISALLOWED_WITHIN_AT_RULE = 'CSS_SYNTAX_PROPERTY_DISALLOWED_WITHIN_AT_RULE'; + const CSS_SYNTAX_PROPERTY_DISALLOWED_TOGETHER_WITH = 'CSS_SYNTAX_PROPERTY_DISALLOWED_TOGETHER_WITH'; + const CSS_SYNTAX_PROPERTY_REQUIRES_QUALIFICATION = 'CSS_SYNTAX_PROPERTY_REQUIRES_QUALIFICATION'; } class ValidationErrorSeverity { const UNKNOWN_SEVERITY = 'UNKNOWN_SEVERITY'; const ERROR = 'ERROR'; const WARNING = 'WARNING'; - const PROD_WARNING = 'PROD_WARNING'; - const DEV_WARNING = 'DEV_WARNING'; } class ValidationResult { @@ -280,13 +317,14 @@ class ValidatorRules { public $spec_file_revision = null; public $template_spec_url = null; public $error_formats = []; + public $error_specificity = []; } class ValidationRulesFactory { public static function createValidationRules() { $o_0 = new ValidatorRules(); $o_1 = new TagSpec(); - $o_1->tag_name = '!doctype'; + $o_1->tag_name = '!DOCTYPE'; $o_1->spec_name = 'html doctype'; $o_1->mandatory = true; $o_1->unique = true; @@ -296,13 +334,14 @@ public static function createValidationRules() { $o_2->mandatory = true; $o_2->value = ''; $o_1->attrs[] = $o_2; + $o_1->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; $o_0->tags[] = $o_1; $o_3 = new TagSpec(); - $o_3->tag_name = 'html'; + $o_3->tag_name = 'HTML'; $o_3->spec_name = 'html \u26a1 for top-level html'; $o_3->mandatory = true; $o_3->unique = true; - $o_3->mandatory_parent = '!doctype'; + $o_3->mandatory_parent = '!DOCTYPE'; $o_4 = new AttrSpec(); $o_4->name = '\u26a1'; $o_4->alternative_names = ['amp']; @@ -310,1598 +349,1686 @@ public static function createValidationRules() { $o_4->value = ''; $o_3->attrs[] = $o_4; $o_3->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; + $o_3->html_format = [TagSpecHtmlFormat::AMP]; $o_0->tags[] = $o_3; $o_5 = new TagSpec(); - $o_5->tag_name = 'head'; + $o_5->tag_name = 'HTML'; + $o_5->spec_name = 'html \u26a14ads for top-level html'; $o_5->mandatory = true; $o_5->unique = true; - $o_5->mandatory_parent = 'html'; - $o_5->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; + $o_5->mandatory_parent = '!DOCTYPE'; + $o_6 = new AttrSpec(); + $o_6->name = '\u26a14ads'; + $o_6->alternative_names = ['amp4ads']; + $o_6->mandatory = true; + $o_6->value = ''; + $o_5->attrs[] = $o_6; + $o_5->spec_url = 'https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md#a4a-format-rules'; + $o_5->html_format = [TagSpecHtmlFormat::AMP4ADS]; $o_0->tags[] = $o_5; - $o_6 = new TagSpec(); - $o_6->tag_name = 'title'; - $o_6->spec_name = 'title'; - $o_0->tags[] = $o_6; $o_7 = new TagSpec(); - $o_7->tag_name = 'base'; - $o_8 = new AttrSpec(); - $o_8->name = 'target'; - $o_8->value_regex_casei = '(_blank|_self)'; - $o_7->attrs[] = $o_8; + $o_7->tag_name = 'HEAD'; + $o_7->mandatory = true; + $o_7->unique = true; + $o_7->mandatory_parent = 'HTML'; + $o_7->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; $o_0->tags[] = $o_7; + $o_8 = new TagSpec(); + $o_8->tag_name = 'TITLE'; + $o_8->spec_name = 'title'; + $o_0->tags[] = $o_8; $o_9 = new TagSpec(); - $o_9->tag_name = 'link'; - $o_9->spec_name = 'link rel='; + $o_9->tag_name = 'BASE'; + $o_9->unique = true; + $o_9->mandatory_parent = 'HEAD'; $o_10 = new AttrSpec(); $o_10->name = 'href'; + $o_10->value = '/'; $o_9->attrs[] = $o_10; $o_11 = new AttrSpec(); - $o_11->name = 'rel'; - $o_11->mandatory = true; - $o_11->blacklisted_value_regex = '(^|\\s)(canonical|components|dns-prefetch|import|manifest|preconnect|prefetch|preload|prerender|serviceworker|stylesheet|subresource|)(\\s|$)'; + $o_11->name = 'target'; + $o_11->value_regex_casei = '(_blank|_self|_top)'; $o_9->attrs[] = $o_11; - $o_12 = new AttrSpec(); - $o_12->name = 'sizes'; - $o_9->attrs[] = $o_12; - $o_13 = new AttrSpec(); - $o_13->name = 'type'; - $o_9->attrs[] = $o_13; - $o_9->attr_lists = ['common-link-attrs']; - $o_9->disallowed_ancestor = ['template']; $o_0->tags[] = $o_9; - $o_14 = new TagSpec(); - $o_14->tag_name = 'link'; - $o_14->spec_name = 'link rel=canonical'; + $o_12 = new TagSpec(); + $o_12->tag_name = 'LINK'; + $o_12->spec_name = 'link rel='; + $o_13 = new AttrSpec(); + $o_13->name = 'href'; + $o_12->attrs[] = $o_13; + $o_14 = new AttrSpec(); + $o_14->name = 'rel'; $o_14->mandatory = true; - $o_14->unique = true; - $o_14->mandatory_parent = 'head'; + $o_14->blacklisted_value_regex = '(^|\\s)(canonical|components|import|manifest|serviceworker|stylesheet|subresource|)(\\s|$)'; + $o_12->attrs[] = $o_14; $o_15 = new AttrSpec(); - $o_15->name = 'href'; - $o_15->mandatory = true; - $o_16 = new UrlSpec(); - $o_16->allowed_protocol = ['http', 'https']; - $o_16->allow_relative = true; - $o_15->value_url = $o_16; - $o_14->attrs[] = $o_15; - $o_17 = new AttrSpec(); - $o_17->name = 'rel'; + $o_15->name = 'sizes'; + $o_12->attrs[] = $o_15; + $o_16 = new AttrSpec(); + $o_16->name = 'type'; + $o_12->attrs[] = $o_16; + $o_12->attr_lists = ['common-link-attrs']; + $o_12->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_12->disallowed_ancestor = ['TEMPLATE']; + $o_0->tags[] = $o_12; + $o_17 = new TagSpec(); + $o_17->tag_name = 'LINK'; + $o_17->spec_name = 'link rel=canonical'; $o_17->mandatory = true; - $o_17->value = 'canonical'; - $o_17->dispatch_key = true; - $o_14->attrs[] = $o_17; - $o_14->attr_lists = ['common-link-attrs']; - $o_14->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; - $o_0->tags[] = $o_14; - $o_18 = new TagSpec(); - $o_18->tag_name = 'link'; - $o_18->spec_name = 'link rel=stylesheet for fonts'; - $o_18->mandatory_parent = 'head'; - $o_19 = new AttrSpec(); - $o_19->name = 'href'; - $o_19->mandatory = true; - $o_19->value_regex = 'https://fonts\\.googleapis\\.com/css\\?.*|https://fonts\\.googleapis\\.com/icon\\?.*|https://fonts\\.googleapis\\.com/earlyaccess/.*\\.css|https://fast\\.fonts\\.net/.*|https://maxcdn\\.bootstrapcdn\\.com/font-awesome/.*'; - $o_18->attrs[] = $o_19; + $o_17->unique = true; + $o_17->mandatory_parent = 'HEAD'; + $o_18 = new AttrSpec(); + $o_18->name = 'href'; + $o_18->mandatory = true; + $o_18->blacklisted_value_regex = '__amp_source_origin'; + $o_19 = new UrlSpec(); + $o_19->allowed_protocol = ['http', 'https']; + $o_19->allow_relative = true; + $o_18->value_url = $o_19; + $o_17->attrs[] = $o_18; $o_20 = new AttrSpec(); $o_20->name = 'rel'; $o_20->mandatory = true; - $o_20->value = 'stylesheet'; $o_20->dispatch_key = true; - $o_18->attrs[] = $o_20; - $o_21 = new AttrSpec(); - $o_21->name = 'type'; - $o_21->value = 'text/css'; - $o_18->attrs[] = $o_21; + $o_20->value_casei = 'canonical'; + $o_17->attrs[] = $o_20; + $o_17->attr_lists = ['common-link-attrs']; + $o_17->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; + $o_17->html_format = [TagSpecHtmlFormat::AMP]; + $o_0->tags[] = $o_17; + $o_21 = new TagSpec(); + $o_21->tag_name = 'LINK'; + $o_21->spec_name = 'link rel=manifest'; + $o_21->mandatory_parent = 'HEAD'; $o_22 = new AttrSpec(); - $o_22->name = 'media'; - $o_18->attrs[] = $o_22; - $o_0->tags[] = $o_18; - $o_23 = new TagSpec(); - $o_23->tag_name = 'link'; - $o_23->spec_name = 'link itemprop=sameAs'; + $o_22->name = 'href'; + $o_22->mandatory = true; + $o_22->blacklisted_value_regex = '__amp_source_origin'; + $o_23 = new UrlSpec(); + $o_23->allowed_protocol = ['https']; + $o_23->allow_relative = true; + $o_22->value_url = $o_23; + $o_21->attrs[] = $o_22; $o_24 = new AttrSpec(); - $o_24->name = 'href'; + $o_24->name = 'rel'; $o_24->mandatory = true; - $o_23->attrs[] = $o_24; - $o_25 = new AttrSpec(); - $o_25->name = 'itemprop'; - $o_25->mandatory = true; - $o_25->value = 'sameAs'; - $o_25->dispatch_key = true; - $o_23->attrs[] = $o_25; - $o_23->attr_lists = ['common-link-attrs']; - $o_0->tags[] = $o_23; - $o_26 = new TagSpec(); - $o_26->tag_name = 'link'; - $o_26->spec_name = 'link itemprop='; + $o_24->dispatch_key = true; + $o_24->value_casei = 'manifest'; + $o_21->attrs[] = $o_24; + $o_21->attr_lists = ['common-link-attrs']; + $o_21->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_21->satisfies = ['amp-app-banner data source']; + $o_0->tags[] = $o_21; + $o_25 = new TagSpec(); + $o_25->tag_name = 'LINK'; + $o_25->spec_name = 'link rel=stylesheet for fonts'; + $o_25->mandatory_parent = 'HEAD'; + $o_26 = new AttrSpec(); + $o_26->name = 'async'; + $o_25->attrs[] = $o_26; $o_27 = new AttrSpec(); $o_27->name = 'href'; $o_27->mandatory = true; - $o_26->attrs[] = $o_27; + $o_27->value_regex = 'https://fonts\\.googleapis\\.com/css\\?.*|https://fonts\\.googleapis\\.com/icon\\?.*|https://fonts\\.googleapis\\.com/earlyaccess/.*\\.css|https://fast\\.fonts\\.net/.*|https://maxcdn\\.bootstrapcdn\\.com/font-awesome/([0-9]+\\.?)+/css/font-awesome\\.min\\.css(\\?.*)?|https://cloud\\.typography\\.com/[0-9]*/[0-9]*/css/fonts\\.css'; + $o_25->attrs[] = $o_27; $o_28 = new AttrSpec(); - $o_28->name = 'itemprop'; + $o_28->name = 'rel'; $o_28->mandatory = true; - $o_26->attrs[] = $o_28; - $o_26->attr_lists = ['common-link-attrs']; - $o_0->tags[] = $o_26; - $o_29 = new TagSpec(); - $o_29->tag_name = 'meta'; - $o_29->spec_name = 'meta charset=utf-8'; - $o_29->mandatory = true; - $o_29->unique = true; - $o_29->mandatory_parent = 'head'; + $o_28->dispatch_key = true; + $o_28->value_casei = 'stylesheet'; + $o_25->attrs[] = $o_28; + $o_29 = new AttrSpec(); + $o_29->name = 'type'; + $o_29->value_casei = 'text/css'; + $o_25->attrs[] = $o_29; $o_30 = new AttrSpec(); - $o_30->name = 'charset'; - $o_30->mandatory = true; - $o_30->value = 'utf-8'; - $o_30->dispatch_key = true; - $o_29->attrs[] = $o_30; - $o_29->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; - $o_0->tags[] = $o_29; - $o_31 = new TagSpec(); - $o_31->tag_name = 'meta'; - $o_31->spec_name = 'meta name=viewport'; - $o_31->mandatory = true; - $o_31->unique = true; - $o_31->mandatory_parent = 'head'; + $o_30->name = 'media'; + $o_25->attrs[] = $o_30; + $o_31 = new AttrSpec(); + $o_31->name = 'crossorigin'; + $o_25->attrs[] = $o_31; $o_32 = new AttrSpec(); - $o_32->name = 'content'; - $o_32->mandatory = true; - $o_33 = new PropertySpecList(); - $o_34 = new PropertySpec(); - $o_34->name = 'width'; + $o_32->name = 'integrity'; + $o_25->attrs[] = $o_32; + $o_25->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#custom-fonts'; + $o_0->tags[] = $o_25; + $o_33 = new TagSpec(); + $o_33->tag_name = 'LINK'; + $o_33->spec_name = 'link itemprop=sameAs'; + $o_34 = new AttrSpec(); + $o_34->name = 'href'; $o_34->mandatory = true; - $o_34->value = 'device-width'; - $o_33->properties[] = $o_34; - $o_35 = new PropertySpec(); - $o_35->name = 'height'; - $o_33->properties[] = $o_35; - $o_36 = new PropertySpec(); - $o_36->name = 'initial-scale'; - $o_33->properties[] = $o_36; - $o_37 = new PropertySpec(); - $o_37->name = 'minimum-scale'; + $o_33->attrs[] = $o_34; + $o_35 = new AttrSpec(); + $o_35->name = 'itemprop'; + $o_35->mandatory = true; + $o_35->dispatch_key = true; + $o_35->value_casei = 'sameas'; + $o_33->attrs[] = $o_35; + $o_33->attr_lists = ['common-link-attrs']; + $o_33->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_0->tags[] = $o_33; + $o_36 = new TagSpec(); + $o_36->tag_name = 'LINK'; + $o_36->spec_name = 'link itemprop='; + $o_37 = new AttrSpec(); + $o_37->name = 'href'; $o_37->mandatory = true; - $o_37->value_double = 1.0; - $o_33->properties[] = $o_37; - $o_38 = new PropertySpec(); - $o_38->name = 'maximum-scale'; - $o_33->properties[] = $o_38; - $o_39 = new PropertySpec(); - $o_39->name = 'shrink-to-fit'; - $o_33->properties[] = $o_39; - $o_40 = new PropertySpec(); - $o_40->name = 'user-scalable'; - $o_33->properties[] = $o_40; - $o_32->value_properties = $o_33; - $o_31->attrs[] = $o_32; + $o_36->attrs[] = $o_37; + $o_38 = new AttrSpec(); + $o_38->name = 'itemprop'; + $o_38->mandatory = true; + $o_36->attrs[] = $o_38; + $o_36->attr_lists = ['common-link-attrs']; + $o_36->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_0->tags[] = $o_36; + $o_39 = new TagSpec(); + $o_39->tag_name = 'LINK'; + $o_39->spec_name = 'link property='; + $o_40 = new AttrSpec(); + $o_40->name = 'href'; + $o_40->mandatory = true; + $o_39->attrs[] = $o_40; $o_41 = new AttrSpec(); - $o_41->name = 'name'; + $o_41->name = 'property'; $o_41->mandatory = true; - $o_41->value = 'viewport'; - $o_41->dispatch_key = true; - $o_31->attrs[] = $o_41; - $o_31->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; - $o_0->tags[] = $o_31; + $o_39->attrs[] = $o_41; + $o_39->attr_lists = ['common-link-attrs']; + $o_39->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_0->tags[] = $o_39; $o_42 = new TagSpec(); - $o_42->tag_name = 'meta'; - $o_42->spec_name = 'meta http-equiv=X-UA-Compatible'; + $o_42->tag_name = 'META'; + $o_42->spec_name = 'meta charset=utf-8'; + $o_42->mandatory = true; + $o_42->unique = true; + $o_42->mandatory_parent = 'HEAD'; $o_43 = new AttrSpec(); - $o_43->name = 'http-equiv'; + $o_43->name = 'charset'; $o_43->mandatory = true; - $o_43->value = 'X-UA-Compatible'; $o_43->dispatch_key = true; + $o_43->value_casei = 'utf-8'; $o_42->attrs[] = $o_43; - $o_44 = new AttrSpec(); - $o_44->name = 'content'; + $o_42->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; + $o_0->tags[] = $o_42; + $o_44 = new TagSpec(); + $o_44->tag_name = 'META'; + $o_44->spec_name = 'meta name=viewport'; $o_44->mandatory = true; - $o_45 = new PropertySpecList(); - $o_46 = new PropertySpec(); - $o_46->name = 'ie'; - $o_46->value = 'edge'; - $o_45->properties[] = $o_46; + $o_44->unique = true; + $o_44->mandatory_parent = 'HEAD'; + $o_45 = new AttrSpec(); + $o_45->name = 'content'; + $o_45->mandatory = true; + $o_46 = new PropertySpecList(); $o_47 = new PropertySpec(); - $o_47->name = 'chrome'; - $o_47->value = '1'; - $o_45->properties[] = $o_47; - $o_44->value_properties = $o_45; - $o_42->attrs[] = $o_44; - $o_0->tags[] = $o_42; - $o_48 = new TagSpec(); - $o_48->tag_name = 'meta'; - $o_48->spec_name = 'meta name= and content='; - $o_49 = new AttrSpec(); - $o_49->name = 'name'; - $o_49->blacklisted_value_regex = '(^|\\s)(viewport|content-disposition|revisit-after)(\\s|$)'; - $o_48->attrs[] = $o_49; - $o_50 = new AttrSpec(); - $o_50->name = 'content'; - $o_48->attrs[] = $o_50; - $o_51 = new AttrSpec(); - $o_51->name = 'property'; - $o_48->attrs[] = $o_51; - $o_52 = new AttrSpec(); - $o_52->name = 'itemprop'; - $o_48->attrs[] = $o_52; - $o_0->tags[] = $o_48; - $o_53 = new TagSpec(); - $o_53->tag_name = 'meta'; - $o_53->spec_name = 'meta http-equiv=content-type'; + $o_47->name = 'width'; + $o_47->mandatory = true; + $o_47->value = 'device-width'; + $o_46->properties[] = $o_47; + $o_48 = new PropertySpec(); + $o_48->name = 'height'; + $o_46->properties[] = $o_48; + $o_49 = new PropertySpec(); + $o_49->name = 'initial-scale'; + $o_46->properties[] = $o_49; + $o_50 = new PropertySpec(); + $o_50->name = 'minimum-scale'; + $o_50->mandatory = true; + $o_50->value_double = 1.0; + $o_46->properties[] = $o_50; + $o_51 = new PropertySpec(); + $o_51->name = 'maximum-scale'; + $o_46->properties[] = $o_51; + $o_52 = new PropertySpec(); + $o_52->name = 'shrink-to-fit'; + $o_46->properties[] = $o_52; + $o_53 = new PropertySpec(); + $o_53->name = 'user-scalable'; + $o_46->properties[] = $o_53; + $o_45->value_properties = $o_46; + $o_44->attrs[] = $o_45; $o_54 = new AttrSpec(); - $o_54->name = 'http-equiv'; + $o_54->name = 'name'; $o_54->mandatory = true; - $o_54->value = 'content-type'; + $o_54->value = 'viewport'; $o_54->dispatch_key = true; - $o_53->attrs[] = $o_54; - $o_55 = new AttrSpec(); - $o_55->name = 'content'; - $o_55->mandatory = true; - $o_55->value = 'text/html; charset=utf-8'; - $o_53->attrs[] = $o_55; - $o_0->tags[] = $o_53; - $o_56 = new TagSpec(); - $o_56->tag_name = 'meta'; - $o_56->spec_name = 'meta http-equiv=Content-Type'; + $o_44->attrs[] = $o_54; + $o_44->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#required-markup'; + $o_0->tags[] = $o_44; + $o_55 = new TagSpec(); + $o_55->tag_name = 'META'; + $o_55->spec_name = 'meta http-equiv=X-UA-Compatible'; + $o_56 = new AttrSpec(); + $o_56->name = 'http-equiv'; + $o_56->mandatory = true; + $o_56->dispatch_key = true; + $o_56->value_casei = 'x-ua-compatible'; + $o_55->attrs[] = $o_56; $o_57 = new AttrSpec(); - $o_57->name = 'http-equiv'; + $o_57->name = 'content'; $o_57->mandatory = true; - $o_57->value = 'Content-Type'; - $o_57->dispatch_key = true; - $o_56->attrs[] = $o_57; - $o_58 = new AttrSpec(); - $o_58->name = 'content'; - $o_58->mandatory = true; - $o_58->value = 'text/html; charset=utf-8'; - $o_56->attrs[] = $o_58; - $o_0->tags[] = $o_56; - $o_59 = new TagSpec(); - $o_59->tag_name = 'meta'; - $o_59->spec_name = 'meta http-equiv=content-language'; - $o_60 = new AttrSpec(); - $o_60->name = 'http-equiv'; - $o_60->mandatory = true; - $o_60->value = 'content-language'; - $o_60->dispatch_key = true; - $o_59->attrs[] = $o_60; - $o_61 = new AttrSpec(); - $o_61->name = 'content'; - $o_61->mandatory = true; - $o_59->attrs[] = $o_61; - $o_0->tags[] = $o_59; - $o_62 = new TagSpec(); - $o_62->tag_name = 'meta'; - $o_62->spec_name = 'meta http-equiv=pics-label'; + $o_58 = new PropertySpecList(); + $o_59 = new PropertySpec(); + $o_59->name = 'ie'; + $o_59->value = 'edge'; + $o_58->properties[] = $o_59; + $o_60 = new PropertySpec(); + $o_60->name = 'chrome'; + $o_60->value = '1'; + $o_58->properties[] = $o_60; + $o_57->value_properties = $o_58; + $o_55->attrs[] = $o_57; + $o_55->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_0->tags[] = $o_55; + $o_61 = new TagSpec(); + $o_61->tag_name = 'META'; + $o_61->spec_name = 'meta name=apple-itunes-app'; + $o_61->mandatory_parent = 'HEAD'; + $o_62 = new AttrSpec(); + $o_62->name = 'name'; + $o_62->mandatory = true; + $o_62->dispatch_key = true; + $o_62->value_casei = 'apple-itunes-app'; + $o_61->attrs[] = $o_62; $o_63 = new AttrSpec(); - $o_63->name = 'http-equiv'; + $o_63->name = 'content'; $o_63->mandatory = true; - $o_63->value = 'pics-label'; - $o_63->dispatch_key = true; - $o_62->attrs[] = $o_63; - $o_64 = new AttrSpec(); - $o_64->name = 'content'; - $o_64->mandatory = true; - $o_62->attrs[] = $o_64; - $o_0->tags[] = $o_62; - $o_65 = new TagSpec(); - $o_65->tag_name = 'meta'; - $o_65->spec_name = 'meta http-equiv=imagetoolbar'; + $o_63->value_regex = '.*app-id=.*'; + $o_61->attrs[] = $o_63; + $o_61->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_61->satisfies = ['amp-app-banner data source']; + $o_0->tags[] = $o_61; + $o_64 = new TagSpec(); + $o_64->tag_name = 'META'; + $o_64->spec_name = 'meta name= and content='; + $o_65 = new AttrSpec(); + $o_65->name = 'name'; + $o_65->blacklisted_value_regex = '(^|\\s)(viewport|content-disposition|revisit-after|apple-itunes-app)(\\s|$)'; + $o_64->attrs[] = $o_65; $o_66 = new AttrSpec(); - $o_66->name = 'http-equiv'; - $o_66->mandatory = true; - $o_66->value = 'imagetoolbar'; - $o_66->dispatch_key = true; - $o_65->attrs[] = $o_66; + $o_66->name = 'content'; + $o_64->attrs[] = $o_66; $o_67 = new AttrSpec(); - $o_67->name = 'content'; - $o_67->mandatory = true; - $o_65->attrs[] = $o_67; - $o_0->tags[] = $o_65; - $o_68 = new TagSpec(); - $o_68->tag_name = 'meta'; - $o_68->spec_name = 'meta http-equiv=Content-Style-Type'; - $o_69 = new AttrSpec(); - $o_69->name = 'http-equiv'; - $o_69->mandatory = true; - $o_69->value = 'Content-Style-Type'; - $o_69->dispatch_key = true; - $o_68->attrs[] = $o_69; + $o_67->name = 'property'; + $o_64->attrs[] = $o_67; + $o_68 = new AttrSpec(); + $o_68->name = 'itemprop'; + $o_64->attrs[] = $o_68; + $o_0->tags[] = $o_64; + $o_69 = new TagSpec(); + $o_69->tag_name = 'META'; + $o_69->spec_name = 'meta http-equiv=Content-Type'; $o_70 = new AttrSpec(); - $o_70->name = 'content'; + $o_70->name = 'http-equiv'; $o_70->mandatory = true; - $o_70->value = 'text/css'; - $o_68->attrs[] = $o_70; - $o_0->tags[] = $o_68; - $o_71 = new TagSpec(); - $o_71->tag_name = 'meta'; - $o_71->spec_name = 'meta http-equiv=Content-Script-Type'; - $o_72 = new AttrSpec(); - $o_72->name = 'http-equiv'; - $o_72->mandatory = true; - $o_72->value = 'Content-Script-Type'; - $o_72->dispatch_key = true; - $o_71->attrs[] = $o_72; + $o_70->dispatch_key = true; + $o_70->value_casei = 'content-type'; + $o_69->attrs[] = $o_70; + $o_71 = new AttrSpec(); + $o_71->name = 'content'; + $o_71->mandatory = true; + $o_71->value_casei = 'text/html; charset=utf-8'; + $o_69->attrs[] = $o_71; + $o_69->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_0->tags[] = $o_69; + $o_72 = new TagSpec(); + $o_72->tag_name = 'META'; + $o_72->spec_name = 'meta http-equiv=content-language'; $o_73 = new AttrSpec(); - $o_73->name = 'content'; + $o_73->name = 'http-equiv'; $o_73->mandatory = true; - $o_73->value = 'text/javascript'; - $o_71->attrs[] = $o_73; - $o_0->tags[] = $o_71; - $o_74 = new TagSpec(); - $o_74->tag_name = 'meta'; - $o_74->spec_name = 'meta http-equiv=resource-type'; - $o_75 = new AttrSpec(); - $o_75->name = 'http-equiv'; - $o_75->mandatory = true; - $o_75->value = 'RESOURCE-TYPE'; - $o_75->dispatch_key = true; - $o_74->attrs[] = $o_75; + $o_73->dispatch_key = true; + $o_73->value_casei = 'content-language'; + $o_72->attrs[] = $o_73; + $o_74 = new AttrSpec(); + $o_74->name = 'content'; + $o_74->mandatory = true; + $o_72->attrs[] = $o_74; + $o_72->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_0->tags[] = $o_72; + $o_75 = new TagSpec(); + $o_75->tag_name = 'META'; + $o_75->spec_name = 'meta http-equiv=pics-label'; $o_76 = new AttrSpec(); - $o_76->name = 'content'; + $o_76->name = 'http-equiv'; $o_76->mandatory = true; - $o_74->attrs[] = $o_76; - $o_0->tags[] = $o_74; - $o_77 = new TagSpec(); - $o_77->tag_name = 'style'; - $o_77->spec_name = 'style amp-custom'; - $o_77->unique = true; - $o_77->mandatory_parent = 'head'; - $o_78 = new AttrSpec(); - $o_78->name = 'amp-custom'; - $o_78->mandatory = true; - $o_78->value = ''; - $o_77->attrs[] = $o_78; + $o_76->dispatch_key = true; + $o_76->value_casei = 'pics-label'; + $o_75->attrs[] = $o_76; + $o_77 = new AttrSpec(); + $o_77->name = 'content'; + $o_77->mandatory = true; + $o_75->attrs[] = $o_77; + $o_75->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#html-tags'; + $o_0->tags[] = $o_75; + $o_78 = new TagSpec(); + $o_78->tag_name = 'META'; + $o_78->spec_name = 'meta http-equiv=imagetoolbar'; $o_79 = new AttrSpec(); - $o_79->name = 'type'; - $o_79->value = 'text/css'; - $o_77->attrs[] = $o_79; - $o_77->spec_url = 'https://www.ampproject.org/docs/reference/spec.html#stylesheets'; - $o_80 = new CdataSpec(); - $o_80->max_bytes = 50000; - $o_80->max_bytes_spec_url = 'https://www.ampproject.org/docs/reference/spec.html#maximum-size'; - $o_81 = new BlackListedCDataRegex(); - $o_81->regex = ' + diff --git a/tests/test-data/full-html/mandatory_dimensions.html.out b/tests/test-data/full-html/mandatory_dimensions.html.out index 206b6895..b90b2ecc 100644 --- a/tests/test-data/full-html/mandatory_dimensions.html.out +++ b/tests/test-data/full-html/mandatory_dimensions.html.out @@ -118,7 +118,7 @@ - + @@ -273,7 +273,7 @@ Line 110: Line 111: Line 112: Line 113: -Line 114: +Line 114: Line 115: Line 116: Line 117: From 514a7433fbbbf6a06ae10ddc444dbddd8f242fdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Gerbore?= Date: Fri, 27 Jan 2017 13:22:32 +0000 Subject: [PATCH 15/27] youtube-start-time : Fix IframeYotubeTransformPass::getYouTubeCode() --- src/Pass/IframeYouTubeTagTransformPass.php | 24 ++----- .../youtube-bad-fragment.html.out | 2 +- .../fragment-html/youtube-fragment.html | 32 ++++++++- .../fragment-html/youtube-fragment.html.out | 70 +++++++++++++++++-- 4 files changed, 104 insertions(+), 24 deletions(-) diff --git a/src/Pass/IframeYouTubeTagTransformPass.php b/src/Pass/IframeYouTubeTagTransformPass.php index e55b0ffa..46b8bcf5 100644 --- a/src/Pass/IframeYouTubeTagTransformPass.php +++ b/src/Pass/IframeYouTubeTagTransformPass.php @@ -113,6 +113,7 @@ protected function isYouTubeIframe(DOMQuery $el) * * @param DOMQuery $el * @return string + * */ protected function getYouTubeCode(DOMQuery $el) { @@ -120,24 +121,11 @@ protected function getYouTubeCode(DOMQuery $el) $youtube_code = ''; $href = $el->attr('src'); - // @todo there seem to be a lot of ways to embed a youtube video. We probably need to capture all patterns here - // The next one is the embed code that youtube gives you - if (preg_match('&(*UTF8)/embed/([^/?\&]+)&i', $href, $matches)) { - if (!empty($matches[1])) { - $youtube_code = $matches[1]; - return htmlspecialchars($youtube_code); - } - } - - if (preg_match('&(*UTF8)youtu\.be/([^/?\&]+)&i', $href, $matches)) { - if (!empty($matches[1])) { - $youtube_code = $matches[1]; - return htmlspecialchars($youtube_code); - } - } - - if (preg_match('!(*UTF8)watch\?v=([^&]+)!i', $href, $matches)) { - if (!empty($matches[1])) { + // This regex is supposed to catch all possible way to embed youtube video + if (preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $href, $matches)) + { + if (!empty($matches[1])) + { $youtube_code = $matches[1]; return htmlspecialchars($youtube_code); } diff --git a/tests/test-data/fragment-html/youtube-bad-fragment.html.out b/tests/test-data/fragment-html/youtube-bad-fragment.html.out index 4bd97cc4..259906ea 100644 --- a/tests/test-data/fragment-html/youtube-bad-fragment.html.out +++ b/tests/test-data/fragment-html/youtube-bad-fragment.html.out @@ -1,4 +1,4 @@ - + ORIGINAL HTML diff --git a/tests/test-data/fragment-html/youtube-fragment.html b/tests/test-data/fragment-html/youtube-fragment.html index eab435e2..f1207f1e 100644 --- a/tests/test-data/fragment-html/youtube-fragment.html +++ b/tests/test-data/fragment-html/youtube-fragment.html @@ -1,4 +1,34 @@ \ No newline at end of file + + + + + + + + + + + + + diff --git a/tests/test-data/fragment-html/youtube-fragment.html.out b/tests/test-data/fragment-html/youtube-fragment.html.out index d711b65a..21365f43 100644 --- a/tests/test-data/fragment-html/youtube-fragment.html.out +++ b/tests/test-data/fragment-html/youtube-fragment.html.out @@ -1,11 +1,55 @@ + + + + + + + + + + + + + ORIGINAL HTML --------------- -Line 1: +Line 1: +Line 5: +Line 6: +Line 10: +Line 11: +Line 15: +Line 16: +Line 20: +Line 21: +Line 25: +Line 26: +Line 30: +Line 31: +Line 35: Transformations made from HTML tags to AMP custom tags @@ -14,6 +58,24 @@ Transformations made from HTML tags to AMP custom tags -Line 2: +Line 2: Transformations made from HTML tags to AMP custom tags ------------------------------------------------------- - at line 1 - ACTION TAKEN: iframe (with associated script tag) hulu embed code was converted to the amp-hulu tag. +