/** * Copyright schukai GmbH and contributors 2022. All Rights Reserved. * Node module: @schukai/monster * This file is licensed under the AGPLv3 License. * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html */ import { extend } from "../data/extend.mjs"; import { Base } from "../types/base.mjs"; import { getGlobalObject } from "../types/global.mjs"; import {equipWithInternal} from "../types/internal.mjs"; import { isArray } from "../types/is.mjs"; import { ATTRIBUTE_HREF, ATTRIBUTE_SRC } from "./constants.mjs"; import { Resource } from "./resource.mjs"; import { Data } from "./resource/data.mjs"; import { Stylesheet } from "./resource/link/stylesheet.mjs"; import { Script } from "./resource/script.mjs"; export { ResourceManager }; /** * The ResourceManager is a singleton that manages all resources. * * @license AGPLv3 * @since 1.25.0 * @copyright schukai GmbH * @memberOf Monster.DOM * @summary A Resource class */ class ResourceManager extends Base { /** * * @param {Object} options * throw {Error} unsupported document type */ constructor(options) { super(options); equipWithInternal.call(this); if (!(this.getOption("document") instanceof Document)) { throw new Error("unsupported document type"); } } /** * @deprecated since 3.15.0 use getInternal instead * @property {string} baseurl */ getOption(key) { return this.getInternal(key); } /** * @property {string} baseurl */ getBaseURL() { this.getOption("document")?.baseURL; } /** * @property {string} baseurl * @deprecated since 3.15.0 use internalDefaults instead */ get defaults() { return this.internalDefaults; } /** * * @property {HTMLDocument} document=document Document * @property {Object} resources * @property {Array} resources.scripts=[] array with {@link Monster.DOM.Resource.Script} objects * @property {Array} resources.stylesheets=[] array with {@link Monster.DOM.Resource.Link.Stylesheet} objects * @property {Array} resources.data=[] array with {@link Monster.DOM.Resource.Data} objects */ get internalDefaults() { return Object.assign({}, { document: getGlobalObject("document"), resources: { scripts: [], stylesheets: [], data: [], }, }); } /** * Append Tags to DOM * * @return {Monster.DOM.ResourceManager} * @throws {Error} unsupported resource definition */ connect() { runResourceMethod.call(this, "connect"); return this; } /** * Check if available * * @return {Promise} * @throws {Error} unsupported resource definition */ available() { return Promise.all(runResourceMethod.call(this, "available")); } /** * Add a script * * @param {string|URL} url * @param [Object|undefined} options * @return {Monster.DOM.ResourceManager} * @see Monster.DOM.Resource.Script */ addScript(url, options) { return addResource.call(this, "scripts", url, options); } /** * Add Stylesheet * * @param {string|URL} url * @param [Object|undefined} options * @return {Monster.DOM.ResourceManager} * @see Monster.DOM.Resource.Link.Stylesheet */ addStylesheet(url, options) { return addResource.call(this, "stylesheets", url, options); } /** * Add Data Tag * * @param {string|URL} url * @param [Object|undefined} options * @return {Monster.DOM.ResourceManager} * @see Monster.DOM.Resource.Data */ addData(url, options) { return addResource.call(this, "data", url, options); } } /** * @private * @param {string} method * @return {Array} */ function runResourceMethod(method) { const self = this; const result = []; for (const type of ["scripts", "stylesheets", "data"]) { const resources = self.getOption(`resources.${type}`); if (!isArray(resources)) { continue; } for (const resource of resources) { if (!(resource instanceof Resource)) { throw new Error("unsupported resource definition"); } result.push(resource[method]()); } } return result; } /** * * @param {string} type * @param {string|URL} url * @param [Object|undefined} options * @return {Monster.DOM.ResourceManager} * @private */ function addResource(type, url, options) { const self = this; if (url instanceof URL) { url = url.toString(); } options = options || {}; let resource; switch (type) { case "scripts": resource = new Script(extend({}, options, { [ATTRIBUTE_SRC]: url })); break; case "stylesheets": resource = new Stylesheet(extend({}, options, { [ATTRIBUTE_HREF]: url })); break; case "data": resource = new Data(extend({}, options, { [ATTRIBUTE_SRC]: url })); break; default: throw new Error(`unsupported type ${type}`); } self.getOption("resources")?.[type].push(resource); return self; }