@altano/html-cdnify
Version:
Transform the relative URLs in your HTML markup (e.g. scripts, stylesheets, images) to use your CDN URL.
67 lines (65 loc) • 2.92 kB
JavaScript
import HtmlTransformer from "./HtmlTransformer.js";
import { groupBy } from "lodash";
//#region src/HtmlAttributeStreamTransformer.ts
/**
* 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 HtmlAttributeStreamTransformer = class HtmlAttributeStreamTransformer extends HtmlTransformer {
condensedTransformOptions = [];
constructor(options) {
super();
this.options = options;
this.processTransforms();
this.applyTransforms();
}
static attributeParsers = { default: (attr, transformFunction) => transformFunction(attr) };
applyTransforms() {
this.condensedTransformOptions.forEach((settings) => {
const selector = settings.selector;
const attribute = settings.attribute;
const parser = settings.attributeParser;
this.stream.selectAll(selector, (elem) => {
const oldAttributeValue = elem.getAttribute(attribute);
if (typeof oldAttributeValue === "string") {
const newAttributeValue = parser && parser(oldAttributeValue, this.options.transformFunction);
if (newAttributeValue && newAttributeValue !== oldAttributeValue) elem.setAttribute(attribute, newAttributeValue);
}
});
});
const { attributeToMarkElementToBeIgnored } = this.options;
if (attributeToMarkElementToBeIgnored) this.stream.selectAll(`[${attributeToMarkElementToBeIgnored}]`, (elem) => {
elem.removeAttribute(attributeToMarkElementToBeIgnored);
});
}
processTransforms() {
this.options.transformDefinitions.forEach((option) => {
if (!option.attributeParser) option.attributeParser = HtmlAttributeStreamTransformer.attributeParsers["default"];
if (typeof option.selector !== "string") throw new Error(`Invalid selector specified.`);
if (typeof option.attribute !== "string") throw new Error(`Invalid attribute specified.`);
if (!(option.attributeParser instanceof Function)) throw new Error("Invalid attributeParser specified.");
});
/**
* As a performance enhancement, we can condense the list of transformDefinitions such that
* selectors with the same attribute and attributeParser can be combined into a single,
* comma-delimited CSS selector.
*/
const groupedTransformOptions = groupBy(this.options.transformDefinitions, (obj) => {
return [obj.attribute, obj.attributeParser];
});
this.condensedTransformOptions = Object.values(groupedTransformOptions).map((likeTransformOptions) => {
const attribute = likeTransformOptions[0].attribute;
const attributeParser = likeTransformOptions[0].attributeParser;
return {
attribute,
attributeParser,
selector: likeTransformOptions.map((likeTransformOption) => likeTransformOption.selector).join(", ")
};
});
}
};
//#endregion
export { HtmlAttributeStreamTransformer };
//# sourceMappingURL=HtmlAttributeStreamTransformer.js.map