@libsrcdev/gatsby-remark-images-anywhere 0.1.2 → 0.1.4

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.
package/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { Node, NodePluginArgs } from "gatsby";
2
2
  import { FileSystemNode } from "gatsby-source-filesystem";
3
- import { Literal } from "mdast";
3
+ import { Literal, Literal as RemarkLiteral, Node as RemarkNode } from "mdast";
4
4
 
5
5
  //#region src/custom-http-headers/http-request-header-options.d.ts
6
6
  type HttpRequestHeaderOptions = {
7
7
  dangerouslyBuildRequestHttpHeaders?: (url: string) => Record<string, string> | undefined;
8
- httpHeaderProviders: ((url: string) => Record<string, string> | undefined)[];
8
+ httpHeaderProviders?: HttpRequestHeaderProvider[];
9
9
  };
10
+ type HttpRequestHeaderProvider = (url: string) => Record<string, string> | undefined;
10
11
  //#endregion
11
12
  //#region src/type.d.ts
12
13
  type SharpMethod = 'fluid' | 'fixed' | 'resize';
@@ -54,6 +55,87 @@ interface Options extends Partial<MarkupOptions>, HttpRequestHeaderOptions {
54
55
  [key: string]: unknown;
55
56
  }
56
57
  //#endregion
58
+ //#region src/constants.d.ts
59
+ declare const CLASS_WRAPPER = "gria-image-wrapper";
60
+ declare const CLASS_PADDING = "gria-image-padding";
61
+ declare const CLASS_LINK = "gria-image-link";
62
+ declare const CLASS_IMAGE = "gria-image";
63
+ declare const CLASS_PLACEHOLDER = "gria-image-placeholder";
64
+ declare const SUPPORT_EXTS: string[];
65
+ //#endregion
66
+ //#region src/custom-http-headers/is-trusted-url.d.ts
67
+ type UrlCheckOptions = {
68
+ allowedDomains: string[];
69
+ schemes?: string[];
70
+ allowSubdomains?: boolean;
71
+ maxSubdomainDepth?: number;
72
+ allowedPorts?: string[] | null;
73
+ disallowedQueryParams?: string[];
74
+ };
75
+ declare function isTrustedUrl(input: string, options: UrlCheckOptions): boolean;
76
+ //#endregion
77
+ //#region src/custom-http-headers/http-header-trusted-provider.d.ts
78
+ declare function httpHeaderTrustedProvider(options: UrlCheckOptions, headerBuilder: (url: string) => Record<string, string> | undefined): (url: string) => Record<string, string> | undefined;
79
+ declare function forTrustedDomains(domains: string[], headerBuilder: (url: string) => Record<string, string> | undefined): (url: string) => Record<string, string> | undefined;
80
+ declare const buildRequestHttpHeadersWith: (httpHeaderProviders: HttpRequestHeaderProvider[]) => (url: string) => Record<string, string> | undefined;
81
+ //#endregion
82
+ //#region src/default-markup.d.ts
83
+ declare const defaultMarkup: CreateMarkup;
84
+ //#endregion
85
+ //#region src/relative-protocol-whitelist.d.ts
86
+ type MakeWhitelistTest = (whitelist: string[]) => (url: string) => boolean;
87
+ declare const makeWhitelistTest: MakeWhitelistTest;
88
+ declare const isWhitelisted: (url: string) => boolean;
89
+ //#endregion
90
+ //#region src/util-download-image.d.ts
91
+ declare const downloadImage: ({
92
+ id,
93
+ url,
94
+ getCache,
95
+ getNode,
96
+ touchNode,
97
+ cache,
98
+ createNode,
99
+ createNodeId,
100
+ reporter,
101
+ dangerouslyBuildImageRequestHttpHeaders
102
+ }: any) => Promise<any>;
103
+ declare const processImage: ({
104
+ file,
105
+ reporter,
106
+ cache,
107
+ pathPrefix,
108
+ sharpMethod,
109
+ imageOptions
110
+ }: {
111
+ sharpMethod: SharpMethod;
112
+ } & {
113
+ [key: string]: any;
114
+ }) => Promise<SharpResult>;
115
+ //#endregion
116
+ //#region src/util-html-to-md.d.ts
117
+ type RemarkImageNode = RemarkLiteral & {
118
+ url?: string;
119
+ title?: string;
120
+ alt?: string;
121
+ data: Record<string, any>;
122
+ };
123
+ declare const toMdNode: (node: RemarkLiteral) => RemarkImageNode | null;
124
+ //#endregion
125
+ //#region src/utils.d.ts
126
+ /**
127
+ * Resolves a potentially incomplete URL to a full URL with protocol
128
+ * @param url - The URL to resolve (can be protocol-relative or full)
129
+ * @returns The full URL with protocol, or null if invalid or relative
130
+ */
131
+ declare function resolveFullUrl(url: string): string | undefined;
132
+ /**
133
+ * Resolves a relative URL by validating and returning it if it's relative
134
+ * @param url - The URL to check and resolve
135
+ * @returns The relative URL if valid, or undefined if not relative or invalid
136
+ */
137
+ declare function resolveRelativeUrl(url: string): string | undefined;
138
+ //#endregion
57
139
  //#region src/index.d.ts
58
140
  declare function remarkImagesAnywhere({
59
141
  markdownAST: mdast,
@@ -68,4 +150,5 @@ declare function remarkImagesAnywhere({
68
150
  cache,
69
151
  pathPrefix
70
152
  }: Args, pluginOptions: Options): Promise<(null | undefined)[]>;
71
- export = remarkImagesAnywhere;
153
+ //#endregion
154
+ export { Args, CLASS_IMAGE, CLASS_LINK, CLASS_PADDING, CLASS_PLACEHOLDER, CLASS_WRAPPER, CreateMarkup, CreateMarkupArgs, HttpRequestHeaderOptions, HttpRequestHeaderProvider, MarkupOptions, Options, RemarkImageNode, type RemarkLiteral, type RemarkNode, SUPPORT_EXTS, SharpMethod, SharpResult, UrlCheckOptions, buildRequestHttpHeadersWith, remarkImagesAnywhere as default, defaultMarkup, downloadImage, forTrustedDomains, httpHeaderTrustedProvider, isTrustedUrl, isWhitelisted, makeWhitelistTest, processImage, resolveFullUrl, resolveRelativeUrl, toMdNode };
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
1
2
  //#region rolldown:runtime
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -32,6 +33,8 @@ let unist_util_select = require("unist-util-select");
32
33
  let slash = require("slash");
33
34
  slash = __toESM(slash);
34
35
  let parse5 = require("parse5");
36
+ let is_relative_url = require("is-relative-url");
37
+ is_relative_url = __toESM(is_relative_url);
35
38
 
36
39
  //#region node_modules/universalify/index.js
37
40
  var require_universalify = /* @__PURE__ */ __commonJSMin(((exports) => {
@@ -70916,22 +70919,99 @@ const makeWhitelistTest = (whitelist) => (url$3) => {
70916
70919
  const isWhitelisted = makeWhitelistTest(rpWhitelist);
70917
70920
 
70918
70921
  //#endregion
70919
- //#region src/custom-http-headers/http-header-trusted-provider.ts
70920
- function createRequestHttpHeaderBuilder({ dangerouslyBuildRequestHttpHeaders, httpHeaderProviders }) {
70921
- if (dangerouslyBuildRequestHttpHeaders) return dangerouslyBuildRequestHttpHeaders;
70922
- if (httpHeaderProviders) return (url$3) => {
70923
- for (const httpHeaderProvider of httpHeaderProviders) {
70924
- const httpHeaders = httpHeaderProvider(url$3);
70925
- if (httpHeaders) return httpHeaders;
70922
+ //#region src/custom-http-headers/is-trusted-url.ts
70923
+ function isTrustedUrl(input, options) {
70924
+ const { allowedDomains, schemes = ["http", "https"], allowSubdomains = false, maxSubdomainDepth = Infinity, allowedPorts = null, disallowedQueryParams = [] } = options;
70925
+ try {
70926
+ const url$3 = new URL(input);
70927
+ const protocol = url$3.protocol.replace(":", "");
70928
+ if (!schemes.includes(protocol)) return false;
70929
+ const hostname = url$3.hostname.toLowerCase();
70930
+ let domainMatch = false;
70931
+ for (const allowedDomain of allowedDomains) {
70932
+ const domain = allowedDomain.toLowerCase();
70933
+ if (hostname === domain) {
70934
+ domainMatch = true;
70935
+ break;
70936
+ }
70937
+ if (allowSubdomains && hostname.endsWith("." + domain)) {
70938
+ if (hostname.slice(0, -(domain.length + 1)).split(".").length <= maxSubdomainDepth) {
70939
+ domainMatch = true;
70940
+ break;
70941
+ }
70942
+ }
70943
+ }
70944
+ if (!domainMatch) return false;
70945
+ if (disallowedQueryParams.length > 0) {
70946
+ for (const param of disallowedQueryParams) if (url$3.searchParams.has(param)) return false;
70947
+ }
70948
+ if (allowedPorts) {
70949
+ const port = url$3.port || (protocol === "https" ? "443" : protocol === "http" ? "80" : "");
70950
+ if (!allowedPorts.includes(port)) return false;
70926
70951
  }
70952
+ return true;
70953
+ } catch {
70954
+ return false;
70955
+ }
70956
+ }
70957
+
70958
+ //#endregion
70959
+ //#region src/custom-http-headers/http-header-trusted-provider.ts
70960
+ function httpHeaderTrustedProvider(options, headerBuilder) {
70961
+ return (url$3) => {
70962
+ if (!isTrustedUrl(url$3, options)) return;
70963
+ return headerBuilder(url$3);
70927
70964
  };
70928
- return (_$2) => void 0;
70965
+ }
70966
+ function forTrustedDomains(domains, headerBuilder) {
70967
+ return httpHeaderTrustedProvider({
70968
+ allowedDomains: domains,
70969
+ allowSubdomains: false
70970
+ }, headerBuilder);
70971
+ }
70972
+ const buildRequestHttpHeadersWith = (httpHeaderProviders) => (url$3) => {
70973
+ for (const httpHeaderProvider of httpHeaderProviders ?? []) {
70974
+ const httpHeaders = httpHeaderProvider(url$3);
70975
+ if (httpHeaders) return httpHeaders;
70976
+ }
70977
+ };
70978
+
70979
+ //#endregion
70980
+ //#region src/utils.ts
70981
+ /**
70982
+ * Resolves a potentially incomplete URL to a full URL with protocol
70983
+ * @param url - The URL to resolve (can be protocol-relative or full)
70984
+ * @returns The full URL with protocol, or null if invalid or relative
70985
+ */
70986
+ function resolveFullUrl(url$3) {
70987
+ const trimmed = url$3.trim();
70988
+ if (!trimmed) return;
70989
+ if ((0, is_relative_url.default)(trimmed)) return;
70990
+ let resolvedUrl = trimmed;
70991
+ if (trimmed.startsWith("//")) resolvedUrl = `https:${trimmed}`;
70992
+ try {
70993
+ new URL(resolvedUrl);
70994
+ return resolvedUrl;
70995
+ } catch {
70996
+ return;
70997
+ }
70998
+ }
70999
+ /**
71000
+ * Resolves a relative URL by validating and returning it if it's relative
71001
+ * @param url - The URL to check and resolve
71002
+ * @returns The relative URL if valid, or undefined if not relative or invalid
71003
+ */
71004
+ function resolveRelativeUrl(url$3) {
71005
+ const trimmed = url$3.trim();
71006
+ if (!trimmed) return;
71007
+ if (!(0, is_relative_url.default)(trimmed)) return;
71008
+ return trimmed;
70929
71009
  }
70930
71010
 
70931
71011
  //#endregion
70932
71012
  //#region src/index.ts
70933
71013
  async function remarkImagesAnywhere({ markdownAST: mdast, markdownNode, actions: actions$1, store, files, getNode, getCache, createNodeId, reporter, cache: cache$3, pathPrefix }, pluginOptions$1) {
70934
- const { plugins, staticDir = "static", createMarkup = defaultMarkup, sharpMethod = "fluid", loading = "lazy", linkImagesToOriginal = false, showCaptions = false, wrapperStyle = "", backgroundColor = "#fff", tracedSVG = false, blurUp = true, dangerouslyBuildRequestHttpHeaders, httpHeaderProviders, ...imageOptions } = pluginOptions$1;
71014
+ const { plugins, staticDir = "static", createMarkup = defaultMarkup, sharpMethod = "fluid", loading = "lazy", linkImagesToOriginal = false, showCaptions = false, wrapperStyle = "", backgroundColor = "#fff", tracedSVG = false, blurUp = true, dangerouslyBuildRequestHttpHeaders, httpHeaderProviders = [], ...imageOptions } = pluginOptions$1;
70935
71015
  if ([
70936
71016
  "fluid",
70937
71017
  "fixed",
@@ -70948,27 +71028,28 @@ async function remarkImagesAnywhere({ markdownAST: mdast, markdownNode, actions:
70948
71028
  let url$3 = node.url;
70949
71029
  let gImgFileNode;
70950
71030
  if (isWhitelisted(url$3)) url$3 = `https:${url$3}`;
70951
- if (url$3.startsWith("http")) gImgFileNode = await downloadImage({
70952
- id: markdownNode.id,
70953
- url: url$3,
70954
- getCache,
70955
- getNode,
70956
- touchNode,
70957
- cache: cache$3,
70958
- createNode,
70959
- createNodeId,
70960
- reporter,
70961
- dangerouslyBuildImageRequestHttpHeaders: createRequestHttpHeaderBuilder({
70962
- dangerouslyBuildRequestHttpHeaders,
70963
- httpHeaderProviders
70964
- })
70965
- });
70966
- else {
71031
+ const remoteFullImageUrl = resolveFullUrl(url$3);
71032
+ const relativeImageUrl = resolveRelativeUrl(url$3);
71033
+ if (remoteFullImageUrl) {
71034
+ const buildRequestHttpHeaders = dangerouslyBuildRequestHttpHeaders ?? buildRequestHttpHeadersWith(httpHeaderProviders);
71035
+ gImgFileNode = await downloadImage({
71036
+ id: markdownNode.id,
71037
+ url: new URL(url$3).protocol,
71038
+ getCache,
71039
+ getNode,
71040
+ touchNode,
71041
+ cache: cache$3,
71042
+ createNode,
71043
+ createNodeId,
71044
+ reporter,
71045
+ dangerouslyBuildImageRequestHttpHeaders: buildRequestHttpHeaders
71046
+ });
71047
+ } else if (relativeImageUrl) {
70967
71048
  let filePath;
70968
71049
  if (dirPath && url$3[0] === ".") filePath = (0, slash.default)(path.default.join(dirPath, url$3));
70969
71050
  else filePath = path.default.join(directory, staticDir, url$3);
70970
71051
  gImgFileNode = files.find((fileNode) => fileNode.absolutePath && fileNode.absolutePath === filePath);
70971
- }
71052
+ } else reporter.warn(`Skipping invalid image URL ${url$3}`);
70972
71053
  if (!gImgFileNode) return;
70973
71054
  if (!SUPPORT_EXTS.includes(gImgFileNode.extension)) return;
70974
71055
  const imageResult = await processImage({
@@ -71003,4 +71084,22 @@ async function remarkImagesAnywhere({ markdownAST: mdast, markdownNode, actions:
71003
71084
  }
71004
71085
 
71005
71086
  //#endregion
71006
- module.exports = remarkImagesAnywhere;
71087
+ exports.CLASS_IMAGE = CLASS_IMAGE;
71088
+ exports.CLASS_LINK = CLASS_LINK;
71089
+ exports.CLASS_PADDING = CLASS_PADDING;
71090
+ exports.CLASS_PLACEHOLDER = CLASS_PLACEHOLDER;
71091
+ exports.CLASS_WRAPPER = CLASS_WRAPPER;
71092
+ exports.SUPPORT_EXTS = SUPPORT_EXTS;
71093
+ exports.buildRequestHttpHeadersWith = buildRequestHttpHeadersWith;
71094
+ exports.default = remarkImagesAnywhere;
71095
+ exports.defaultMarkup = defaultMarkup;
71096
+ exports.downloadImage = downloadImage;
71097
+ exports.forTrustedDomains = forTrustedDomains;
71098
+ exports.httpHeaderTrustedProvider = httpHeaderTrustedProvider;
71099
+ exports.isTrustedUrl = isTrustedUrl;
71100
+ exports.isWhitelisted = isWhitelisted;
71101
+ exports.makeWhitelistTest = makeWhitelistTest;
71102
+ exports.processImage = processImage;
71103
+ exports.resolveFullUrl = resolveFullUrl;
71104
+ exports.resolveRelativeUrl = resolveRelativeUrl;
71105
+ exports.toMdNode = toMdNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libsrcdev/gatsby-remark-images-anywhere",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Handle images with relative, absolute, remote path for gatsby-transformer-remark.",
5
5
  "keywords": [
6
6
  "gatsby",
@@ -35,25 +35,26 @@
35
35
  "prepare": "npm run build"
36
36
  },
37
37
  "dependencies": {
38
+ "is-relative-url": "^4.1.0",
38
39
  "parse5": "^8.0.0",
39
40
  "slash": "^3.0.0",
40
41
  "unist-util-select": "^5.1.0"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@swc/core": "^1.15.3",
45
+ "@types/fs-extra": "^8.0.0",
44
46
  "@types/mdast": "^4.0.4",
45
47
  "eslint": "^9.39.1",
46
48
  "gatsby": "^5.15.0",
49
+ "gatsby-plugin-sharp": "^5.10.0",
50
+ "gatsby-source-filesystem": "^5.10.0",
47
51
  "husky": "^9.1.7",
48
52
  "mdast": "^2.3.2",
49
53
  "nodemon": "^3.1.11",
54
+ "tap": "^14.9.2",
50
55
  "tsdown": "^0.16.6",
51
56
  "tslib": "^2.8.1",
52
- "typescript": "^5.9.3",
53
- "@types/fs-extra": "^8.0.0",
54
- "gatsby-plugin-sharp": "^5.10.0",
55
- "gatsby-source-filesystem": "^5.10.0",
56
- "tap": "^14.9.2"
57
+ "typescript": "^5.9.3"
57
58
  },
58
59
  "typings": "dist/index.d.ts",
59
60
  "prettier": {
@@ -62,4 +63,4 @@
62
63
  "singleQuote": true,
63
64
  "trailingComma": "es5"
64
65
  }
65
- }
66
+ }