Skip to content

Commit

Permalink
Enable amp-autocomplete in AMP4Email with doc level opt-in (#27174)
Browse files Browse the repository at this point in the history
* Add doc-level opt-in flag

* Add validation rules and tests

* Rename doc level flag to "amp-autocomplete-opt-in"

* s/list/autocomplete

* Remove duplicate allowance of "template"

* Update out

* Allow amp-autocomplete in email validator test

* Update assertion message.

* Add warning to email documentation

* data- prefix opt-in attr

* Add comment explaining validator rules
  • Loading branch information
caroqliu committed Mar 27, 2020
1 parent 65bead6 commit d5b64c4
Show file tree
Hide file tree
Showing 7 changed files with 542 additions and 0 deletions.
9 changes: 9 additions & 0 deletions extensions/amp-autocomplete/0.1/amp-autocomplete.js
Expand Up @@ -34,6 +34,7 @@ import {dev, user, userAssert} from '../../../src/log';
import {dict, hasOwn, map, ownProperty} from '../../../src/utils/object';
import {getValueForExpr, tryParseJson} from '../../../src/json';
import {includes, startsWith} from '../../../src/string';
import {isAmp4Email} from '../../../src/format';
import {isArray, isEnumValue, toArray} from '../../../src/types';
import {mod} from '../../../src/utils/math';
import {once} from '../../../src/utils/function';
Expand Down Expand Up @@ -215,6 +216,14 @@ export class AmpAutocomplete extends AMP.BaseElement {

/** @override */
buildCallback() {
const doc = this.element.ownerDocument;
const isEmail = doc && isAmp4Email(doc);
userAssert(
!isEmail ||
doc.documentElement.hasAttribute('data-amp-autocomplete-opt-in'),
'<amp-autocomplete> is not currently available in AMP4Email.'
);

this.action_ = Services.actionServiceForDoc(this.element);
this.viewport_ = Services.viewportForDoc(this.element);

Expand Down
7 changes: 7 additions & 0 deletions extensions/amp-autocomplete/amp-autocomplete.md
Expand Up @@ -2,6 +2,7 @@
$category: dynamic-content
formats:
- websites
- email
teaser:
text: Suggests completed results corresponding to the user input as they type into the input field.
---
Expand All @@ -24,6 +25,12 @@ limitations under the License.

# amp-autocomplete

[filter formats="email"]

Warning: This component is currently experimental in the AMP for Email format as email clients add support for the feature. Until the component is publicly available in the format, you will notice the component is in some cases valid and sendable in emails but may be only functioning in its fallback behavior capacity across email clients as well as in their respective playgrounds. The fallback for the component does not display autocomplete suggestions, and will behave as the unenhanced `input` or `textarea` field it is given.

[/filter] <!-- formats="email" -->

## Behavior

The `amp-autocomplete` extension should be used for suggesting completed items based on user input to help users carry out their task more quickly.
Expand Down
54 changes: 54 additions & 0 deletions extensions/amp-autocomplete/validator-amp-autocomplete.protoascii
Expand Up @@ -24,6 +24,17 @@ tags: { # amp-autocomplete
}
attr_lists: "common-extension-attrs"
}
tags: { # amp-autocomplete
html_format: AMP4EMAIL
tag_name: "SCRIPT"
spec_name: "SCRIPT[custom-element=amp-autocomplete] (AMP4EMAIL)"
extension_spec: {
name: "amp-autocomplete"
# AMP4EMAIL doesn't allow version: "latest".
version: "0.1"
}
attr_lists: "common-extension-attrs"
}
tags: { # <amp-autocomplete>
html_format: AMP
tag_name: "AMP-AUTOCOMPLETE"
Expand Down Expand Up @@ -81,6 +92,49 @@ tags: { # <amp-autocomplete>
supported_layouts: CONTAINER
}
}
# AMP4EMAIL disallows mustache in src attribute, filter attribute.
tags: { # <amp-autocomplete>
html_format: AMP4EMAIL
tag_name: "AMP-AUTOCOMPLETE"
spec_name: "AMP-AUTOCOMPLETE (AMP4EMAIL)"
requires_extension: "amp-autocomplete"
disallowed_ancestor: "AMP-AUTOCOMPLETE"
disallowed_ancestor: "AMP-STATE"
disallowed_ancestor: "TEMPLATE"
attrs: { name: "highlight-user-entry" }
attrs: { name: "inline" }
attrs: { name: "items" }
attrs: { name: "max-entries" }
attrs: { name: "min-characters" }
attrs: {
name: "query"
trigger: {
also_requires_attr: "src"
}
}
attrs: { name: "submit-on-enter" }
attrs: {
name: "suggest-first"
}
attrs: {
name: "src"
mandatory: true
value_url: {
protocol: "https"
allow_relative: false
}
blacklisted_value_regex: "__amp_source_origin|"
"{{|}}" # Mustache is disallowed in src.
}
attrs: {
name: "template"
value_oneof_set: TEMPLATE_IDS
}
attr_lists: "extended-amp-global"
amp_layout: {
supported_layouts: CONTAINER
}
}
tags: { # <amp-autocomplete> > <input>
html_format: AMP
tag_name: "INPUT"
Expand Down
1 change: 1 addition & 0 deletions validator/engine/validator_test.js
Expand Up @@ -1326,6 +1326,7 @@ describe('ValidatorRulesMakeSense', () => {
// Working Group, @wg-amp4email.
const approvedAmp4EmailExtensions = {
'AMP-ACCORDION': ['0.1'],
'AMP-AUTOCOMPLETE': ['0.1'],
'AMP-ANIM': ['0.1'],
'AMP-BIND-MACRO': ['0.1'],
'AMP-CAROUSEL': ['0.1'],
Expand Down
209 changes: 209 additions & 0 deletions validator/testdata/amp4email_feature_tests/amp-autocomplete.html
@@ -0,0 +1,209 @@
<!--
Copyright 2020 The AMP HTML Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS-IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the license.
-->
<!--
Test Description:
Tests the additional restrictions AMP4EMAIL sets on AMP-AUTOCOMPLETE.
-->
<!DOCTYPE html>
<!-- "data-amp-autocomplete-opt-in" is disallowed by the validator -->
<html ⚡4email data-amp-autocomplete-opt-in>
<head>
<meta charset="utf-8" />
<style amp4email-boilerplate>
body {
visibility: hidden;
}
</style>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script
async
custom-element="amp-autocomplete"
src="https://cdn.ampproject.org/v0/amp-autocomplete-0.1.js"
></script>
<script
async
custom-element="amp-form"
src="https://cdn.ampproject.org/v0/amp-form-0.1.js"
></script>
<script
async
custom-template="amp-mustache"
src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"
></script>
</head>
<body>
<!-- Valid: amp-component with remote data -->
<amp-autocomplete src="https://data.com/articles.json?ref=CANONICAL_URL">
<input />
</amp-autocomplete>

<!-- Valid: amp-autocomplete textarea -->
<amp-autocomplete src="https://data.com/articles.json?ref=CANONICAL_URL">
<textarea></textarea>
</amp-autocomplete>

<!-- Valid: amp-autocomplete with textarea with other attrs -->
<amp-autocomplete src="https://data.com/articles.json?ref=CANONICAL_URL">
<textarea autoexpand placeholder="Reply"></textarea>
</amp-autocomplete>

<!-- Valid: input and src and query attr -->
<amp-autocomplete
src="https://data.com/articles.json?ref=CANONICAL_URL"
query="q"
>
<input />
</amp-autocomplete>

<!-- Valid: other attributes -->
<amp-autocomplete
src="https://data.com/articles.json?ref=CANONICAL_URL"
highlight-user-entry
inline
min-characters="0"
max-entries="3"
submit-on-enter
suggest-first
>
<input />
</amp-autocomplete>

<!-- Invalid: amp-component with static data -->
<amp-autocomplete>
<input />
<script type="application/json">
{}
</script>
</amp-autocomplete>

<!-- Invalid: amp-component with filter attribute -->
<amp-autocomplete
filter="prefix"
src="https://data.com/articles.json?ref=CANONICAL_URL"
>
<input />
</amp-autocomplete>

<!-- Invalid: amp-component with filter-value attribute -->
<amp-autocomplete
filter-value="property"
src="https://data.com/articles.json?ref=CANONICAL_URL"
>
<input />
</amp-autocomplete>

<!-- Invalid: Nested XHRs not allowed. This example is banned in general AMP but
for a different reason: a template cannot be a descendant of another template. -->
<amp-autocomplete src="https://data.com/articles.json?ref=CANONICAL_URL">
<template type="amp-mustache">
<div>
<amp-autocomplete
src="https://data.com/articles.json?ref=CANONICAL_URL"
>
<template type="amp-mustache" id="1234">
<div>
<a href="https://somelink.com">{{blah}}</a>
</div>
</template>
</amp-autocomplete>
</div>
</template>
</amp-autocomplete>

<!-- Invalid: Nested XHRs not allowed. -->
<amp-autocomplete src="https://data.com/articles.json?ref=CANONICAL_URL">
<template type="amp-mustache">
<div>
<amp-state src="https://someserver.json">
<script type="application/json">
{}
</script>
</amp-state>
</div>
</template>
</amp-autocomplete>

<!-- Invalid: Nested XHRs not allowed. -->
<amp-autocomplete src="https://data.com/articles.json?ref=CANONICAL_URL">
<template type="amp-mustache">
<div>
<amp-autocomplete
src="https://data.com/articles.json?ref=CANONICAL_URL"
template="1234"
>
</amp-autocomplete>
</div>
</template>
</amp-autocomplete>

<!-- Invalid: Nested XHRs not allowed. -->
<amp-autocomplete src="https://data.com/articles.json?ref=CANONICAL_URL">
<template type="amp-mustache">
<div>
<amp-state id="123" src="https://someserver.json" template="1234">
<script type="application/json">
{}
</script>
</amp-state>
</div>
</template>
</amp-autocomplete>

<!-- Invalid: Nested XHRs not allowed. -->
<template type="amp-mustache">
<div>
<amp-autocomplete
src="https://data.com/articles.json?ref=CANONICAL_URL"
template="1234"
>
</amp-autocomplete>
</div>
</template>

<!-- Invalid: URLs cannot be empty. -->
<amp-autocomplete src="">
<input />
</amp-autocomplete>

<!-- Invalid: The protocol can only be https -->
<amp-autocomplete src="http://data.com/articles.json?ref=CANONICAL_URL">
<input />
</amp-autocomplete>

<!-- Invalid: src of amp-autocomplete is not bindable -->
<amp-autocomplete [src]="data">
<input />
</amp-autocomplete>

<!-- Invalid: Mustache delimiters are disallowed in src -->
<amp-autocomplete src="foo{{bar">
<input />
</amp-autocomplete>

<!-- Invalid: Mustache delimiters are disallowed in src -->
<amp-autocomplete src="foo{{bar">
<input />
</amp-autocomplete>

<!-- Invalid: Mustache variables cannot be concatenated in href -->
<amp-autocomplete src="http://data.com/articles.json?ref=CANONICAL_URL">
<input />
<template type="amp-mustache">
<a href="{{bar}}{{foo}}">disallowed</a>
</template>
</amp-autocomplete>
</body>
</html>

0 comments on commit d5b64c4

Please sign in to comment.