express-hbs 2.4.2 → 3.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/lib/hbs.js CHANGED
@@ -10,12 +10,12 @@ var _ = require('lodash');
10
10
  /**
11
11
  * Regex pattern for layout directive. {{!< layout }}
12
12
  */
13
- var layoutPattern = /{{!<\s+([A-Za-z0-9\._\-\/]+)\s*}}/;
13
+ var layoutPattern = /{{!<\s+([A-Za-z0-9._\-/]+)\s*}}/;
14
14
 
15
15
  /**
16
16
  * Constructor
17
17
  */
18
- var ExpressHbs = function() {
18
+ var ExpressHbs = function () {
19
19
  this.handlebars = handlebars.create();
20
20
  this.SafeString = this.handlebars.SafeString;
21
21
  this.Utils = this.handlebars.Utils;
@@ -33,7 +33,7 @@ var ExpressHbs = function() {
33
33
  * <link rel="stylesheet" href='{{{URL "css/style.css"}}}' />
34
34
  * {{/contentFor}}
35
35
  */
36
- ExpressHbs.prototype.content = function(name, options, context) {
36
+ ExpressHbs.prototype.content = function (name, options, context) {
37
37
  var block = options.data.root.blockCache[name] || (options.data.root.blockCache[name] = []);
38
38
  block.push(options.fn(context));
39
39
  };
@@ -46,9 +46,8 @@ ExpressHbs.prototype.content = function(name, options, context) {
46
46
  * @param {String} filename Path to template file.
47
47
  * @param {String} layout Layout path.
48
48
  */
49
- ExpressHbs.prototype.layoutPath = function(filename, layout) {
50
- var dirs,
51
- layoutPath;
49
+ ExpressHbs.prototype.layoutPath = function (filename, layout) {
50
+ var dirs, layoutPath;
52
51
  if (layout[0] === '.') {
53
52
  dirs = path.dirname(filename);
54
53
  } else if (this.layoutsDir) {
@@ -71,7 +70,7 @@ ExpressHbs.prototype.layoutPath = function(filename, layout) {
71
70
  * @param {String} filename Path to template
72
71
  * @returns {String|undefined} Returns the path to layout.
73
72
  */
74
- ExpressHbs.prototype.declaredLayoutFile = function(str, filename) {
73
+ ExpressHbs.prototype.declaredLayoutFile = function (str, filename) {
75
74
  var matches = str.match(layoutPattern);
76
75
  if (matches) {
77
76
  var layout = matches[1];
@@ -96,9 +95,18 @@ ExpressHbs.prototype.declaredLayoutFile = function(str, filename) {
96
95
  * @param {Boolean} useCache Cache the compiled layout?
97
96
  * @param {Function} cb Callback called with layouts stack
98
97
  */
99
- ExpressHbs.prototype.cacheLayout = function(layoutFile, useCache, cb) {
98
+ ExpressHbs.prototype.cacheLayout = function (layoutFile, useCache, cb) {
100
99
  var self = this;
101
100
 
101
+ if (this.restrictLayoutsTo) {
102
+ if (!layoutFile.startsWith(this.restrictLayoutsTo)) {
103
+ var err = new Error(
104
+ 'Cannot read ' + layoutFile + ' it does not reside in ' + this.restrictLayoutsTo,
105
+ );
106
+ return cb(err, null);
107
+ }
108
+ }
109
+
102
110
  // assume hbs extension
103
111
  if (path.extname(layoutFile) === '') layoutFile += this._options.extname;
104
112
 
@@ -106,14 +114,14 @@ ExpressHbs.prototype.cacheLayout = function(layoutFile, useCache, cb) {
106
114
  var layoutTemplates = this.cache[layoutFile];
107
115
  if (layoutTemplates) return cb(null, layoutTemplates);
108
116
 
109
- fs.readFile(layoutFile, 'utf8', function(err, str) {
117
+ fs.readFile(layoutFile, 'utf8', function (err, str) {
110
118
  if (err) return cb(err);
111
119
 
112
120
  // File path of eventual declared parent layout
113
121
  var parentLayoutFile = self.declaredLayoutFile(str, layoutFile);
114
122
 
115
123
  // This function returns the current layout stack to the caller
116
- var _returnLayouts = function(layouts) {
124
+ var _returnLayouts = function (layouts) {
117
125
  var currentLayout;
118
126
  layouts = layouts.slice(0);
119
127
  currentLayout = self.compile(str, layoutFile);
@@ -126,7 +134,7 @@ ExpressHbs.prototype.cacheLayout = function(layoutFile, useCache, cb) {
126
134
 
127
135
  if (parentLayoutFile) {
128
136
  // Recursively compile/cache parent layouts
129
- self.cacheLayout(parentLayoutFile, useCache, function(err, parentLayouts) {
137
+ self.cacheLayout(parentLayoutFile, useCache, function (err, parentLayouts) {
130
138
  if (err) return cb(err);
131
139
  _returnLayouts(parentLayouts);
132
140
  });
@@ -140,7 +148,7 @@ ExpressHbs.prototype.cacheLayout = function(layoutFile, useCache, cb) {
140
148
  /**
141
149
  * Cache partial templates found under directories configure in partialsDir.
142
150
  */
143
- ExpressHbs.prototype.cachePartials = function(cb) {
151
+ ExpressHbs.prototype.cachePartials = function (cb) {
144
152
  var self = this;
145
153
 
146
154
  if (!(this.partialsDir instanceof Array)) {
@@ -151,36 +159,36 @@ ExpressHbs.prototype.cachePartials = function(cb) {
151
159
  var count = 0;
152
160
 
153
161
  function readNext() {
154
- readdirp(self.partialsDir[count], {fileFilter: '*' + self._options.extname})
155
- .on('warn', function(err) {
156
- console.warn('Non-fatal error in express-hbs cachePartials.', err);
157
- })
158
- .on('error', function(err) {
159
- console.error('Fatal error in express-hbs cachePartials', err);
160
- return cb(err);
161
- })
162
- .on('data', function(entry) {
163
- if (!entry) return;
164
- var source = fs.readFileSync(entry.fullPath, 'utf8');
165
- var dirname = path.dirname(entry.path);
166
- dirname = dirname === '.' ? '' : dirname + '/';
167
-
168
- var name = dirname + path.basename(entry.basename, self._options.extname);
169
- // fix the path in windows
170
- name = name.split('\\').join('/');
171
- self.registerPartial(name, source, entry.fullPath);
172
- })
173
- .on('end', function() {
174
- count += 1;
175
-
176
- // If all directories aren't read, read the next directory
177
- if (count < self.partialsDir.length) {
178
- readNext();
179
- } else {
180
- self.isPartialCachingComplete = true;
181
- if (cb) cb(null, true);
182
- }
183
- });
162
+ readdirp(self.partialsDir[count], { fileFilter: '*' + self._options.extname })
163
+ .on('warn', function (err) {
164
+ console.warn('Non-fatal error in express-hbs cachePartials.', err);
165
+ })
166
+ .on('error', function (err) {
167
+ console.error('Fatal error in express-hbs cachePartials', err);
168
+ return cb(err);
169
+ })
170
+ .on('data', function (entry) {
171
+ if (!entry) return;
172
+ var source = fs.readFileSync(entry.fullPath, 'utf8');
173
+ var dirname = path.dirname(entry.path);
174
+ dirname = dirname === '.' ? '' : dirname + '/';
175
+
176
+ var name = dirname + path.basename(entry.basename, self._options.extname);
177
+ // fix the path in windows
178
+ name = name.split('\\').join('/');
179
+ self.registerPartial(name, source, entry.fullPath);
180
+ })
181
+ .on('end', function () {
182
+ count += 1;
183
+
184
+ // If all directories aren't read, read the next directory
185
+ if (count < self.partialsDir.length) {
186
+ readNext();
187
+ } else {
188
+ self.isPartialCachingComplete = true;
189
+ if (cb) cb(null, true);
190
+ }
191
+ });
184
192
  }
185
193
 
186
194
  readNext();
@@ -203,7 +211,7 @@ ExpressHbs.prototype.cachePartials = function(cb) {
203
211
  * }
204
212
  * }
205
213
  */
206
- ExpressHbs.prototype.express3 = function(options) {
214
+ ExpressHbs.prototype.express3 = function (options) {
207
215
  var self = this;
208
216
 
209
217
  // Set defaults
@@ -220,31 +228,31 @@ ExpressHbs.prototype.express3 = function(options) {
220
228
 
221
229
  if (options.i18n) {
222
230
  var i18n = options.i18n;
223
- this.handlebars.registerHelper('__', function() {
231
+ this.handlebars.registerHelper('__', function () {
224
232
  var args = Array.prototype.slice.call(arguments);
225
233
  var options = args.pop();
226
234
  return i18n.__.apply(options.data.root, args);
227
235
  });
228
- this.handlebars.registerHelper('__n', function() {
236
+ this.handlebars.registerHelper('__n', function () {
229
237
  var args = Array.prototype.slice.call(arguments);
230
238
  var options = args.pop();
231
239
  return i18n.__n.apply(options.data.root, args);
232
240
  });
233
241
  }
234
242
 
235
- this.handlebars.registerHelper(this._options.blockHelperName, function(name, options) {
243
+ this.handlebars.registerHelper(this._options.blockHelperName, function (name, options) {
236
244
  var val = options.data.root.blockCache[name];
237
245
  if (val === undefined && typeof options.fn === 'function') {
238
246
  val = options.fn(this);
239
247
  }
240
248
  if (Array.isArray(val)) {
241
- val = val.join('\n');
249
+ val = val.join('\n');
242
250
  }
243
251
  return val;
244
252
  });
245
253
 
246
254
  // Pass 'this' as context of helper function to don't lose context call of helpers.
247
- this.handlebars.registerHelper(this._options.contentHelperName, function(name, options) {
255
+ this.handlebars.registerHelper(this._options.contentHelperName, function (name, options) {
248
256
  return self.content(name, options, this);
249
257
  });
250
258
 
@@ -254,6 +262,8 @@ ExpressHbs.prototype.express3 = function(options) {
254
262
  // Absolute path to the layouts directory
255
263
  this.layoutsDir = this._options.layoutsDir;
256
264
 
265
+ this.restrictLayoutsTo = this._options.restrictLayoutsTo;
266
+
257
267
  // express passes this through ___express func, gulp pass in an option
258
268
  this.viewsDir = null;
259
269
  this.viewsDirOpt = this._options.viewsDir;
@@ -291,12 +301,12 @@ ExpressHbs.prototype.express4 = ExpressHbs.prototype.express3;
291
301
  *
292
302
  * @param {Boolean} useCache Whether to cache.
293
303
  */
294
- ExpressHbs.prototype.loadDefaultLayout = function(useCache, cb) {
304
+ ExpressHbs.prototype.loadDefaultLayout = function (useCache, cb) {
295
305
  var self = this;
296
306
  if (!this._options.defaultLayout) return cb();
297
307
  if (useCache && this.defaultLayoutTemplates) return cb(null, this.defaultLayoutTemplates);
298
308
 
299
- this.cacheLayout(this._options.defaultLayout, useCache, function(err, templates) {
309
+ this.cacheLayout(this._options.defaultLayout, useCache, function (err, templates) {
300
310
  if (err) return cb(err);
301
311
  self.defaultLayoutTemplates = templates.slice(0);
302
312
  return cb(null, templates);
@@ -306,7 +316,7 @@ ExpressHbs.prototype.loadDefaultLayout = function(useCache, cb) {
306
316
  /**
307
317
  * Expose useful methods.
308
318
  */
309
- ExpressHbs.prototype.registerHelper = function(name, fn) {
319
+ ExpressHbs.prototype.registerHelper = function (name, fn) {
310
320
  this.handlebars.registerHelper(name, fn);
311
321
  };
312
322
 
@@ -316,7 +326,7 @@ ExpressHbs.prototype.registerHelper = function(name, fn) {
316
326
  * @param {String} name The name of the partial as used in a template.
317
327
  * @param {String} source String source of the partial.
318
328
  */
319
- ExpressHbs.prototype.registerPartial = function(name, source, filename) {
329
+ ExpressHbs.prototype.registerPartial = function (name, source, filename) {
320
330
  this.handlebars.registerPartial(name, this.compile(source, filename));
321
331
  };
322
332
 
@@ -326,7 +336,7 @@ ExpressHbs.prototype.registerPartial = function(name, source, filename) {
326
336
  * @param {String} source The source to compile.
327
337
  * @param {String} filename The path used to embed into __filename for errors.
328
338
  */
329
- ExpressHbs.prototype.compile = function(source, filename) {
339
+ ExpressHbs.prototype.compile = function (source, filename) {
330
340
  // Handlebars has a bug with comment only partial causes errors. This must
331
341
  // be a string so the block below can add a space.
332
342
  if (typeof source !== 'string') {
@@ -359,53 +369,46 @@ ExpressHbs.prototype.compile = function(source, filename) {
359
369
  * @param {String} name The name of the partial as used in a template.
360
370
  * @param {String} fn The `function(options, cb)`
361
371
  */
362
- ExpressHbs.prototype.registerAsyncHelper = function(name, fn) {
363
- this.handlebars.registerHelper(name, function(context, options) {
364
- var resolverCache = this.resolverCache ||
372
+ ExpressHbs.prototype.registerAsyncHelper = function (name, fn) {
373
+ this.handlebars.registerHelper(name, function (context, options) {
374
+ var resolverCache =
375
+ this.resolverCache ||
365
376
  _.get(context, 'data.root.resolverCache') ||
366
377
  _.get(options, 'data.root.resolverCache');
367
378
  if (!resolverCache) {
368
379
  throw new Error('Could not find resolver cache in async helper ' + name + '.');
369
380
  }
370
381
  if (options && fn.length > 2) {
371
- var resolveFunc = function(arr, cb) {
382
+ var resolveFunc = function (arr, cb) {
372
383
  return fn.call(this, arr[0], arr[1], cb);
373
384
  };
374
385
 
375
- return resolver.resolve(
376
- resolverCache,
377
- resolveFunc.bind(this),
378
- [context, options]
379
- );
386
+ return resolver.resolve(resolverCache, resolveFunc.bind(this), [context, options]);
380
387
  }
381
- return resolver.resolve(
382
- resolverCache,
383
- fn.bind(this),
384
- context
385
- );
388
+ return resolver.resolve(resolverCache, fn.bind(this), context);
386
389
  });
387
390
  };
388
391
 
389
- ExpressHbs.prototype.getTemplateOptions = function() {
392
+ ExpressHbs.prototype.getTemplateOptions = function () {
390
393
  return this._options.templateOptions;
391
394
  };
392
395
 
393
- ExpressHbs.prototype.updateTemplateOptions = function(templateOptions) {
396
+ ExpressHbs.prototype.updateTemplateOptions = function (templateOptions) {
394
397
  this._options.templateOptions = templateOptions;
395
398
  };
396
399
 
397
- ExpressHbs.prototype.getLocalTemplateOptions = function(locals) {
400
+ ExpressHbs.prototype.getLocalTemplateOptions = function (locals) {
398
401
  return locals._templateOptions || {};
399
402
  };
400
403
 
401
- ExpressHbs.prototype.updateLocalTemplateOptions = function(locals, localTemplateOptions) {
402
- return locals._templateOptions = localTemplateOptions;
404
+ ExpressHbs.prototype.updateLocalTemplateOptions = function (locals, localTemplateOptions) {
405
+ return (locals._templateOptions = localTemplateOptions);
403
406
  };
404
407
 
405
408
  /**
406
409
  * Creates a new instance of ExpressHbs.
407
410
  */
408
- ExpressHbs.prototype.create = function() {
411
+ ExpressHbs.prototype.create = function () {
409
412
  return new ExpressHbs();
410
413
  };
411
414
 
@@ -499,7 +502,6 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
499
502
  cb(null, res);
500
503
  }
501
504
 
502
-
503
505
  /**
504
506
  * Renders `template` with an optional set of nested `layoutTemplates` using
505
507
  * data in `locals`.
@@ -511,7 +513,7 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
511
513
  // being passed the rendered string of the previous ones as `body`
512
514
  var i = layoutTemplates.length - 1;
513
515
 
514
- var _stackRenderer = function(err, htmlStr) {
516
+ var _stackRenderer = function (err, htmlStr) {
515
517
  if (err) return cb(err);
516
518
 
517
519
  if (i >= 0) {
@@ -526,7 +528,6 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
526
528
  renderTemplate(template, locals, _stackRenderer);
527
529
  }
528
530
 
529
-
530
531
  /**
531
532
  * Lazy loads js-beautify, which should not be used in production env.
532
533
  */
@@ -552,14 +553,14 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
552
553
  }
553
554
  }
554
555
 
555
- fs.readFile(filename, 'utf8', function(err, source) {
556
+ fs.readFile(filename, 'utf8', function (err, source) {
556
557
  if (err) return cb(err);
557
558
 
558
559
  var template = self.compile(source, filename);
559
560
  if (options.cache) {
560
561
  self.cache[filename] = {
561
562
  source: source,
562
- template: template
563
+ template: template,
563
564
  };
564
565
  }
565
566
  return cb(null, source, template);
@@ -570,16 +571,16 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
570
571
  * Compiles a file into a template and a layoutTemplate, then renders it above.
571
572
  */
572
573
  function compileFile(locals, cb) {
573
- getSourceTemplate(function(err, source, template) {
574
+ getSourceTemplate(function (err, source, template) {
574
575
  if (err) return cb(err);
575
576
 
576
577
  // Try to get the layout
577
- parseLayout(source, filename, function(err, layoutTemplates) {
578
+ parseLayout(source, filename, function (err, layoutTemplates) {
578
579
  if (err) return cb(err);
579
580
 
580
581
  function renderIt(layoutTemplates) {
581
582
  if (self._options.beautify) {
582
- return render(template, locals, layoutTemplates, function(err, html) {
583
+ return render(template, locals, layoutTemplates, function (err, html) {
583
584
  if (err) return cb(err);
584
585
  loadBeautify();
585
586
  return cb(null, self.beautify(html, self.beautifyrc));
@@ -599,7 +600,7 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
599
600
  } else if (typeof options.layout !== 'undefined' && options.layout) {
600
601
  // 2. Layout specified by options from render
601
602
  var layoutFile = self.layoutPath(filename, options.layout);
602
- self.cacheLayout(layoutFile, options.cache, function(err, layoutTemplates) {
603
+ self.cacheLayout(layoutFile, options.cache, function (err, layoutTemplates) {
603
604
  if (err) return cb(err);
604
605
  renderIt(layoutTemplates);
605
606
  });
@@ -616,11 +617,11 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
616
617
 
617
618
  function replaceValue(values, text) {
618
619
  if (typeof text === 'string') {
619
- Object.keys(values).forEach(function(id) {
620
- text = text.replace(id, function() {
620
+ Object.keys(values).forEach(function (id) {
621
+ text = text.replace(id, function () {
621
622
  return values[id];
622
623
  });
623
- text = text.replace(self.Utils.escapeExpression(id), function() {
624
+ text = text.replace(self.Utils.escapeExpression(id), function () {
624
625
  return self.Utils.escapeExpression(values[id]);
625
626
  });
626
627
  });
@@ -631,9 +632,9 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
631
632
  // Handles waiting for async helpers
632
633
  function handleAsync(err, res) {
633
634
  if (err) return cb(err);
634
- resolver.done(options.resolverCache, function(err, values) {
635
+ resolver.done(options.resolverCache, function (err, values) {
635
636
  if (err) return cb(err);
636
- Object.keys(values).forEach(function(key) {
637
+ Object.keys(values).forEach(function (key) {
637
638
  values[key] = replaceValue(values, values[key]);
638
639
  });
639
640
  res = replaceValue(values, res);
@@ -645,13 +646,13 @@ ExpressHbs.prototype.___express = function ___express(filename, source, options,
645
646
  }
646
647
 
647
648
  // kick it off by loading default template (if any)
648
- this.loadDefaultLayout(options.cache, function(err) {
649
+ this.loadDefaultLayout(options.cache, function (err) {
649
650
  if (err) return cb(err);
650
651
 
651
652
  // Force reloading of all partials if caching is not used. Inefficient but there
652
653
  // is no loading partial event.
653
654
  if (self.partialsDir && (!options.cache || !self.isPartialCachingComplete)) {
654
- return self.cachePartials(function(err) {
655
+ return self.cachePartials(function (err) {
655
656
  if (err) return cb(err);
656
657
  return compileFile(options, handleAsync);
657
658
  });
package/lib/resolver.js CHANGED
@@ -14,9 +14,9 @@ var ID_SUFFIX = '__';
14
14
 
15
15
  function resolve(cache, fn, context) {
16
16
  var id = ID_PREFIX + ID_ESCAPED_STRING + generateId(ID_LENGTH) + ID_SUFFIX;
17
- cache[id] = new Promise(function(passed, failed) {
17
+ cache[id] = new Promise(function (passed, failed) {
18
18
  try {
19
- fn(context, function(res) {
19
+ fn(context, function (res) {
20
20
  passed(res);
21
21
  });
22
22
  } catch (error) {
@@ -29,23 +29,24 @@ function resolve(cache, fn, context) {
29
29
  // cache is an object where the keys are cache keys and values are promises. See above.
30
30
  function done(cache, callback) {
31
31
  return Promise.all(Object.values(cache))
32
- .then(function(values) {
32
+ .then(function (values) {
33
33
  var resolvedCache = {};
34
34
  var keys = Object.keys(cache);
35
- values.forEach(function(value, index) {
35
+ values.forEach(function (value, index) {
36
36
  resolvedCache[keys[index]] = value;
37
37
  });
38
38
  callback(null, resolvedCache);
39
- }).catch(function(error) {
40
- callback(error);
41
- });
39
+ })
40
+ .catch(function (error) {
41
+ callback(error);
42
+ });
42
43
  }
43
44
 
44
45
  function hasResolvers(text) {
45
46
  // NOTE: We specifically search the text for the ID_PREFIX **NOT** including the escapable character
46
47
  // This is because that character can be escaped in the text, and lead us to not finding unresolved
47
48
  // async helper outputs.
48
- if (text.search(ID_PREFIX) > 0) {
49
+ if (text.search(ID_PREFIX) >= 0) {
49
50
  return true;
50
51
  }
51
52
  return false;
@@ -54,5 +55,5 @@ function hasResolvers(text) {
54
55
  module.exports = {
55
56
  done: done,
56
57
  hasResolvers: hasResolvers,
57
- resolve: resolve
58
+ resolve: resolve,
58
59
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-hbs",
3
- "version": "2.4.2",
3
+ "version": "3.0.0",
4
4
  "description": "Express handlebars template engine complete with multiple layouts, partials and blocks.",
5
5
  "keywords": [
6
6
  "express4",
@@ -10,17 +10,12 @@
10
10
  "partials"
11
11
  ],
12
12
  "main": "index.js",
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
13
16
  "directories": {
14
17
  "example": "example"
15
18
  },
16
- "scripts": {
17
- "lint": "eslint --ext .js --cache lib/**",
18
- "test": "mocha",
19
- "posttest": "yarn lint",
20
- "coverage": "nyc yarn test",
21
- "preship": "yarn test",
22
- "ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn publish && git push --follow-tags; fi"
23
- },
24
19
  "repository": {
25
20
  "type": "git",
26
21
  "url": "https://github.com/TryGhost/express-hbs"
@@ -29,21 +24,33 @@
29
24
  "author": "Mario Gutierrez <mario@barc.com>",
30
25
  "license": "MIT",
31
26
  "devDependencies": {
32
- "cookie-parser": "1.4.6",
33
- "eslint": "8.48.0",
34
- "express": "4.18.2",
35
- "i18n": "0.15.1",
36
- "mocha": "10.2.0",
37
- "nyc": "15.1.0",
38
- "rewire": "7.0.0",
39
- "supertest": "6.3.3"
27
+ "cookie-parser": "1.4.7",
28
+ "express": "5.2.1",
29
+ "i18n": "0.15.3",
30
+ "mocha": "11.7.6",
31
+ "nyc": "18.0.0",
32
+ "oxfmt": "0.57.0",
33
+ "oxlint": "1.72.0",
34
+ "rewire": "9.0.1",
35
+ "supertest": "7.2.2"
40
36
  },
41
37
  "dependencies": {
42
- "handlebars": "^4.7.7",
43
- "lodash": "^4.17.21",
44
- "readdirp": "^3.6.0"
38
+ "@tryghost/pro-ship": "1.1.5",
39
+ "handlebars": "4.7.9",
40
+ "lodash": "4.18.1",
41
+ "readdirp": "3.6.0"
45
42
  },
46
43
  "optionalDependencies": {
47
- "js-beautify": "^1.13.11"
44
+ "js-beautify": "^2.0.0"
45
+ },
46
+ "scripts": {
47
+ "lint": "oxlint --quiet && oxfmt --check .",
48
+ "lint:fix": "oxlint --fix && oxfmt .",
49
+ "format": "oxfmt .",
50
+ "test": "mocha",
51
+ "posttest": "pnpm lint",
52
+ "coverage": "nyc --check-coverage mocha",
53
+ "preship": "pnpm test",
54
+ "ship": "pro-ship"
48
55
  }
49
- }
56
+ }
package/renovate.json CHANGED
@@ -1,6 +1,13 @@
1
1
  {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
2
3
  "extends": [
3
- "@tryghost:quietJS",
4
- "@tryghost:automergeDevDependencies"
4
+ "local>TryGhost/renovate-config"
5
+ ],
6
+ "packageRules": [
7
+ {
8
+ "description": "Keep pnpm on 10.x while this repo supports Node 20; pnpm 11 requires Node 22.13 or newer.",
9
+ "matchPackageNames": ["pnpm"],
10
+ "allowedVersions": "<11"
11
+ }
5
12
  ]
6
13
  }