From c67efab1dab903e7e458fdcb1eb6274e3d51085d Mon Sep 17 00:00:00 2001 From: Keshav Varadachari Date: Fri, 10 Dec 2021 14:19:15 -0500 Subject: [PATCH] refactor amp/bento video extensions: * brightcove * jwplayer * video-iframe * video * vimeo * youtube --- .../amp-brightcove/1.0/amp-brightcove.js | 31 ++++-- extensions/amp-brightcove/1.0/base-element.js | 32 ++---- extensions/amp-brightcove/1.0/element.js | 25 +++++ extensions/amp-jwplayer/1.0/amp-jwplayer.js | 31 +++++- extensions/amp-jwplayer/1.0/base-element.js | 97 ++++--------------- extensions/amp-jwplayer/1.0/element.js | 93 ++++++++++++++++++ .../amp-video-iframe/1.0/amp-video-iframe.js | 19 +++- .../amp-video-iframe/1.0/base-element.js | 28 ++---- extensions/amp-video-iframe/1.0/element.js | 21 ++++ extensions/amp-video/1.0/amp-video.js | 4 +- extensions/amp-video/1.0/base-element.js | 53 +++------- extensions/amp-video/1.0/element.js | 42 ++++++++ .../amp-video/1.0/video-base-element.js | 43 +++++++- extensions/amp-vimeo/1.0/amp-vimeo.js | 27 +++++- extensions/amp-vimeo/1.0/base-element.js | 30 +++--- extensions/amp-vimeo/1.0/element.js | 17 ++++ extensions/amp-youtube/1.0/amp-youtube.js | 18 +++- extensions/amp-youtube/1.0/base-element.js | 28 ++---- extensions/amp-youtube/1.0/element.js | 21 ++++ 19 files changed, 437 insertions(+), 223 deletions(-) create mode 100644 extensions/amp-brightcove/1.0/element.js create mode 100644 extensions/amp-jwplayer/1.0/element.js create mode 100644 extensions/amp-video-iframe/1.0/element.js create mode 100644 extensions/amp-video/1.0/element.js create mode 100644 extensions/amp-vimeo/1.0/element.js create mode 100644 extensions/amp-youtube/1.0/element.js diff --git a/extensions/amp-brightcove/1.0/amp-brightcove.js b/extensions/amp-brightcove/1.0/amp-brightcove.js index cf55a5fb8dff9..d05dc8eb14439 100644 --- a/extensions/amp-brightcove/1.0/amp-brightcove.js +++ b/extensions/amp-brightcove/1.0/amp-brightcove.js @@ -3,17 +3,18 @@ import { getConsentPolicySharedData, getConsentPolicyState, } from '../../../src/consent'; -import {BaseElement} from './base-element'; import {CSS} from '../../../build/amp-brightcove-1.0.css'; import {dict} from '#core/types/object'; import {isExperimentOn} from '#experiments'; import {userAssert} from '#utils/log'; import {Services} from '#service'; +import {Component, layoutSizeDefined, props, usesShadowDom} from './element'; +import {AmpVideoBaseElement} from '../../amp-video/1.0/video-base-element'; /** @const {string} */ const TAG = 'amp-brightcove'; -class AmpBrightcove extends BaseElement { +class AmpBrightcove extends AmpVideoBaseElement { /** @override @nocollapse */ static getPreconnects() { return ['https://players.brightcove.net']; @@ -62,6 +63,24 @@ class AmpBrightcove extends BaseElement { } } +/** @override */ +AmpBrightcove['Component'] = Component; + +/** @override */ +AmpBrightcove['props'] = { + ...props, + 'referrer': { + attrs: ['data-referrer'], + parseAttrs: getReferrerFromElement, + }, +}; + +/** @override */ +AmpBrightcove['layoutSizeDefined'] = layoutSizeDefined; + +/** @override */ +AmpBrightcove['usesShadowDom'] = usesShadowDom; + AMP.extension(TAG, '1.0', (AMP) => { AMP.registerElement(TAG, AmpBrightcove, CSS); }); @@ -77,11 +96,3 @@ function getReferrerFromElement(element) { ) : undefined; } - -AmpBrightcove['props'] = { - ...BaseElement['props'], - 'referrer': { - attrs: ['data-referrer'], - parseAttrs: getReferrerFromElement, - }, -}; diff --git a/extensions/amp-brightcove/1.0/base-element.js b/extensions/amp-brightcove/1.0/base-element.js index 00f1b5a73f7bd..d22b1471bed75 100644 --- a/extensions/amp-brightcove/1.0/base-element.js +++ b/extensions/amp-brightcove/1.0/base-element.js @@ -1,34 +1,16 @@ -import {BentoBrightcove} from './component'; -import {VideoBaseElement} from '../../amp-video/1.0/video-base-element'; -import {createParseAttrsWithPrefix} from '#preact/parse-props'; +import {BaseElement as BentoVideoBaseElement} from '../../amp-video/1.0/base-element'; +import {Component, layoutSizeDefined, props, usesShadowDom} from './element'; -export class BaseElement extends VideoBaseElement {} +export class BaseElement extends BentoVideoBaseElement {} /** @override */ -BaseElement['Component'] = BentoBrightcove; +BaseElement['Component'] = Component; /** @override */ -BaseElement['props'] = { - 'account': {attr: 'data-account'}, - 'autoplay': {attr: 'autoplay', type: 'boolean'}, - 'embed': {attr: 'data-embed', default: 'default'}, - 'player': { - attrs: ['data-player', 'data-player-id'], - parseAttrs(element) { - const {'player': player, 'playerId': playerId} = element.dataset; - return player || playerId || 'default'; - }, - }, - 'playlistId': {attr: 'data-playlist-id'}, - 'referrer': {attr: 'data-referrer'}, - 'urlParams': createParseAttrsWithPrefix('data-param-'), - 'videoId': {attr: 'data-video-id'}, - // TODO(wg-bento): These props have no internal implementation yet. - 'dock': {attr: 'dock', media: true}, -}; +BaseElement['props'] = props; /** @override */ -BaseElement['layoutSizeDefined'] = true; +BaseElement['layoutSizeDefined'] = layoutSizeDefined; /** @override */ -BaseElement['usesShadowDom'] = true; +BaseElement['usesShadowDom'] = usesShadowDom; diff --git a/extensions/amp-brightcove/1.0/element.js b/extensions/amp-brightcove/1.0/element.js new file mode 100644 index 0000000000000..79a2dc4f38111 --- /dev/null +++ b/extensions/amp-brightcove/1.0/element.js @@ -0,0 +1,25 @@ +import {createParseAttrsWithPrefix} from '#preact/parse-props'; +export {BentoBrightcove as Component} from './component'; + +export const props = { + 'account': {attr: 'data-account'}, + 'autoplay': {attr: 'autoplay', type: 'boolean'}, + 'embed': {attr: 'data-embed', default: 'default'}, + 'player': { + attrs: ['data-player', 'data-player-id'], + parseAttrs(element) { + const {'player': player, 'playerId': playerId} = element.dataset; + return player || playerId || 'default'; + }, + }, + 'playlistId': {attr: 'data-playlist-id'}, + 'referrer': {attr: 'data-referrer'}, + 'urlParams': createParseAttrsWithPrefix('data-param-'), + 'videoId': {attr: 'data-video-id'}, + // TODO(wg-bento): These props have no internal implementation yet. + 'dock': {attr: 'dock', media: true}, +}; + +export const layoutSizeDefined = true; + +export const usesShadowDom = true; diff --git a/extensions/amp-jwplayer/1.0/amp-jwplayer.js b/extensions/amp-jwplayer/1.0/amp-jwplayer.js index 2e9149513762a..c30e2a9f847e4 100644 --- a/extensions/amp-jwplayer/1.0/amp-jwplayer.js +++ b/extensions/amp-jwplayer/1.0/amp-jwplayer.js @@ -4,21 +4,31 @@ import {isExperimentOn} from '#experiments'; import {userAssert} from '#utils/log'; -import {BaseElement} from './base-element'; +import { + Component, + getJwplayerProps, + layoutSizeDefined, + loadable, + props, + usesShadowDom, +} from './element'; import { getConsentMetadata, getConsentPolicyInfo, getConsentPolicyState, } from '../../../src/consent'; +import {AmpVideoBaseElement} from '../../amp-video/1.0/video-base-element'; /** @const {string} */ const TAG = 'amp-jwplayer'; /** @implements {../../../src/video-interface.VideoInterface} */ -class AmpJwplayer extends BaseElement { +class AmpJwplayer extends AmpVideoBaseElement { /** @override */ init() { + super.init(); + const consentPolicy = this.getConsentPolicy(); if (consentPolicy) { this.getConsentInfo().then((consentInfo) => { @@ -37,7 +47,7 @@ class AmpJwplayer extends BaseElement { }); } - return super.init(); + return getJwplayerProps(this.element); } /** @@ -63,6 +73,21 @@ class AmpJwplayer extends BaseElement { } } +/** @override */ +AmpJwplayer['Component'] = Component; + +/** @override */ +AmpJwplayer['props'] = props; + +/** @override */ +AmpJwplayer['layoutSizeDefined'] = layoutSizeDefined; + +/** @override */ +AmpJwplayer['usesShadowDom'] = usesShadowDom; + +/** @override */ +AmpJwplayer['loadable'] = loadable; + AMP.extension(TAG, '1.0', (AMP) => { AMP.registerElement(TAG, AmpJwplayer); }); diff --git a/extensions/amp-jwplayer/1.0/base-element.js b/extensions/amp-jwplayer/1.0/base-element.js index 6858c779fef91..424681d822c57 100644 --- a/extensions/amp-jwplayer/1.0/base-element.js +++ b/extensions/amp-jwplayer/1.0/base-element.js @@ -1,93 +1,32 @@ -import {getDataParamsFromAttributes} from '#core/dom'; -import {dict} from '#core/types/object'; - -import {createParseAttrsWithPrefix} from '#preact/parse-props'; - -import {BentoJwplayer} from './component'; - -import {VideoBaseElement} from '../../amp-video/1.0/video-base-element'; - -export class BaseElement extends VideoBaseElement { +import { + Component, + getJwplayerProps, + layoutSizeDefined, + loadable, + props, + usesShadowDom, +} from './element'; + +import {BaseElement as BentoVideoBaseElement} from '../../amp-video/1.0/base-element'; + +export class BaseElement extends BentoVideoBaseElement { /** @override */ init() { - super.init(); - - return dict({ - 'queryParams': this.mergeQueryParams( - getDataParamsFromAttributes(this.element, null, /^playerParam(.+)/), - this.element.getAttribute('data-player-querystring') - ), - 'contentSearch': this.getContextualSearch( - this.element.getAttribute('data-content-search') - ), - }); - } - - /** - * Gets contextual search value - * @param {string} searchVal - * @return {string} contextual search value - */ - getContextualSearch(searchVal) { - if (searchVal !== '__CONTEXTUAL__') { - return searchVal; - } - - const {head, title} = this.element.ownerDocument; - const ogTitleElement = head.querySelector('meta[property="og:title"]'); - const ogTitle = ogTitleElement - ? ogTitleElement.getAttribute('content') - : null; - return ogTitle || title || ''; - } - - /** - * Merges query params from multiple sources into 1 string - * @param {Object} playerParams - * @param {string} playerQueryString - * @return {string} - */ - mergeQueryParams(playerParams, playerQueryString) { - const addEntries = (acc, entries) => { - for (const entry of entries) { - acc[entry[0]] = entry[1]; - } - }; - const p1 = new URLSearchParams(playerParams || ''); - const p2 = new URLSearchParams(playerQueryString || ''); - const params = {}; - addEntries(params, p1.entries()); - addEntries(params, p2.entries()); - return params; + return getJwplayerProps(this.element); } } /** @override */ -BaseElement['Component'] = BentoJwplayer; +BaseElement['Component'] = Component; /** @override */ -BaseElement['props'] = { - 'playerId': {attr: 'data-player-id'}, - 'mediaId': {attr: 'data-media-id'}, - 'playlistId': {attr: 'data-playlist-id'}, - 'contentRecency': {attr: 'data-content-recency'}, - 'contentBackfill': {attr: 'data-content-backfill', type: 'boolean'}, - 'adCustParams': {attr: 'data-ad-cust-params'}, - 'adMacros': createParseAttrsWithPrefix('data-ad-macro-'), - 'config': createParseAttrsWithPrefix('data-config-'), - 'autoplay': {attr: 'autoplay', type: 'boolean'}, - // TODO(wg-components): Current behavior defaults to loading="auto". - // Refactor to make loading="lazy" as the default. - 'loading': {attr: 'data-loading'}, - // TODO(wg-bento): These props have no internal implementation yet. - 'dock': {attr: 'dock', media: true}, -}; +BaseElement['props'] = props; /** @override */ -BaseElement['layoutSizeDefined'] = true; +BaseElement['layoutSizeDefined'] = layoutSizeDefined; /** @override */ -BaseElement['usesShadowDom'] = true; +BaseElement['usesShadowDom'] = usesShadowDom; /** @override */ -BaseElement['loadable'] = true; +BaseElement['loadable'] = loadable; diff --git a/extensions/amp-jwplayer/1.0/element.js b/extensions/amp-jwplayer/1.0/element.js new file mode 100644 index 0000000000000..7f5e025b25fdb --- /dev/null +++ b/extensions/amp-jwplayer/1.0/element.js @@ -0,0 +1,93 @@ +import {getDataParamsFromAttributes} from '#core/dom'; +import {dict} from '#core/types/object'; + +import {createParseAttrsWithPrefix} from '#preact/parse-props'; +export {BentoJwplayer as Component} from './component'; + +export const props = { + 'playerId': {attr: 'data-player-id'}, + 'mediaId': {attr: 'data-media-id'}, + 'playlistId': {attr: 'data-playlist-id'}, + 'contentRecency': {attr: 'data-content-recency'}, + 'contentBackfill': {attr: 'data-content-backfill', type: 'boolean'}, + 'adCustParams': {attr: 'data-ad-cust-params'}, + 'adMacros': createParseAttrsWithPrefix('data-ad-macro-'), + 'config': createParseAttrsWithPrefix('data-config-'), + 'autoplay': {attr: 'autoplay', type: 'boolean'}, + // TODO(wg-components): Current behavior defaults to loading="auto". + // Refactor to make loading="lazy" as the default. + 'loading': {attr: 'data-loading'}, + // TODO(wg-bento): These props have no internal implementation yet. + 'dock': {attr: 'dock', media: true}, +}; + +export const layoutSizeDefined = true; + +export const usesShadowDom = true; + +export const loadable = true; + +/** + * @param {Element} element + * @return {JsonObject} + */ +export function getJwplayerProps(element) { + return dict({ + 'queryParams': mergeQueryParams(element), + 'contentSearch': getContextualSearch(element), + }); +} + +/** + * Gets contextual search value + * @param {Element} element + * @return {string} contextual search value + */ +function getContextualSearch(element) { + const searchVal = element.getAttribute('data-content-search'); + if (searchVal !== '__CONTEXTUAL__') { + return searchVal; + } + + const {head, title} = element.ownerDocument; + const ogTitleElement = head.querySelector('meta[property="og:title"]'); + const ogTitle = ogTitleElement + ? ogTitleElement.getAttribute('content') + : null; + return ogTitle || title || ''; +} + +/** + * Merges query params from multiple sources into 1 string + * @param {Element} element + * @return {string} + */ +function mergeQueryParams(element) { + const playerParams = getDataParamsFromAttributes( + element, + null, + /^playerParam(.+)/ + ); + const playerQueryString = element.getAttribute('data-player-querystring'); + return mergeQueryParams_(playerParams, playerQueryString); +} + +/** + * Merges query params from multiple sources into 1 string + * @param {Object} playerParams + * @param {string} playerQueryString + * @return {string} + */ +function mergeQueryParams_(playerParams, playerQueryString) { + const addEntries = (acc, entries) => { + for (const entry of entries) { + acc[entry[0]] = entry[1]; + } + }; + const p1 = new URLSearchParams(playerParams || ''); + const p2 = new URLSearchParams(playerQueryString || ''); + const params = {}; + addEntries(params, p1.entries()); + addEntries(params, p2.entries()); + return params; +} diff --git a/extensions/amp-video-iframe/1.0/amp-video-iframe.js b/extensions/amp-video-iframe/1.0/amp-video-iframe.js index ed61dc12daca4..a7888a42c8d23 100644 --- a/extensions/amp-video-iframe/1.0/amp-video-iframe.js +++ b/extensions/amp-video-iframe/1.0/amp-video-iframe.js @@ -6,7 +6,9 @@ import {isExperimentOn} from '#experiments'; import {createCustomEvent} from '#utils/event-helper'; import {userAssert} from '#utils/log'; -import {BaseElement} from './base-element'; +import {AmpVideoBaseElement} from 'extensions/amp-video/1.0/video-base-element'; + +import {Component, loadable, props, usesShadowDom} from './element'; import {CSS} from '../../../build/amp-video-iframe-1.0.css'; import {postMessageWhenAvailable} from '../../../src/iframe-video'; @@ -30,7 +32,7 @@ function getIntersectionRatioMinAutoplay(element) { ); } -class AmpVideoIframe extends BaseElement { +class AmpVideoIframe extends AmpVideoBaseElement { /** @override */ isLayoutSupported(layout) { userAssert( @@ -105,6 +107,19 @@ const makeMethodMessage = (method) => 'method': method.toLowerCase(), }); +/** @override */ +AmpVideoIframe['Component'] = Component; + +/** @override */ +AmpVideoIframe['props'] = props; + +/** @override */ +AmpVideoIframe['usesShadowDom'] = usesShadowDom; + +/** @override */ +AmpVideoIframe['loadable'] = loadable; + +/** @override */ AmpVideoIframe['staticProps'] = dict({ 'onMessage': onMessage, 'makeMethodMessage': makeMethodMessage, diff --git a/extensions/amp-video-iframe/1.0/base-element.js b/extensions/amp-video-iframe/1.0/base-element.js index f2f280c6e47eb..98285e493e057 100644 --- a/extensions/amp-video-iframe/1.0/base-element.js +++ b/extensions/amp-video-iframe/1.0/base-element.js @@ -1,31 +1,17 @@ -import {BentoVideoIframe} from './component'; +import {Component, loadable, props, usesShadowDom} from './element'; -import {VideoBaseElement} from '../../amp-video/1.0/video-base-element'; +import {BaseElement as BentoVideoBaseElement} from '../../amp-video/1.0/base-element'; -export class BaseElement extends VideoBaseElement {} +export class BaseElement extends BentoVideoBaseElement {} /** @override */ -BaseElement['Component'] = BentoVideoIframe; +BaseElement['Component'] = Component; /** @override */ -BaseElement['props'] = { - 'autoplay': {attr: 'autoplay', type: 'boolean'}, - 'referrerpolicy': {attr: 'referrerpolicy'}, - 'implements-media-session': {attr: 'mediasession', type: 'boolean'}, - 'poster': {attr: 'poster'}, - 'src': {attr: 'src'}, - 'controls': {attr: 'controls', type: 'boolean'}, - // TODO(wg-components): Current behavior defaults to loading="auto". - // Refactor to make loading="lazy" as the default. - 'loading': {attr: 'data-loading'}, - - // TODO(alanorozco): These props have no internal implementation yet. - 'dock': {attr: 'dock'}, - 'rotate-to-fullscreen': {attr: 'rotate-to-fullscreen', type: 'boolean'}, -}; +BaseElement['props'] = props; /** @override */ -BaseElement['usesShadowDom'] = true; +BaseElement['usesShadowDom'] = usesShadowDom; /** @override */ -BaseElement['loadable'] = true; +BaseElement['loadable'] = loadable; diff --git a/extensions/amp-video-iframe/1.0/element.js b/extensions/amp-video-iframe/1.0/element.js new file mode 100644 index 0000000000000..e6785e84580d7 --- /dev/null +++ b/extensions/amp-video-iframe/1.0/element.js @@ -0,0 +1,21 @@ +export {BentoVideoIframe as Component} from './component'; + +export const props = { + 'autoplay': {attr: 'autoplay', type: 'boolean'}, + 'referrerpolicy': {attr: 'referrerpolicy'}, + 'implements-media-session': {attr: 'mediasession', type: 'boolean'}, + 'poster': {attr: 'poster'}, + 'src': {attr: 'src'}, + 'controls': {attr: 'controls', type: 'boolean'}, + // TODO(wg-components): Current behavior defaults to loading="auto". + // Refactor to make loading="lazy" as the default. + 'loading': {attr: 'data-loading'}, + + // TODO(alanorozco): These props have no internal implementation yet. + 'dock': {attr: 'dock'}, + 'rotate-to-fullscreen': {attr: 'rotate-to-fullscreen', type: 'boolean'}, +}; + +export const usesShadowDom = true; + +export const loadable = true; diff --git a/extensions/amp-video/1.0/amp-video.js b/extensions/amp-video/1.0/amp-video.js index 3a21e4393a937..156e859d102d5 100644 --- a/extensions/amp-video/1.0/amp-video.js +++ b/extensions/amp-video/1.0/amp-video.js @@ -1,12 +1,12 @@ import {CSS} from '../../../build/amp-video-1.0.css'; -import {VideoBaseElement} from './video-base-element'; +import {AmpVideoBaseElement} from './video-base-element'; import {isExperimentOn} from '#experiments'; import {userAssert} from '#utils/log'; /** @const {string} */ const TAG = 'amp-video'; -class AmpVideo extends VideoBaseElement { +class AmpVideo extends AmpVideoBaseElement { /** @override */ isLayoutSupported(layout) { userAssert( diff --git a/extensions/amp-video/1.0/base-element.js b/extensions/amp-video/1.0/base-element.js index 2dfe75b8d2b39..98992ff6f8a36 100644 --- a/extensions/amp-video/1.0/base-element.js +++ b/extensions/amp-video/1.0/base-element.js @@ -1,18 +1,24 @@ -import {CSS} from './component.jss'; -import {CSS as CSS_AUTOPLAY} from './autoplay.jss'; import {PreactBaseElement} from '#preact/base-element'; -import {BentoVideo} from './component'; + +import { + Component, + layoutSizeDefined, + loadable, + props, + shadowCss, + usesShadowDom, +} from './element'; export class BaseElement extends PreactBaseElement {} /** @override */ -BaseElement['Component'] = BentoVideo; +BaseElement['Component'] = Component; /** @override */ -BaseElement['loadable'] = true; +BaseElement['loadable'] = loadable; /** @override */ -BaseElement['layoutSizeDefined'] = true; +BaseElement['layoutSizeDefined'] = layoutSizeDefined; /** * Defaults to `{component: 'video'}` from `BentoVideo` component. @@ -27,39 +33,10 @@ BaseElement['layoutSizeDefined'] = true; BaseElement['staticProps']; /** @override */ -BaseElement['props'] = { - 'album': {attr: 'album'}, - 'alt': {attr: 'alt'}, - 'artist': {attr: 'artist'}, - 'artwork': {attr: 'artwork'}, - 'attribution': {attr: 'attribution'}, - 'autoplay': {attr: 'autoplay', type: 'boolean'}, - 'controls': {attr: 'controls', type: 'boolean'}, - 'controlslist': {attr: 'controlslist'}, - 'crossorigin': {attr: 'crossorigin'}, - 'disableremoteplayback': {attr: 'disableremoteplayback'}, - 'loop': {attr: 'loop', type: 'boolean'}, - 'noaudio': {attr: 'noaudio', type: 'boolean'}, - 'poster': {attr: 'poster'}, - 'sources': { - selector: 'source', - single: false, - clone: true, - }, - 'src': {attr: 'src'}, - 'title': {attr: 'title'}, - - // TODO(alanorozco): These props have no internal implementation yet. - 'dock': {attr: 'dock', media: true}, - 'rotate-to-fullscreen': { - attr: 'rotate-to-fullscreen', - type: 'boolean', - media: true, - }, -}; +BaseElement['props'] = props; /** @override */ -BaseElement['shadowCss'] = CSS + CSS_AUTOPLAY; +BaseElement['shadowCss'] = shadowCss; /** @override */ -BaseElement['usesShadowDom'] = true; +BaseElement['usesShadowDom'] = usesShadowDom; diff --git a/extensions/amp-video/1.0/element.js b/extensions/amp-video/1.0/element.js new file mode 100644 index 0000000000000..d10cf15d55236 --- /dev/null +++ b/extensions/amp-video/1.0/element.js @@ -0,0 +1,42 @@ +import {CSS} from './component.jss'; +import {CSS as CSS_AUTOPLAY} from './autoplay.jss'; + +export {BentoVideo as Component} from './component'; + +export const loadable = true; + +export const layoutSizeDefined = true; + +export const props = { + 'album': {attr: 'album'}, + 'alt': {attr: 'alt'}, + 'artist': {attr: 'artist'}, + 'artwork': {attr: 'artwork'}, + 'attribution': {attr: 'attribution'}, + 'autoplay': {attr: 'autoplay', type: 'boolean'}, + 'controls': {attr: 'controls', type: 'boolean'}, + 'controlslist': {attr: 'controlslist'}, + 'crossorigin': {attr: 'crossorigin'}, + 'disableremoteplayback': {attr: 'disableremoteplayback'}, + 'loop': {attr: 'loop', type: 'boolean'}, + 'noaudio': {attr: 'noaudio', type: 'boolean'}, + 'poster': {attr: 'poster'}, + 'sources': { + selector: 'source', + single: false, + clone: true, + }, + 'src': {attr: 'src'}, + 'title': {attr: 'title'}, + + // TODO(alanorozco): These props have no internal implementation yet. + 'dock': {attr: 'dock', media: true}, + 'rotate-to-fullscreen': { + attr: 'rotate-to-fullscreen', + type: 'boolean', + media: true, + }, +}; +export const shadowCss = CSS + CSS_AUTOPLAY; + +export const usesShadowDom = true; diff --git a/extensions/amp-video/1.0/video-base-element.js b/extensions/amp-video/1.0/video-base-element.js index a88660c4d9287..d7e1954782f2d 100644 --- a/extensions/amp-video/1.0/video-base-element.js +++ b/extensions/amp-video/1.0/video-base-element.js @@ -1,8 +1,17 @@ import {ActionTrust_Enum} from '#core/constants/action-constants'; -import {BaseElement} from './base-element'; + +import { + Component, + layoutSizeDefined, + loadable, + props, + shadowCss, + usesShadowDom, +} from './element'; +import {AmpPreactBaseElement} from '#preact/amp-base-element'; /** @extends {PreactBaseElement} */ -export class VideoBaseElement extends BaseElement { +export class AmpVideoBaseElement extends AmpPreactBaseElement { /** @override */ init() { this.registerApiAction_('play', (api) => api.play()); @@ -41,3 +50,33 @@ export class VideoBaseElement extends BaseElement { ); } } + +/** @override */ +AmpVideoBaseElement['Component'] = Component; + +/** @override */ +AmpVideoBaseElement['loadable'] = loadable; + +/** @override */ +AmpVideoBaseElement['layoutSizeDefined'] = layoutSizeDefined; + +/** + * Defaults to `{component: 'video'}` from `BentoVideo` component. + * Subclasses may set: + * ``` + * AmpMyPlayer['staticProps'] = dict({ + * 'component': MyPlayerComponent, + * }); + * ``` + * @override + */ +AmpVideoBaseElement['staticProps']; + +/** @override */ +AmpVideoBaseElement['props'] = props; + +/** @override */ +AmpVideoBaseElement['shadowCss'] = shadowCss; + +/** @override */ +AmpVideoBaseElement['usesShadowDom'] = usesShadowDom; diff --git a/extensions/amp-vimeo/1.0/amp-vimeo.js b/extensions/amp-vimeo/1.0/amp-vimeo.js index f5ad9dbe2dabf..13b1feaae6858 100644 --- a/extensions/amp-vimeo/1.0/amp-vimeo.js +++ b/extensions/amp-vimeo/1.0/amp-vimeo.js @@ -2,14 +2,22 @@ import {isExperimentOn} from '#experiments'; import {userAssert} from '#utils/log'; -import {BaseElement} from './base-element'; +import {AmpVideoBaseElement} from 'extensions/amp-video/1.0/video-base-element'; + +import { + Component, + layoutSizeDefined, + loadable, + props, + usesShadowDom, +} from './element'; import {CSS} from '../../../build/amp-vimeo-1.0.css'; /** @const {string} */ const TAG = 'amp-vimeo'; -class AmpVimeo extends BaseElement { +class AmpVimeo extends AmpVideoBaseElement { /** @override */ isLayoutSupported(layout) { userAssert( @@ -21,6 +29,21 @@ class AmpVimeo extends BaseElement { } } +/** @override */ +AmpVimeo['Component'] = Component; + +/** @override */ +AmpVimeo['props'] = props; + +/** @override */ +AmpVimeo['layoutSizeDefined'] = layoutSizeDefined; + +/** @override */ +AmpVimeo['usesShadowDom'] = usesShadowDom; + +/** @override */ +AmpVimeo['loadable'] = loadable; + AMP.extension(TAG, '1.0', (AMP) => { AMP.registerElement(TAG, AmpVimeo, CSS); }); diff --git a/extensions/amp-vimeo/1.0/base-element.js b/extensions/amp-vimeo/1.0/base-element.js index 71a8bea0a1c45..aec46def247b1 100644 --- a/extensions/amp-vimeo/1.0/base-element.js +++ b/extensions/amp-vimeo/1.0/base-element.js @@ -1,28 +1,26 @@ -import {BentoVimeo} from './component'; +import { + Component, + layoutSizeDefined, + loadable, + props, + usesShadowDom, +} from './element'; -import {VideoBaseElement} from '../../amp-video/1.0/video-base-element'; +import {BaseElement as BentoVideoBaseElement} from '../../amp-video/1.0/base-element'; -export class BaseElement extends VideoBaseElement {} +export class BaseElement extends BentoVideoBaseElement {} /** @override */ -BaseElement['Component'] = BentoVimeo; +BaseElement['Component'] = Component; /** @override */ -BaseElement['props'] = { - 'autoplay': {attr: 'autoplay', type: 'boolean'}, - 'controls': {attr: 'controls', type: 'boolean'}, - 'videoid': {attr: 'data-videoid'}, - 'doNotTrack': {attr: 'do-not-track'}, - // TODO(wg-components): Current behavior defaults to loading="auto". - // Refactor to make loading="lazy" as the default. - 'loading': {attr: 'data-loading'}, -}; +BaseElement['props'] = props; /** @override */ -BaseElement['layoutSizeDefined'] = true; +BaseElement['layoutSizeDefined'] = layoutSizeDefined; /** @override */ -BaseElement['usesShadowDom'] = true; +BaseElement['usesShadowDom'] = usesShadowDom; /** @override */ -BaseElement['loadable'] = true; +BaseElement['loadable'] = loadable; diff --git a/extensions/amp-vimeo/1.0/element.js b/extensions/amp-vimeo/1.0/element.js new file mode 100644 index 0000000000000..052894d2a89da --- /dev/null +++ b/extensions/amp-vimeo/1.0/element.js @@ -0,0 +1,17 @@ +export {BentoVimeo as Component} from './component'; + +export const props = { + 'autoplay': {attr: 'autoplay', type: 'boolean'}, + 'controls': {attr: 'controls', type: 'boolean'}, + 'videoid': {attr: 'data-videoid'}, + 'doNotTrack': {attr: 'do-not-track'}, + // TODO(wg-components): Current behavior defaults to loading="auto". + // Refactor to make loading="lazy" as the default. + 'loading': {attr: 'data-loading'}, +}; + +export const layoutSizeDefined = true; + +export const usesShadowDom = true; + +export const loadable = true; diff --git a/extensions/amp-youtube/1.0/amp-youtube.js b/extensions/amp-youtube/1.0/amp-youtube.js index 8a356f3082beb..b06c470a8c8c9 100644 --- a/extensions/amp-youtube/1.0/amp-youtube.js +++ b/extensions/amp-youtube/1.0/amp-youtube.js @@ -2,14 +2,16 @@ import {isExperimentOn} from '#experiments'; import {userAssert} from '#utils/log'; -import {BaseElement} from './base-element'; +import {AmpVideoBaseElement} from 'extensions/amp-video/1.0/video-base-element'; + +import {Component, loadable, props, usesShadowDom} from './element'; import {CSS} from '../../../build/amp-youtube-1.0.css'; /** @const {string} */ const TAG = 'amp-youtube'; -class AmpYoutube extends BaseElement { +class AmpYoutube extends AmpVideoBaseElement { /** @override */ isLayoutSupported(layout) { userAssert( @@ -21,6 +23,18 @@ class AmpYoutube extends BaseElement { } } +/** @override */ +AmpYoutube['Component'] = Component; + +/** @override */ +AmpYoutube['loadable'] = loadable; + +/** @override */ +AmpYoutube['props'] = props; + +/** @override */ +AmpYoutube['usesShadowDom'] = usesShadowDom; + AMP.extension(TAG, '1.0', (AMP) => { AMP.registerElement(TAG, AmpYoutube, CSS); }); diff --git a/extensions/amp-youtube/1.0/base-element.js b/extensions/amp-youtube/1.0/base-element.js index 3c21d17f50d0f..ca7f0799cf0ff 100644 --- a/extensions/amp-youtube/1.0/base-element.js +++ b/extensions/amp-youtube/1.0/base-element.js @@ -1,31 +1,17 @@ -import {createParseAttrsWithPrefix} from '#preact/parse-props'; +import {Component, loadable, props, usesShadowDom} from './element'; -import {BentoYoutube} from './component'; +import {BaseElement as BentoVideoBaseElement} from '../../amp-video/1.0/base-element'; -import {VideoBaseElement} from '../../amp-video/1.0/video-base-element'; - -export class BaseElement extends VideoBaseElement {} +export class BaseElement extends BentoVideoBaseElement {} /** @override */ -BaseElement['Component'] = BentoYoutube; +BaseElement['Component'] = Component; /** @override */ -BaseElement['loadable'] = true; +BaseElement['loadable'] = loadable; /** @override */ -BaseElement['props'] = { - 'autoplay': {attr: 'autoplay', type: 'boolean'}, - 'loop': {attr: 'loop', type: 'boolean'}, - 'controls': {attr: 'controls', type: 'boolean'}, - 'videoid': {attr: 'data-videoid'}, - 'liveChannelid': {attr: 'data-live-channelid'}, - 'dock': {attr: 'dock', media: true}, - 'credentials': {attr: 'credentials'}, - // TODO(wg-components): Current behavior defaults to loading="auto". - // Refactor to make loading="lazy" as the default. - 'loading': {attr: 'data-loading'}, - 'params': createParseAttrsWithPrefix('data-param-'), -}; +BaseElement['props'] = props; /** @override */ -BaseElement['usesShadowDom'] = true; +BaseElement['usesShadowDom'] = usesShadowDom; diff --git a/extensions/amp-youtube/1.0/element.js b/extensions/amp-youtube/1.0/element.js new file mode 100644 index 0000000000000..4d30625134904 --- /dev/null +++ b/extensions/amp-youtube/1.0/element.js @@ -0,0 +1,21 @@ +import {createParseAttrsWithPrefix} from '#preact/parse-props'; + +export {BentoYoutube as Component} from './component'; + +export const loadable = true; + +export const props = { + 'autoplay': {attr: 'autoplay', type: 'boolean'}, + 'loop': {attr: 'loop', type: 'boolean'}, + 'controls': {attr: 'controls', type: 'boolean'}, + 'videoid': {attr: 'data-videoid'}, + 'liveChannelid': {attr: 'data-live-channelid'}, + 'dock': {attr: 'dock', media: true}, + 'credentials': {attr: 'credentials'}, + // TODO(wg-components): Current behavior defaults to loading="auto". + // Refactor to make loading="lazy" as the default. + 'loading': {attr: 'data-loading'}, + 'params': createParseAttrsWithPrefix('data-param-'), +}; + +export const usesShadowDom = true;