Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update allowed tags/attributes from spec in amphtml to 2005050322002 #4701

Merged
merged 4 commits into from
May 20, 2020

Conversation

westonruter
Copy link
Member

@westonruter westonruter commented May 13, 2020

Previously #4548.

  • Run ./bin/amphtml-update.sh (lando ssh -c 'bash ./bin/amphtml-update.sh vendor/amphtml').
  • Examine diff for changelog.
  • Examine upstream diff to ensure nothing was missed.
  • Update spec generator as needed based on spec format changes.
  • Modify validating sanitizer based on changes to spec, if needed.
  • Add tests for key changes.

Changelog

  • Allow amp-state and template in amp-story-grid-layer.
  • Add show-tooltip attribute to a elements (only relevant to stories apparently).
  • Add support for [data-tweetid] AMP-bind attribute on amp-twitter.
  • Require src on amp-ad-custom elements.
  • Add amp-story-page-attachment[href] spec.
  • Remove blacklisted_value_regex from style attributes. This is not because !important is now allowed, but because the validator is now doing CSS parsing. This means font_url_spec and image_url_spec are removed from the CSS validator spec; a new doc_css_bytes property is added which apparently refers to gathering the byte length of style attributes to add to style[amp-custom], which isn't relevant for the plugin since all inline styles are transformed to style rules.
  • Add enterkeyhint attribute to input (and other input-like AMP components).
  • Recognize Google Fonts v2 stylesheet URLs and relax FontAwesome stylesheet URL allowlist.

Details

(
    PREV_VERSION=2004142326360;
    THIS_VERSION=2005050322002; 
    git checkout $THIS_VERSION;
    git diff $PREV_VERSION...$THIS_VERSION -w -- $( git ls-files | grep '.protoascii' );
    git checkout - > /dev/null
)
2004142326360...2005050322002
diff --git a/extensions/amp-ad-custom/validator-amp-ad-custom.protoascii b/extensions/amp-ad-custom/validator-amp-ad-custom.protoascii
index a6c8580be..c0afd0715 100644
--- a/extensions/amp-ad-custom/validator-amp-ad-custom.protoascii
+++ b/extensions/amp-ad-custom/validator-amp-ad-custom.protoascii
@@ -33,6 +33,7 @@ tags: {  # <amp-ad-custom>
   disallowed_ancestor: "AMP-APP-BANNER"
   attrs: {
     name: "src"
+    mandatory: true
     value_url: {
       protocol: "https"
       allow_relative: false
diff --git a/extensions/amp-list/validator-amp-list.protoascii b/extensions/amp-list/validator-amp-list.protoascii
index 9f490851a..49714710a 100644
--- a/extensions/amp-list/validator-amp-list.protoascii
+++ b/extensions/amp-list/validator-amp-list.protoascii
@@ -117,7 +117,6 @@ tags: {  # <amp-list> with mandatory src and/or [src] attr
   }
   attr_lists: "extended-amp-global"
   amp_layout: {
-    supported_layouts: CONTAINER
     supported_layouts: FILL
     supported_layouts: FIXED
     supported_layouts: FIXED_HEIGHT
@@ -214,6 +213,7 @@ tags: {  # <amp-list>
     value: "always"
     value: "no"
     value: "refresh"
+    value: "refresh-evaluate" # Experimental.
   }
   attrs: {
     name: "diffable"
@@ -242,7 +242,7 @@ tags: {  # <amp-list>
   }
   attr_lists: "extended-amp-global"
   amp_layout: {
-    supported_layouts: CONTAINER
+    supported_layouts: CONTAINER # Experimental, email-only.
     supported_layouts: FILL
     supported_layouts: FIXED
     supported_layouts: FIXED_HEIGHT
@@ -308,7 +308,6 @@ tags: {  # <amp-list>
   }
   attr_lists: "extended-amp-global"
   amp_layout: {
-    supported_layouts: CONTAINER
     supported_layouts: FILL
     supported_layouts: FIXED
     supported_layouts: FIXED_HEIGHT
diff --git a/extensions/amp-story/validator-amp-story.protoascii b/extensions/amp-story/validator-amp-story.protoascii
index 9b1c87daa..28f50ae94 100644
--- a/extensions/amp-story/validator-amp-story.protoascii
+++ b/extensions/amp-story/validator-amp-story.protoascii
@@ -621,7 +621,7 @@ descendant_tag_list: {
 }
 descendant_tag_list: {
   name: "amp-story-grid-layer-allowed-descendants"
-  tag: "A"
+  tag: "A" # `show-tooltip` attribute is whitelisted in validator-main.protoascii.
   tag: "ABBR"
   tag: "ADDRESS"
   tag: "AMP-ANALYTICS"
@@ -637,6 +637,7 @@ descendant_tag_list: {
   tag: "AMP-LIST"
   tag: "AMP-LIVE-LIST"
   tag: "AMP-PIXEL"
+  tag: "AMP-STATE"
   tag: "AMP-TIMEAGO"
   tag: "AMP-TWITTER"
   tag: "AMP-VIDEO"
@@ -736,6 +737,7 @@ descendant_tag_list: {
   tag: "TABLE"
   tag: "TBODY"
   tag: "TD"
+  tag: "TEMPLATE"
   tag: "TEXT"
   tag: "TEXTPATH"
   tag: "TFOOT"
@@ -755,9 +757,38 @@ descendant_tag_list: {
   tag: "VKERN"
   tag: "WBR"
 }
-tags: {  # <amp-story-page-attachment>
+tags: {  # <amp-story-page-attachment> with href
+  html_format: AMP
+  tag_name: "AMP-STORY-PAGE-ATTACHMENT"
+  spec_name: "amp-story-page-attachment[href]"
+  mandatory_ancestor: "AMP-STORY-PAGE"
+  mandatory_last_child: true
+  attrs: {
+    name: "layout"
+    mandatory: true
+    value: "nodisplay"
+  }
+  attrs: {
+    name: "theme"
+    value: "dark"
+    value: "light"
+  }
+  attrs: {
+    name: "href"
+    mandatory: true
+    value_url: {
+      protocol: "http"
+      protocol: "https"
+    }
+  }
+  child_tags: {
+    mandatory_num_child_tags: 0
+  }
+}
+tags: {  # <amp-story-page-attachment> with no href
   html_format: AMP
   tag_name: "AMP-STORY-PAGE-ATTACHMENT"
+  spec_name: "amp-story-page-attachment"
   mandatory_ancestor: "AMP-STORY-PAGE"
   descendant_tag_list: "amp-story-page-attachment-allowed-descendants"
   mandatory_last_child: true
diff --git a/extensions/amp-twitter/validator-amp-twitter.protoascii b/extensions/amp-twitter/validator-amp-twitter.protoascii
index 8922ff7ae..6a2c3fc48 100644
--- a/extensions/amp-twitter/validator-amp-twitter.protoascii
+++ b/extensions/amp-twitter/validator-amp-twitter.protoascii
@@ -104,6 +104,10 @@ tags: {  # <amp-twitter>
     name: "data-tweetid"
     mandatory_oneof: "['data-momentid', 'data-timeline-source-type', 'data-tweetid']"
   }
+  # <amp-bind>
+  attrs: {
+    name: "[data-tweetid]"
+  }
   attr_lists: "extended-amp-global"
   amp_layout: {
     supported_layouts: FILL
diff --git a/validator/validator-css.protoascii b/validator/validator-css.protoascii
index e4777e882..8de8067ba 100644
--- a/validator/validator-css.protoascii
+++ b/validator/validator-css.protoascii
@@ -14,16 +14,455 @@
 # limitations under the license.
 #
 
-# Defines how much css is allowed in the entire document. This is the sum of
-# `<style amp-custom>` and `style=` attribute inline CSS. If a CssLengthSpec
-# is not defined for a particular html_format, then no limit is enforced for
-# inline styles but a limit may be enforced on particular style tags. Those
-# would be defined in that tag's CdataSpec.
-css_length_spec: {
+declaration_list {
+  name: "BASIC_DECLARATIONS"
+  declaration: { name: "align-content" }
+  declaration: { name: "align-items" }
+  declaration: { name: "align-self" }
+  declaration: { name: "all" }
+  declaration: { name: "animation" }
+  declaration: { name: "animation-delay" }
+  declaration: { name: "animation-direction" }
+  declaration: { name: "animation-duration" }
+  declaration: { name: "animation-fill-mode" }
+  declaration: { name: "animation-iteration-count" }
+  declaration: { name: "animation-name" }
+  declaration: { name: "animation-play-state" }
+  declaration: { name: "animation-timing-function" }
+  declaration: { name: "backface-visibility" }
+  declaration: { name: "background" }
+  declaration: { name: "background-attachment" }
+  declaration: { name: "background-blend-mode" }
+  declaration: { name: "background-clip" }
+  declaration: { name: "background-color" }
+  declaration: { name: "background-image" }
+  declaration: { name: "background-origin" }
+  declaration: { name: "background-position" }
+  declaration: { name: "background-repeat" }
+  declaration: { name: "background-size" }
+  declaration: { name: "border" }
+  declaration: { name: "border-bottom" }
+  declaration: { name: "border-bottom-color" }
+  declaration: { name: "border-bottom-left-radius" }
+  declaration: { name: "border-bottom-right-radius" }
+  declaration: { name: "border-bottom-style" }
+  declaration: { name: "border-bottom-width" }
+  declaration: { name: "border-collapse" }
+  declaration: { name: "border-color" }
+  declaration: { name: "border-image" }
+  declaration: { name: "border-image-outset" }
+  declaration: { name: "border-image-repeat" }
+  declaration: { name: "border-image-slice" }
+  declaration: { name: "border-image-source" }
+  declaration: { name: "border-image-width" }
+  declaration: { name: "border-left" }
+  declaration: { name: "border-left-color" }
+  declaration: { name: "border-left-style" }
+  declaration: { name: "border-left-width" }
+  declaration: { name: "border-radius" }
+  declaration: { name: "border-right" }
+  declaration: { name: "border-right-color" }
+  declaration: { name: "border-right-style" }
+  declaration: { name: "border-right-width" }
+  declaration: { name: "border-spacing" }
+  declaration: { name: "border-style" }
+  declaration: { name: "border-top" }
+  declaration: { name: "border-top-color" }
+  declaration: { name: "border-top-left-radius" }
+  declaration: { name: "border-top-right-radius" }
+  declaration: { name: "border-top-style" }
+  declaration: { name: "border-top-width" }
+  declaration: { name: "border-width" }
+  declaration: { name: "bottom" }
+  declaration: { name: "box-decoration-break" }
+  declaration: { name: "box-shadow" }
+  declaration: { name: "box-sizing" }
+  declaration: { name: "break-after" }
+  declaration: { name: "break-before" }
+  declaration: { name: "break-inside" }
+  declaration: { name: "caption-side" }
+  declaration: { name: "caret-color" }
+  declaration: { name: "clear" }
+  declaration: { name: "clip" }
+  declaration: { name: "color" }
+  declaration: { name: "column-count" }
+  declaration: { name: "column-fill" }
+  declaration: { name: "column-gap" }
+  declaration: { name: "column-rule" }
+  declaration: { name: "column-rule-color" }
+  declaration: { name: "column-rule-style" }
+  declaration: { name: "column-rule-width" }
+  declaration: { name: "column-span" }
+  declaration: { name: "column-width" }
+  declaration: { name: "columns" }
+  declaration: { name: "content" }
+  declaration: { name: "counter-increment" }
+  declaration: { name: "counter-reset" }
+  declaration: { name: "cursor" }
+  declaration: { name: "direction" }
+  declaration: { name: "display" }
+  declaration: { name: "empty-cells" }
+  declaration: { name: "filter" }
+  declaration: { name: "flex" }
+  declaration: { name: "flex-basis" }
+  declaration: { name: "flex-direction" }
+  declaration: { name: "flex-flow" }
+  declaration: { name: "flex-grow" }
+  declaration: { name: "flex-shrink" }
+  declaration: { name: "flex-wrap" }
+  declaration: { name: "float" }
+  declaration: { name: "font" }
+  declaration: { name: "font-family" }
+  declaration: { name: "font-feature-settings" }
+  declaration: { name: "font-kerning" }
+  declaration: { name: "font-language-override" }
+  declaration: { name: "font-size" }
+  declaration: { name: "font-size-adjust" }
+  declaration: { name: "font-stretch" }
+  declaration: { name: "font-style" }
+  declaration: { name: "font-synthesis" }
+  declaration: { name: "font-variant" }
+  declaration: { name: "font-variant-alternates" }
+  declaration: { name: "font-variant-caps" }
+  declaration: { name: "font-variant-east-asian" }
+  declaration: { name: "font-variant-ligatures" }
+  declaration: { name: "font-variant-numeric" }
+  declaration: { name: "font-variant-position" }
+  declaration: { name: "font-weight" }
+  declaration: { name: "grid" }
+  declaration: { name: "grid-area" }
+  declaration: { name: "grid-auto-columns" }
+  declaration: { name: "grid-auto-flow" }
+  declaration: { name: "grid-auto-rows" }
+  declaration: { name: "grid-column" }
+  declaration: { name: "grid-column-end" }
+  declaration: { name: "grid-column-gap" }
+  declaration: { name: "grid-column-start" }
+  declaration: { name: "grid-gap" }
+  declaration: { name: "grid-row" }
+  declaration: { name: "grid-row-end" }
+  declaration: { name: "grid-row-gap" }
+  declaration: { name: "grid-row-start" }
+  declaration: { name: "grid-template" }
+  declaration: { name: "grid-template-areas" }
+  declaration: { name: "grid-template-columns" }
+  declaration: { name: "grid-template-rows" }
+  declaration: { name: "hanging-punctuation" }
+  declaration: { name: "height" }
+  declaration: { name: "hyphens" }
+  declaration: { name: "image-rendering" }
+  declaration: { name: "isolation" }
+  declaration: { name: "justify-content" }
+  declaration: { name: "left" }
+  declaration: { name: "letter-spacing" }
+  declaration: { name: "line-break" }
+  declaration: { name: "line-height" }
+  declaration: { name: "list-style" }
+  declaration: { name: "list-style-image" }
+  declaration: { name: "list-style-position" }
+  declaration: { name: "list-style-type" }
+  declaration: { name: "margin" }
+  declaration: { name: "margin-bottom" }
+  declaration: { name: "margin-left" }
+  declaration: { name: "margin-right" }
+  declaration: { name: "margin-top" }
+  declaration: { name: "max-height" }
+  declaration: { name: "max-width" }
+  declaration: { name: "min-height" }
+  declaration: { name: "min-width" }
+  declaration: { name: "mix-blend-mode" }
+  declaration: { name: "object-fit" }
+  declaration: { name: "object-position" }
+  declaration: { name: "opacity" }
+  declaration: { name: "order" }
+  declaration: { name: "orphans" }
+  declaration: { name: "outline" }
+  declaration: { name: "outline-color" }
+  declaration: { name: "outline-offset" }
+  declaration: { name: "outline-style" }
+  declaration: { name: "outline-width" }
+  declaration: { name: "overflow" }
+  declaration: { name: "overflow-wrap" }
+  declaration: { name: "overflow-x" }
+  declaration: { name: "overflow-y" }
+  declaration: { name: "padding" }
+  declaration: { name: "padding-bottom" }
+  declaration: { name: "padding-left" }
+  declaration: { name: "padding-right" }
+  declaration: { name: "padding-top" }
+  declaration: { name: "page-break-after" }
+  declaration: { name: "page-break-before" }
+  declaration: { name: "page-break-inside" }
+  declaration: { name: "perspective" }
+  declaration: { name: "perspective-origin" }
+  declaration: { name: "pointer-events" }
+  # CSS property `position` with values `fixed` and `sticky are not allowed.
+  # From https://www.w3schools.com/cssref/pr_class_position.asp
+  declaration: {
+    name: "position"
+    value_casei: "absolute"
+    value_casei: "inherit"
+    value_casei: "initial"
+    value_casei: "relative"
+    value_casei: "static"
+  }
+  declaration: { name: "quotes" }
+  declaration: { name: "resize" }
+  declaration: { name: "right" }
+  declaration: { name: "tab-size" }
+  declaration: { name: "table-layout" }
+  declaration: { name: "text-align" }
+  declaration: { name: "text-align-last" }
+  declaration: { name: "text-combine-upright" }
+  declaration: { name: "text-decoration" }
+  declaration: { name: "text-decoration-color" }
+  declaration: { name: "text-decoration-line" }
+  declaration: { name: "text-decoration-style" }
+  declaration: { name: "text-fill-color" }
+  declaration: { name: "text-indent" }
+  declaration: { name: "text-justify" }
+  declaration: { name: "text-orientation" }
+  declaration: { name: "text-overflow" }
+  declaration: { name: "text-shadow" }
+  declaration: { name: "text-stroke" }
+  declaration: { name: "text-stroke-color" }
+  declaration: { name: "text-stroke-width" }
+  declaration: { name: "text-transform" }
+  declaration: { name: "text-underline-position" }
+  declaration: { name: "top" }
+  declaration: { name: "transform" }
+  declaration: { name: "transform-origin" }
+  declaration: { name: "transform-style" }
+  declaration: { name: "transition" }
+  declaration: { name: "transition-delay" }
+  declaration: { name: "transition-duration" }
+  declaration: { name: "transition-property" }
+  declaration: { name: "transition-timing-function" }
+  declaration: { name: "unicode-bidi" }
+  declaration: { name: "user-select" }
+  declaration: { name: "vertical-align" }
+  declaration: { name: "visibility" }
+  declaration: { name: "white-space" }
+  declaration: { name: "widows" }
+  declaration: { name: "width" }
+  declaration: { name: "word-break" }
+  declaration: { name: "word-spacing" }
+  declaration: { name: "word-wrap" }
+  declaration: { name: "writing-mode" }
+  declaration: { name: "z-index" }
+}
+
+declaration_list {
+  name: "SVG_BASIC_DECLARATIONS"
+  # SVG specific properties:
+  # https://www.w3.org/TR/SVG11/styling.html#SVGStylingProperties
+  declaration: { name: "alignment-baseline" }
+  declaration: { name: "baseline-shift" }
+  declaration: { name: "clip-path" }
+  declaration: { name: "clip-rule" }
+  declaration: { name: "color-interpolation" }
+  declaration: { name: "color-interpolation-filters" }
+  declaration: { name: "color-profile" } # SVG
+  declaration: { name: "color-rendering" } # SVG
+  declaration: { name: "dominant-baseline" }
+  declaration: { name: "enable-background" }
+  declaration: { name: "fill" }
+  declaration: { name: "fill-opacity" }
+  declaration: { name: "fill-rule" }
+  declaration: { name: "flood-color" }
+  declaration: { name: "flood-opacity" }
+  declaration: { name: "glyph-orientation-horizontal" }
+  declaration: { name: "glyph-orientation-vertical" }
+  declaration: { name: "kerning" }
+  declaration: { name: "lighting-color" }
+  declaration: { name: "marker" }
+  declaration: { name: "marker-end" }
+  declaration: { name: "marker-mid" }
+  declaration: { name: "marker-start" }
+  declaration: { name: "mask" }
+  declaration: { name: "shape-rendering" }
+  declaration: { name: "stop-color" }
+  declaration: { name: "stop-opacity" }
+  declaration: { name: "stroke" }
+  declaration: { name: "stroke-dasharray" }
+  declaration: { name: "stroke-dashoffset" }
+  declaration: { name: "stroke-linecap" }
+  declaration: { name: "stroke-linejoin" }
+  declaration: { name: "stroke-miterlimit" }
+  declaration: { name: "stroke-opacity" }
+  declaration: { name: "stroke-width" }
+  declaration: { name: "text-anchor" }
+  declaration: { name: "text-rendering" }
+}
+
+declaration_list {
+  name: "AMP_ONLY_DECLARATIONS"
+  declaration: { name: "clip-path" }
+}
+
+# DocCSS rules for AMP for non-transformed documents.
+css {
   html_format: AMP
+  disabled_by: "transformed"
+  spec_url:
+  "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#stylesheets"
+
   max_bytes: 75000
   max_bytes_per_inline_style: 1000
-  spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
+  max_bytes_spec_url:
+  "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
+  url_bytes_included: true
+
+  # This is a legacy requirement. Style tags support all declarations while
+  # style attributes limit the allowed declarations. Support for style
+  # attributes was added at a later date than style tags, and more validation
+  # requirements were able to be enforced at that time.
+  allow_all_declaration_in_style_tag: true
+  allow_important: false
+  image_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  font_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  expand_vendor_prefixes: true
+  declaration_list: "BASIC_DECLARATIONS"
+  declaration_list_svg: "SVG_BASIC_DECLARATIONS"
+  declaration_list: "AMP_ONLY_DECLARATIONS"
+}
+
+# DocCss Rules for AMP transformed documents.
+# Identical to the non-transformed specification except that
+# `url_bytes_included` is false.
+css {
+  html_format: AMP
+  enabled_by: "transformed"
+  spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#stylesheets"
+
+  max_bytes: 75000
+  max_bytes_per_inline_style: 1000
+  max_bytes_spec_url:
+  "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
+  url_bytes_included: false
+
+  allow_all_declaration_in_style_tag: true
+  allow_important: false
+  image_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  font_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  expand_vendor_prefixes: true
+  declaration_list: "BASIC_DECLARATIONS"
+  declaration_list_svg: "SVG_BASIC_DECLARATIONS"
+  declaration_list: "AMP_ONLY_DECLARATIONS"
+}
+
+# DocCss rules for ACTIONS
+css {
+  html_format: ACTIONS
+  spec_url:
+  "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#stylesheets"
+
+  # Due to a bug, we allowed unlimited doc-level bytes for CSS in ACTIONS
+  # formats. To avoid breaking existing docs, this is temporarily allowed until
+  # we determine the next course of action.
+  # max_bytes: 75000
+  # max_bytes_per_inline_style: 1000
+  max_bytes_spec_url:
+  "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
+  url_bytes_included: true
+
+  allow_all_declaration_in_style_tag: true
+  allow_important: false
+  image_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  font_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  expand_vendor_prefixes: true
+  declaration_list: "BASIC_DECLARATIONS"
+  declaration_list_svg: "SVG_BASIC_DECLARATIONS"
+}
+
+# DocCss rules for AMP4ADS.
+css {
+  html_format: AMP4ADS
+  spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/a4a_spec#css"
+
+  # AMP4ADS currently allows unlimited inline style, and only limits style in
+  # the <style amp-custom> tag in the document head.
+  # max_bytes: 20000
+  # max_bytes_per_inline_style: 1000
+  max_bytes_spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/a4a_spec#css"
+
+  allow_all_declaration_in_style_tag: true
+  allow_important: false
+  image_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  font_url_spec: {
+    protocol: "https"
+    protocol: "http"
+    protocol: "data"
+    allow_empty: true
+  }
+  expand_vendor_prefixes: true
+  declaration_list: "BASIC_DECLARATIONS"
+  declaration_list_svg: "SVG_BASIC_DECLARATIONS"
+}
+
+# DocCss rules for AMP4EMAIL
+css {
+  html_format: AMP4EMAIL
+  spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#stylesheets"
+
+  # Due to a bug, we allowed unlimited doc-level bytes for CSS in AMP4EMAIL
+  # formats. To avoid breaking emails, this is temporarily set to a warning but
+  # we intend to change to an error at a later time.
+  max_bytes_is_warning: true
+  max_bytes: 75000
+  max_bytes_per_inline_style: 1000
+
+  max_bytes_spec_url:
+  "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
+  url_bytes_included: true
+
+  # This is a legacy requirement. Style tags support all declarations while
+  # style attributes limit the allowed declarations. Support for style
+  # attributes was added at a later date than style tags, and more validation
+  # requirements were able to be enforced at that time.
+  allow_all_declaration_in_style_tag: true
+  allow_important: false
+  image_url_spec: {
+    protocol: "https"
+  }
+  expand_vendor_prefixes: true
+  declaration_list: "BASIC_DECLARATIONS"
+  declaration_list_svg: "SVG_BASIC_DECLARATIONS"
 }
 
 # This variant of <style amp-custom> is designed to help developers see how
@@ -62,7 +501,6 @@ tags: {  # <style amp-custom-length-check>, ALL FORMATS
 tags: {  # <style amp-custom>, [AMP, ACTIONS]
   html_format: AMP
   html_format: ACTIONS
-  disabled_by: "transformed"
   tag_name: "STYLE"
   spec_name: "style amp-custom"
   named_id: STYLE_AMP_CUSTOM
@@ -84,127 +522,17 @@ tags: {  # <style amp-custom>, [AMP, ACTIONS]
     value_casei: "text/css"
   }
   cdata: {
+    doc_css_bytes: true
     max_bytes: 75000
-    max_bytes_spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
-    css_spec: {
-      at_rule_spec: {
-        name: 'font-face'
-        type: PARSE_AS_DECLARATIONS
-      }
-      at_rule_spec: {
-        name: 'keyframes'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: 'media'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: 'page'
-        type: PARSE_AS_DECLARATIONS
-      }
-      at_rule_spec: {
-        name: 'supports'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: '$DEFAULT'  # matches if none of the above match
-        type: PARSE_AS_ERROR
-      }
-      image_url_spec: {
-        protocol: "https"
-        protocol: "http"
-        protocol: "data"
-        protocol: "absolute"  # Temporary / will go away.
-        allow_empty: true
-      }
-      font_url_spec: {
-        protocol: "https"
-        protocol: "http"
-        protocol: "data"
-        allow_empty: true
-      }
-    }
-    blacklisted_cdata_regex: {
-      regex: "<!--"
-      error_message: "html comments"
-    }
-    # These regex blacklists are temporary hacks to validate essential CSS
-    # rules. They will be replaced later with more principled solutions.
-    blacklisted_cdata_regex: {
-      regex: "(^|\\W)i-amphtml-"
-      error_message: "CSS i-amphtml- name prefix"
-    }
-  }
-  spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#stylesheets"
-}
+    max_bytes_spec_url:
+    "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
 
-tags: {  # `<style amp-custom>`, transformed [AMP, ACTIONS]
-  html_format: AMP
-  html_format: ACTIONS
-  enabled_by: "transformed"
-  tag_name: "STYLE"
-  spec_name: "style amp-custom (transformed)"
-  unique: true
-  mandatory_parent: "HEAD"
-  attrs: {
-    name: "amp-custom"
-    mandatory: true
-    value: ""
-    # This is a fine dispatch key, but we would prefer that this tagspec
-    # is used for errors related to <style> tags missing the amp-custom
-    # attribute rather than the boilerplate tagspec which doesn't have an
-    # attribute and thus can't have a dispatch_key.
-    # dispatch_key: NAME_DISPATCH
-  }
-  attrs: {  # Allow the default.
-    name: "type"
-    value_casei: "text/css"
-  }
-  cdata: {
-    max_bytes: 75000
-    # For transformed AMP non-data URLs are not counted against the total byte
-    # limit for <style amp-custom>.
-    url_bytes_included: false
-    max_bytes_spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
     css_spec: {
-      at_rule_spec: {
-        name: 'font-face'
-        type: PARSE_AS_DECLARATIONS
-      }
-      at_rule_spec: {
-        name: 'keyframes'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: 'media'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: 'page'
-        type: PARSE_AS_DECLARATIONS
-      }
-      at_rule_spec: {
-        name: 'supports'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: '$DEFAULT'  # matches if none of the above match
-        type: PARSE_AS_ERROR
-      }
-      image_url_spec: {
-        protocol: "https"
-        protocol: "http"
-        protocol: "data"
-        protocol: "absolute"  # Temporary / will go away.
-        allow_empty: true
-      }
-      font_url_spec: {
-        protocol: "https"
-        protocol: "http"
-        protocol: "data"
-        allow_empty: true
-      }
+      at_rule_spec: { name: 'font-face' }
+      at_rule_spec: { name: 'keyframes' }
+      at_rule_spec: { name: 'media' }
+      at_rule_spec: { name: 'page' }
+      at_rule_spec: { name: 'supports' }
     }
     blacklisted_cdata_regex: {
       regex: "<!--"
@@ -242,20 +570,15 @@ tags: {  # <style amp-custom>, AMP4ADS
     value_casei: "text/css"
   }
   cdata: {
+    doc_css_bytes: true
     max_bytes: 20000  # Smaller than AMP, which is 75,000.
-    max_bytes_spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/a4a_spec#css"
+    max_bytes_spec_url:
+    "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
     css_spec: {
-      at_rule_spec: {
-        name: 'font-face'
-        type: PARSE_AS_DECLARATIONS
-      }
-      at_rule_spec: {
-        name: 'keyframes'
-        type: PARSE_AS_RULES
-      }
+      at_rule_spec: { name: 'font-face' }
+      at_rule_spec: { name: 'keyframes' }
       at_rule_spec: {
         name: 'media'
-        type: PARSE_AS_RULES
         media_query_spec: {
           issues_as_error: false
           type: 'all'
@@ -269,27 +592,7 @@ tags: {  # <style amp-custom>, AMP4ADS
           feature: 'resolution'
         }
       }
-      at_rule_spec: {
-        name: 'supports'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: '$DEFAULT'  # matches if none of the above match
-        type: PARSE_AS_ERROR
-      }
-      image_url_spec: {
-        protocol: "https"
-        protocol: "http"
-        protocol: "data"
-        protocol: "absolute"  # Temporary / will go away.
-        allow_empty: true
-      }
-      font_url_spec: {
-        protocol: "https"
-        protocol: "http"
-        protocol: "data"
-        allow_empty: true
-      }
+      at_rule_spec: { name: 'supports' }
       validate_amp4ads: true
     }
     blacklisted_cdata_regex: {
@@ -328,12 +631,14 @@ tags: {  # <style amp-custom>, AMP4EMAIL
   }
   # TODO(b/68756045): Whitelist CSS properties allowed in Dynamic Mail.
   cdata: {
+    doc_css_bytes: true
     max_bytes: 75000
-    max_bytes_spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
+    max_bytes_spec_url:
+    "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#maximum-size"
+
     css_spec: {
       at_rule_spec: {
         name: 'media'
-        type: PARSE_AS_RULES
         media_query_spec: {
           issues_as_error: true
           type: 'all'
@@ -345,17 +650,7 @@ tags: {  # <style amp-custom>, AMP4EMAIL
           feature: 'width'
         }
       }
-      at_rule_spec: {
-        name: 'page'
-        type: PARSE_AS_DECLARATIONS
-      }
-      at_rule_spec: {
-        name: '$DEFAULT'  # matches if none of the above match
-        type: PARSE_AS_ERROR
-      }
-      image_url_spec: {
-        protocol: "https"
-      }
+      at_rule_spec: { name: 'page' }
     }
     blacklisted_cdata_regex: {
       regex: "<!--"
@@ -388,6 +683,7 @@ tags: {  # `<style amp-boilerplate>`, [AMP, ACTIONS]
     dispatch_key: NAME_VALUE_PARENT_DISPATCH
   }
   cdata: {
+    doc_css_bytes: false
     # This regex allows arbitrary whitespace whenever some whitespace
     # is required in the boilerplate. It was made by replacing ' ' with \\s+.
     cdata_regex: "\\s*body\\s*{\\s*-webkit-animation:\\s*-amp-start\\s+8s\\s+steps\\(1,\\s*end\\)\\s+0s\\s+1\\s+normal\\s+both;\\s*-moz-animation:\\s*-amp-start\\s+8s\\s+steps\\s*\\(1\\s*,\\s*end\\s*\\)\\s+0s\\s+1\\s+normal\\s+both;\\s*-ms-animation:\\s*-amp-start\\s+8s\\s+steps\\s*\\(1\\s*,\\s*end\\s*\\)\\s+0s\\s+1\\s+normal\\s+both;\\s*animation:\\s*-amp-start\\s+8s\\s+steps\\(1,\\s*end\\)\\s+0s\\s+1\\s+normal\\s+both;?\\s*}\\s*@-webkit-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@-moz-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@-ms-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@-o-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*"
@@ -410,6 +706,7 @@ tags: {  # `<style amp-boilerplate>`, transformed [AMP, ACTIONS]
     dispatch_key: NAME_VALUE_PARENT_DISPATCH
   }
   cdata: {
+    doc_css_bytes: false
     # This regex allows arbitrary whitespace whenever some whitespace
     # is required in the boilerplate. It was made by replacing ' ' with \\s+.
     cdata_regex: "\\s*body\\s*{\\s*-webkit-animation:\\s*-amp-start\\s+8s\\s+steps\\(1,\\s*end\\)\\s+0s\\s+1\\s+normal\\s+both;\\s*-moz-animation:\\s*-amp-start\\s+8s\\s+steps\\s*\\(1\\s*,\\s*end\\s*\\)\\s+0s\\s+1\\s+normal\\s+both;\\s*-ms-animation:\\s*-amp-start\\s+8s\\s+steps\\s*\\(1\\s*,\\s*end\\s*\\)\\s+0s\\s+1\\s+normal\\s+both;\\s*animation:\\s*-amp-start\\s+8s\\s+steps\\(1,\\s*end\\)\\s+0s\\s+1\\s+normal\\s+both;?\\s*}\\s*@-webkit-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@-moz-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@-ms-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@-o-keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*@keyframes\\s+-amp-start\\s*{\\s*from\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*to\\s*{\\s*visibility:\\s*visible;?\\s*}\\s*}\\s*"
@@ -432,6 +729,7 @@ tags: {  # `<style amp4ads-boilerplate>`, AMP4ADS
     dispatch_key: NAME_VALUE_PARENT_DISPATCH
   }
   cdata: {
+    doc_css_bytes: false
     # This regex allows arbitrary whitespace around the body statement, but
     # not inside it. This is a compromise to keep things simple, but allow
     # pretty printing tools some latitude.
@@ -454,6 +752,7 @@ tags: {  # `<style amp4email-boilerplate>`, AMP4EMAIL
     dispatch_key: NAME_VALUE_PARENT_DISPATCH
   }
   cdata: {
+    doc_css_bytes: false
     # This regex allows arbitrary whitespace whenever some whitespace
     # is required in the boilerplate. It was made by replacing ' ' with \\s+.
     cdata_regex: "\\s*body\\s*{\\s*visibility:\\s*hidden;?\\s*}\\s*"
@@ -479,6 +778,7 @@ tags: {  # `<style amp-boilerplate>`, [AMP, ACTIONS]
     dispatch_key: NAME_VALUE_PARENT_DISPATCH
   }
   cdata {
+    doc_css_bytes: false
     cdata_regex: "\\s*body\\s*{\\s*-webkit-animation:\\s*none;\\s*-moz-animation:\\s*none;\\s*-ms-animation:\\s*none;\\s*animation:\\s*none;?\\s*}\\s*"
   }
   spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amp-boilerplate?format=websites"
@@ -500,6 +800,7 @@ tags: {  # `<style amp-boilerplate>`, transformed [AMP, ACTIONS]
     dispatch_key: NAME_VALUE_PARENT_DISPATCH
   }
   cdata {
+    doc_css_bytes: false
     cdata_regex: "\\s*body\\s*{\\s*-webkit-animation:\\s*none;\\s*-moz-animation:\\s*none;\\s*-ms-animation:\\s*none;\\s*animation:\\s*none;?\\s*}\\s*"
   }
   spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amp-boilerplate?format=websites"
@@ -521,25 +822,16 @@ tags: {  # `<style amp-keyframes>`, [AMP, AMP4ADS, ACTIONS]
      dispatch_key: NAME_DISPATCH
   }
   cdata: {
+    # amp-keyframes CSS bytes do not count against the document CSS byte limit
+    # as these style tags must come at the end of the document and are limited
+    # to animation keyframes rules.
+    doc_css_bytes: false
     max_bytes: 500000
     max_bytes_spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#keyframes-stylesheet"
     css_spec: {
-      at_rule_spec: {
-        name: 'keyframes'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: 'media'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: 'supports'
-        type: PARSE_AS_RULES
-      }
-      at_rule_spec: {
-        name: '$DEFAULT'  # matches if none of the above match
-        type: PARSE_AS_ERROR
-      }
+      at_rule_spec: { name: 'keyframes' }
+      at_rule_spec: { name: 'media' }
+      at_rule_spec: { name: 'supports' }
       validate_keyframes: true
       declaration: "animation-timing-function"
       declaration: "offset-distance"
diff --git a/validator/validator-main.protoascii b/validator/validator-main.protoascii
index ce170315b..db8f115ba 100644
--- a/validator/validator-main.protoascii
+++ b/validator/validator-main.protoascii
@@ -20,13 +20,13 @@
 # in production from crashing. This id is not relevant to validator.js
 # because thus far, engine (validator.js) and spec file
 # (validator-main.protoascii, etc) are always released together.
-min_validator_revision_required: 375
+min_validator_revision_required: 455
 
 # The spec file revision allows the validator engine to distinguish
 # newer versions of the spec file. This is currently a Google internal
 # mechanism, validator.js does not use this facility. However, any
 # change to this file (validator-main.js) requires updating this revision id.
-spec_file_revision: 1028
+spec_file_revision: 1043
 
 styles_spec_url: "https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/style_pages"
 script_spec_url: "https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml#html-tags"
@@ -322,14 +322,14 @@ tags: {
                  "https://cloud\\.typography\\.com/"
                  "[0-9]*/[0-9]*/css/fonts\\.css|"
                  "https://fast\\.fonts\\.net/.*|"
-                 "https://fonts\\.googleapis\\.com/css\\?.*|"
+                 "https://fonts\\.googleapis\\.com/css2?\\?.*|"
                  "https://fonts\\.googleapis\\.com/icon\\?.*|"
                  "https://fonts\\.googleapis\\.com/earlyaccess/.*\\.css|"
                  "https://maxcdn\\.bootstrapcdn\\.com/font-awesome/"
                  "([0-9]+\\.?)+/css/font-awesome\\.min\\.css(\\?.*)?|"
                  "https://(use|pro)\\.fontawesome\\.com/releases/v([0-9]+\\.?)+"
-                 "/css/(all|brands|solid|regular|light|fontawesome)\\.css|"
-                 "https://(use|pro)\\.fontawesome\\.com/[0-9a-zA-Z]+\\.css|"
+                 "/css/[0-9a-zA-Z-]+\\.css|"
+                 "https://(use|pro)\\.fontawesome\\.com/[0-9a-zA-Z-]+\\.css|"
                  "https://use\\.typekit\\.net/[\\w\\p{L}\\p{N}_]+\\.css"
   }
   attrs: { name: "integrity" }  # SRI attribute (https://www.w3.org/TR/SRI/)
@@ -1421,6 +1421,11 @@ tags: {
     value_casei: "text/html"
     value_casei: "application/rss+xml"
   }
+  attrs: {
+    name: "show-tooltip"
+    value: "auto"
+    value: "true"
+  }
   attr_lists: "name-attr"
   # <amp-bind>
   attrs: { name: "[href]" }
@@ -2339,288 +2344,9 @@ attr_lists: {
   name: "svg-style-attr"
   attrs: {
     name: "style"
-    blacklisted_value_regex: "!\\s*important"
-    # CSS proprities: https://www.w3schools.com/cssref/default.asp
-    # SVG specific properties: https://www.w3.org/TR/SVG11/styling.html#SVGStylingProperties
-    # Disallowed:
-    # css_declaration: { name: "@charset" }
-    # css_declaration: { name: "@font-face" }
-    # css_declaration: { name: "@font-feature-values" }
-    # css_declaration: { name: "@import" }
-    # css_declaration: { name: "@keyframes" }
-    # css_declaration: { name: "@media" }
-    # Allowed:
-    css_declaration: { name: "align-content" }
-    css_declaration: { name: "align-items" }
-    css_declaration: { name: "align-self" }
-    css_declaration: { name: "alignment-baseline" } # SVG
-    css_declaration: { name: "all" }
-    css_declaration: { name: "animation" }
-    css_declaration: { name: "animation-delay" }
-    css_declaration: { name: "animation-direction" }
-    css_declaration: { name: "animation-duration" }
-    css_declaration: { name: "animation-fill-mode" }
-    css_declaration: { name: "animation-iteration-count" }
-    css_declaration: { name: "animation-name" }
-    css_declaration: { name: "animation-play-state" }
-    css_declaration: { name: "animation-timing-function" }
-    css_declaration: { name: "backface-visibility" }
-    css_declaration: { name: "background" }
-    css_declaration: { name: "background-attachment" }
-    css_declaration: { name: "background-blend-mode" }
-    css_declaration: { name: "background-clip" }
-    css_declaration: { name: "background-color" }
-    css_declaration: { name: "background-image" }
-    css_declaration: { name: "background-origin" }
-    css_declaration: { name: "background-position" }
-    css_declaration: { name: "background-repeat" }
-    css_declaration: { name: "background-size" }
-    css_declaration: { name: "baseline-shift" } # SVG
-    css_declaration: { name: "border" }
-    css_declaration: { name: "border-bottom" }
-    css_declaration: { name: "border-bottom-color" }
-    css_declaration: { name: "border-bottom-left-radius" }
-    css_declaration: { name: "border-bottom-right-radius" }
-    css_declaration: { name: "border-bottom-style" }
-    css_declaration: { name: "border-bottom-width" }
-    css_declaration: { name: "border-collapse" }
-    css_declaration: { name: "border-color" }
-    css_declaration: { name: "border-image" }
-    css_declaration: { name: "border-image-outset" }
-    css_declaration: { name: "border-image-repeat" }
-    css_declaration: { name: "border-image-slice" }
-    css_declaration: { name: "border-image-source" }
-    css_declaration: { name: "border-image-width" }
-    css_declaration: { name: "border-left" }
-    css_declaration: { name: "border-left-color" }
-    css_declaration: { name: "border-left-style" }
-    css_declaration: { name: "border-left-width" }
-    css_declaration: { name: "border-radius" }
-    css_declaration: { name: "border-right" }
-    css_declaration: { name: "border-right-color" }
-    css_declaration: { name: "border-right-style" }
-    css_declaration: { name: "border-right-width" }
-    css_declaration: { name: "border-spacing" }
-    css_declaration: { name: "border-style" }
-    css_declaration: { name: "border-top" }
-    css_declaration: { name: "border-top-color" }
-    css_declaration: { name: "border-top-left-radius" }
-    css_declaration: { name: "border-top-right-radius" }
-    css_declaration: { name: "border-top-style" }
-    css_declaration: { name: "border-top-width" }
-    css_declaration: { name: "border-width" }
-    css_declaration: { name: "bottom" }
-    css_declaration: { name: "box-decoration-break" }
-    css_declaration: { name: "box-shadow" }
-    css_declaration: { name: "box-sizing" }
-    css_declaration: { name: "break-after" }
-    css_declaration: { name: "break-before" }
-    css_declaration: { name: "break-inside" }
-    css_declaration: { name: "caption-side" }
-    css_declaration: { name: "caret-color" }
-    css_declaration: { name: "clear" }
-    css_declaration: { name: "clip" }
-    css_declaration: { name: "clip-path" } # SVG
-    css_declaration: { name: "clip-rule" } # SVG
-    css_declaration: { name: "color" }
-    css_declaration: { name: "color-interpolation" } # SVG
-    css_declaration: { name: "color-interpolation-filters" } # SVG
-    css_declaration: { name: "color-profile" } # SVG
-    css_declaration: { name: "color-rendering" } # SVG
-    css_declaration: { name: "column-count" }
-    css_declaration: { name: "column-fill" }
-    css_declaration: { name: "column-gap" }
-    css_declaration: { name: "column-rule" }
-    css_declaration: { name: "column-rule-color" }
-    css_declaration: { name: "column-rule-style" }
-    css_declaration: { name: "column-rule-width" }
-    css_declaration: { name: "column-span" }
-    css_declaration: { name: "column-width" }
-    css_declaration: { name: "columns" }
-    css_declaration: { name: "content" }
-    css_declaration: { name: "counter-increment" }
-    css_declaration: { name: "counter-reset" }
-    css_declaration: { name: "cursor" }
-    css_declaration: { name: "direction" }
-    css_declaration: { name: "display" }
-    css_declaration: { name: "dominant-baseline" } # SVG
-    css_declaration: { name: "empty-cells" }
-    css_declaration: { name: "enable-background" } # SVG
-    css_declaration: { name: "fill" } # SVG
-    css_declaration: { name: "fill-opacity" } # SVG
-    css_declaration: { name: "fill-rule" } # SVG
-    css_declaration: { name: "filter" }
-    css_declaration: { name: "flex" }
-    css_declaration: { name: "flex-basis" }
-    css_declaration: { name: "flex-direction" }
-    css_declaration: { name: "flex-flow" }
-    css_declaration: { name: "flex-grow" }
-    css_declaration: { name: "flex-shrink" }
-    css_declaration: { name: "flex-wrap" }
-    css_declaration: { name: "float" }
-    css_declaration: { name: "flood-color" } # SVG
-    css_declaration: { name: "flood-opacity" } # SVG
-    css_declaration: { name: "font" }
-    css_declaration: { name: "font-family" }
-    css_declaration: { name: "font-feature-settings" }
-    css_declaration: { name: "font-kerning" }
-    css_declaration: { name: "font-language-override" }
-    css_declaration: { name: "font-size" }
-    css_declaration: { name: "font-size-adjust" }
-    css_declaration: { name: "font-stretch" }
-    css_declaration: { name: "font-style" }
-    css_declaration: { name: "font-synthesis" }
-    css_declaration: { name: "font-variant" }
-    css_declaration: { name: "font-variant-alternates" }
-    css_declaration: { name: "font-variant-caps" }
-    css_declaration: { name: "font-variant-east-asian" }
-    css_declaration: { name: "font-variant-ligatures" }
-    css_declaration: { name: "font-variant-numeric" }
-    css_declaration: { name: "font-variant-position" }
-    css_declaration: { name: "font-weight" }
-    css_declaration: { name: "glyph-orientation-horizontal" } # SVG
-    css_declaration: { name: "glyph-orientation-vertical" } # SVG
-    css_declaration: { name: "grid" }
-    css_declaration: { name: "grid-area" }
-    css_declaration: { name: "grid-auto-columns" }
-    css_declaration: { name: "grid-auto-flow" }
-    css_declaration: { name: "grid-auto-rows" }
-    css_declaration: { name: "grid-column" }
-    css_declaration: { name: "grid-column-end" }
-    css_declaration: { name: "grid-column-gap" }
-    css_declaration: { name: "grid-column-start" }
-    css_declaration: { name: "grid-gap" }
-    css_declaration: { name: "grid-row" }
-    css_declaration: { name: "grid-row-end" }
-    css_declaration: { name: "grid-row-gap" }
-    css_declaration: { name: "grid-row-start" }
-    css_declaration: { name: "grid-template" }
-    css_declaration: { name: "grid-template-areas" }
-    css_declaration: { name: "grid-template-columns" }
-    css_declaration: { name: "grid-template-rows" }
-    css_declaration: { name: "hanging-punctuation" }
-    css_declaration: { name: "height" }
-    css_declaration: { name: "hyphens" }
-    css_declaration: { name: "image-rendering" }
-    css_declaration: { name: "isolation" }
-    css_declaration: { name: "justify-content" }
-    css_declaration: { name: "kerning" } # SVG
-    css_declaration: { name: "left" }
-    css_declaration: { name: "letter-spacing" }
-    css_declaration: { name: "lighting-color" } # SVG
-    css_declaration: { name: "line-break" }
-    css_declaration: { name: "line-height" }
-    css_declaration: { name: "list-style" }
-    css_declaration: { name: "list-style-image" }
-    css_declaration: { name: "list-style-position" }
-    css_declaration: { name: "list-style-type" }
-    css_declaration: { name: "margin" }
-    css_declaration: { name: "margin-bottom" }
-    css_declaration: { name: "margin-left" }
-    css_declaration: { name: "margin-right" }
-    css_declaration: { name: "margin-top" }
-    css_declaration: { name: "marker" } # SVG
-    css_declaration: { name: "marker-end" } # SVG
-    css_declaration: { name: "marker-mid" } # SVG
-    css_declaration: { name: "marker-start" } # SVG
-    css_declaration: { name: "mask" } # SVG
-    css_declaration: { name: "max-height" }
-    css_declaration: { name: "max-width" }
-    css_declaration: { name: "min-height" }
-    css_declaration: { name: "min-width" }
-    css_declaration: { name: "mix-blend-mode" }
-    css_declaration: { name: "object-fit" }
-    css_declaration: { name: "object-position" }
-    css_declaration: { name: "opacity" }
-    css_declaration: { name: "order" }
-    css_declaration: { name: "orphans" }
-    css_declaration: { name: "outline" }
-    css_declaration: { name: "outline-color" }
-    css_declaration: { name: "outline-offset" }
-    css_declaration: { name: "outline-style" }
-    css_declaration: { name: "outline-width" }
-    css_declaration: { name: "overflow" }
-    css_declaration: { name: "overflow-wrap" }
-    css_declaration: { name: "overflow-x" }
-    css_declaration: { name: "overflow-y" }
-    css_declaration: { name: "padding" }
-    css_declaration: { name: "padding-bottom" }
-    css_declaration: { name: "padding-left" }
-    css_declaration: { name: "padding-right" }
-    css_declaration: { name: "padding-top" }
-    css_declaration: { name: "page-break-after" }
-    css_declaration: { name: "page-break-before" }
-    css_declaration: { name: "page-break-inside" }
-    css_declaration: { name: "perspective" }
-    css_declaration: { name: "perspective-origin" }
-    css_declaration: { name: "pointer-events" }
-    # CSS property `position` with values `fixed` and `sticky are not allowed.
-    # From https://www.w3schools.com/cssref/pr_class_position.asp
-    css_declaration: {
-      name: "position"
-      value_casei: "absolute"
-      value_casei: "inherit"
-      value_casei: "initial"
-      value_casei: "relative"
-      value_casei: "static"
-    }
-    css_declaration: { name: "quotes" }
-    css_declaration: { name: "resize" }
-    css_declaration: { name: "right" }
-    css_declaration: { name: "shape-rendering" } # SVG
-    css_declaration: { name: "stop-color" } # SVG
-    css_declaration: { name: "stop-opacity" } # SVG
-    css_declaration: { name: "stroke" } # SVG
-    css_declaration: { name: "stroke-dasharray" } # SVG
-    css_declaration: { name: "stroke-dashoffset" } # SVG
-    css_declaration: { name: "stroke-linecap" } # SVG
-    css_declaration: { name: "stroke-linejoin" } # SVG
-    css_declaration: { name: "stroke-miterlimit" } # SVG
-    css_declaration: { name: "stroke-opacity" } # SVG
-    css_declaration: { name: "stroke-width" } # SVG
-    css_declaration: { name: "tab-size" }
-    css_declaration: { name: "table-layout" }
-    css_declaration: { name: "text-align" }
-    css_declaration: { name: "text-align-last" }
-    css_declaration: { name: "text-anchor" } # SVG
-    css_declaration: { name: "text-combine-upright" }
-    css_declaration: { name: "text-decoration" }
-    css_declaration: { name: "text-decoration-color" }
-    css_declaration: { name: "text-decoration-line" }
-    css_declaration: { name: "text-decoration-style" }
-    css_declaration: { name: "text-fill-color" }
-    css_declaration: { name: "text-indent" }
-    css_declaration: { name: "text-justify" }
-    css_declaration: { name: "text-orientation" }
-    css_declaration: { name: "text-overflow" }
-    css_declaration: { name: "text-rendering" } # SVG
-    css_declaration: { name: "text-shadow" }
-    css_declaration: { name: "text-stroke" }
-    css_declaration: { name: "text-stroke-color" }
-    css_declaration: { name: "text-stroke-width" }
-    css_declaration: { name: "text-transform" }
-    css_declaration: { name: "text-underline-position" }
-    css_declaration: { name: "top" }
-    css_declaration: { name: "transform" }
-    css_declaration: { name: "transform-origin" }
-    css_declaration: { name: "transform-style" }
-    css_declaration: { name: "transition" }
-    css_declaration: { name: "transition-delay" }
-    css_declaration: { name: "transition-duration" }
-    css_declaration: { name: "transition-property" }
-    css_declaration: { name: "transition-timing-function" }
-    css_declaration: { name: "unicode-bidi" }
-    css_declaration: { name: "user-select" }
-    css_declaration: { name: "vertical-align" }
-    css_declaration: { name: "visibility" }
-    css_declaration: { name: "white-space" }
-    css_declaration: { name: "widows" }
-    css_declaration: { name: "width" }
-    css_declaration: { name: "word-break" }
-    css_declaration: { name: "word-spacing" }
-    css_declaration: { name: "word-wrap" }
-    css_declaration: { name: "writing-mode" }
-    css_declaration: { name: "z-index" }
+    # `style` attribute value validated against Document Level CSS rules defined
+    # in validator-css.protoascii.
+    value_doc_svg_css: true
   }
 }
 
@@ -3888,6 +3614,14 @@ attr_lists: {
     disabled_by: "amp4email"
     name: "list"
   }
+  attrs: { 
+    disabled_by: "amp4email"
+    name: "enterkeyhint"
+  }
+  attrs: {
+    disabled_by: "amp4email"
+    name: "enterkeyhint"
+  }
   attrs: { name: "max" }
   attrs: { name: "maxlength" }
   attrs: { name: "min" }
@@ -5712,250 +5446,9 @@ attr_lists: {
   attrs: { name: "rev" }
   attrs: {
     name: "style"
-    blacklisted_value_regex: "(!\\s*important|<!--)"
-    # CSS proprities: https://www.w3schools.com/cssref/default.asp
-    # Disallowed:
-    # css_declaration: { name: "@charset" }
-    # css_declaration: { name: "@font-face" }
-    # css_declaration: { name: "@font-feature-values" }
-    # css_declaration: { name: "@import" }
-    # css_declaration: { name: "@keyframes" }
-    # css_declaration: { name: "@media" }
-    # Allowed:
-    css_declaration: { name: "align-content" }
-    css_declaration: { name: "align-items" }
-    css_declaration: { name: "align-self" }
-    css_declaration: { name: "all" }
-    css_declaration: { name: "animation" }
-    css_declaration: { name: "animation-delay" }
-    css_declaration: { name: "animation-direction" }
-    css_declaration: { name: "animation-duration" }
-    css_declaration: { name: "animation-fill-mode" }
-    css_declaration: { name: "animation-iteration-count" }
-    css_declaration: { name: "animation-name" }
-    css_declaration: { name: "animation-play-state" }
-    css_declaration: { name: "animation-timing-function" }
-    css_declaration: { name: "backface-visibility" }
-    css_declaration: { name: "background" }
-    css_declaration: { name: "background-attachment" }
-    css_declaration: { name: "background-blend-mode" }
-    css_declaration: { name: "background-clip" }
-    css_declaration: { name: "background-color" }
-    css_declaration: { name: "background-image" }
-    css_declaration: { name: "background-origin" }
-    css_declaration: { name: "background-position" }
-    css_declaration: { name: "background-repeat" }
-    css_declaration: { name: "background-size" }
-    css_declaration: { name: "border" }
-    css_declaration: { name: "border-bottom" }
-    css_declaration: { name: "border-bottom-color" }
-    css_declaration: { name: "border-bottom-left-radius" }
-    css_declaration: { name: "border-bottom-right-radius" }
-    css_declaration: { name: "border-bottom-style" }
-    css_declaration: { name: "border-bottom-width" }
-    css_declaration: { name: "border-collapse" }
-    css_declaration: { name: "border-color" }
-    css_declaration: { name: "border-image" }
-    css_declaration: { name: "border-image-outset" }
-    css_declaration: { name: "border-image-repeat" }
-    css_declaration: { name: "border-image-slice" }
-    css_declaration: { name: "border-image-source" }
-    css_declaration: { name: "border-image-width" }
-    css_declaration: { name: "border-left" }
-    css_declaration: { name: "border-left-color" }
-    css_declaration: { name: "border-left-style" }
-    css_declaration: { name: "border-left-width" }
-    css_declaration: { name: "border-radius" }
-    css_declaration: { name: "border-right" }
-    css_declaration: { name: "border-right-color" }
-    css_declaration: { name: "border-right-style" }
-    css_declaration: { name: "border-right-width" }
-    css_declaration: { name: "border-spacing" }
-    css_declaration: { name: "border-style" }
-    css_declaration: { name: "border-top" }
-    css_declaration: { name: "border-top-color" }
-    css_declaration: { name: "border-top-left-radius" }
-    css_declaration: { name: "border-top-right-radius" }
-    css_declaration: { name: "border-top-style" }
-    css_declaration: { name: "border-top-width" }
-    css_declaration: { name: "border-width" }
-    css_declaration: { name: "bottom" }
-    css_declaration: { name: "box-decoration-break" }
-    css_declaration: { name: "box-shadow" }
-    css_declaration: { name: "box-sizing" }
-    css_declaration: { name: "break-after" }
-    css_declaration: { name: "break-before" }
-    css_declaration: { name: "break-inside" }
-    css_declaration: { name: "caption-side" }
-    css_declaration: { name: "caret-color" }
-    css_declaration: { name: "clear" }
-    css_declaration: { name: "clip" }
-    css_declaration: { name: "color" }
-    css_declaration: { name: "column-count" }
-    css_declaration: { name: "column-fill" }
-    css_declaration: { name: "column-gap" }
-    css_declaration: { name: "column-rule" }
-    css_declaration: { name: "column-rule-color" }
-    css_declaration: { name: "column-rule-style" }
-    css_declaration: { name: "column-rule-width" }
-    css_declaration: { name: "column-span" }
-    css_declaration: { name: "column-width" }
-    css_declaration: { name: "columns" }
-    css_declaration: { name: "content" }
-    css_declaration: { name: "counter-increment" }
-    css_declaration: { name: "counter-reset" }
-    css_declaration: { name: "cursor" }
-    css_declaration: { name: "direction" }
-    css_declaration: { name: "display" }
-    css_declaration: { name: "empty-cells" }
-    css_declaration: { name: "filter" }
-    css_declaration: { name: "flex" }
-    css_declaration: { name: "flex-basis" }
-    css_declaration: { name: "flex-direction" }
-    css_declaration: { name: "flex-flow" }
-    css_declaration: { name: "flex-grow" }
-    css_declaration: { name: "flex-shrink" }
-    css_declaration: { name: "flex-wrap" }
-    css_declaration: { name: "float" }
-    css_declaration: { name: "font" }
-    css_declaration: { name: "font-family" }
-    css_declaration: { name: "font-feature-settings" }
-    css_declaration: { name: "font-kerning" }
-    css_declaration: { name: "font-language-override" }
-    css_declaration: { name: "font-size" }
-    css_declaration: { name: "font-size-adjust" }
-    css_declaration: { name: "font-stretch" }
-    css_declaration: { name: "font-style" }
-    css_declaration: { name: "font-synthesis" }
-    css_declaration: { name: "font-variant" }
-    css_declaration: { name: "font-variant-alternates" }
-    css_declaration: { name: "font-variant-caps" }
-    css_declaration: { name: "font-variant-east-asian" }
-    css_declaration: { name: "font-variant-ligatures" }
-    css_declaration: { name: "font-variant-numeric" }
-    css_declaration: { name: "font-variant-position" }
-    css_declaration: { name: "font-weight" }
-    css_declaration: { name: "grid" }
-    css_declaration: { name: "grid-area" }
-    css_declaration: { name: "grid-auto-columns" }
-    css_declaration: { name: "grid-auto-flow" }
-    css_declaration: { name: "grid-auto-rows" }
-    css_declaration: { name: "grid-column" }
-    css_declaration: { name: "grid-column-end" }
-    css_declaration: { name: "grid-column-gap" }
-    css_declaration: { name: "grid-column-start" }
-    css_declaration: { name: "grid-gap" }
-    css_declaration: { name: "grid-row" }
-    css_declaration: { name: "grid-row-end" }
-    css_declaration: { name: "grid-row-gap" }
-    css_declaration: { name: "grid-row-start" }
-    css_declaration: { name: "grid-template" }
-    css_declaration: { name: "grid-template-areas" }
-    css_declaration: { name: "grid-template-columns" }
-    css_declaration: { name: "grid-template-rows" }
-    css_declaration: { name: "hanging-punctuation" }
-    css_declaration: { name: "height" }
-    css_declaration: { name: "hyphens" }
-    css_declaration: { name: "image-rendering" }
-    css_declaration: { name: "isolation" }
-    css_declaration: { name: "justify-content" }
-    css_declaration: { name: "left" }
-    css_declaration: { name: "letter-spacing" }
-    css_declaration: { name: "line-break" }
-    css_declaration: { name: "line-height" }
-    css_declaration: { name: "list-style" }
-    css_declaration: { name: "list-style-image" }
-    css_declaration: { name: "list-style-position" }
-    css_declaration: { name: "list-style-type" }
-    css_declaration: { name: "margin" }
-    css_declaration: { name: "margin-bottom" }
-    css_declaration: { name: "margin-left" }
-    css_declaration: { name: "margin-right" }
-    css_declaration: { name: "margin-top" }
-    css_declaration: { name: "max-height" }
-    css_declaration: { name: "max-width" }
-    css_declaration: { name: "min-height" }
-    css_declaration: { name: "min-width" }
-    css_declaration: { name: "mix-blend-mode" }
-    css_declaration: { name: "object-fit" }
-    css_declaration: { name: "object-position" }
-    css_declaration: { name: "opacity" }
-    css_declaration: { name: "order" }
-    css_declaration: { name: "orphans" }
-    css_declaration: { name: "outline" }
-    css_declaration: { name: "outline-color" }
-    css_declaration: { name: "outline-offset" }
-    css_declaration: { name: "outline-style" }
-    css_declaration: { name: "outline-width" }
-    css_declaration: { name: "overflow" }
-    css_declaration: { name: "overflow-wrap" }
-    css_declaration: { name: "overflow-x" }
-    css_declaration: { name: "overflow-y" }
-    css_declaration: { name: "padding" }
-    css_declaration: { name: "padding-bottom" }
-    css_declaration: { name: "padding-left" }
-    css_declaration: { name: "padding-right" }
-    css_declaration: { name: "padding-top" }
-    css_declaration: { name: "page-break-after" }
-    css_declaration: { name: "page-break-before" }
-    css_declaration: { name: "page-break-inside" }
-    css_declaration: { name: "perspective" }
-    css_declaration: { name: "perspective-origin" }
-    css_declaration: { name: "pointer-events" }
-    # CSS property `position` with values `fixed` and `sticky are not allowed.
-    # From https://www.w3schools.com/cssref/pr_class_position.asp
-    css_declaration: {
-      name: "position"
-      value_casei: "absolute"
-      value_casei: "inherit"
-      value_casei: "initial"
-      value_casei: "relative"
-      value_casei: "static"
-    }
-    css_declaration: { name: "quotes" }
-    css_declaration: { name: "resize" }
-    css_declaration: { name: "right" }
-    css_declaration: { name: "tab-size" }
-    css_declaration: { name: "table-layout" }
-    css_declaration: { name: "text-align" }
-    css_declaration: { name: "text-align-last" }
-    css_declaration: { name: "text-combine-upright" }
-    css_declaration: { name: "text-decoration" }
-    css_declaration: { name: "text-decoration-color" }
-    css_declaration: { name: "text-decoration-line" }
-    css_declaration: { name: "text-decoration-style" }
-    css_declaration: { name: "text-fill-color" }
-    css_declaration: { name: "text-indent" }
-    css_declaration: { name: "text-justify" }
-    css_declaration: { name: "text-orientation" }
-    css_declaration: { name: "text-overflow" }
-    css_declaration: { name: "text-shadow" }
-    css_declaration: { name: "text-stroke" }
-    css_declaration: { name: "text-stroke-color" }
-    css_declaration: { name: "text-stroke-width" }
-    css_declaration: { name: "text-transform" }
-    css_declaration: { name: "text-underline-position" }
-    css_declaration: { name: "top" }
-    css_declaration: { name: "transform" }
-    css_declaration: { name: "transform-origin" }
-    css_declaration: { name: "transform-style" }
-    css_declaration: { name: "transition" }
-    css_declaration: { name: "transition-delay" }
-    css_declaration: { name: "transition-duration" }
-    css_declaration: { name: "transition-property" }
-    css_declaration: { name: "transition-timing-function" }
-    css_declaration: { name: "unicode-bidi" }
-    css_declaration: { name: "user-select" }
-    css_declaration: { name: "vertical-align" }
-    css_declaration: { name: "visibility" }
-    css_declaration: { name: "white-space" }
-    css_declaration: { name: "widows" }
-    css_declaration: { name: "width" }
-    css_declaration: { name: "word-break" }
-    css_declaration: { name: "word-spacing" }
-    css_declaration: { name: "word-wrap" }
-    css_declaration: { name: "writing-mode" }
-    css_declaration: { name: "z-index" }
+    # `style` attribute value validated against Document Level CSS rules defined
+    # in validator-css.protoascii.
+    value_doc_css: true
   }
   attrs: { name: "typeof" }
   attrs: { name: "vocab" }

@googlebot googlebot added the cla: yes Signed the Google CLA label May 13, 2020
@westonruter westonruter self-assigned this May 13, 2020
…phtml-2005050322002

* 'develop' of github.com:ampproject/amp-wp: (47 commits)
  Adapt docblocks
  Display PHPStan version in Travis
  Update dependency eslint-plugin-jest to v23.13.1
  Adapt in libraries as well
  Always download latest version of PHPStan
  Update dependency autoprefixer to v9.8.0
  Update dependency eslint-plugin-jest to v23.13.0
  Fix phpdoc for sanitizer_classes and embed_handler_classes
  Remove array_column() polyfill since plugin requires PHP 5.6+
  Update dependency @wordpress/scripts to v9.1.0
  Remove redundant subtraction
  Raise level to 3
  Adapt type-hint for AMP_Image_Dimension_Extractor::normalize_url()
  Use empty string for pruning textContent
  Adapt typehint for AMP_Content->sanitizer_classes
  Adapt typehint for AMP_Tag_And_Attribute_Sanitizer->allowed_tags
  Adapt typehints for methods returning a rule spec check result
  Adapt typehint for AMP_Style_Sanitizer->current_sources
  Adapt return typehint for AMP_YouTube_Embed_Handler::get_video_id_from_url()
  Adapt return value for failed AMP_Twitter_Embed_Handler::get_tweet_id()
  ...
@westonruter westonruter marked this pull request as ready for review May 20, 2020 03:45
@westonruter westonruter requested a review from pierlon May 20, 2020 03:46
Copy link
Member

@amedina amedina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@westonruter westonruter merged commit 8d5f29f into develop May 20, 2020
@westonruter westonruter deleted the update/amphtml-2005050322002 branch May 20, 2020 04:09
@westonruter westonruter added this to the v1.6 milestone Jun 2, 2020
@westonruter westonruter removed the request for review from pierlon June 16, 2020 16:16
@westonruter westonruter removed their assignment Jun 16, 2020
@westonruter westonruter added the Changelogged Whether the issue/PR has been added to release notes. label Jul 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelogged Whether the issue/PR has been added to release notes. cla: yes Signed the Google CLA
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants