@tryghost/url-utils 4.4.14 → 5.0.0-rc.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/lib/UrlUtils.js CHANGED
@@ -2,6 +2,24 @@
2
2
  const _ = require('lodash');
3
3
  const utils = require('./utils');
4
4
 
5
+ const STATIC_IMAGE_URL_PREFIX = 'content/images';
6
+ const STATIC_FILES_URL_PREFIX = 'content/files';
7
+ const STATIC_MEDIA_URL_PREFIX = 'content/media';
8
+
9
+ /**
10
+ * @typedef {Object} AssetBaseUrls
11
+ * @property {string} [image] Absolute base URL for images
12
+ * @property {string} [files] Absolute base URL for files
13
+ * @property {string} [media] Absolute base URL for media
14
+ */
15
+
16
+ function trimTrailingSlash(url) {
17
+ if (!url) {
18
+ return url;
19
+ }
20
+ return url.replace(/\/+$/, '');
21
+ }
22
+
5
23
  // similar to Object.assign but will not override defaults if a source value is undefined
6
24
  function assignOptions(target, ...sources) {
7
25
  const options = sources.map((x) => {
@@ -22,24 +40,49 @@ module.exports = class UrlUtils {
22
40
  * @param {('content' | 'admin')} [options.defaultApiType='content'] default API type to be used
23
41
  * @param {Object} [options.slugs] object with 2 properties reserved and protected containing arrays of special case slugs
24
42
  * @param {Number} [options.redirectCacheMaxAge]
25
- * @param {String} [options.staticImageUrlPrefix='content/images'] static prefix for serving images. Should not be passed in, unless customizing ghost instance image storage
26
- */
43
+ * @param {AssetBaseUrls} [options.assetBaseUrls] asset CDN base URLs
44
+ */
27
45
  constructor(options = {}) {
28
46
  const defaultOptions = {
29
47
  slugs: null,
30
48
  redirectCacheMaxAge: null,
31
49
  baseApiPath: '/ghost/api',
32
- defaultApiType: 'content',
33
- staticImageUrlPrefix: 'content/images'
50
+ defaultApiType: 'content'
34
51
  };
35
52
 
36
53
  this._config = assignOptions({}, defaultOptions, options);
54
+ this._config.staticImageUrlPrefix = STATIC_IMAGE_URL_PREFIX;
55
+ this._config.staticFilesUrlPrefix = STATIC_FILES_URL_PREFIX;
56
+ this._config.staticMediaUrlPrefix = STATIC_MEDIA_URL_PREFIX;
57
+
58
+ const assetBaseUrls = options.assetBaseUrls || {};
59
+ this._assetBaseUrls = {
60
+ image: trimTrailingSlash(assetBaseUrls.image || null),
61
+ files: trimTrailingSlash(assetBaseUrls.files || null),
62
+ media: trimTrailingSlash(assetBaseUrls.media || null)
63
+ };
37
64
 
38
65
  this.getSubdir = options.getSubdir;
39
66
  this.getSiteUrl = options.getSiteUrl;
40
67
  this.getAdminUrl = options.getAdminUrl;
41
68
  }
42
69
 
70
+ _assetOptionDefaults() {
71
+ const siteBase = trimTrailingSlash(this.getSiteUrl ? this.getSiteUrl() : null);
72
+ return {
73
+ staticImageUrlPrefix: this._config.staticImageUrlPrefix,
74
+ staticFilesUrlPrefix: this._config.staticFilesUrlPrefix,
75
+ staticMediaUrlPrefix: this._config.staticMediaUrlPrefix,
76
+ imageBaseUrl: this._assetBaseUrls.image || siteBase,
77
+ filesBaseUrl: this._assetBaseUrls.files || null,
78
+ mediaBaseUrl: this._assetBaseUrls.media || null
79
+ };
80
+ }
81
+
82
+ _buildAssetOptions(additionalDefaults = {}, options) {
83
+ return assignOptions({}, this._assetOptionDefaults(), additionalDefaults, options || {});
84
+ }
85
+
43
86
  getProtectedSlugs() {
44
87
  let subDir = this.getSubdir();
45
88
 
@@ -234,23 +277,28 @@ module.exports = class UrlUtils {
234
277
  options = itemPath;
235
278
  itemPath = null;
236
279
  }
237
- return utils.toTransformReady(url, this.getSiteUrl(), itemPath, options);
280
+ const _options = this._buildAssetOptions({}, options);
281
+ return utils.toTransformReady(url, this.getSiteUrl(), itemPath, _options);
238
282
  }
239
283
 
240
284
  absoluteToTransformReady(url, options) {
241
- return utils.absoluteToTransformReady(url, this.getSiteUrl(), options);
285
+ const _options = this._buildAssetOptions({}, options);
286
+ return utils.absoluteToTransformReady(url, this.getSiteUrl(), _options);
242
287
  }
243
288
 
244
289
  relativeToTransformReady(url, options) {
245
- return utils.relativeToTransformReady(url, this.getSiteUrl(), options);
290
+ const _options = this._buildAssetOptions({}, options);
291
+ return utils.relativeToTransformReady(url, this.getSiteUrl(), _options);
246
292
  }
247
293
 
248
294
  transformReadyToAbsolute(url, options) {
249
- return utils.transformReadyToAbsolute(url, this.getSiteUrl(), options);
295
+ const _options = this._buildAssetOptions({}, options);
296
+ return utils.transformReadyToAbsolute(url, this.getSiteUrl(), _options);
250
297
  }
251
298
 
252
299
  transformReadyToRelative(url, options) {
253
- return utils.transformReadyToRelative(url, this.getSiteUrl(), options);
300
+ const _options = this._buildAssetOptions({}, options);
301
+ return utils.transformReadyToRelative(url, this.getSiteUrl(), _options);
254
302
  }
255
303
 
256
304
  htmlToTransformReady(html, itemPath, options) {
@@ -258,7 +306,8 @@ module.exports = class UrlUtils {
258
306
  options = itemPath;
259
307
  itemPath = null;
260
308
  }
261
- return utils.htmlToTransformReady(html, this.getSiteUrl(), itemPath, options);
309
+ const _options = this._buildAssetOptions({}, options);
310
+ return utils.htmlToTransformReady(html, this.getSiteUrl(), itemPath, _options);
262
311
  }
263
312
 
264
313
  /**
@@ -276,11 +325,9 @@ module.exports = class UrlUtils {
276
325
  options = itemPath;
277
326
  itemPath = null;
278
327
  }
279
- const defaultOptions = {
280
- assetsOnly: false,
281
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
282
- };
283
- const _options = assignOptions({}, defaultOptions, options || {});
328
+ const _options = this._buildAssetOptions({
329
+ assetsOnly: false
330
+ }, options);
284
331
  return utils.htmlRelativeToAbsolute(html, this.getSiteUrl(), itemPath, _options);
285
332
  }
286
333
 
@@ -289,29 +336,23 @@ module.exports = class UrlUtils {
289
336
  options = itemPath;
290
337
  itemPath = null;
291
338
  }
292
- const defaultOptions = {
293
- assetsOnly: false,
294
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
295
- };
296
- const _options = assignOptions({}, defaultOptions, options || {});
339
+ const _options = this._buildAssetOptions({
340
+ assetsOnly: false
341
+ }, options);
297
342
  return utils.htmlRelativeToTransformReady(html, this.getSiteUrl(), itemPath, _options);
298
343
  }
299
344
 
300
345
  htmlAbsoluteToRelative(html, options = {}) {
301
- const defaultOptions = {
302
- assetsOnly: false,
303
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
304
- };
305
- const _options = assignOptions({}, defaultOptions, options);
346
+ const _options = this._buildAssetOptions({
347
+ assetsOnly: false
348
+ }, options);
306
349
  return utils.htmlAbsoluteToRelative(html, this.getSiteUrl(), _options);
307
350
  }
308
351
 
309
352
  htmlAbsoluteToTransformReady(html, options = {}) {
310
- const defaultOptions = {
311
- assetsOnly: false,
312
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
313
- };
314
- const _options = assignOptions({}, defaultOptions, options);
353
+ const _options = this._buildAssetOptions({
354
+ assetsOnly: false
355
+ }, options);
315
356
  return utils.htmlAbsoluteToTransformReady(html, this.getSiteUrl(), _options);
316
357
  }
317
358
 
@@ -320,7 +361,8 @@ module.exports = class UrlUtils {
320
361
  options = itemPath;
321
362
  itemPath = null;
322
363
  }
323
- return utils.markdownToTransformReady(markdown, this.getSiteUrl(), itemPath, options);
364
+ const _options = this._buildAssetOptions({}, options);
365
+ return utils.markdownToTransformReady(markdown, this.getSiteUrl(), itemPath, _options);
324
366
  }
325
367
 
326
368
  markdownRelativeToAbsolute(markdown, itemPath, options) {
@@ -328,11 +370,9 @@ module.exports = class UrlUtils {
328
370
  options = itemPath;
329
371
  itemPath = null;
330
372
  }
331
- const defaultOptions = {
332
- assetsOnly: false,
333
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
334
- };
335
- const _options = assignOptions({}, defaultOptions, options || {});
373
+ const _options = this._buildAssetOptions({
374
+ assetsOnly: false
375
+ }, options);
336
376
  return utils.markdownRelativeToAbsolute(markdown, this.getSiteUrl(), itemPath, _options);
337
377
  }
338
378
 
@@ -341,29 +381,23 @@ module.exports = class UrlUtils {
341
381
  options = itemPath;
342
382
  itemPath = null;
343
383
  }
344
- const defaultOptions = {
345
- assetsOnly: false,
346
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
347
- };
348
- const _options = assignOptions({}, defaultOptions, options || {});
384
+ const _options = this._buildAssetOptions({
385
+ assetsOnly: false
386
+ }, options);
349
387
  return utils.markdownRelativeToTransformReady(markdown, this.getSiteUrl(), itemPath, _options);
350
388
  }
351
389
 
352
390
  markdownAbsoluteToRelative(markdown, options = {}) {
353
- const defaultOptions = {
354
- assetsOnly: false,
355
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
356
- };
357
- const _options = assignOptions({}, defaultOptions, options);
391
+ const _options = this._buildAssetOptions({
392
+ assetsOnly: false
393
+ }, options);
358
394
  return utils.markdownAbsoluteToRelative(markdown, this.getSiteUrl(), _options);
359
395
  }
360
396
 
361
397
  markdownAbsoluteToTransformReady(markdown, options) {
362
- const defaultOptions = {
363
- assetsOnly: false,
364
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
365
- };
366
- const _options = assignOptions({}, defaultOptions, options);
398
+ const _options = this._buildAssetOptions({
399
+ assetsOnly: false
400
+ }, options);
367
401
  return utils.markdownAbsoluteToTransformReady(markdown, this.getSiteUrl(), _options);
368
402
  }
369
403
 
@@ -372,10 +406,9 @@ module.exports = class UrlUtils {
372
406
  options = itemPath;
373
407
  itemPath = null;
374
408
  }
375
- const defaultOptions = {
409
+ const _options = this._buildAssetOptions({
376
410
  cardTransformers: this._config.cardTransformers
377
- };
378
- const _options = assignOptions({}, defaultOptions, options || {});
411
+ }, options);
379
412
  return utils.mobiledocToTransformReady(serializedMobiledoc, this.getSiteUrl(), itemPath, _options);
380
413
  }
381
414
 
@@ -384,12 +417,10 @@ module.exports = class UrlUtils {
384
417
  options = itemPath;
385
418
  itemPath = null;
386
419
  }
387
- const defaultOptions = {
420
+ const _options = this._buildAssetOptions({
388
421
  assetsOnly: false,
389
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
390
422
  cardTransformers: this._config.cardTransformers
391
- };
392
- const _options = assignOptions({}, defaultOptions, options || {});
423
+ }, options);
393
424
  return utils.mobiledocRelativeToAbsolute(serializedMobiledoc, this.getSiteUrl(), itemPath, _options);
394
425
  }
395
426
 
@@ -398,32 +429,26 @@ module.exports = class UrlUtils {
398
429
  options = itemPath;
399
430
  itemPath = null;
400
431
  }
401
- const defaultOptions = {
432
+ const _options = this._buildAssetOptions({
402
433
  assetsOnly: false,
403
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
404
434
  cardTransformers: this._config.cardTransformers
405
- };
406
- const _options = assignOptions({}, defaultOptions, options || {});
435
+ }, options);
407
436
  return utils.mobiledocRelativeToTransformReady(serializedMobiledoc, this.getSiteUrl(), itemPath, _options);
408
437
  }
409
438
 
410
439
  mobiledocAbsoluteToRelative(serializedMobiledoc, options = {}) {
411
- const defaultOptions = {
440
+ const _options = this._buildAssetOptions({
412
441
  assetsOnly: false,
413
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
414
442
  cardTransformers: this._config.cardTransformers
415
- };
416
- const _options = assignOptions({}, defaultOptions, options);
443
+ }, options);
417
444
  return utils.mobiledocAbsoluteToRelative(serializedMobiledoc, this.getSiteUrl(), _options);
418
445
  }
419
446
 
420
447
  mobiledocAbsoluteToTransformReady(serializedMobiledoc, options = {}) {
421
- const defaultOptions = {
448
+ const _options = this._buildAssetOptions({
422
449
  assetsOnly: false,
423
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
424
450
  cardTransformers: this._config.cardTransformers
425
- };
426
- const _options = assignOptions({}, defaultOptions, options);
451
+ }, options);
427
452
  return utils.mobiledocAbsoluteToTransformReady(serializedMobiledoc, this.getSiteUrl(), _options);
428
453
  }
429
454
 
@@ -432,10 +457,9 @@ module.exports = class UrlUtils {
432
457
  options = itemPath;
433
458
  itemPath = null;
434
459
  }
435
- const defaultOptions = {
460
+ const _options = this._buildAssetOptions({
436
461
  cardTransformers: this._config.cardTransformers
437
- };
438
- const _options = assignOptions({}, defaultOptions, options || {});
462
+ }, options);
439
463
  return utils.lexicalToTransformReady(serializedLexical, this.getSiteUrl(), itemPath, _options);
440
464
  }
441
465
 
@@ -444,12 +468,10 @@ module.exports = class UrlUtils {
444
468
  options = itemPath;
445
469
  itemPath = null;
446
470
  }
447
- const defaultOptions = {
471
+ const _options = this._buildAssetOptions({
448
472
  assetsOnly: false,
449
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
450
473
  cardTransformers: this._config.cardTransformers
451
- };
452
- const _options = assignOptions({}, defaultOptions, options || {});
474
+ }, options);
453
475
  return utils.lexicalRelativeToAbsolute(serializedLexical, this.getSiteUrl(), itemPath, _options);
454
476
  }
455
477
 
@@ -458,40 +480,31 @@ module.exports = class UrlUtils {
458
480
  options = itemPath;
459
481
  itemPath = null;
460
482
  }
461
- const defaultOptions = {
483
+ const _options = this._buildAssetOptions({
462
484
  assetsOnly: false,
463
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
464
485
  cardTransformers: this._config.cardTransformers
465
- };
466
- const _options = assignOptions({}, defaultOptions, options || {});
486
+ }, options);
467
487
  return utils.lexicalRelativeToTransformReady(serializedLexical, this.getSiteUrl(), itemPath, _options);
468
488
  }
469
489
 
470
490
  lexicalAbsoluteToRelative(serializedLexical, options = {}) {
471
- const defaultOptions = {
491
+ const _options = this._buildAssetOptions({
472
492
  assetsOnly: false,
473
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
474
493
  cardTransformers: this._config.cardTransformers
475
- };
476
- const _options = assignOptions({}, defaultOptions, options);
494
+ }, options);
477
495
  return utils.lexicalAbsoluteToRelative(serializedLexical, this.getSiteUrl(), _options);
478
496
  }
479
497
 
480
498
  lexicalAbsoluteToTransformReady(serializedLexical, options = {}) {
481
- const defaultOptions = {
499
+ const _options = this._buildAssetOptions({
482
500
  assetsOnly: false,
483
- staticImageUrlPrefix: this._config.staticImageUrlPrefix,
484
501
  cardTransformers: this._config.cardTransformers
485
- };
486
- const _options = assignOptions({}, defaultOptions, options);
502
+ }, options);
487
503
  return utils.lexicalAbsoluteToTransformReady(serializedLexical, this.getSiteUrl(), _options);
488
504
  }
489
505
 
490
506
  plaintextToTransformReady(plaintext, options = {}) {
491
- const defaultOptions = {
492
- staticImageUrlPrefix: this._config.staticImageUrlPrefix
493
- };
494
- const _options = assignOptions({}, defaultOptions, options);
507
+ const _options = this._buildAssetOptions({}, options);
495
508
  return utils.plaintextToTransformReady(plaintext, this.getSiteUrl(), _options);
496
509
  }
497
510
 
@@ -534,7 +547,15 @@ module.exports = class UrlUtils {
534
547
  * my-content/another-dir/images/2017/01/02/author.png
535
548
  */
536
549
  get STATIC_IMAGE_URL_PREFIX() {
537
- return this._config.staticImageUrlPrefix;
550
+ return STATIC_IMAGE_URL_PREFIX;
551
+ }
552
+
553
+ get STATIC_FILES_URL_PREFIX() {
554
+ return STATIC_FILES_URL_PREFIX;
555
+ }
556
+
557
+ get STATIC_MEDIA_URL_PREFIX() {
558
+ return STATIC_MEDIA_URL_PREFIX;
538
559
  }
539
560
 
540
561
  // expose underlying functions to ease testing
@@ -1,23 +1,101 @@
1
+ const {URL} = require('url');
1
2
  const absoluteToRelative = require('./absolute-to-relative');
2
3
 
3
- const absoluteToTransformReady = function (url, root, _options) {
4
+ function normalizeBaseUrl(baseUrl) {
5
+ if (!baseUrl) {
6
+ return null;
7
+ }
8
+
9
+ try {
10
+ const parsed = new URL(baseUrl);
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;
22
+ }
23
+ }
24
+
25
+ function matchCdnBase(parsedUrl, options) {
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}`;
62
+ }
63
+
64
+ return null;
65
+ }
66
+
67
+ const absoluteToTransformReady = function (url, root, _options = {}) {
4
68
  const defaultOptions = {
5
69
  replacementStr: '__GHOST_URL__',
6
- withoutSubdirectory: true
70
+ withoutSubdirectory: true,
71
+ staticImageUrlPrefix: 'content/images',
72
+ staticFilesUrlPrefix: 'content/files',
73
+ staticMediaUrlPrefix: 'content/media',
74
+ imageBaseUrl: null,
75
+ filesBaseUrl: null,
76
+ mediaBaseUrl: null
7
77
  };
8
78
  const options = Object.assign({}, defaultOptions, _options);
9
79
 
10
- // return relative urls as-is
80
+ let parsedInput;
11
81
  try {
12
- const parsedURL = new URL(url, 'http://relative');
13
- if (parsedURL.origin === 'http://relative') {
14
- return url;
15
- }
82
+ parsedInput = new URL(url, 'http://relative');
16
83
  } catch (e) {
17
84
  // url was unparseable
18
85
  return url;
19
86
  }
20
87
 
88
+ if (parsedInput.origin !== 'http://relative') {
89
+ const cdnMatch = matchCdnBase(parsedInput, options);
90
+ if (cdnMatch) {
91
+ return `${options.replacementStr}${cdnMatch}`;
92
+ }
93
+ }
94
+
95
+ if (parsedInput.origin === 'http://relative') {
96
+ return url;
97
+ }
98
+
21
99
  // convert to relative with stripped subdir
22
100
  // always returns root-relative starting with forward slash
23
101
  const relativeUrl = absoluteToRelative(url, root, options);
@@ -2,9 +2,22 @@ function escapeRegExp(string) {
2
2
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
3
3
  }
4
4
 
5
+ function trimTrailingSlash(url) {
6
+ if (!url) {
7
+ return url;
8
+ }
9
+ return url.replace(/\/+$/, '');
10
+ }
11
+
5
12
  const transformReadyToAbsolute = function (str = '', root, _options = {}) {
6
13
  const defaultOptions = {
7
- replacementStr: '__GHOST_URL__'
14
+ replacementStr: '__GHOST_URL__',
15
+ staticImageUrlPrefix: 'content/images',
16
+ staticFilesUrlPrefix: 'content/files',
17
+ staticMediaUrlPrefix: 'content/media',
18
+ imageBaseUrl: null,
19
+ filesBaseUrl: null,
20
+ mediaBaseUrl: null
8
21
  };
9
22
  const options = Object.assign({}, defaultOptions, _options);
10
23
 
@@ -13,8 +26,28 @@ const transformReadyToAbsolute = function (str = '', root, _options = {}) {
13
26
  }
14
27
 
15
28
  const replacementRegex = new RegExp(escapeRegExp(options.replacementStr), 'g');
29
+ const fallbackBase = trimTrailingSlash(options.imageBaseUrl || root);
30
+ const mediaBase = trimTrailingSlash(options.mediaBaseUrl);
31
+ const filesBase = trimTrailingSlash(options.filesBaseUrl);
32
+ const imageBase = trimTrailingSlash(options.imageBaseUrl) || fallbackBase;
33
+
34
+ return str.replace(replacementRegex, (match, offset) => {
35
+ const remainder = str.slice(offset + match.length);
36
+
37
+ if (options.staticMediaUrlPrefix && remainder.startsWith(`/${options.staticMediaUrlPrefix}`) && mediaBase) {
38
+ return mediaBase;
39
+ }
40
+
41
+ if (options.staticFilesUrlPrefix && remainder.startsWith(`/${options.staticFilesUrlPrefix}`) && filesBase) {
42
+ return filesBase;
43
+ }
44
+
45
+ if (options.staticImageUrlPrefix && remainder.startsWith(`/${options.staticImageUrlPrefix}`) && imageBase) {
46
+ return imageBase;
47
+ }
16
48
 
17
- return str.replace(replacementRegex, root.replace(/\/$/, ''));
49
+ return fallbackBase;
50
+ });
18
51
  };
19
52
 
20
53
  module.exports = transformReadyToAbsolute;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryghost/url-utils",
3
- "version": "4.4.14",
3
+ "version": "5.0.0-rc.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/TryGhost/SDK.git",
@@ -25,8 +25,8 @@
25
25
  "devDependencies": {
26
26
  "@tryghost/config-url-helpers": "^1.0.17",
27
27
  "c8": "10.1.3",
28
- "mocha": "11.2.2",
29
- "rewire": "8.0.0",
28
+ "mocha": "11.7.4",
29
+ "rewire": "9.0.1",
30
30
  "should": "13.2.3",
31
31
  "sinon": "21.0.0"
32
32
  },
@@ -38,6 +38,5 @@
38
38
  "remark": "^11.0.2",
39
39
  "remark-footnotes": "^1.0.0",
40
40
  "unist-util-visit": "^2.0.0"
41
- },
42
- "gitHead": "b10773947244536b8829fec0540819990c901987"
41
+ }
43
42
  }