@tryghost/url-utils 5.0.0-rc.0 → 5.0.0
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/index.js +1 -0
- package/lib/UrlUtils.d.ts +3 -0
- package/lib/UrlUtils.js +45 -111
- package/lib/utils/absolute-to-relative.d.ts +13 -0
- package/lib/utils/absolute-to-relative.js +5 -13
- package/lib/utils/absolute-to-transform-ready.d.ts +4 -0
- package/lib/utils/absolute-to-transform-ready.js +31 -91
- package/lib/utils/build-early-exit-match.d.ts +14 -0
- package/lib/utils/build-early-exit-match.js +39 -0
- package/lib/utils/deduplicate-double-slashes.d.ts +1 -0
- package/lib/utils/deduplicate-double-slashes.js +6 -2
- package/lib/utils/deduplicate-subdirectory.d.ts +9 -0
- package/lib/utils/deduplicate-subdirectory.js +3 -7
- package/lib/utils/html-absolute-to-relative.d.ts +3 -0
- package/lib/utils/html-absolute-to-relative.js +3 -6
- package/lib/utils/html-absolute-to-transform-ready.d.ts +4 -0
- package/lib/utils/html-absolute-to-transform-ready.js +6 -9
- package/lib/utils/html-relative-to-absolute.d.ts +3 -0
- package/lib/utils/html-relative-to-absolute.js +3 -5
- package/lib/utils/html-relative-to-transform-ready.d.ts +3 -0
- package/lib/utils/html-relative-to-transform-ready.js +2 -5
- package/lib/utils/html-to-transform-ready.d.ts +3 -0
- package/lib/utils/html-to-transform-ready.js +2 -2
- package/lib/utils/html-transform.d.ts +4 -0
- package/lib/utils/html-transform.js +10 -30
- package/lib/utils/index.d.ts +0 -0
- package/lib/utils/index.js +2 -0
- package/lib/utils/is-ssl.d.ts +2 -0
- package/lib/utils/is-ssl.js +4 -4
- package/lib/utils/lexical-absolute-to-relative.d.ts +2 -0
- package/lib/utils/lexical-absolute-to-relative.js +4 -6
- package/lib/utils/lexical-absolute-to-transform-ready.d.ts +2 -0
- package/lib/utils/lexical-absolute-to-transform-ready.js +4 -6
- package/lib/utils/lexical-relative-to-absolute.d.ts +3 -0
- package/lib/utils/lexical-relative-to-absolute.js +4 -5
- package/lib/utils/lexical-relative-to-transform-ready.d.ts +3 -0
- package/lib/utils/lexical-relative-to-transform-ready.js +4 -5
- package/lib/utils/lexical-to-transform-ready.d.ts +3 -0
- package/lib/utils/lexical-to-transform-ready.js +2 -2
- package/lib/utils/lexical-transform.d.ts +2 -0
- package/lib/utils/lexical-transform.js +6 -19
- package/lib/utils/markdown-absolute-to-relative.d.ts +4 -0
- package/lib/utils/markdown-absolute-to-relative.js +3 -6
- package/lib/utils/markdown-absolute-to-transform-ready.d.ts +5 -0
- package/lib/utils/markdown-absolute-to-transform-ready.js +5 -8
- package/lib/utils/markdown-relative-to-absolute.d.ts +4 -0
- package/lib/utils/markdown-relative-to-absolute.js +3 -6
- package/lib/utils/markdown-relative-to-transform-ready.d.ts +4 -0
- package/lib/utils/markdown-relative-to-transform-ready.js +3 -6
- package/lib/utils/markdown-to-transform-ready.d.ts +3 -0
- package/lib/utils/markdown-to-transform-ready.js +2 -2
- package/lib/utils/markdown-transform.d.ts +5 -0
- package/lib/utils/markdown-transform.js +7 -25
- package/lib/utils/mobiledoc-absolute-to-relative.d.ts +2 -0
- package/lib/utils/mobiledoc-absolute-to-relative.js +4 -6
- package/lib/utils/mobiledoc-absolute-to-transform-ready.d.ts +2 -0
- package/lib/utils/mobiledoc-absolute-to-transform-ready.js +4 -6
- package/lib/utils/mobiledoc-relative-to-absolute.d.ts +3 -0
- package/lib/utils/mobiledoc-relative-to-absolute.js +4 -5
- package/lib/utils/mobiledoc-relative-to-transform-ready.d.ts +3 -0
- package/lib/utils/mobiledoc-relative-to-transform-ready.js +4 -5
- package/lib/utils/mobiledoc-to-transform-ready.d.ts +3 -0
- package/lib/utils/mobiledoc-to-transform-ready.js +2 -2
- package/lib/utils/mobiledoc-transform.d.ts +1 -0
- package/lib/utils/mobiledoc-transform.js +4 -10
- package/lib/utils/plaintext-absolute-to-transform-ready.d.ts +4 -0
- package/lib/utils/plaintext-absolute-to-transform-ready.js +18 -10
- package/lib/utils/plaintext-relative-to-transform-ready.d.ts +2 -0
- package/lib/utils/plaintext-relative-to-transform-ready.js +2 -3
- package/lib/utils/plaintext-to-transform-ready.d.ts +3 -0
- package/lib/utils/plaintext-to-transform-ready.js +2 -2
- package/lib/utils/relative-to-absolute.d.ts +13 -0
- package/lib/utils/relative-to-absolute.js +6 -18
- package/lib/utils/relative-to-transform-ready.d.ts +2 -0
- package/lib/utils/relative-to-transform-ready.js +2 -9
- package/lib/utils/replace-permalink.d.ts +5 -0
- package/lib/utils/replace-permalink.js +2 -3
- package/lib/utils/strip-subdirectory-from-path.d.ts +9 -0
- package/lib/utils/strip-subdirectory-from-path.js +5 -9
- package/lib/utils/to-transform-ready.d.ts +3 -0
- package/lib/utils/to-transform-ready.js +2 -2
- package/lib/utils/transform-ready-to-absolute.d.ts +1 -0
- package/lib/utils/transform-ready-to-absolute.js +9 -27
- package/lib/utils/transform-ready-to-relative.d.ts +1 -0
- package/lib/utils/transform-ready-to-relative.js +2 -6
- package/lib/utils/url-join.d.ts +9 -0
- package/lib/utils/url-join.js +2 -8
- package/package.json +16 -7
|
@@ -1,69 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
const { URL } = require('url');
|
|
2
4
|
const absoluteToRelative = require('./absolute-to-relative');
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!baseUrl) {
|
|
6
|
-
return null;
|
|
7
|
-
}
|
|
8
|
-
|
|
5
|
+
function isRelative(url) {
|
|
6
|
+
let parsedInput;
|
|
9
7
|
try {
|
|
10
|
-
|
|
11
|
-
let pathname = parsed.pathname.replace(/\/$/, '');
|
|
12
|
-
if (pathname === '/') {
|
|
13
|
-
pathname = '';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
origin: parsed.origin,
|
|
18
|
-
pathname
|
|
19
|
-
};
|
|
20
|
-
} catch (e) {
|
|
21
|
-
return null;
|
|
8
|
+
parsedInput = new URL(url, 'http://relative');
|
|
22
9
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const candidates = [
|
|
27
|
-
{base: normalizeBaseUrl(options.mediaBaseUrl), prefix: options.staticMediaUrlPrefix},
|
|
28
|
-
{base: normalizeBaseUrl(options.filesBaseUrl), prefix: options.staticFilesUrlPrefix}
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
for (const candidate of candidates) {
|
|
32
|
-
if (!candidate.base || !candidate.prefix) {
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (parsedUrl.origin !== candidate.base.origin) {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
let pathname = parsedUrl.pathname;
|
|
41
|
-
const basePath = candidate.base.pathname;
|
|
42
|
-
|
|
43
|
-
if (basePath) {
|
|
44
|
-
if (pathname === basePath) {
|
|
45
|
-
pathname = '/';
|
|
46
|
-
} else if (pathname.startsWith(basePath + '/')) {
|
|
47
|
-
pathname = pathname.slice(basePath.length);
|
|
48
|
-
} else {
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (!pathname.startsWith('/')) {
|
|
54
|
-
pathname = `/${pathname}`;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (!pathname.startsWith(`/${candidate.prefix}`)) {
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return `${pathname}${parsedUrl.search}${parsedUrl.hash}`;
|
|
10
|
+
catch (e) {
|
|
11
|
+
// url was unparseable
|
|
12
|
+
return false;
|
|
62
13
|
}
|
|
63
|
-
|
|
64
|
-
return null;
|
|
14
|
+
return parsedInput.origin === 'http://relative';
|
|
65
15
|
}
|
|
66
|
-
|
|
67
16
|
const absoluteToTransformReady = function (url, root, _options = {}) {
|
|
68
17
|
const defaultOptions = {
|
|
69
18
|
replacementStr: '__GHOST_URL__',
|
|
@@ -76,42 +25,33 @@ const absoluteToTransformReady = function (url, root, _options = {}) {
|
|
|
76
25
|
mediaBaseUrl: null
|
|
77
26
|
};
|
|
78
27
|
const options = Object.assign({}, defaultOptions, _options);
|
|
79
|
-
|
|
80
|
-
let parsedInput;
|
|
81
|
-
try {
|
|
82
|
-
parsedInput = new URL(url, 'http://relative');
|
|
83
|
-
} catch (e) {
|
|
84
|
-
// url was unparseable
|
|
28
|
+
if (isRelative(url)) {
|
|
85
29
|
return url;
|
|
86
30
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
31
|
+
// convert to relative with stripped subdir
|
|
32
|
+
// always returns root-relative starting with forward slash
|
|
33
|
+
const rootRelativeUrl = absoluteToRelative(url, root, options);
|
|
34
|
+
if (isRelative(rootRelativeUrl)) {
|
|
35
|
+
return `${options.replacementStr}${rootRelativeUrl}`;
|
|
36
|
+
}
|
|
37
|
+
if (options.mediaBaseUrl) {
|
|
38
|
+
const mediaRelativeUrl = absoluteToRelative(url, options.mediaBaseUrl, options);
|
|
39
|
+
if (isRelative(mediaRelativeUrl)) {
|
|
40
|
+
return `${options.replacementStr}${mediaRelativeUrl}`;
|
|
92
41
|
}
|
|
93
42
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
43
|
+
if (options.filesBaseUrl) {
|
|
44
|
+
const filesRelativeUrl = absoluteToRelative(url, options.filesBaseUrl, options);
|
|
45
|
+
if (isRelative(filesRelativeUrl)) {
|
|
46
|
+
return `${options.replacementStr}${filesRelativeUrl}`;
|
|
47
|
+
}
|
|
97
48
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// return still absolute urls as-is (eg. external site, mailto, etc)
|
|
104
|
-
try {
|
|
105
|
-
const parsedURL = new URL(relativeUrl, 'http://relative');
|
|
106
|
-
if (parsedURL.origin !== 'http://relative') {
|
|
107
|
-
return url;
|
|
49
|
+
if (options.imageBaseUrl) {
|
|
50
|
+
const imageRelativeUrl = absoluteToRelative(url, options.imageBaseUrl, options);
|
|
51
|
+
if (isRelative(imageRelativeUrl)) {
|
|
52
|
+
return `${options.replacementStr}${imageRelativeUrl}`;
|
|
108
53
|
}
|
|
109
|
-
} catch (e) {
|
|
110
|
-
// url was unparseable
|
|
111
|
-
return url;
|
|
112
54
|
}
|
|
113
|
-
|
|
114
|
-
return `${options.replacementStr}${relativeUrl}`;
|
|
55
|
+
return url;
|
|
115
56
|
};
|
|
116
|
-
|
|
117
57
|
module.exports = absoluteToTransformReady;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a regex pattern that matches any of the configured base URLs (site URL + CDN URLs).
|
|
3
|
+
* This is used for early exit optimizations - if content doesn't contain any of these URLs,
|
|
4
|
+
* we can skip expensive parsing.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} siteUrl - The site's base URL
|
|
7
|
+
* @param {Object} options - Options containing CDN base URLs
|
|
8
|
+
* @param {string} [options.imageBaseUrl] - CDN base URL for images
|
|
9
|
+
* @param {string} [options.filesBaseUrl] - CDN base URL for files
|
|
10
|
+
* @param {string} [options.mediaBaseUrl] - CDN base URL for media
|
|
11
|
+
* @param {boolean} [options.ignoreProtocol=true] - Whether to strip protocol from URLs
|
|
12
|
+
* @returns {string|null} Regex pattern matching any configured base URL, or null if none configured
|
|
13
|
+
*/
|
|
14
|
+
declare function buildEarlyExitMatch(siteUrl: any, options?: {}): any;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
function escapeRegExp(string) {
|
|
4
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Build a regex pattern that matches any of the configured base URLs (site URL + CDN URLs).
|
|
8
|
+
* This is used for early exit optimizations - if content doesn't contain any of these URLs,
|
|
9
|
+
* we can skip expensive parsing.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} siteUrl - The site's base URL
|
|
12
|
+
* @param {Object} options - Options containing CDN base URLs
|
|
13
|
+
* @param {string} [options.imageBaseUrl] - CDN base URL for images
|
|
14
|
+
* @param {string} [options.filesBaseUrl] - CDN base URL for files
|
|
15
|
+
* @param {string} [options.mediaBaseUrl] - CDN base URL for media
|
|
16
|
+
* @param {boolean} [options.ignoreProtocol=true] - Whether to strip protocol from URLs
|
|
17
|
+
* @returns {string|null} Regex pattern matching any configured base URL, or null if none configured
|
|
18
|
+
*/
|
|
19
|
+
function buildEarlyExitMatch(siteUrl, options = {}) {
|
|
20
|
+
const candidates = [siteUrl, options.imageBaseUrl, options.filesBaseUrl, options.mediaBaseUrl]
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.map((value) => {
|
|
23
|
+
let normalized = options.ignoreProtocol ? value.replace(/http:|https:/, '') : value;
|
|
24
|
+
return normalized.replace(/\/$/, '');
|
|
25
|
+
})
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.map(escapeRegExp);
|
|
28
|
+
if (!candidates.length) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
if (candidates.length === 1) {
|
|
32
|
+
return candidates[0];
|
|
33
|
+
}
|
|
34
|
+
return `(?:${candidates.join('|')})`;
|
|
35
|
+
}
|
|
36
|
+
module.exports = {
|
|
37
|
+
buildEarlyExitMatch,
|
|
38
|
+
escapeRegExp
|
|
39
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare function deduplicateDoubleSlashes(url: any): any;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
function deduplicateDoubleSlashes(url) {
|
|
2
|
-
|
|
4
|
+
// Preserve protocol slashes (e.g., http://, https://) and only deduplicate
|
|
5
|
+
// slashes in the path portion. The pattern (^|[^:])\/\/+ matches double slashes
|
|
6
|
+
// that are either at the start of the string or not preceded by a colon.
|
|
7
|
+
return url.replace(/(^|[^:])\/\/+/g, '$1/');
|
|
3
8
|
}
|
|
4
|
-
|
|
5
9
|
module.exports = deduplicateDoubleSlashes;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const URL: any;
|
|
2
|
+
/**
|
|
3
|
+
* Remove duplicated directories from the start of a path or url's path
|
|
4
|
+
*
|
|
5
|
+
* @param {string} url URL or pathname with possible duplicate subdirectory
|
|
6
|
+
* @param {string} rootUrl Root URL with an optional subdirectory
|
|
7
|
+
* @returns {string} URL or pathname with any duplicated subdirectory removed
|
|
8
|
+
*/
|
|
9
|
+
declare const deduplicateSubdirectory: (url: any, rootUrl: any) => any;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
const { URL } = require('url');
|
|
3
4
|
/**
|
|
4
5
|
* Remove duplicated directories from the start of a path or url's path
|
|
5
6
|
*
|
|
@@ -12,20 +13,15 @@ const deduplicateSubdirectory = function deduplicateSubdirectory(url, rootUrl) {
|
|
|
12
13
|
if (!rootUrl.endsWith('/')) {
|
|
13
14
|
rootUrl = `${rootUrl}/`;
|
|
14
15
|
}
|
|
15
|
-
|
|
16
16
|
const parsedRoot = new URL(rootUrl);
|
|
17
|
-
|
|
18
17
|
// do nothing if rootUrl does not have a subdirectory
|
|
19
18
|
if (parsedRoot.pathname === '/') {
|
|
20
19
|
return url;
|
|
21
20
|
}
|
|
22
|
-
|
|
23
21
|
const subdir = parsedRoot.pathname.replace(/(^\/|\/$)+/g, '');
|
|
24
22
|
// we can have subdirs that match TLDs so we need to restrict matches to
|
|
25
23
|
// duplicates that start with a / or the beginning of the url
|
|
26
24
|
const subdirRegex = new RegExp(`(^|/)${subdir}/${subdir}(/|$)`);
|
|
27
|
-
|
|
28
25
|
return url.replace(subdirRegex, `$1${subdir}/`);
|
|
29
26
|
};
|
|
30
|
-
|
|
31
27
|
module.exports = deduplicateSubdirectory;
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const htmlTransform = require('./html-transform');
|
|
2
4
|
const absoluteToRelative = require('./absolute-to-relative');
|
|
3
|
-
|
|
4
5
|
function htmlAbsoluteToRelative(html = '', siteUrl, _options) {
|
|
5
|
-
const defaultOptions = {assetsOnly: false, ignoreProtocol: true};
|
|
6
|
+
const defaultOptions = { assetsOnly: false, ignoreProtocol: true };
|
|
6
7
|
const options = Object.assign({}, defaultOptions, _options || {});
|
|
7
|
-
|
|
8
8
|
// exit early and avoid parsing if the content does not contain the siteUrl
|
|
9
9
|
options.earlyExitMatchStr = options.ignoreProtocol ? siteUrl.replace(/http:|https:/, '') : siteUrl;
|
|
10
10
|
options.earlyExitMatchStr = options.earlyExitMatchStr.replace(/\/$/, '');
|
|
11
|
-
|
|
12
11
|
// need to ignore itemPath because absoluteToRelative doesn't take that option
|
|
13
12
|
const transformFunction = function (_url, _siteUrl, _itemPath, __options) {
|
|
14
13
|
return absoluteToRelative(_url, _siteUrl, __options);
|
|
15
14
|
};
|
|
16
|
-
|
|
17
15
|
return htmlTransform(html, siteUrl, transformFunction, '', options);
|
|
18
16
|
}
|
|
19
|
-
|
|
20
17
|
module.exports = htmlAbsoluteToRelative;
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const htmlTransform = require('./html-transform');
|
|
2
4
|
const absoluteToTransformReady = require('./absolute-to-transform-ready');
|
|
3
|
-
|
|
5
|
+
const { buildEarlyExitMatch } = require('./build-early-exit-match');
|
|
4
6
|
const htmlAbsoluteToTransformReady = function (html = '', siteUrl, _options) {
|
|
5
|
-
const defaultOptions = {assetsOnly: false, ignoreProtocol: true};
|
|
7
|
+
const defaultOptions = { assetsOnly: false, ignoreProtocol: true };
|
|
6
8
|
const options = Object.assign({}, defaultOptions, _options || {});
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
options.earlyExitMatchStr = options.ignoreProtocol ? siteUrl.replace(/http:|https:/, '') : siteUrl;
|
|
10
|
-
options.earlyExitMatchStr = options.earlyExitMatchStr.replace(/\/$/, '');
|
|
11
|
-
|
|
9
|
+
// exit early and avoid parsing if the content does not contain the siteUrl or configured asset bases
|
|
10
|
+
options.earlyExitMatchStr = buildEarlyExitMatch(siteUrl, options);
|
|
12
11
|
// need to ignore itemPath because absoluteToRelative doesn't take that option
|
|
13
12
|
const transformFunction = function (_url, _siteUrl, _itemPath, __options) {
|
|
14
13
|
return absoluteToTransformReady(_url, _siteUrl, __options);
|
|
15
14
|
};
|
|
16
|
-
|
|
17
15
|
return htmlTransform(html, siteUrl, transformFunction, '', options);
|
|
18
16
|
};
|
|
19
|
-
|
|
20
17
|
module.exports = htmlAbsoluteToTransformReady;
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const htmlTransform = require('./html-transform');
|
|
2
4
|
const relativeToAbsolute = require('./relative-to-absolute');
|
|
3
|
-
|
|
4
5
|
function htmlRelativeToAbsolute(html = '', siteUrl, itemPath, _options) {
|
|
5
|
-
const defaultOptions = {assetsOnly: false, secure: false};
|
|
6
|
+
const defaultOptions = { assetsOnly: false, secure: false };
|
|
6
7
|
const options = Object.assign({}, defaultOptions, _options || {});
|
|
7
|
-
|
|
8
8
|
// exit early and avoid parsing if the content does not contain an attribute we might transform
|
|
9
9
|
options.earlyExitMatchStr = 'href=|src=|srcset=';
|
|
10
10
|
if (options.assetsOnly) {
|
|
11
11
|
options.earlyExitMatchStr = options.staticImageUrlPrefix;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
13
|
return htmlTransform(html, siteUrl, relativeToAbsolute, itemPath, options);
|
|
15
14
|
}
|
|
16
|
-
|
|
17
15
|
module.exports = htmlRelativeToAbsolute;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const htmlTransform = require('./html-transform');
|
|
2
4
|
const relativeToTransformReady = require('./relative-to-transform-ready');
|
|
3
|
-
|
|
4
5
|
const htmlRelativeToTransformReady = function (html = '', root, itemPath, _options) {
|
|
5
6
|
// itemPath is optional, if it's an object may be the options param instead
|
|
6
7
|
if (typeof itemPath === 'object' && !_options) {
|
|
7
8
|
_options = itemPath;
|
|
8
9
|
itemPath = null;
|
|
9
10
|
}
|
|
10
|
-
|
|
11
11
|
const defaultOptions = {
|
|
12
12
|
replacementStr: '__GHOST_URL__'
|
|
13
13
|
};
|
|
@@ -15,14 +15,11 @@ const htmlRelativeToTransformReady = function (html = '', root, itemPath, _optio
|
|
|
15
15
|
secure: false
|
|
16
16
|
};
|
|
17
17
|
const options = Object.assign({}, defaultOptions, _options, overrideOptions);
|
|
18
|
-
|
|
19
18
|
// exit early and avoid parsing if the content does not contain an attribute we might transform
|
|
20
19
|
options.earlyExitMatchStr = 'href=|src=|srcset=';
|
|
21
20
|
if (options.assetsOnly) {
|
|
22
21
|
options.earlyExitMatchStr = options.staticImageUrlPrefix;
|
|
23
22
|
}
|
|
24
|
-
|
|
25
23
|
return htmlTransform(html, root, relativeToTransformReady, itemPath, options);
|
|
26
24
|
};
|
|
27
|
-
|
|
28
25
|
module.exports = htmlRelativeToTransformReady;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const htmlRelativeToAbsolute = require('./html-relative-to-absolute');
|
|
2
4
|
const htmlAbsoluteToTransformReady = require('./html-absolute-to-transform-ready');
|
|
3
|
-
|
|
4
5
|
function htmlToTransformReady(html, siteUrl, itemPath, options) {
|
|
5
6
|
if (typeof itemPath === 'object' && !options) {
|
|
6
7
|
options = itemPath;
|
|
@@ -9,5 +10,4 @@ function htmlToTransformReady(html, siteUrl, itemPath, options) {
|
|
|
9
10
|
const absolute = htmlRelativeToAbsolute(html, siteUrl, itemPath, options);
|
|
10
11
|
return htmlAbsoluteToTransformReady(absolute, siteUrl, options);
|
|
11
12
|
}
|
|
12
|
-
|
|
13
13
|
module.exports = htmlToTransformReady;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
declare const cheerio: any;
|
|
2
|
+
declare function extractSrcsetUrls(srcset?: string): string[];
|
|
3
|
+
declare function extractStyleUrls(style?: string): string[];
|
|
4
|
+
declare function htmlTransform(html: string | undefined, siteUrl: any, transformFunction: any, itemPath: any, _options: any): string;
|
|
@@ -1,36 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
const cheerio = require('cheerio');
|
|
1
4
|
function escapeRegExp(string) {
|
|
2
5
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3
6
|
}
|
|
4
|
-
|
|
5
7
|
function extractSrcsetUrls(srcset = '') {
|
|
6
8
|
return srcset.split(',').map((part) => {
|
|
7
9
|
return part.trim().split(/\s+/)[0];
|
|
8
10
|
});
|
|
9
11
|
}
|
|
10
|
-
|
|
11
12
|
function extractStyleUrls(style = '') {
|
|
12
13
|
const urls = [];
|
|
13
14
|
const regex = /url\(['|"]([^)]+)['|"]\)/g;
|
|
14
15
|
let match;
|
|
15
|
-
|
|
16
16
|
while ((match = regex.exec(style)) !== null) {
|
|
17
17
|
urls.push(match[1]);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
19
|
return urls;
|
|
21
20
|
}
|
|
22
|
-
|
|
23
21
|
function htmlTransform(html = '', siteUrl, transformFunction, itemPath, _options) {
|
|
24
|
-
const defaultOptions = {assetsOnly: false, secure: false};
|
|
22
|
+
const defaultOptions = { assetsOnly: false, secure: false };
|
|
25
23
|
const options = Object.assign({}, defaultOptions, _options || {});
|
|
26
|
-
|
|
27
24
|
if (!html || (options.earlyExitMatchStr && !html.match(new RegExp(options.earlyExitMatchStr)))) {
|
|
28
25
|
return html;
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
const cheerio = require('cheerio');
|
|
32
|
-
const htmlContent = cheerio.load(html, {decodeEntities: false});
|
|
33
|
-
|
|
27
|
+
const htmlContent = cheerio.load(html, { decodeEntities: false });
|
|
34
28
|
// replacements is keyed with the attr name + original relative value so
|
|
35
29
|
// that we can implement skips for untouchable urls
|
|
36
30
|
//
|
|
@@ -42,17 +36,13 @@ function htmlTransform(html = '', siteUrl, transformFunction, itemPath, _options
|
|
|
42
36
|
// ]
|
|
43
37
|
// }
|
|
44
38
|
const replacements = {};
|
|
45
|
-
|
|
46
39
|
function addReplacement(replacement) {
|
|
47
40
|
const key = `${replacement.name}="${replacement.originalValue}"`;
|
|
48
|
-
|
|
49
41
|
if (!replacements[key]) {
|
|
50
42
|
replacements[key] = [];
|
|
51
43
|
}
|
|
52
|
-
|
|
53
44
|
replacements[key].push(replacement);
|
|
54
45
|
}
|
|
55
|
-
|
|
56
46
|
// find all of the relative url attributes that we care about
|
|
57
47
|
['href', 'src', 'srcset', 'style'].forEach((attributeName) => {
|
|
58
48
|
htmlContent('[' + attributeName + ']').each((ix, el) => {
|
|
@@ -65,28 +55,24 @@ function htmlTransform(html = '', siteUrl, transformFunction, itemPath, _options
|
|
|
65
55
|
});
|
|
66
56
|
return;
|
|
67
57
|
}
|
|
68
|
-
|
|
69
58
|
el = htmlContent(el);
|
|
70
59
|
const originalValue = el.attr(attributeName);
|
|
71
|
-
|
|
72
60
|
if (attributeName === 'srcset' || attributeName === 'style') {
|
|
73
61
|
let urls;
|
|
74
|
-
|
|
75
62
|
if (attributeName === 'srcset') {
|
|
76
63
|
urls = extractSrcsetUrls(originalValue);
|
|
77
|
-
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
78
66
|
urls = extractStyleUrls(originalValue);
|
|
79
67
|
}
|
|
80
68
|
const absoluteUrls = urls.map(url => transformFunction(url, siteUrl, itemPath, options));
|
|
81
69
|
let transformedValue = originalValue;
|
|
82
|
-
|
|
83
70
|
urls.forEach((url, i) => {
|
|
84
71
|
if (absoluteUrls[i]) {
|
|
85
72
|
let regex = new RegExp(escapeRegExp(url), 'g');
|
|
86
73
|
transformedValue = transformedValue.replace(regex, absoluteUrls[i]);
|
|
87
74
|
}
|
|
88
75
|
});
|
|
89
|
-
|
|
90
76
|
if (transformedValue !== originalValue) {
|
|
91
77
|
addReplacement({
|
|
92
78
|
name: attributeName,
|
|
@@ -94,9 +80,9 @@ function htmlTransform(html = '', siteUrl, transformFunction, itemPath, _options
|
|
|
94
80
|
transformedValue
|
|
95
81
|
});
|
|
96
82
|
}
|
|
97
|
-
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
98
85
|
const transformedValue = transformFunction(originalValue, siteUrl, itemPath, options);
|
|
99
|
-
|
|
100
86
|
if (transformedValue !== originalValue) {
|
|
101
87
|
addReplacement({
|
|
102
88
|
name: attributeName,
|
|
@@ -107,24 +93,20 @@ function htmlTransform(html = '', siteUrl, transformFunction, itemPath, _options
|
|
|
107
93
|
}
|
|
108
94
|
});
|
|
109
95
|
});
|
|
110
|
-
|
|
111
96
|
// Loop over all replacements and use a regex to replace urls in the original html string.
|
|
112
97
|
// Allows indentation and formatting to be kept compared to using DOM manipulation and render
|
|
113
98
|
for (const [, attrs] of Object.entries(replacements)) {
|
|
114
99
|
let skipCount = 0;
|
|
115
|
-
|
|
116
|
-
attrs.forEach(({skip, name, originalValue, transformedValue}) => {
|
|
100
|
+
attrs.forEach(({ skip, name, originalValue, transformedValue }) => {
|
|
117
101
|
if (skip) {
|
|
118
102
|
skipCount += 1;
|
|
119
103
|
return;
|
|
120
104
|
}
|
|
121
|
-
|
|
122
105
|
// this regex avoids matching unrelated plain text by checking that the attribute/value pair
|
|
123
106
|
// is surrounded by <> - that should be sufficient because if the plain text had that wrapper
|
|
124
107
|
// it would be parsed as a tag
|
|
125
108
|
// eslint-disable-next-line no-useless-escape
|
|
126
109
|
const regex = new RegExp(`<[a-zA-Z][^>]*?(${name}=['"](${escapeRegExp(originalValue)})['"]).*?>`, 'gs');
|
|
127
|
-
|
|
128
110
|
let matchCount = 0;
|
|
129
111
|
html = html.replace(regex, (match, p1) => {
|
|
130
112
|
let result = match;
|
|
@@ -136,8 +118,6 @@ function htmlTransform(html = '', siteUrl, transformFunction, itemPath, _options
|
|
|
136
118
|
});
|
|
137
119
|
});
|
|
138
120
|
}
|
|
139
|
-
|
|
140
121
|
return html;
|
|
141
122
|
}
|
|
142
|
-
|
|
143
123
|
module.exports = htmlTransform;
|
|
File without changes
|
package/lib/utils/index.js
CHANGED
package/lib/utils/is-ssl.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
// require the whatwg compatible URL library (same behaviour in node and browser)
|
|
2
|
-
const {URL} = require('url');
|
|
3
|
-
|
|
4
|
+
const { URL } = require('url');
|
|
4
5
|
function isSSL(urlToParse) {
|
|
5
|
-
const {protocol} = new URL(urlToParse);
|
|
6
|
+
const { protocol } = new URL(urlToParse);
|
|
6
7
|
return protocol === 'https:';
|
|
7
8
|
}
|
|
8
|
-
|
|
9
9
|
module.exports = isSSL;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const absoluteToRelative = require('./absolute-to-relative');
|
|
2
4
|
const lexicalTransform = require('./lexical-transform');
|
|
3
|
-
|
|
4
5
|
function lexicalAbsoluteToRelative(serializedLexical, siteUrl, _options = {}) {
|
|
5
|
-
const defaultOptions = {assetsOnly: false, secure: false, nodes: [], transformMap: {}};
|
|
6
|
-
const overrideOptions = {siteUrl, transformType: 'absoluteToRelative'};
|
|
6
|
+
const defaultOptions = { assetsOnly: false, secure: false, nodes: [], transformMap: {} };
|
|
7
|
+
const overrideOptions = { siteUrl, transformType: 'absoluteToRelative' };
|
|
7
8
|
const options = Object.assign({}, defaultOptions, _options, overrideOptions);
|
|
8
|
-
|
|
9
9
|
const transformFunction = function (_url, _siteUrl, _itemPath, __options) {
|
|
10
10
|
return absoluteToRelative(_url, _siteUrl, __options);
|
|
11
11
|
};
|
|
12
|
-
|
|
13
12
|
return lexicalTransform(serializedLexical, siteUrl, transformFunction, '', options);
|
|
14
13
|
}
|
|
15
|
-
|
|
16
14
|
module.exports = lexicalAbsoluteToRelative;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const absoluteToTransformReady = require('./absolute-to-transform-ready');
|
|
2
4
|
const lexicalTransform = require('./lexical-transform');
|
|
3
|
-
|
|
4
5
|
function lexicalAbsoluteToRelative(serializedLexical, siteUrl, _options = {}) {
|
|
5
|
-
const defaultOptions = {assetsOnly: false, secure: false, nodes: [], transformMap: {}};
|
|
6
|
-
const overrideOptions = {siteUrl, transformType: 'toTransformReady'};
|
|
6
|
+
const defaultOptions = { assetsOnly: false, secure: false, nodes: [], transformMap: {} };
|
|
7
|
+
const overrideOptions = { siteUrl, transformType: 'toTransformReady' };
|
|
7
8
|
const options = Object.assign({}, defaultOptions, _options, overrideOptions);
|
|
8
|
-
|
|
9
9
|
const transformFunction = function (_url, _siteUrl, _itemPath, __options) {
|
|
10
10
|
return absoluteToTransformReady(_url, _siteUrl, __options);
|
|
11
11
|
};
|
|
12
|
-
|
|
13
12
|
return lexicalTransform(serializedLexical, siteUrl, transformFunction, '', options);
|
|
14
13
|
}
|
|
15
|
-
|
|
16
14
|
module.exports = lexicalAbsoluteToRelative;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
1
3
|
const relativeToAbsolute = require('./relative-to-absolute');
|
|
2
4
|
const lexicalTransform = require('./lexical-transform');
|
|
3
|
-
|
|
4
5
|
function lexicalRelativeToAbsolute(serializedLexical, siteUrl, itemPath, _options = {}) {
|
|
5
|
-
const defaultOptions = {assetsOnly: false, secure: false, nodes: [], transformMap: {}};
|
|
6
|
-
const overrideOptions = {siteUrl, itemPath, transformType: 'relativeToAbsolute'};
|
|
6
|
+
const defaultOptions = { assetsOnly: false, secure: false, nodes: [], transformMap: {} };
|
|
7
|
+
const overrideOptions = { siteUrl, itemPath, transformType: 'relativeToAbsolute' };
|
|
7
8
|
const options = Object.assign({}, defaultOptions, _options, overrideOptions);
|
|
8
|
-
|
|
9
9
|
return lexicalTransform(serializedLexical, siteUrl, relativeToAbsolute, itemPath, options);
|
|
10
10
|
}
|
|
11
|
-
|
|
12
11
|
module.exports = lexicalRelativeToAbsolute;
|