UNPKG

tiny-essentials

Version:

Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.

160 lines (143 loc) 5 kB
'use strict'; var TinyHtmlTemplate = require('../TinyHtmlTemplate.cjs'); /** * TinyHtmlSource is a helper class for creating and validating <source> elements. * The <source> tag has contextual rules depending on its parent: * * - If inside <audio> or <video>, `src` is required, and `srcset`, `sizes`, `height`, `width` are forbidden. * - If inside <picture>, `srcset` is required, `sizes` is allowed, and `src` is forbidden. * * @example * // For <video> * const sourceVideo = new TinyHtmlSource({ * src: 'movie.mp4', * type: 'video/mp4', * context: 'video' * }); * * // For <picture> * const sourcePicture = new TinyHtmlSource({ * srcset: 'image-200.jpg 200w, image-400.jpg 400w', * sizes: '(max-width: 600px) 200px, 400px', * type: 'image/jpeg', * context: 'picture' * }); * * @extends TinyHtmlTemplate<HTMLSourceElement> */ class TinyHtmlSource extends TinyHtmlTemplate { /** * Creates a new TinyHtmlSource instance. * @param {Object} config - Configuration object. * @param {string} [config.type] - MIME type (optionally with codecs). * @param {string} [config.src] - Resource URL (required in audio/video, forbidden in picture). * @param {string} [config.srcset] - Comma-separated list of image candidates (required in picture). * @param {string} [config.sizes] - List of source sizes (only valid in picture with srcset). * @param {string} [config.media] - Media query for conditional loading. * @param {number} [config.height] - Intrinsic image height (only valid in picture). * @param {number} [config.width] - Intrinsic image width (only valid in picture). * @param {string|string[]|Set<string>} [config.tags=[]] - Initial CSS classes. * @param {string} [config.mainClass=""] - Main CSS class. * @param {"audio"|"video"|"picture"} [config.context] - Parent context type (used for validation). * @throws {TypeError|Error} If attributes are invalid or violate context rules. */ constructor({ type, src, srcset, sizes, media, height, width, tags = [], mainClass = '', context, } = {}) { super(document.createElement('source'), tags, mainClass); // Validate context if (context !== undefined && !['audio', 'video', 'picture'].includes(context)) { throw new Error( `TinyHtmlSource: "context" must be "audio", "video", or "picture". Got: ${context}`, ); } // Context rules if (context === 'audio' || context === 'video') { if (!src) { throw new Error(`TinyHtmlSource: "src" is required for <${context}> context.`); } if ( srcset !== undefined || sizes !== undefined || height !== undefined || width !== undefined ) { throw new Error( `TinyHtmlSource: "srcset", "sizes", "height", and "width" are not allowed in <${context}> context.`, ); } } if (context === 'picture') { if (!srcset) { throw new Error('TinyHtmlSource: "srcset" is required for <picture> context.'); } if (src !== undefined) { throw new Error('TinyHtmlSource: "src" is not allowed in <picture> context.'); } } // Assign attributes if (type !== undefined) this.type = type; if (src !== undefined) this.src = src; if (srcset !== undefined) this.srcset = srcset; if (sizes !== undefined) this.sizes = sizes; if (media !== undefined) this.media = media; if (height !== undefined) this.height = height; if (width !== undefined) this.width = width; } /** @param {string} type */ set type(type) { if (typeof type !== 'string') throw new TypeError('TinyHtmlSource: "type" must be a string.'); this.setAttr('type', type); } /** @returns {string|null} */ get type() { return this.attrString('type'); } /** @param {string} src */ set src(src) { if (typeof src !== 'string') throw new TypeError('TinyHtmlSource: "src" must be a string.'); this.setAttr('src', src); } /** @returns {string|null} */ get src() { return this.attrString('src'); } /** @param {string} srcset */ set srcset(srcset) { if (typeof srcset !== 'string') throw new TypeError('TinyHtmlSource: "srcset" must be a string.'); this.setAttr('srcset', srcset); } /** @returns {string|null} */ get srcset() { return this.attrString('srcset'); } /** @param {string} sizes */ set sizes(sizes) { if (typeof sizes !== 'string') throw new TypeError('TinyHtmlSource: "sizes" must be a string.'); this.setAttr('sizes', sizes); } /** @returns {string|null} */ get sizes() { return this.attrString('sizes'); } /** @param {string} media */ set media(media) { if (typeof media !== 'string') throw new TypeError('TinyHtmlSource: "media" must be a string.'); this.setAttr('media', media); } /** @returns {string|null} */ get media() { return this.attrString('media'); } } module.exports = TinyHtmlSource;