/
githubmirror
/
amphtml
Обзор
Документация
Войти
/
githubmirror
/
amphtml
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/core/dom/layout/index.js
253 строки
7 KB
Jake Fried
Core Typechecking: enable noImplicitAny (#37201)
14 дек 2021, 02:31
Не верифицирован
14 дек 2021, 02:31
1f332cf
Код
Авторство
О чём код?
/** * @fileoverview Implements element layout. See https://goo.gl/9avXuT for * details. */ import {userAssert} from '#core/assert'; import {isFiniteNumber} from '#core/types'; import {isEnumValue} from '#core/types/enum'; /** * @enum {string} */ export const Layout_Enum = { NODISPLAY: 'nodisplay', FIXED: 'fixed', FIXED_HEIGHT: 'fixed-height', RESPONSIVE: 'responsive', CONTAINER: 'container', FILL: 'fill', FLEX_ITEM: 'flex-item', FLUID: 'fluid', INTRINSIC: 'intrinsic', }; /** * Layout priorities to use with BaseElement#getLayoutPriority() and * BaseElement#updateLayoutPriority(). * @enum {number} */ export const LayoutPriority_Enum = { CONTENT: 0, METADATA: 1, ADS: 2, BACKGROUND: 3, }; /** * CSS Length type. E.g. "1px" or "20vh". * @typedef {string} LengthDef; */ /** * @typedef {{ * width: string, * height: string * }} DimensionsDef; */ /** * Elements that the progress can be shown for. This set has to be externalized * since the element's implementation may not be downloaded yet. * This list does not include video players which are found via regex later. * @enum {string} * @private Visible for testing only */ export const LOADING_ELEMENTS_ENUM = { AMP_AD: 'AMP-AD', AMP_ANIM: 'AMP-ANIM', AMP_EMBED: 'AMP-EMBED', AMP_FACEBOOK: 'AMP-FACEBOOK', AMP_FACEBOOK_COMMENTS: 'AMP-FACEBOOK-COMMENTS', AMP_FACEBOOK_PAGE: 'AMP-FACEBOOK-PAGE', AMP_GOOGLE_DOCUMENT_EMBED: 'AMP-GOOGLE-DOCUMENT-EMBED', AMP_IFRAME: 'AMP-IFRAME', AMP_IMG: 'AMP-IMG', AMP_INSTAGRAM: 'AMP-INSTAGRAM', AMP_LIST: 'AMP-LIST', AMP_PINTEREST: 'AMP-PINTEREST', AMP_PLAYBUZZ: 'AMP-PLAYBUZZ', AMP_RENDER: 'AMP-RENDER', AMP_TIKTOK: 'AMP-TIKTOK', AMP_TWITTER: 'AMP-TWITTER', }; /** * All video player components must either have a) "video" or b) "player" in * their name. A few components don't follow this convention for historical * reasons, so they are listed individually. * @private @const {RegExp} */ const videoPlayerTagNameRe = /^amp\-(video|.+player)|AMP-BRIGHTCOVE|AMP-DAILYMOTION|AMP-YOUTUBE|AMP-VIMEO|AMP-IMA-VIDEO/i; /** * @param {string} s * @return {Layout_Enum|undefined} Returns undefined in case of failure to parse * the layout string. */ export function parseLayout(s) { if (isEnumValue(Layout_Enum, s)) { return /** @type {Layout_Enum} */ (s); } return undefined; } /** * @param {Layout_Enum} layout * @return {string} */ export function getLayoutClass(layout) { return 'i-amphtml-layout-' + layout; } /** * Whether an element with this layout inherently defines the size. * @param {Layout_Enum} layout * @return {boolean} */ export function isLayoutSizeDefined(layout) { return ( layout == Layout_Enum.FIXED || layout == Layout_Enum.FIXED_HEIGHT || layout == Layout_Enum.RESPONSIVE || layout == Layout_Enum.FILL || layout == Layout_Enum.FLEX_ITEM || layout == Layout_Enum.FLUID || layout == Layout_Enum.INTRINSIC ); } /** * Whether an element with this layout has a fixed dimension. * @param {Layout_Enum} layout * @return {boolean} */ export function isLayoutSizeFixed(layout) { return layout == Layout_Enum.FIXED || layout == Layout_Enum.FIXED_HEIGHT; } /** * Parses the CSS length value. If no units specified, the assumed value is * "px". Returns undefined in case of parsing error. * @param {string|undefined|null} s * @return {LengthDef|undefined} */ export function parseLength(s) { if (typeof s == 'number') { return s + 'px'; } if (!s) { return undefined; } if (!/^\d+(\.\d+)?(px|em|rem|vh|vw|vmin|vmax|cm|mm|q|in|pc|pt)?$/.test(s)) { return undefined; } if (/^\d+(\.\d+)?$/.test(s)) { return s + 'px'; } return s; } /** * Asserts that the supplied value is a non-percent CSS Length value. * @param {LengthDef|string|null|undefined} length * @return {LengthDef} * @closurePrimitive {asserts.matchesReturn} */ export function assertLength(length) { userAssert( /^\d+(\.\d+)?(px|em|rem|vh|vw|vmin|vmax|cm|mm|q|in|pc|pt)$/.test( length ?? '' ), 'Invalid length value: %s', length ); return /** @type {LengthDef} */ (length); } /** * Asserts that the supplied value is a CSS Length value * (including percent unit). * @param {LengthDef|string} length * @return {LengthDef} * @closurePrimitive {asserts.matchesReturn} */ export function assertLengthOrPercent(length) { userAssert( /^\d+(\.\d+)?(px|em|rem|vh|vw|vmin|vmax|%)$/.test(length), 'Invalid length or percent value: %s', length ); return length; } /** * Returns units from the CSS length value. * @param {LengthDef|string|null|undefined} length * @return {string} */ export function getLengthUnits(length) { assertLength(length); const m = /[a-z]+/i.exec(length ?? ''); userAssert(m, 'Failed to read units from %s', length); return m[0]; } /** * Returns the numeric value of a CSS length value. * @param {LengthDef|string|null|undefined|number} length * @return {number|undefined} */ export function getLengthNumeral(length) { // TS demands that we only pass a string to `parseFloat`, even though the spec // allows anything. const res = parseFloat(/** @type {?} */ (length)); return isFiniteNumber(res) ? res : undefined; } /** * Whether the loading can be shown for the specified element. This set has * to be externalized since the element's implementation may not be * downloaded yet. * @param {Element} element * @return {boolean} */ export function isLoadingAllowed(element) { const tagName = element.tagName.toUpperCase(); return ( isEnumValue(LOADING_ELEMENTS_ENUM, tagName) || isIframeVideoPlayerComponent(tagName) ); } /** * All video player components must either have a) "video" or b) "player" in * their name. A few components don't follow this convention for historical * reasons, so they're present in the LOADING_ELEMENTS_ENUM allowlist. * @param {string} tagName * @return {boolean} */ export function isIframeVideoPlayerComponent(tagName) { if (tagName == 'AMP-VIDEO') { return false; } return videoPlayerTagNameRe.test(tagName); } /** * Configures the supplied element to have a "fill content" layout. The * exact interpretation of "fill content" depends on the element's layout. * * If `opt_replacedContent` is specified, it indicates whether the "replaced * content" styling should be applied. Replaced content is not allowed to * have its own paddings or border. * * @param {Element} element * @param {boolean=} opt_replacedContent */ export function applyFillContent(element, opt_replacedContent) { element.classList.add('i-amphtml-fill-content'); if (opt_replacedContent) { element.classList.add('i-amphtml-replaced-content'); } }