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

✨ implement amp-embedly-card component #14819

Merged
merged 47 commits into from
Jul 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
09bc275
amp-embedly-card: Extension skeleton
juanlizarazo Apr 23, 2018
546205d
amp-embedly-card: Embedly 3p script basic.
juanlizarazo Apr 23, 2018
af2f37b
amp-embedly-card: Register 3p script.
juanlizarazo Apr 23, 2018
12a5a54
amp-embedly-card: Consume 3p iframe.
juanlizarazo Apr 23, 2018
8c078a7
amp-embedly-card: Require data-url. Place dom mutations in layoutCall…
juanlizarazo Apr 23, 2018
72c1f4f
amp-embedly-card: Use data-url in 3p script
juanlizarazo Apr 23, 2018
338215e
amp-embedly-card: Resize events.
juanlizarazo Apr 23, 2018
4930c4d
amp-embedly-card: Add amp-embedly-key and embedly-service. Set option…
juanlizarazo Apr 23, 2018
246eea9
amp-embedly-card: Allow data key option to remove branding.
juanlizarazo Apr 23, 2018
84a01bf
amp-embedly-card: Set customizable attributes from component data att…
juanlizarazo Apr 23, 2018
d99d2f3
amp-embedly-card: Correct resize size.
juanlizarazo Apr 24, 2018
e52f0b6
amp-embedly-card: update whitelisted options
juanlizarazo Apr 24, 2018
bec4e9a
amp-embedly-card: Documentation
juanlizarazo Apr 24, 2018
e6e4a54
amp-embedly-card: Update validator
juanlizarazo Apr 24, 2018
3be8902
amp-embedly-card: Unit tests
juanlizarazo Apr 24, 2018
018ad26
amp-embedly-card: Correct import test
juanlizarazo Apr 24, 2018
0e5a10c
Reference amp-embedly-card.md
juanlizarazo Apr 24, 2018
125046b
amp-embedly-card: Read embedly sdk object with bracket notation
juanlizarazo Apr 24, 2018
342aa9a
amp-embedly-card: Remove service
juanlizarazo Jun 11, 2018
c9efe6b
amp-embedly-card: Query api key directly from element when provided
juanlizarazo Jun 11, 2018
ca41f80
amp-embedly-card: Fix lint
juanlizarazo Jun 11, 2018
924503b
amp-embedly-card: Fix lint in card implementation file.
juanlizarazo Jun 11, 2018
ce4efd2
amp-embedly-card: Correct compiler type.
juanlizarazo Jun 11, 2018
8a08dcf
amp-embedly-card: Add validator tests [WIP]
juanlizarazo Jun 11, 2018
a82ce24
amp-embedly-card: Move validator tests to correct location [WIP]
juanlizarazo Jun 11, 2018
573184c
amp-embedly-card: Update validator test cases and .out file.
juanlizarazo Jun 11, 2018
2c01772
amp-embedly-card: Correct validator test case
juanlizarazo Jun 11, 2018
9ae088b
amp-embedly-card: update validator test cases
juanlizarazo Jun 11, 2018
f4f3544
amp-embedly-card: Update protoascii rules
juanlizarazo Jun 11, 2018
efee91d
amp-embedly-card: Move and rename validator html and out files
juanlizarazo Jun 12, 2018
aa69e53
amp-embedly-card: update validation rules (unique tag, protocol, remo…
juanlizarazo Jun 12, 2018
f83fd97
amp-embedly-card: Update validator test cases
juanlizarazo Jun 12, 2018
640a2b3
amp-embedly-card: Clean up attributes in documentation
juanlizarazo Jun 12, 2018
f28525c
amp-embedly-card: Update jsdoc description
juanlizarazo Jun 12, 2018
32da3c8
touchups
Jun 12, 2018
31c0ddf
touchup2
Jun 12, 2018
7ce1743
amp-embedly-card: Initialize card correctly. Add data-card-embed supp…
juanlizarazo Jul 9, 2018
f943e9c
amp-embedly-card: Update documentation.
juanlizarazo Jul 9, 2018
549c1a5
amp-embedly-card: Support embedly dark theme.
juanlizarazo Jul 9, 2018
3fc9795
amp-embedly-card: Update theme documentation.
juanlizarazo Jul 9, 2018
478d900
amp-embedly-card: Update data-card-theme docs
juanlizarazo Jul 9, 2018
3f97841
amp-embedly-card: Update data-card-theme docs
juanlizarazo Jul 9, 2018
3fc98a0
amp-embedly-card: Add entry to bundles.config
juanlizarazo Jul 9, 2018
d240129
amp-embedly-card: update comment
juanlizarazo Jul 9, 2018
265be3c
amp-embedly-card: update docs
juanlizarazo Jul 9, 2018
a47cd2e
amp-embedly-card: Remove lint so tests pass
juanlizarazo Jul 15, 2018
3f18a27
touchups
Jul 16, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion 3p/ampcontext-integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ export class IntegrationAmpContext extends AbstractAmpContext {
|| this.embedType_ === 'github'
|| this.embedType_ === 'mathml'
|| this.embedType_ === 'reddit'
|| this.embedType_ === 'yotpo');
|| this.embedType_ === 'yotpo'
|| this.embedType_ === 'embedly'
);
}

/** @return {!Window} */
Expand Down
118 changes: 118 additions & 0 deletions 3p/embedly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* Copyright 2018 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 {loadScript} from './3p';
import {setStyle} from '../src/style';

/**
* Embedly platform library url to create cards.
* @const {string}
*/
const EMBEDLY_SDK_URL = 'https://cdn.embedly.com/widgets/platform.js';

/**
* Event name emitted by embedly's SDK.
* @type {string}
*/
const RESIZE_EVENT_NAME = 'card.resize';

/**
* Css class expected by embedly library to style card.
* @const {string}
*/
const CARD_CSS_CLASS = 'embedly-card';

/**
* Whitelisted card options.
*
* - Key is in camel case as received in "data".
* - The value is in the format expected by embedly.
*
* @see {@link http://docs.embed.ly/docs/cards#customize}
* @const @enum {string}
*/
export const CardOptions = {
cardVia: 'card-via',
cardTheme: 'card-theme',
cardImage: 'card-image',
cardControls: 'card-controls',
cardAlign: 'card-align',
cardRecommend: 'card-recommend',
cardEmbed: 'card-embed',
cardKey: 'card-key',
};

/**
* Loads embedly card SDK that is consumed by this 3p integration.
*
* @param {!Window} global
* @param {function(!Object)} callback
* @visibleForTesting
*/
function getEmbedly(global, callback) {
loadScript(global, EMBEDLY_SDK_URL, function() {
callback(global);
});
}

/**
* Creates embedly card using sdk.
*
* @param {!Window} global
* @param {!Object} data
*/
export function embedly(global, data) {
const card = global.document.createElement('a');

card.href = data.url;
card.classList.add(CARD_CSS_CLASS);

// Add whitelisted data attributes and values to card
// when these are provided by component.
for (const key in CardOptions) {
if (
CardOptions.hasOwnProperty(key) &&
typeof data[key] !== 'undefined'
) {
card.setAttribute(`data-${CardOptions[key]}`, data[key]);
}
}

const container = global.document.getElementById('c');

// Adds support to embedly dark theme not set by the sdk
if (data['cardTheme'] === 'dark') {
setStyle(container, 'background', 'rgba(51, 51, 51)');
}

container.appendChild(card);

getEmbedly(global, function() {
// Given by the parent frame.
delete data.width;
delete data.height;

global.window['embedly']('card', card);

// Use embedly SDK to listen to resize event from loaded card
global.window['embedly']('on', RESIZE_EVENT_NAME, function(iframe) {
context.requestResize(
iframe./*OK*/width,
parseInt(iframe./*OK*/height, 10) + /* margin */ 5
);
});
});
}
2 changes: 2 additions & 0 deletions 3p/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {urls} from '../src/config';
// 3P - please keep in alphabetic order
import {beopinion} from './beopinion';
import {bodymovinanimation} from './bodymovinanimation';
import {embedly} from './embedly';
import {facebook} from './facebook';
import {github} from './github';
import {gltfViewer} from './3d-gltf/index';
Expand Down Expand Up @@ -336,6 +337,7 @@ register('distroscale', distroscale);
register('dotandads', dotandads);
register('eadv', eadv);
register('eas', eas);
register('embedly', embedly);
register('engageya', engageya);
register('epeex', epeex);
register('eplanning', eplanning);
Expand Down
1 change: 1 addition & 0 deletions bundles.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ exports.extensionBundles = [
{name: 'amp-date-countdown', version: '0.1', type: TYPES.MISC},
{name: 'amp-google-document-embed', version: '0.1', type: TYPES.MISC},
{name: 'amp-dynamic-css-classes', version: '0.1', type: TYPES.MISC},
{name: 'amp-embedly-card', version: '0.1', type: TYPES.MISC},
{name: 'amp-experiment', version: '0.1', type: TYPES.MISC},
{name: 'amp-facebook', version: '0.1', type: TYPES.MISC},
{name: 'amp-facebook-comments', version: '0.1', type: TYPES.MISC},
Expand Down
29 changes: 29 additions & 0 deletions examples/amp-embedly-card.amp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!doctype html>
<html ⚡>
<head>
<meta charset="utf-8">
<title>amp-embedly-card example</title>
<link rel="canonical" href="amps.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async custom-element="amp-embedly-card" src="https://cdn.ampproject.org/v0/amp-embedly-card-0.1.js"></script>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
<amp-embedly-card
data-url="https://twitter.com/AMPhtml/status/986750295077040128"
layout="responsive"
width="150"
height="80"
data-card-theme="dark"
data-card-controls="0"
></amp-embedly-card>

<amp-embedly-card
data-url="https://www.youtube.com/watch?v=lBTCB7yLs8Y"
layout="responsive"
width="100"
height="50"
></amp-embedly-card>
</body>
</html>
113 changes: 113 additions & 0 deletions extensions/amp-embedly-card/0.1/amp-embedly-card-impl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* Copyright 2018 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 {TAG as KEY_TAG} from './amp-embedly-key';
import {Layout} from '../../../src/layout';
import {getIframe} from '../../../src/3p-frame';
import {listenFor} from '../../../src/iframe-helper';
import {removeElement} from '../../../src/dom';
import {user} from '../../../src/log';

/**
* Component tag identifier.
* @const {string}
*/
export const TAG = 'amp-embedly-card';

/**
* Attribute name used to set api key with name
* expected by embedly.
* @const {string}
*/
const API_KEY_ATTR_NAME = 'data-card-key';

/**
* Implementation of the amp-embedly-card component.
* See {@link ../amp-embedly-card.md} for the spec.
*/
export class AmpEmbedlyCard extends AMP.BaseElement {

/** @param {!AmpElement} element */
constructor(element) {
super(element);

/** @private {?HTMLIFrameElement} */
this.iframe_ = null;

/** @private {?string} */
this.apiKey_ = null;
}

/** @override */
buildCallback() {
user().assert(
this.element.getAttribute('data-url'),
`The data-url attribute is required for <${TAG}> %s`,
this.element
);

const ampEmbedlyKeyElement = document.querySelector(KEY_TAG);
if (ampEmbedlyKeyElement) {
this.apiKey_ = ampEmbedlyKeyElement.getAttribute('value');
}
}

/** @override */
layoutCallback() {
// Add optional paid api key attribute if provided
// to remove embedly branding.
if (this.apiKey_) {
this.element.setAttribute(API_KEY_ATTR_NAME, this.apiKey_);
}

const iframe = getIframe(this.win, this.element, 'embedly');

const opt_is3P = true;
listenFor(iframe, 'embed-size', data => {
this./*OK*/changeHeight(data['height']);
}, opt_is3P);

this.applyFillContent(iframe);
this.getVsync().mutate(() => this.element.appendChild(iframe));

this.iframe_ = iframe;

return this.loadPromise(iframe);
}

/** @override */
unlayoutCallback() {
if (this.iframe_) {
removeElement(this.iframe_);
this.iframe_ = null;
}

return true;
}

/** @override */
isLayoutSupported(layout) {
return layout == Layout.RESPONSIVE;
}

/**
* @param {boolean=} opt_onLayout
* @override
*/
preconnectCallback(opt_onLayout) {
this.preconnect.url('https://cdn.embedly.com', opt_onLayout);
}
}
23 changes: 23 additions & 0 deletions extensions/amp-embedly-card/0.1/amp-embedly-card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright 2018 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 {AmpEmbedlyCard, TAG} from './amp-embedly-card-impl';
import {AmpEmbedlyKey, TAG as KEY_TAG} from './amp-embedly-key';

AMP.extension(TAG, '0.1', function(AMP) {
AMP.registerElement(TAG, AmpEmbedlyCard);
AMP.registerElement(KEY_TAG, AmpEmbedlyKey);
});
49 changes: 49 additions & 0 deletions extensions/amp-embedly-card/0.1/amp-embedly-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Copyright 2018 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 {Layout} from '../../../src/layout';
import {user} from '../../../src/log';

/** @const {string} */
export const TAG = 'amp-embedly-key';

/**
* Implementation of the amp-embedly-key component.
*
* Gets api key from user input to be used by other embedly components.
*
* See {@link ../amp-embedly-card.md} for the spec.
*/
export class AmpEmbedlyKey extends AMP.BaseElement {
/** @param {!AmpElement} element */
constructor(element) {
super(element);
}

/** @override */
buildCallback() {
user().assert(
this.element.getAttribute('value'),
`The value attribute is required for <${TAG}> %s`,
this.element
);
}

/** @override */
isLayoutSupported(layout) {
return layout === Layout.NODISPLAY;
}
}
Loading