@altano/html-cdnify 6.0.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
- import { HtmlAttributeStreamTransformer, TransformDefinition } from "./HtmlAttributeStreamTransformer.js";
1
+ import { HtmlAttributeStreamTransformer, HtmlAttributeStreamTransformer_d_exports, TransformDefinition } from "./HtmlAttributeStreamTransformer.js";
2
2
  //#region src/CDNTransformer.d.ts
3
- type CDNTransformFunction = (cdnUrl: string, oldUrl: string, bufferPath: string) => string;
4
- interface CDNTransformerOptions {
3
+ export type CDNTransformFunction = (cdnUrl: string, oldUrl: string, bufferPath: string) => string;
4
+ export interface CDNTransformerOptions {
5
5
  cdnUrl: string;
6
6
  bufferPath?: string;
7
7
  transformDefinitions?: TransformDefinition[];
@@ -13,12 +13,11 @@ interface CDNTransformerOptions {
13
13
  * attributes that identify CDN-able resources converted to
14
14
  * use the given CDN URL.
15
15
  */
16
- declare class CDNTransformer extends HtmlAttributeStreamTransformer {
16
+ export declare class CDNTransformer extends HtmlAttributeStreamTransformer {
17
17
  #private;
18
18
  cdnOptions: Required<CDNTransformerOptions>;
19
19
  constructor(cdnOptions: CDNTransformerOptions);
20
20
  static defaultTransformFunction: CDNTransformFunction;
21
21
  }
22
22
  //#endregion
23
- export { CDNTransformFunction, CDNTransformer, CDNTransformerOptions };
24
23
  //# sourceMappingURL=CDNTransformer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CDNTransformer.js","names":["HtmlAttributeStreamTransformer.HtmlAttributeStreamTransformer","#defaultHtmlAttributeStreamTransformerOptions","#cdnifyAttribute","#defaultCdnOptions","urlConverter"],"sources":["../src/CDNTransformer.ts"],"sourcesContent":["import { unionBy, merge, mergeWith } from \"lodash-es\";\nimport urlConverter from \"./urlConverter.js\";\n\nimport * as HtmlAttributeStreamTransformer from \"./HtmlAttributeStreamTransformer.js\";\n\nexport type CDNTransformFunction = (\n cdnUrl: string,\n oldUrl: string,\n bufferPath: string,\n) => string;\n\nexport interface CDNTransformerOptions {\n cdnUrl: string;\n bufferPath?: string;\n\n transformDefinitions?: HtmlAttributeStreamTransformer.TransformDefinition[];\n transformFunction?: CDNTransformFunction;\n}\n\n/**\n * Handles merging objects that have TransformDefinition arrays\n */\nclass OptionsMerger {\n static isTransformDefinition(\n a: unknown,\n ): a is HtmlAttributeStreamTransformer.TransformDefinition {\n return (\n a != null &&\n typeof a === \"object\" &&\n \"selector\" in a &&\n \"attribute\" in a &&\n typeof a.selector === \"string\" &&\n typeof a.selector === \"string\" &&\n typeof a.attribute === \"string\"\n );\n }\n\n static isTransformDefinitions(\n a: unknown,\n ): a is HtmlAttributeStreamTransformer.TransformDefinition[] {\n return (\n Array.isArray(a) &&\n a.length > 0 &&\n OptionsMerger.isTransformDefinition(a[0])\n );\n }\n\n static mergeCustomizer = (objValue: unknown, srcValue: unknown): unknown => {\n if (\n OptionsMerger.isTransformDefinitions(objValue) &&\n OptionsMerger.isTransformDefinitions(srcValue)\n ) {\n const result = unionBy(\n srcValue,\n objValue, // reverse order to allow srcValue to take precedence\n (value: HtmlAttributeStreamTransformer.TransformDefinition) =>\n `${value.selector} / ${value.attribute}`,\n );\n\n return result;\n } else {\n return undefined;\n }\n };\n\n static merge<T, U, V, W>(\n target: T,\n source1: U,\n source2: V,\n source3: W,\n ): T & U & V & W {\n return mergeWith(\n target,\n source1,\n source2,\n source3,\n OptionsMerger.mergeCustomizer,\n );\n }\n}\n\n/**\n * Wraps an HtmlRewriteStream, w/ HTML as input and\n * HTML as output. The output will have all non-absolute-URL\n * attributes that identify CDN-able resources converted to\n * use the given CDN URL.\n */\nexport class CDNTransformer\n extends HtmlAttributeStreamTransformer.HtmlAttributeStreamTransformer\n{\n public cdnOptions: Required<CDNTransformerOptions>;\n\n constructor(cdnOptions: CDNTransformerOptions) {\n super(\n OptionsMerger.merge(\n {},\n CDNTransformer.#defaultHtmlAttributeStreamTransformerOptions,\n {\n transformDefinitions: [],\n transformFunction: (attribute: string) =>\n this.#cdnifyAttribute(attribute),\n },\n {\n transformDefinitions: cdnOptions.transformDefinitions,\n },\n ),\n );\n\n this.cdnOptions = merge(\n {\n transformDefinitions: [],\n },\n CDNTransformer.#defaultCdnOptions,\n cdnOptions,\n );\n\n if (typeof this.cdnOptions.cdnUrl !== \"string\") {\n throw new Error(`Invalid cdnUrl specified.`);\n }\n }\n\n #cdnifyAttribute(oldUrl: string): string {\n return this.cdnOptions.transformFunction(\n this.cdnOptions.cdnUrl,\n oldUrl,\n this.cdnOptions.bufferPath,\n );\n }\n\n static #defaultCdnOptions = {\n bufferPath: \".\",\n transformFunction: urlConverter,\n } as const;\n\n public static defaultTransformFunction: CDNTransformFunction =\n CDNTransformer.#defaultCdnOptions.transformFunction;\n\n static #defaultHtmlAttributeStreamTransformerOptions = {\n attributeToMarkElementToBeIgnored: \"data-cdn-ignore\",\n\n // inspired by https://github.com/callumlocke/grunt-cdnify/blob/master/tasks/cdnify.js#L31\n transformDefinitions: [\n {\n selector: `video[poster]:not([data-cdn-ignore])`,\n attribute: \"poster\",\n },\n {\n selector: `img[data-src]:not([data-cdn-ignore])`,\n attribute: \"data-src\",\n },\n {\n selector: `script[src]:not([data-cdn-ignore])`,\n attribute: \"src\",\n },\n {\n selector: `source[src]:not([data-cdn-ignore])`,\n attribute: \"src\",\n },\n {\n selector: `link[rel=\"apple-touch-icon\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `link[rel=\"icon\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `link[rel=\"shortcut icon\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `link[rel=\"stylesheet\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `img[src]:not([data-cdn-ignore])`,\n attribute: \"src\",\n },\n {\n selector: `img[srcset]:not([data-cdn-ignore])`,\n attribute: \"srcset\",\n attributeParser(\n attr: string,\n transformFunction: HtmlAttributeStreamTransformer.TransformFunction,\n ): string {\n return attr\n .split(\",\")\n .map((imgInfo) => imgInfo.replace(/([^ ]+)/, transformFunction))\n .join(\",\");\n },\n },\n ],\n } as const;\n}\n"],"mappings":";;;;;;;;AAsBA,IAAM,gBAAN,MAAM,cAAc;CAClB,OAAO,sBACL,GACyD;EACzD,OACE,KAAK,QACL,OAAO,MAAM,YACb,cAAc,KACd,eAAe,KACf,OAAO,EAAE,aAAa,YACtB,OAAO,EAAE,aAAa,YACtB,OAAO,EAAE,cAAc;CAE3B;CAEA,OAAO,uBACL,GAC2D;EAC3D,OACE,MAAM,QAAQ,CAAC,KACf,EAAE,SAAS,KACX,cAAc,sBAAsB,EAAE,EAAE;CAE5C;CAEA,OAAO,mBAAmB,UAAmB,aAA+B;EAC1E,IACE,cAAc,uBAAuB,QAAQ,KAC7C,cAAc,uBAAuB,QAAQ,GAS7C,OAPe,QACb,UACA,WACC,UACC,GAAG,MAAM,SAAS,KAAK,MAAM,WAGrB;OAEZ;CAEJ;CAEA,OAAO,MACL,QACA,SACA,SACA,SACe;EACf,OAAO,UACL,QACA,SACA,SACA,SACA,cAAc,eAChB;CACF;AACF;;;;;;;AAQA,IAAa,iBAAb,MAAa,uBACHA,+BACV;CACE,AAAO;CAEP,YAAY,YAAmC;EAC7C,MACE,cAAc,MACZ,CAAC,GACD,eAAeC,+CACf;GACE,sBAAsB,CAAC;GACvB,oBAAoB,cAClB,KAAKC,iBAAiB,SAAS;EACnC,GACA,EACE,sBAAsB,WAAW,qBACnC,CACF,CACF;EAEA,KAAK,aAAa,MAChB,EACE,sBAAsB,CAAC,EACzB,GACA,eAAeC,oBACf,UACF;EAEA,IAAI,OAAO,KAAK,WAAW,WAAW,UACpC,MAAM,IAAI,MAAM,2BAA2B;CAE/C;CAEA,iBAAiB,QAAwB;EACvC,OAAO,KAAK,WAAW,kBACrB,KAAK,WAAW,QAChB,QACA,KAAK,WAAW,UAClB;CACF;CAEA,OAAOA,qBAAqB;EAC1B,YAAY;EACZ,mBAAmBC;CACrB;CAEA,OAAc,2BACZ,eAAeD,mBAAmB;CAEpC,OAAOF,gDAAgD;EACrD,mCAAmC;EAGnC,sBAAsB;GACpB;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;IACX,gBACE,MACA,mBACQ;KACR,OAAO,KACJ,MAAM,GAAG,CAAC,CACV,KAAK,YAAY,QAAQ,QAAQ,WAAW,iBAAiB,CAAC,CAAC,CAC/D,KAAK,GAAG;IACb;GACF;EACF;CACF;AACF"}
1
+ {"version":3,"file":"CDNTransformer.js","names":["HtmlAttributeStreamTransformer.HtmlAttributeStreamTransformer","urlConverter"],"sources":["../src/CDNTransformer.ts"],"sourcesContent":["import { unionBy, merge, mergeWith } from \"lodash-es\";\nimport urlConverter from \"./urlConverter.js\";\n\nimport * as HtmlAttributeStreamTransformer from \"./HtmlAttributeStreamTransformer.js\";\n\nexport type CDNTransformFunction = (\n cdnUrl: string,\n oldUrl: string,\n bufferPath: string,\n) => string;\n\nexport interface CDNTransformerOptions {\n cdnUrl: string;\n bufferPath?: string;\n\n transformDefinitions?: HtmlAttributeStreamTransformer.TransformDefinition[];\n transformFunction?: CDNTransformFunction;\n}\n\n/**\n * Handles merging objects that have TransformDefinition arrays\n */\nclass OptionsMerger {\n static isTransformDefinition(\n a: unknown,\n ): a is HtmlAttributeStreamTransformer.TransformDefinition {\n return (\n a != null &&\n typeof a === \"object\" &&\n \"selector\" in a &&\n \"attribute\" in a &&\n typeof a.selector === \"string\" &&\n typeof a.selector === \"string\" &&\n typeof a.attribute === \"string\"\n );\n }\n\n static isTransformDefinitions(\n a: unknown,\n ): a is HtmlAttributeStreamTransformer.TransformDefinition[] {\n return (\n Array.isArray(a) &&\n a.length > 0 &&\n OptionsMerger.isTransformDefinition(a[0])\n );\n }\n\n static mergeCustomizer = (objValue: unknown, srcValue: unknown): unknown => {\n if (\n OptionsMerger.isTransformDefinitions(objValue) &&\n OptionsMerger.isTransformDefinitions(srcValue)\n ) {\n const result = unionBy(\n srcValue,\n objValue, // reverse order to allow srcValue to take precedence\n (value: HtmlAttributeStreamTransformer.TransformDefinition) =>\n `${value.selector} / ${value.attribute}`,\n );\n\n return result;\n } else {\n return undefined;\n }\n };\n\n static merge<T, U, V, W>(\n target: T,\n source1: U,\n source2: V,\n source3: W,\n ): T & U & V & W {\n return mergeWith(\n target,\n source1,\n source2,\n source3,\n OptionsMerger.mergeCustomizer,\n );\n }\n}\n\n/**\n * Wraps an HtmlRewriteStream, w/ HTML as input and\n * HTML as output. The output will have all non-absolute-URL\n * attributes that identify CDN-able resources converted to\n * use the given CDN URL.\n */\nexport class CDNTransformer\n extends HtmlAttributeStreamTransformer.HtmlAttributeStreamTransformer\n{\n public cdnOptions: Required<CDNTransformerOptions>;\n\n constructor(cdnOptions: CDNTransformerOptions) {\n super(\n OptionsMerger.merge(\n {},\n CDNTransformer.#defaultHtmlAttributeStreamTransformerOptions,\n {\n transformDefinitions: [],\n transformFunction: (attribute: string) =>\n this.#cdnifyAttribute(attribute),\n },\n {\n transformDefinitions: cdnOptions.transformDefinitions,\n },\n ),\n );\n\n this.cdnOptions = merge(\n {\n transformDefinitions: [],\n },\n CDNTransformer.#defaultCdnOptions,\n cdnOptions,\n );\n\n if (typeof this.cdnOptions.cdnUrl !== \"string\") {\n throw new Error(`Invalid cdnUrl specified.`);\n }\n }\n\n #cdnifyAttribute(oldUrl: string): string {\n return this.cdnOptions.transformFunction(\n this.cdnOptions.cdnUrl,\n oldUrl,\n this.cdnOptions.bufferPath,\n );\n }\n\n static #defaultCdnOptions = {\n bufferPath: \".\",\n transformFunction: urlConverter,\n } as const;\n\n public static defaultTransformFunction: CDNTransformFunction =\n CDNTransformer.#defaultCdnOptions.transformFunction;\n\n static #defaultHtmlAttributeStreamTransformerOptions = {\n attributeToMarkElementToBeIgnored: \"data-cdn-ignore\",\n\n // inspired by https://github.com/callumlocke/grunt-cdnify/blob/master/tasks/cdnify.js#L31\n transformDefinitions: [\n {\n selector: `video[poster]:not([data-cdn-ignore])`,\n attribute: \"poster\",\n },\n {\n selector: `img[data-src]:not([data-cdn-ignore])`,\n attribute: \"data-src\",\n },\n {\n selector: `script[src]:not([data-cdn-ignore])`,\n attribute: \"src\",\n },\n {\n selector: `source[src]:not([data-cdn-ignore])`,\n attribute: \"src\",\n },\n {\n selector: `link[rel=\"apple-touch-icon\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `link[rel=\"icon\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `link[rel=\"shortcut icon\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `link[rel=\"stylesheet\"]:not([data-cdn-ignore])`,\n attribute: \"href\",\n },\n {\n selector: `img[src]:not([data-cdn-ignore])`,\n attribute: \"src\",\n },\n {\n selector: `img[srcset]:not([data-cdn-ignore])`,\n attribute: \"srcset\",\n attributeParser(\n attr: string,\n transformFunction: HtmlAttributeStreamTransformer.TransformFunction,\n ): string {\n return attr\n .split(\",\")\n .map((imgInfo) => imgInfo.replace(/([^ ]+)/, transformFunction))\n .join(\",\");\n },\n },\n ],\n } as const;\n}\n"],"mappings":";;;;;;;;AAsBA,IAAM,gBAAN,MAAM,cAAc;CAClB,OAAO,sBACL,GACyD;EACzD,OACE,KAAK,QACL,OAAO,MAAM,YACb,cAAc,KACd,eAAe,KACf,OAAO,EAAE,aAAa,YACtB,OAAO,EAAE,aAAa,YACtB,OAAO,EAAE,cAAc;CAE3B;CAEA,OAAO,uBACL,GAC2D;EAC3D,OACE,MAAM,QAAQ,CAAC,KACf,EAAE,SAAS,KACX,cAAc,sBAAsB,EAAE,EAAE;CAE5C;CAEA,OAAO,mBAAmB,UAAmB,aAA+B;EAC1E,IACE,cAAc,uBAAuB,QAAQ,KAC7C,cAAc,uBAAuB,QAAQ,GAS7C,OAPe,QACb,UACA,WACC,UACC,GAAG,MAAM,SAAS,KAAK,MAAM,WAGrB;OAEZ;CAEJ;CAEA,OAAO,MACL,QACA,SACA,SACA,SACe;EACf,OAAO,UACL,QACA,SACA,SACA,SACA,cAAc,eAChB;CACF;AACF;;;;;;;AAQA,IAAa,iBAAb,MAAa,uBACHA,+BACV;CACE,AAAO;CAEP,YAAY,YAAmC;EAC7C,MACE,cAAc,MACZ,CAAC,GACD,eAAe,+CACf;GACE,sBAAsB,CAAC;GACvB,oBAAoB,cAClB,KAAK,iBAAiB,SAAS;EACnC,GACA,EACE,sBAAsB,WAAW,qBACnC,CACF,CACF;EAEA,KAAK,aAAa,MAChB,EACE,sBAAsB,CAAC,EACzB,GACA,eAAe,oBACf,UACF;EAEA,IAAI,OAAO,KAAK,WAAW,WAAW,UACpC,MAAM,IAAI,MAAM,2BAA2B;CAE/C;CAEA,iBAAiB,QAAwB;EACvC,OAAO,KAAK,WAAW,kBACrB,KAAK,WAAW,QAChB,QACA,KAAK,WAAW,UAClB;CACF;CAEA,OAAO,qBAAqB;EAC1B,YAAY;EACZ,mBAAmBC;CACrB;CAEA,OAAc,2BACZ,eAAe,mBAAmB;CAEpC,OAAO,gDAAgD;EACrD,mCAAmC;EAGnC,sBAAsB;GACpB;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;GACb;GACA;IACE,UAAU;IACV,WAAW;IACX,gBACE,MACA,mBACQ;KACR,OAAO,KACJ,MAAM,GAAG,CAAC,CACV,KAAK,YAAY,QAAQ,QAAQ,WAAW,iBAAiB,CAAC,CAAC,CAC/D,KAAK,GAAG;IACb;GACF;EACF;CACF;AACF"}
@@ -1,20 +1,22 @@
1
1
  import HtmlTransformer from "./HtmlTransformer.js";
2
- //#region src/HtmlAttributeStreamTransformer.d.ts
3
- interface HtmlAttributeStreamTransformerOptions {
2
+ declare namespace HtmlAttributeStreamTransformer_d_exports {
3
+ export { AttributeParser, AttributeParsers, HtmlAttributeStreamTransformer, HtmlAttributeStreamTransformerOptions, TransformDefinition, TransformFunction };
4
+ }
5
+ export interface HtmlAttributeStreamTransformerOptions {
4
6
  transformDefinitions: TransformDefinition[];
5
7
  transformFunction: TransformFunction;
6
8
  attributeToMarkElementToBeIgnored?: string;
7
9
  }
8
- interface TransformDefinition {
10
+ export interface TransformDefinition {
9
11
  selector: string;
10
12
  attribute: string;
11
13
  attributeParser?: undefined | ((oldAttribute: string, transformFunction: TransformFunction) => string);
12
14
  }
13
- type TransformFunction = (oldAttribute: string) => string;
14
- interface AttributeParser {
15
+ export type TransformFunction = (oldAttribute: string) => string;
16
+ export interface AttributeParser {
15
17
  (oldAttribute: string, transformFunction: TransformFunction): string;
16
18
  }
17
- interface AttributeParsers {
19
+ export interface AttributeParsers {
18
20
  [index: string]: AttributeParser;
19
21
  }
20
22
  /**
@@ -23,7 +25,7 @@ interface AttributeParsers {
23
25
  * attributes that identify CDN-able resources converted to
24
26
  * use the given CDN URL.
25
27
  */
26
- declare class HtmlAttributeStreamTransformer extends HtmlTransformer {
28
+ export declare class HtmlAttributeStreamTransformer extends HtmlTransformer {
27
29
  condensedTransformOptions: TransformDefinition[];
28
30
  options: HtmlAttributeStreamTransformerOptions;
29
31
  constructor(options: HtmlAttributeStreamTransformerOptions);
@@ -32,5 +34,5 @@ declare class HtmlAttributeStreamTransformer extends HtmlTransformer {
32
34
  private processTransforms;
33
35
  }
34
36
  //#endregion
35
- export { AttributeParser, AttributeParsers, HtmlAttributeStreamTransformer, HtmlAttributeStreamTransformerOptions, TransformDefinition, TransformFunction };
37
+ export { HtmlAttributeStreamTransformer_d_exports };
36
38
  //# sourceMappingURL=HtmlAttributeStreamTransformer.d.ts.map
@@ -7,12 +7,12 @@ import { RewritingStream } from "parse5-html-rewriting-stream";
7
7
  * `true` rather than `""`, so callers can tell it apart from an attribute
8
8
  * holding a real value.
9
9
  */
10
- interface SelectedElement {
10
+ export interface SelectedElement {
11
11
  getAttribute(name: string): string | true | undefined;
12
12
  setAttribute(name: string, value: string): void;
13
13
  removeAttribute(name: string): void;
14
14
  }
15
- type SelectionHandler = (element: SelectedElement) => void;
15
+ export type SelectionHandler = (element: SelectedElement) => void;
16
16
  /**
17
17
  * An HTML-in, HTML-out transform stream that rewrites attributes on elements
18
18
  * matching a CSS selector.
@@ -27,7 +27,7 @@ type SelectionHandler = (element: SelectedElement) => void;
27
27
  * ships, and every selector its tests exercise, is element-local: a tag name
28
28
  * plus attribute predicates, optionally negated with `:not()`.
29
29
  */
30
- declare class HtmlRewriteStream extends RewritingStream {
30
+ export declare class HtmlRewriteStream extends RewritingStream {
31
31
  #private;
32
32
  constructor();
33
33
  /**
@@ -44,5 +44,4 @@ declare class HtmlRewriteStream extends RewritingStream {
44
44
  override _final(callback: (error?: Error | null, data?: string) => void): void;
45
45
  }
46
46
  //#endregion
47
- export { HtmlRewriteStream, SelectedElement, SelectionHandler };
48
47
  //# sourceMappingURL=HtmlRewriteStream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlRewriteStream.js","names":["#selections","#decoder"],"sources":["../src/HtmlRewriteStream.ts"],"sourcesContent":["import { RewritingStream } from \"parse5-html-rewriting-stream\";\nimport { Element } from \"domhandler\";\nimport { compile } from \"css-select\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type { Element as DomElement } from \"domhandler\";\n\n/**\n * css-select's own `CompiledQuery` isn't re-exported from its entry point, but\n * it is structurally just a predicate over a node.\n */\ntype CompiledSelector = (node: DomElement) => boolean;\n\n/**\n * The subset of a DOM element that transforms are allowed to touch.\n *\n * `getAttribute` reports a valueless attribute (`<img data-cdn-ignore>`) as\n * `true` rather than `\"\"`, so callers can tell it apart from an attribute\n * holding a real value.\n */\nexport interface SelectedElement {\n getAttribute(name: string): string | true | undefined;\n setAttribute(name: string, value: string): void;\n removeAttribute(name: string): void;\n}\n\nexport type SelectionHandler = (element: SelectedElement) => void;\n\ninterface Selection {\n match: CompiledSelector;\n handler: SelectionHandler;\n}\n\n/**\n * An HTML-in, HTML-out transform stream that rewrites attributes on elements\n * matching a CSS selector.\n *\n * Anything the selectors don't match passes through byte-for-byte; a matched\n * start tag is re-serialized, so its internal whitespace collapses and a\n * self-closing `/` is dropped. That asymmetry is deliberate — it reproduces the\n * observable behavior of `@gofunky/trumpet`, which this replaced.\n *\n * Selectors are evaluated against each start tag on its own, so combinators\n * (descendant, child, sibling) will not match. Every selector this package\n * ships, and every selector its tests exercise, is element-local: a tag name\n * plus attribute predicates, optionally negated with `:not()`.\n */\nexport class HtmlRewriteStream extends RewritingStream {\n readonly #selections: Selection[] = [];\n readonly #decoder = new StringDecoder(\"utf8\");\n\n constructor() {\n super();\n\n this.on(\"startTag\", (token, raw) => {\n let dirty = false;\n\n const element: SelectedElement = {\n getAttribute(name) {\n const attr = token.attrs.find((a) => a.name === name);\n if (attr == null) {\n return undefined;\n }\n return attr.value === \"\" ? true : attr.value;\n },\n setAttribute(name, value) {\n const attr = token.attrs.find((a) => a.name === name);\n if (attr) {\n attr.value = value;\n } else {\n token.attrs.push({ name, value });\n }\n dirty = true;\n },\n removeAttribute(name) {\n const before = token.attrs.length;\n token.attrs = token.attrs.filter((a) => a.name !== name);\n if (token.attrs.length !== before) {\n dirty = true;\n }\n },\n };\n\n // css-select needs a domhandler node. Building a throwaway one per start\n // tag keeps this independent of any parse tree.\n const node = new Element(\n token.tagName,\n Object.fromEntries(token.attrs.map((a) => [a.name, a.value])),\n );\n\n for (const { match, handler } of this.#selections) {\n if (match(node)) handler(element);\n }\n\n if (dirty) {\n // trumpet emitted `<img>` for `<img />`; parse5 would keep the marker.\n token.selfClosing = false;\n this.emitStartTag(token);\n } else {\n // Untouched tags go out exactly as they came in, quirks and all.\n this.emitRaw(raw);\n }\n });\n }\n\n /**\n * Register a handler to run against every element matching `selector`.\n * Must be called before any data is written to the stream.\n */\n selectAll(selector: string, handler: SelectionHandler): void {\n this.#selections.push({ match: compile(selector), handler });\n }\n\n /**\n * parse5's parser accepts only strings, but callers pipe Buffers in. Decode\n * through a StringDecoder rather than `chunk.toString()`, so a multi-byte\n * character split across two chunks survives the boundary.\n */\n override _transform(\n chunk: string | Buffer,\n encoding: string,\n callback: (error?: Error | null, data?: string) => void,\n ): void {\n const text = typeof chunk === \"string\" ? chunk : this.#decoder.write(chunk);\n super._transform(text, encoding, callback);\n }\n\n override _final(\n callback: (error?: Error | null, data?: string) => void,\n ): void {\n // Anything the decoder is still holding is an incomplete sequence at end\n // of input; `end()` turns it into replacement characters. Push it through\n // the parser before finishing rather than dropping it.\n const rest = this.#decoder.end();\n if (rest !== \"\") this.push(this._transformChunk(rest));\n super._final(callback);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8CA,IAAa,oBAAb,cAAuC,gBAAgB;CACrD,AAASA,cAA2B,CAAC;CACrC,AAASC,WAAW,IAAI,cAAc,MAAM;CAE5C,cAAc;EACZ,MAAM;EAEN,KAAK,GAAG,aAAa,OAAO,QAAQ;GAClC,IAAI,QAAQ;GAEZ,MAAM,UAA2B;IAC/B,aAAa,MAAM;KACjB,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,IAAI;KACpD,IAAI,QAAQ,MACV;KAEF,OAAO,KAAK,UAAU,KAAK,OAAO,KAAK;IACzC;IACA,aAAa,MAAM,OAAO;KACxB,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,IAAI;KACpD,IAAI,MACF,KAAK,QAAQ;UAEb,MAAM,MAAM,KAAK;MAAE;MAAM;KAAM,CAAC;KAElC,QAAQ;IACV;IACA,gBAAgB,MAAM;KACpB,MAAM,SAAS,MAAM,MAAM;KAC3B,MAAM,QAAQ,MAAM,MAAM,QAAQ,MAAM,EAAE,SAAS,IAAI;KACvD,IAAI,MAAM,MAAM,WAAW,QACzB,QAAQ;IAEZ;GACF;GAIA,MAAM,OAAO,IAAI,QACf,MAAM,SACN,OAAO,YAAY,MAAM,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAC9D;GAEA,KAAK,MAAM,EAAE,OAAO,aAAa,KAAKD,aACpC,IAAI,MAAM,IAAI,GAAG,QAAQ,OAAO;GAGlC,IAAI,OAAO;IAET,MAAM,cAAc;IACpB,KAAK,aAAa,KAAK;GACzB,OAEE,KAAK,QAAQ,GAAG;EAEpB,CAAC;CACH;;;;;CAMA,UAAU,UAAkB,SAAiC;EAC3D,KAAKA,YAAY,KAAK;GAAE,OAAO,QAAQ,QAAQ;GAAG;EAAQ,CAAC;CAC7D;;;;;;CAOA,AAAS,WACP,OACA,UACA,UACM;EACN,MAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAKC,SAAS,MAAM,KAAK;EAC1E,MAAM,WAAW,MAAM,UAAU,QAAQ;CAC3C;CAEA,AAAS,OACP,UACM;EAIN,MAAM,OAAO,KAAKA,SAAS,IAAI;EAC/B,IAAI,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,IAAI,CAAC;EACrD,MAAM,OAAO,QAAQ;CACvB;AACF"}
1
+ {"version":3,"file":"HtmlRewriteStream.js","names":[],"sources":["../src/HtmlRewriteStream.ts"],"sourcesContent":["import { RewritingStream } from \"parse5-html-rewriting-stream\";\nimport { Element } from \"domhandler\";\nimport { compile } from \"css-select\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type { Element as DomElement } from \"domhandler\";\n\n/**\n * css-select's own `CompiledQuery` isn't re-exported from its entry point, but\n * it is structurally just a predicate over a node.\n */\ntype CompiledSelector = (node: DomElement) => boolean;\n\n/**\n * The subset of a DOM element that transforms are allowed to touch.\n *\n * `getAttribute` reports a valueless attribute (`<img data-cdn-ignore>`) as\n * `true` rather than `\"\"`, so callers can tell it apart from an attribute\n * holding a real value.\n */\nexport interface SelectedElement {\n getAttribute(name: string): string | true | undefined;\n setAttribute(name: string, value: string): void;\n removeAttribute(name: string): void;\n}\n\nexport type SelectionHandler = (element: SelectedElement) => void;\n\ninterface Selection {\n match: CompiledSelector;\n handler: SelectionHandler;\n}\n\n/**\n * An HTML-in, HTML-out transform stream that rewrites attributes on elements\n * matching a CSS selector.\n *\n * Anything the selectors don't match passes through byte-for-byte; a matched\n * start tag is re-serialized, so its internal whitespace collapses and a\n * self-closing `/` is dropped. That asymmetry is deliberate — it reproduces the\n * observable behavior of `@gofunky/trumpet`, which this replaced.\n *\n * Selectors are evaluated against each start tag on its own, so combinators\n * (descendant, child, sibling) will not match. Every selector this package\n * ships, and every selector its tests exercise, is element-local: a tag name\n * plus attribute predicates, optionally negated with `:not()`.\n */\nexport class HtmlRewriteStream extends RewritingStream {\n readonly #selections: Selection[] = [];\n readonly #decoder = new StringDecoder(\"utf8\");\n\n constructor() {\n super();\n\n this.on(\"startTag\", (token, raw) => {\n let dirty = false;\n\n const element: SelectedElement = {\n getAttribute(name) {\n const attr = token.attrs.find((a) => a.name === name);\n if (attr == null) {\n return undefined;\n }\n return attr.value === \"\" ? true : attr.value;\n },\n setAttribute(name, value) {\n const attr = token.attrs.find((a) => a.name === name);\n if (attr) {\n attr.value = value;\n } else {\n token.attrs.push({ name, value });\n }\n dirty = true;\n },\n removeAttribute(name) {\n const before = token.attrs.length;\n token.attrs = token.attrs.filter((a) => a.name !== name);\n if (token.attrs.length !== before) {\n dirty = true;\n }\n },\n };\n\n // css-select needs a domhandler node. Building a throwaway one per start\n // tag keeps this independent of any parse tree.\n const node = new Element(\n token.tagName,\n Object.fromEntries(token.attrs.map((a) => [a.name, a.value])),\n );\n\n for (const { match, handler } of this.#selections) {\n if (match(node)) handler(element);\n }\n\n if (dirty) {\n // trumpet emitted `<img>` for `<img />`; parse5 would keep the marker.\n token.selfClosing = false;\n this.emitStartTag(token);\n } else {\n // Untouched tags go out exactly as they came in, quirks and all.\n this.emitRaw(raw);\n }\n });\n }\n\n /**\n * Register a handler to run against every element matching `selector`.\n * Must be called before any data is written to the stream.\n */\n selectAll(selector: string, handler: SelectionHandler): void {\n this.#selections.push({ match: compile(selector), handler });\n }\n\n /**\n * parse5's parser accepts only strings, but callers pipe Buffers in. Decode\n * through a StringDecoder rather than `chunk.toString()`, so a multi-byte\n * character split across two chunks survives the boundary.\n */\n override _transform(\n chunk: string | Buffer,\n encoding: string,\n callback: (error?: Error | null, data?: string) => void,\n ): void {\n const text = typeof chunk === \"string\" ? chunk : this.#decoder.write(chunk);\n super._transform(text, encoding, callback);\n }\n\n override _final(\n callback: (error?: Error | null, data?: string) => void,\n ): void {\n // Anything the decoder is still holding is an incomplete sequence at end\n // of input; `end()` turns it into replacement characters. Push it through\n // the parser before finishing rather than dropping it.\n const rest = this.#decoder.end();\n if (rest !== \"\") this.push(this._transformChunk(rest));\n super._final(callback);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8CA,IAAa,oBAAb,cAAuC,gBAAgB;CACrD,AAAS,cAA2B,CAAC;CACrC,AAAS,WAAW,IAAI,cAAc,MAAM;CAE5C,cAAc;EACZ,MAAM;EAEN,KAAK,GAAG,aAAa,OAAO,QAAQ;GAClC,IAAI,QAAQ;GAEZ,MAAM,UAA2B;IAC/B,aAAa,MAAM;KACjB,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,IAAI;KACpD,IAAI,QAAQ,MACV;KAEF,OAAO,KAAK,UAAU,KAAK,OAAO,KAAK;IACzC;IACA,aAAa,MAAM,OAAO;KACxB,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,IAAI;KACpD,IAAI,MACF,KAAK,QAAQ;UAEb,MAAM,MAAM,KAAK;MAAE;MAAM;KAAM,CAAC;KAElC,QAAQ;IACV;IACA,gBAAgB,MAAM;KACpB,MAAM,SAAS,MAAM,MAAM;KAC3B,MAAM,QAAQ,MAAM,MAAM,QAAQ,MAAM,EAAE,SAAS,IAAI;KACvD,IAAI,MAAM,MAAM,WAAW,QACzB,QAAQ;IAEZ;GACF;GAIA,MAAM,OAAO,IAAI,QACf,MAAM,SACN,OAAO,YAAY,MAAM,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAC9D;GAEA,KAAK,MAAM,EAAE,OAAO,aAAa,KAAK,aACpC,IAAI,MAAM,IAAI,GAAG,QAAQ,OAAO;GAGlC,IAAI,OAAO;IAET,MAAM,cAAc;IACpB,KAAK,aAAa,KAAK;GACzB,OAEE,KAAK,QAAQ,GAAG;EAEpB,CAAC;CACH;;;;;CAMA,UAAU,UAAkB,SAAiC;EAC3D,KAAK,YAAY,KAAK;GAAE,OAAO,QAAQ,QAAQ;GAAG;EAAQ,CAAC;CAC7D;;;;;;CAOA,AAAS,WACP,OACA,UACA,UACM;EACN,MAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,SAAS,MAAM,KAAK;EAC1E,MAAM,WAAW,MAAM,UAAU,QAAQ;CAC3C;CAEA,AAAS,OACP,UACM;EAIN,MAAM,OAAO,KAAK,SAAS,IAAI;EAC/B,IAAI,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,IAAI,CAAC;EACrD,MAAM,OAAO,QAAQ;CACvB;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { HtmlRewriteStream, SelectedElement, SelectionHandler } from "./HtmlRewriteStream.js";
2
2
  //#region src/HtmlTransformer.d.ts
3
- declare class HtmlTransformer {
3
+ export default class HtmlTransformer {
4
4
  private transformStream;
5
5
  /**
6
6
  * Get the underlying transform stream
@@ -12,5 +12,5 @@ declare class HtmlTransformer {
12
12
  get outputBufferPromise(): Promise<Buffer>;
13
13
  }
14
14
  //#endregion
15
- export { HtmlRewriteStream, type SelectedElement, type SelectionHandler, HtmlTransformer as default };
15
+ export { HtmlRewriteStream, type SelectedElement, type SelectionHandler };
16
16
  //# sourceMappingURL=HtmlTransformer.d.ts.map
@@ -0,0 +1,18 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) {
6
+ __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ }
11
+ if (!no_symbols) {
12
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ }
14
+ return target;
15
+ };
16
+
17
+ //#endregion
18
+ export { __exportAll };
package/dist/cdnify.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { CDNTransformerOptions } from "./CDNTransformer.js";
2
2
  //#region src/cdnify.d.ts
3
- interface CdnifyOptions extends CDNTransformerOptions {
3
+ export interface CdnifyOptions extends CDNTransformerOptions {
4
4
  buffer: string | Buffer;
5
5
  }
6
6
  /**
7
7
  * Alternative wrapper for simple Promise-based use of library (as opposed to transform stream)
8
8
  */
9
- declare function cdnify(options: CdnifyOptions): Promise<Buffer>;
9
+ export declare function cdnify(options: CdnifyOptions): Promise<Buffer>;
10
10
  //#endregion
11
- export { CdnifyOptions, cdnify, cdnify as default };
11
+ export { cdnify as default };
12
12
  //# sourceMappingURL=cdnify.d.ts.map
@@ -34,7 +34,7 @@ var urlConverter_default = (newUrlBase, oldUrl, pathOldUrlIsRelativeTo) => {
34
34
  if (!isLocalPath(oldUrl)) return oldUrl;
35
35
  else {
36
36
  oldUrl = oldUrl.trim();
37
- let relativePath = ".";
37
+ let relativePath;
38
38
  if (pathOldUrlIsRelativeTo) relativePath = resolveUrl(pathOldUrlIsRelativeTo.endsWith("/") ? pathOldUrlIsRelativeTo : path.dirname(pathOldUrlIsRelativeTo) + "/", oldUrl);
39
39
  else relativePath = oldUrl;
40
40
  if (relativePath.startsWith("/")) relativePath = relativePath.slice(1);
@@ -1 +1 @@
1
- {"version":3,"file":"urlConverter.js","names":[],"sources":["../src/urlConverter.ts"],"sourcesContent":["import path from \"node:path\";\n\n/** Origin used to resolve path-only bases, which `new URL()` can't parse. */\nconst PLACEHOLDER_ORIGIN = \"http://html-cdnify.invalid\";\n\nconst SCHEME_PATTERN = /^[a-z][a-z0-9+\\-.]*:/i;\n\nfunction isLocalPath(filePath: string): boolean {\n return (\n typeof filePath === \"string\" &&\n filePath.length > 0 &&\n filePath.indexOf(\"//\") === -1 &&\n filePath.indexOf(\"data:\") !== 0\n );\n}\n\n/**\n * Resolve `relativeUrl` against `base`, the way the (deprecated) legacy\n * `url.resolve` did, but using the WHATWG URL API.\n *\n * `new URL()` only accepts a fully absolute base, so the two other base shapes\n * this package supports are resolved against a stand-in that is stripped back\n * off afterwards:\n *\n * - protocol-relative (`//cdn.com/cdn/`) borrows a protocol\n * - path-only (`someDir/`) borrows a whole origin\n */\nfunction resolveUrl(base: string, relativeUrl: string): string {\n if (base.startsWith(\"//\")) {\n return new URL(relativeUrl, `http:${base}`).href.slice(\"http:\".length);\n } else if (SCHEME_PATTERN.test(base)) {\n return new URL(relativeUrl, base).href;\n } else {\n const absoluteBase = new URL(base, PLACEHOLDER_ORIGIN);\n const resolved = new URL(relativeUrl, absoluteBase).href.slice(\n PLACEHOLDER_ORIGIN.length,\n );\n // The placeholder origin makes everything look rooted at `/`. Only keep\n // that slash if it was already there before resolving.\n const isRooted = base.startsWith(\"/\") || relativeUrl.startsWith(\"/\");\n return isRooted ? resolved : resolved.slice(1);\n }\n}\n\n/**\n * Resolve oldUrl against pathOldUrlIsRelativeTo, and then prepend newUrlBase\n */\nexport default (\n newUrlBase: string,\n oldUrl: string,\n pathOldUrlIsRelativeTo?: string,\n): string => {\n if (!isLocalPath(oldUrl)) {\n return oldUrl;\n } else {\n oldUrl = oldUrl.trim();\n let relativePath = \".\";\n\n if (pathOldUrlIsRelativeTo) {\n const isDirAlready = pathOldUrlIsRelativeTo.endsWith(\"/\");\n const fileDirName = isDirAlready\n ? pathOldUrlIsRelativeTo\n : path.dirname(pathOldUrlIsRelativeTo) + \"/\";\n relativePath = resolveUrl(fileDirName, oldUrl);\n } else {\n relativePath = oldUrl;\n }\n\n // When resolving against the CDN URL, we should always use a relative URL.\n //\n // e.g. http://somecdn.com/cdn/ + /article/some.css => http://somecdn.com/cdn/article/some.css\n // and *NOT*\n // http://somecdn.com/cdn/ + /article/some.css => http://somecdn.com/article/some.css\n //\n if (relativePath.startsWith(\"/\")) {\n relativePath = relativePath.slice(1);\n }\n\n if (!newUrlBase.endsWith(\"/\")) {\n newUrlBase += \"/\";\n }\n\n return resolveUrl(newUrlBase, relativePath);\n }\n};\n"],"mappings":";;;;AAGA,MAAM,qBAAqB;AAE3B,MAAM,iBAAiB;AAEvB,SAAS,YAAY,UAA2B;CAC9C,OACE,OAAO,aAAa,YACpB,SAAS,SAAS,KAClB,SAAS,QAAQ,IAAI,MAAM,MAC3B,SAAS,QAAQ,OAAO,MAAM;AAElC;;;;;;;;;;;;AAaA,SAAS,WAAW,MAAc,aAA6B;CAC7D,IAAI,KAAK,WAAW,IAAI,GACtB,OAAO,IAAI,IAAI,aAAa,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAc;MAChE,IAAI,eAAe,KAAK,IAAI,GACjC,OAAO,IAAI,IAAI,aAAa,IAAI,CAAC,CAAC;MAC7B;EACL,MAAM,eAAe,IAAI,IAAI,MAAM,kBAAkB;EACrD,MAAM,WAAW,IAAI,IAAI,aAAa,YAAY,CAAC,CAAC,KAAK,MACvD,EACF;EAIA,OADiB,KAAK,WAAW,GAAG,KAAK,YAAY,WAAW,GAAG,IACjD,WAAW,SAAS,MAAM,CAAC;CAC/C;AACF;;;;AAKA,4BACE,YACA,QACA,2BACW;CACX,IAAI,CAAC,YAAY,MAAM,GACrB,OAAO;MACF;EACL,SAAS,OAAO,KAAK;EACrB,IAAI,eAAe;EAEnB,IAAI,wBAKF,eAAe,WAJM,uBAAuB,SAAS,GACtB,IAC3B,yBACA,KAAK,QAAQ,sBAAsB,IAAI,KACJ,MAAM;OAE7C,eAAe;EASjB,IAAI,aAAa,WAAW,GAAG,GAC7B,eAAe,aAAa,MAAM,CAAC;EAGrC,IAAI,CAAC,WAAW,SAAS,GAAG,GAC1B,cAAc;EAGhB,OAAO,WAAW,YAAY,YAAY;CAC5C;AACF"}
1
+ {"version":3,"file":"urlConverter.js","names":[],"sources":["../src/urlConverter.ts"],"sourcesContent":["import path from \"node:path\";\n\n/** Origin used to resolve path-only bases, which `new URL()` can't parse. */\nconst PLACEHOLDER_ORIGIN = \"http://html-cdnify.invalid\";\n\nconst SCHEME_PATTERN = /^[a-z][a-z0-9+\\-.]*:/i;\n\nfunction isLocalPath(filePath: string): boolean {\n return (\n typeof filePath === \"string\" &&\n filePath.length > 0 &&\n filePath.indexOf(\"//\") === -1 &&\n filePath.indexOf(\"data:\") !== 0\n );\n}\n\n/**\n * Resolve `relativeUrl` against `base`, the way the (deprecated) legacy\n * `url.resolve` did, but using the WHATWG URL API.\n *\n * `new URL()` only accepts a fully absolute base, so the two other base shapes\n * this package supports are resolved against a stand-in that is stripped back\n * off afterwards:\n *\n * - protocol-relative (`//cdn.com/cdn/`) borrows a protocol\n * - path-only (`someDir/`) borrows a whole origin\n */\nfunction resolveUrl(base: string, relativeUrl: string): string {\n if (base.startsWith(\"//\")) {\n return new URL(relativeUrl, `http:${base}`).href.slice(\"http:\".length);\n } else if (SCHEME_PATTERN.test(base)) {\n return new URL(relativeUrl, base).href;\n } else {\n const absoluteBase = new URL(base, PLACEHOLDER_ORIGIN);\n const resolved = new URL(relativeUrl, absoluteBase).href.slice(\n PLACEHOLDER_ORIGIN.length,\n );\n // The placeholder origin makes everything look rooted at `/`. Only keep\n // that slash if it was already there before resolving.\n const isRooted = base.startsWith(\"/\") || relativeUrl.startsWith(\"/\");\n return isRooted ? resolved : resolved.slice(1);\n }\n}\n\n/**\n * Resolve oldUrl against pathOldUrlIsRelativeTo, and then prepend newUrlBase\n */\nexport default (\n newUrlBase: string,\n oldUrl: string,\n pathOldUrlIsRelativeTo?: string,\n): string => {\n if (!isLocalPath(oldUrl)) {\n return oldUrl;\n } else {\n oldUrl = oldUrl.trim();\n let relativePath: string;\n\n if (pathOldUrlIsRelativeTo) {\n const isDirAlready = pathOldUrlIsRelativeTo.endsWith(\"/\");\n const fileDirName = isDirAlready\n ? pathOldUrlIsRelativeTo\n : path.dirname(pathOldUrlIsRelativeTo) + \"/\";\n relativePath = resolveUrl(fileDirName, oldUrl);\n } else {\n relativePath = oldUrl;\n }\n\n // When resolving against the CDN URL, we should always use a relative URL.\n //\n // e.g. http://somecdn.com/cdn/ + /article/some.css => http://somecdn.com/cdn/article/some.css\n // and *NOT*\n // http://somecdn.com/cdn/ + /article/some.css => http://somecdn.com/article/some.css\n //\n if (relativePath.startsWith(\"/\")) {\n relativePath = relativePath.slice(1);\n }\n\n if (!newUrlBase.endsWith(\"/\")) {\n newUrlBase += \"/\";\n }\n\n return resolveUrl(newUrlBase, relativePath);\n }\n};\n"],"mappings":";;;;AAGA,MAAM,qBAAqB;AAE3B,MAAM,iBAAiB;AAEvB,SAAS,YAAY,UAA2B;CAC9C,OACE,OAAO,aAAa,YACpB,SAAS,SAAS,KAClB,SAAS,QAAQ,IAAI,MAAM,MAC3B,SAAS,QAAQ,OAAO,MAAM;AAElC;;;;;;;;;;;;AAaA,SAAS,WAAW,MAAc,aAA6B;CAC7D,IAAI,KAAK,WAAW,IAAI,GACtB,OAAO,IAAI,IAAI,aAAa,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAc;MAChE,IAAI,eAAe,KAAK,IAAI,GACjC,OAAO,IAAI,IAAI,aAAa,IAAI,CAAC,CAAC;MAC7B;EACL,MAAM,eAAe,IAAI,IAAI,MAAM,kBAAkB;EACrD,MAAM,WAAW,IAAI,IAAI,aAAa,YAAY,CAAC,CAAC,KAAK,MACvD,EACF;EAIA,OADiB,KAAK,WAAW,GAAG,KAAK,YAAY,WAAW,GAAG,IACjD,WAAW,SAAS,MAAM,CAAC;CAC/C;AACF;;;;AAKA,4BACE,YACA,QACA,2BACW;CACX,IAAI,CAAC,YAAY,MAAM,GACrB,OAAO;MACF;EACL,SAAS,OAAO,KAAK;EACrB,IAAI;EAEJ,IAAI,wBAKF,eAAe,WAJM,uBAAuB,SAAS,GACtB,IAC3B,yBACA,KAAK,QAAQ,sBAAsB,IAAI,KACJ,MAAM;OAE7C,eAAe;EASjB,IAAI,aAAa,WAAW,GAAG,GAC7B,eAAe,aAAa,MAAM,CAAC;EAGrC,IAAI,CAAC,WAAW,SAAS,GAAG,GAC1B,cAAc;EAGhB,OAAO,WAAW,YAAY,YAAY;CAC5C;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@altano/html-cdnify",
3
- "version": "6.0.0",
3
+ "version": "6.0.1",
4
4
  "description": "Transform the relative URLs in your HTML markup (e.g. scripts, stylesheets, images) to use your CDN URL.",
5
5
  "keywords": [
6
6
  "cdn",
@@ -40,16 +40,16 @@
40
40
  "devDependencies": {
41
41
  "@arethetypeswrong/cli": "^0.18.5",
42
42
  "@types/lodash-es": "^4.17.12",
43
- "@types/node": "^26.1.1",
43
+ "@types/node": "^26.6.4",
44
44
  "@types/streamifier": "^0.1.2",
45
- "@vitest/coverage-v8": "^4.1.10",
45
+ "@vitest/coverage-v8": "^5.0.3",
46
46
  "depcheck": "^1.4.7",
47
- "eslint": "^9.39.5",
48
- "prettier": "3.9.6",
49
- "tsdown": "^0.22.14",
47
+ "eslint": "^10.12.0",
48
+ "prettier": "3.9.9",
49
+ "tsdown": "^0.23.0",
50
50
  "typescript": "^6.0.3",
51
- "vite": "^8.1.5",
52
- "vitest": "^4.1.10",
51
+ "vite": "^8.3.2",
52
+ "vitest": "^5.0.3",
53
53
  "@altano/build-config": "0.0.1",
54
54
  "@altano/testing": "0.0.1",
55
55
  "@altano/tsconfig": "0.0.1"