diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index f0aa95f02a9e..ee8288df3b02 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -7,4 +7,5 @@ Jake Moening
Jordan Adler
Kent Brewster
Malte Ubl
+Niall Kennedy
Taylor Savage
diff --git a/examples/vine.amp.html b/examples/vine.amp.html
new file mode 100644
index 000000000000..5eb35003328e
--- /dev/null
+++ b/examples/vine.amp.html
@@ -0,0 +1,30 @@
+
+
+
+
+ Vine examples
+
+
+
+
+
+
+
+
+
Vine
+
+
+
+
+
+
+
+
diff --git a/extensions/README.md b/extensions/README.md
index 71861283e3ae..a906eb5e6d02 100644
--- a/extensions/README.md
+++ b/extensions/README.md
@@ -30,6 +30,7 @@ Current list of extended components:
| [`amp-lightbox`](amp-lightbox/amp-lightbox.md) | Allows for a “lightbox” or similar experience. |
| [`amp-list`](amp-list/amp-list.md) | A dynamic list that can download data and create list items using a template |
| [`amp-twitter`](amp-twitter/amp-twitter.md) | Displays a Twitter Tweet. |
+| [`amp-vine`](amp-vine/amp-vine.md) | Displays a Vine simple embed. |
| [`amp-youtube`](amp-youtube/amp-youtube.md) | Displays a Youtube video. |
diff --git a/extensions/amp-vine/0.1/amp-vine.js b/extensions/amp-vine/0.1/amp-vine.js
new file mode 100644
index 000000000000..4717f4b4dc71
--- /dev/null
+++ b/extensions/amp-vine/0.1/amp-vine.js
@@ -0,0 +1,73 @@
+
+/**
+ * Copyright 2015 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.
+ */
+
+import {isLayoutSizeDefined} from '../../../src/layout';
+import {loadPromise} from '../../../src/event-helper';
+
+class AmpVine extends AMP.BaseElement {
+
+ /** @override */
+ preconnectCallback(onLayout) {
+ // the Vine iframe
+ this.preconnect.url('https://vine.co', onLayout);
+ // Vine assets loaded in the iframe
+ this.preconnect.url('https://v.cdn.vine.co', onLayout);
+ }
+
+ /** @override */
+ isLayoutSupported(layout) {
+ return isLayoutSizeDefined(layout);
+ }
+
+ /** @override */
+ layoutCallback() {
+ const vineid = AMP.assert(this.element.getAttribute('data-vineid'),
+ 'The data-vineid attribute is required for %s',
+ this.element);
+ const width = this.element.getAttribute('width');
+ const height = this.element.getAttribute('height');
+
+ const iframe = document.createElement('iframe');
+ iframe.setAttribute('frameborder', '0');
+ iframe.src = 'https://vine.co/v/' +
+ encodeURIComponent(vineid) + '/embed/simple';
+
+ this.applyFillContent(iframe);
+
+ iframe.width = width;
+ iframe.height = height;
+ this.element.appendChild(iframe);
+
+ /** @private {?Element} */
+ this.iframe_ = iframe;
+
+ return loadPromise(iframe);
+ }
+
+ /** @override */
+ documentInactiveCallback() {
+ if (this.iframe_ && this.iframe_.contentWindow) {
+ this.iframe_.contentWindow./*OK*/postMessage('pause', '*');
+ }
+
+ // No need to do layout later - user action will be expect to resume
+ // the playback
+ return false;
+ }
+}
+
+AMP.registerElement('amp-vine', AmpVine);
diff --git a/extensions/amp-vine/0.1/test/test-amp-vine.js b/extensions/amp-vine/0.1/test/test-amp-vine.js
new file mode 100644
index 000000000000..66a3ba736356
--- /dev/null
+++ b/extensions/amp-vine/0.1/test/test-amp-vine.js
@@ -0,0 +1,62 @@
+/**
+ * Copyright 2015 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.
+ */
+
+import {createIframePromise} from '../../../../testing/iframe';
+require('../amp-vine');
+import {adopt} from '../../../../src/runtime';
+
+adopt(window);
+
+describe('amp-vine', () => {
+ function getVine(vineId, opt_responsive) {
+ return createIframePromise().then(iframe => {
+ const vine = iframe.doc.createElement('amp-vine');
+ vine.setAttribute('data-vineid', vineId);
+ vine.setAttribute('width', 400);
+ vine.setAttribute('height', 400);
+ if (opt_responsive) {
+ vine.setAttribute('layout', 'responsive');
+ }
+ iframe.doc.body.appendChild(vine);
+ vine.implementation_.layoutCallback();
+ return vine;
+ });
+ }
+
+ it('renders', () => {
+ return getVine('MdKjXez002d').then(vine => {
+ const iframe = vine.querySelector('iframe');
+ expect(iframe).to.not.be.null;
+ expect(iframe.tagName).to.equal('IFRAME');
+ expect(iframe.src).to.equal('https://vine.co/v/MdKjXez002d/embed/simple');
+ expect(iframe.getAttribute('width')).to.equal('400');
+ expect(iframe.getAttribute('height')).to.equal('400');
+ });
+ });
+
+ it('renders responsively', () => {
+ return getVine('MdKjXez002d', true).then(vine => {
+ const iframe = vine.querySelector('iframe');
+ expect(iframe).to.not.be.null;
+ expect(iframe.className).to.match(/-amp-fill-content/);
+ });
+ });
+
+ it('requires data-vineid', () => {
+ return getVine('').should.eventually.be.rejectedWith(
+ /The data-vineid attribute is required for/);
+ });
+});
diff --git a/extensions/amp-vine/amp-vine.md b/extensions/amp-vine/amp-vine.md
new file mode 100644
index 000000000000..dfc58116fa90
--- /dev/null
+++ b/extensions/amp-vine/amp-vine.md
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2015 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.
+ */
+
+ ### `amp-vine`
+
+ Displays a Vine simple embed
+
+ Example:
+
+
+
+
+A Vine simple embed has equal width and height.
+
+#### Attributes
+
+**data-vineid**
+
+The ID of the Vine. In a URL like https://vine.co/v/MdKjXez002d `MdKjXez002d` is the vineID.
diff --git a/gulpfile.js b/gulpfile.js
index 305f14ea9917..a1686c7fe8cb 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -84,6 +84,7 @@ function buildExtensions(options) {
*/
buildExtension('amp-slides', '0.1', false, options);
buildExtension('amp-twitter', '0.1', false, options);
+ buildExtension('amp-vine', '0.1', false, options);
buildExtension('amp-youtube', '0.1', false, options);
}
@@ -305,6 +306,7 @@ function buildExamples(watch) {
buildExample('instagram.amp.html');
buildExample('released.amp.html');
buildExample('twitter.amp.html');
+ buildExample('vine.amp.html');
function copyHandler(name, err) {
if (err) {
diff --git a/spec/amp-html-components.md b/spec/amp-html-components.md
index e14402633a7b..d1be97c36bac 100644
--- a/spec/amp-html-components.md
+++ b/spec/amp-html-components.md
@@ -184,4 +184,5 @@ In these cases, services may set up endpoints that produce data that conforms to
- [amp-iframe](../extensions/amp-iframe/amp-iframe.md)
- [amp-instagram](../extensions/amp-instagram/amp-instagram.md)
- [amp-twitter](../extensions/amp-twitter/amp-twitter.md)
+- [amp-vine](../extensions/amp-vine/amp-vine.md)
- [amp-youtube](../extensions/amp-youtube/amp-youtube.md)
diff --git a/spec/amp-tag-addendum.md b/spec/amp-tag-addendum.md
index 2e0667f273b8..9d23a477e05f 100644
--- a/spec/amp-tag-addendum.md
+++ b/spec/amp-tag-addendum.md
@@ -174,6 +174,7 @@ These may be removed in future versions of AMP
``
``
``
+``
``
``
``
diff --git a/test/integration/test-example-validation.js b/test/integration/test-example-validation.js
index a517d508d2bc..37701acd92cd 100644
--- a/test/integration/test-example-validation.js
+++ b/test/integration/test-example-validation.js
@@ -49,6 +49,7 @@ describe('example', function() {
'instagram.amp.html',
'released.amp.html',
'twitter.amp.html',
+ 'vine.amp.html',
];
/**
diff --git a/test/manual/amp-vine.amp.html b/test/manual/amp-vine.amp.html
new file mode 100644
index 000000000000..579fbdac61c8
--- /dev/null
+++ b/test/manual/amp-vine.amp.html
@@ -0,0 +1,33 @@
+
+
+
+
+ AMP #0
+
+
+
+
+
+
+
+
+