UNPKG

@altano/html-cdnify

Version:

Transform the relative URLs in your HTML markup (e.g. scripts, stylesheets, images) to use your CDN URL.

102 lines (100 loc) 3.55 kB
import urlConverter_default from "./urlConverter.js"; import { HtmlAttributeStreamTransformer } from "./HtmlAttributeStreamTransformer.js"; import { merge, mergeWith, unionBy } from "lodash"; //#region src/CDNTransformer.ts /** * Handles merging objects that have TransformDefinition arrays */ var OptionsMerger = class OptionsMerger { static isTransformDefinition(a) { return a != null && typeof a === "object" && "selector" in a && "attribute" in a && typeof a.selector === "string" && typeof a.selector === "string" && typeof a.attribute === "string"; } static isTransformDefinitions(a) { return Array.isArray(a) && a.length > 0 && OptionsMerger.isTransformDefinition(a[0]); } static mergeCustomizer = (objValue, srcValue) => { if (OptionsMerger.isTransformDefinitions(objValue) && OptionsMerger.isTransformDefinitions(srcValue)) { const result = unionBy(srcValue, objValue, (value) => `${value.selector} / ${value.attribute}`); return result; } else return void 0; }; static merge(target, source1, source2, source3) { return mergeWith(target, source1, source2, source3, OptionsMerger.mergeCustomizer); } }; /** * Wraps a node-trumpet Transform stream, w/ HTML as input and * HTML as output. The output will have all non-absolute-URL * attributes that identify CDN-able resources converted to * use the given CDN URL. */ var CDNTransformer = class CDNTransformer extends HtmlAttributeStreamTransformer { cdnOptions; constructor(cdnOptions) { super(OptionsMerger.merge({}, CDNTransformer.#defaultHtmlAttributeStreamTransformerOptions, { transformDefinitions: [], transformFunction: (attribute) => this.#cdnifyAttribute(attribute) }, { transformDefinitions: cdnOptions.transformDefinitions })); this.cdnOptions = merge({ transformDefinitions: [] }, CDNTransformer.#defaultCdnOptions, cdnOptions); if (typeof this.cdnOptions.cdnUrl !== "string") throw new Error(`Invalid cdnUrl specified.`); } #cdnifyAttribute(oldUrl) { return this.cdnOptions.transformFunction(this.cdnOptions.cdnUrl, oldUrl, this.cdnOptions.bufferPath); } static #defaultCdnOptions = { bufferPath: ".", transformFunction: urlConverter_default }; static defaultTransformFunction = CDNTransformer.#defaultCdnOptions.transformFunction; static #defaultHtmlAttributeStreamTransformerOptions = { attributeToMarkElementToBeIgnored: "data-cdn-ignore", transformDefinitions: [ { selector: `video[poster]:not([data-cdn-ignore])`, attribute: "poster" }, { selector: `img[data-src]:not([data-cdn-ignore])`, attribute: "data-src" }, { selector: `script[src]:not([data-cdn-ignore])`, attribute: "src" }, { selector: `source[src]:not([data-cdn-ignore])`, attribute: "src" }, { selector: `link[rel="apple-touch-icon"]:not([data-cdn-ignore])`, attribute: "href" }, { selector: `link[rel="icon"]:not([data-cdn-ignore])`, attribute: "href" }, { selector: `link[rel="shortcut icon"]:not([data-cdn-ignore])`, attribute: "href" }, { selector: `link[rel="stylesheet"]:not([data-cdn-ignore])`, attribute: "href" }, { selector: `img[src]:not([data-cdn-ignore])`, attribute: "src" }, { selector: `img[srcset]:not([data-cdn-ignore])`, attribute: "srcset", attributeParser(attr, transformFunction) { return attr.split(",").map((imgInfo) => imgInfo.replace(/([^ ]+)/, transformFunction)).join(","); } } ] }; }; //#endregion export { CDNTransformer }; //# sourceMappingURL=CDNTransformer.js.map