hamlet-plugin-template 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -47
- package/index.js +17 -25
- package/lib/partials.js +5 -0
- package/package.json +10 -4
- package/.editorconfig +0 -12
- package/eslint.config.js +0 -3
- package/test/Plugin.test.js +0 -167
package/README.md
CHANGED
|
@@ -5,9 +5,11 @@ Base template for creating Hamlet plugins.
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
7
|
1. Rename the package in `package.json` (e.g. `@scope/hamlet-feature` or `hamlet-plugin-feature`).
|
|
8
|
-
2.
|
|
9
|
-
3.
|
|
10
|
-
4.
|
|
8
|
+
2. Add your Handlebars partials as `.hbs` (or `.xml`, `.handlebars`) files inside `src/`.
|
|
9
|
+
3. Implement helpers and set the namespace in `index.js`.
|
|
10
|
+
4. Run `npm run build:partials` to generate `lib/partials.js` from your source files.
|
|
11
|
+
5. Run the tests.
|
|
12
|
+
6. Publish to npm.
|
|
11
13
|
|
|
12
14
|
## End-user installation
|
|
13
15
|
|
|
@@ -17,28 +19,46 @@ npm install hamlet-plugin-template
|
|
|
17
19
|
|
|
18
20
|
```js
|
|
19
21
|
// hamlet.config.js
|
|
20
|
-
import
|
|
22
|
+
import Sample from 'hamlet-plugin-template'
|
|
21
23
|
|
|
22
24
|
export default {
|
|
23
25
|
plugins: [
|
|
24
|
-
|
|
26
|
+
Sample(),
|
|
25
27
|
// or with options:
|
|
26
|
-
|
|
28
|
+
Sample({ myOption: true }),
|
|
27
29
|
],
|
|
28
30
|
}
|
|
29
31
|
```
|
|
30
32
|
|
|
31
|
-
Plugins are imported and invoked directly from `hamlet.config.js`, similar to Vite or Rollup plugins. Hamlet never resolves plugins by package name—it only consumes the object returned by the plugin factory.
|
|
33
|
+
Plugins are imported and invoked directly from `hamlet.config.js`, similar to Vite or Rollup plugins. Hamlet never resolves plugins by package name — it only consumes the object returned by the plugin factory.
|
|
34
|
+
|
|
35
|
+
## Project structure
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
├── src/
|
|
39
|
+
│ ├── card.hbs ← your partial source files
|
|
40
|
+
│ └── hello.hbs
|
|
41
|
+
├── lib/
|
|
42
|
+
│ └── partials.js ← auto-generated, do not edit
|
|
43
|
+
├── scripts/
|
|
44
|
+
│ └── build-partials.js
|
|
45
|
+
├── index.js
|
|
46
|
+
└── package.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Source files in `src/` are compiled into `lib/partials.js` by `npm run build:partials`. This script runs automatically before publishing via the `prepublishOnly` hook.
|
|
32
50
|
|
|
33
51
|
## Plugin contract
|
|
34
52
|
|
|
35
53
|
A plugin must export a default factory function that receives the user's options and returns an object with the following shape:
|
|
36
54
|
|
|
37
55
|
```js
|
|
56
|
+
import { partials } from './lib/partials.js'
|
|
57
|
+
|
|
38
58
|
export default function hamletPlugin(options = {}) {
|
|
39
59
|
return {
|
|
40
|
-
namespace: '
|
|
41
|
-
partials
|
|
60
|
+
namespace: 'Sample',
|
|
61
|
+
partials,
|
|
42
62
|
helpers: {},
|
|
43
63
|
}
|
|
44
64
|
}
|
|
@@ -48,75 +68,90 @@ export default function hamletPlugin(options = {}) {
|
|
|
48
68
|
|
|
49
69
|
Every plugin must define a unique `namespace`.
|
|
50
70
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
71
|
+
- It must start with a letter.
|
|
72
|
+
- It may contain only letters and digits.
|
|
73
|
+
- It is used to prefix all exported partials and helpers automatically — you only use short names inside the plugin.
|
|
74
|
+
- The namespace `hamlet` is reserved and cannot be used.
|
|
54
75
|
|
|
55
76
|
### partials
|
|
56
77
|
|
|
57
|
-
An object
|
|
78
|
+
An object of Handlebars partials keyed by **short names** (without the namespace prefix). Hamlet registers them as `<namespace>.<name>` automatically.
|
|
58
79
|
|
|
59
|
-
|
|
80
|
+
Add `.hbs`, `.xml`, or `.handlebars` files to `src/` and run `npm run build:partials` to populate `lib/partials.js`. The file name becomes the partial key.
|
|
60
81
|
|
|
61
|
-
Example
|
|
82
|
+
Example — `src/card.hbs`:
|
|
62
83
|
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'MyPlugin.card': '<div>...</div>',
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
84
|
+
```hbs
|
|
85
|
+
<div{{#if className}} class="{{className}}"{{/if}}>
|
|
86
|
+
{{#if title}}<h2>{{title}}</h2>{{/if}}
|
|
87
|
+
{{#if description}}<p>{{description}}</p>{{/if}}
|
|
88
|
+
</div>
|
|
72
89
|
```
|
|
73
90
|
|
|
74
|
-
|
|
91
|
+
This becomes `partials.card`, registered by Hamlet as `Sample.card`:
|
|
75
92
|
|
|
76
|
-
|
|
93
|
+
```hbs
|
|
94
|
+
{{> Sample.card title="Hello"}}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### helpers
|
|
77
98
|
|
|
78
|
-
|
|
99
|
+
An object of Handlebars helpers keyed by **short camelCase names** (without the namespace prefix). Hamlet registers them as `<namespace><Name>` automatically.
|
|
79
100
|
|
|
80
101
|
Example:
|
|
81
102
|
|
|
82
103
|
```js
|
|
83
104
|
export default function hamletPlugin(options = {}) {
|
|
84
105
|
return {
|
|
85
|
-
namespace: '
|
|
106
|
+
namespace: 'Sample',
|
|
86
107
|
helpers: {
|
|
87
|
-
|
|
88
|
-
}
|
|
108
|
+
shout: value => value.toUpperCase(),
|
|
109
|
+
},
|
|
89
110
|
}
|
|
90
111
|
}
|
|
91
112
|
```
|
|
92
113
|
|
|
93
|
-
|
|
114
|
+
This registers the helper as `SampleShout`, usable in templates as:
|
|
115
|
+
|
|
116
|
+
```hbs
|
|
117
|
+
{{SampleShout "hello"}}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Helper names cannot contain dots because Handlebars interprets them as property paths.
|
|
94
121
|
|
|
95
122
|
## Name collisions
|
|
96
123
|
|
|
97
124
|
Hamlet follows a **first registered wins** policy.
|
|
98
125
|
|
|
99
|
-
If a plugin attempts to register a partial or helper whose name already exists (whether
|
|
126
|
+
If a plugin attempts to register a partial or helper whose name already exists (whether built-in to Hamlet, from another plugin, or from the user's project), the duplicate is silently skipped and a warning is printed.
|
|
100
127
|
|
|
101
128
|
## Using Hamlet features inside plugin partials
|
|
102
129
|
|
|
103
|
-
Plugin partials can freely use Hamlet's built-in helpers and partials
|
|
104
|
-
|
|
105
|
-
For example:
|
|
130
|
+
Plugin partials can freely use Hamlet's built-in helpers and partials:
|
|
106
131
|
|
|
107
132
|
```hbs
|
|
108
133
|
{{concat "Hello, " name}}
|
|
109
134
|
|
|
110
135
|
{{#switch value}}
|
|
111
|
-
...
|
|
136
|
+
{{#case "post"}}...{{/case}}
|
|
137
|
+
{{#default}}...{{/default}}
|
|
112
138
|
{{/switch}}
|
|
113
139
|
|
|
114
140
|
{{> hamlet.snippet}}
|
|
115
141
|
```
|
|
116
142
|
|
|
117
|
-
##
|
|
143
|
+
## Scripts
|
|
118
144
|
|
|
119
|
-
|
|
145
|
+
| Script | Description |
|
|
146
|
+
| ------ | ----------- |
|
|
147
|
+
| `npm run build:partials` | Generates `lib/partials.js` from files in `src/` |
|
|
148
|
+
| `npm test` | Runs the test suite |
|
|
149
|
+
| `npm run lint` | Lints the project |
|
|
150
|
+
| `npm run lint:fix` | Lints and auto-fixes |
|
|
151
|
+
|
|
152
|
+
`build:partials` also runs automatically via `prepublishOnly` before every `npm publish`.
|
|
153
|
+
|
|
154
|
+
## Tests
|
|
120
155
|
|
|
121
156
|
```bash
|
|
122
157
|
npm install
|
|
@@ -125,20 +160,20 @@ npm test
|
|
|
125
160
|
|
|
126
161
|
The test suite verifies that:
|
|
127
162
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
163
|
+
- The plugin exports a valid factory function.
|
|
164
|
+
- The returned object follows Hamlet's plugin contract.
|
|
165
|
+
- A valid, non-reserved namespace is exported.
|
|
166
|
+
- Partial and helper names are short (no namespace prefix) and follow Hamlet's naming rules.
|
|
167
|
+
- No computed full name collides with Hamlet's reserved partials or helpers.
|
|
168
|
+
- Partials are strings and compile without Handlebars syntax errors.
|
|
169
|
+
- Helpers are functions (not nested objects).
|
|
170
|
+
- No name is on Hamlet's blocked list (`__proto__`, `constructor`, `prototype`).
|
|
136
171
|
|
|
137
172
|
Feel free to extend the tests with plugin-specific behavior or option validation.
|
|
138
173
|
|
|
139
174
|
## Linting
|
|
140
175
|
|
|
141
|
-
This template uses the same ESLint configuration as Hamlet itself.
|
|
176
|
+
This template uses the same ESLint configuration as Hamlet itself (`@antfu/eslint-config`).
|
|
142
177
|
|
|
143
178
|
```bash
|
|
144
179
|
npm run lint
|
package/index.js
CHANGED
|
@@ -1,39 +1,31 @@
|
|
|
1
|
+
import { partials } from './lib/partials.js'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Hamlet plugin template.
|
|
3
5
|
*
|
|
4
6
|
* Export a factory function that receives the options from
|
|
5
7
|
* hamlet.config.js and returns:
|
|
6
8
|
*
|
|
7
|
-
* - namespace: A unique plugin namespace.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - partials: An object of Handlebars partials. Every partial name
|
|
11
|
-
* must be prefixed with "<namespace>." (e.g. "myPlugin.card").
|
|
9
|
+
* - namespace: A unique plugin namespace. Hamlet uses it to
|
|
10
|
+
* prefix all exported partials and helpers automatically,
|
|
11
|
+
* so you only need to define short names here.
|
|
12
12
|
*
|
|
13
|
-
* -
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* - partials: An object of Handlebars partials. Use short names
|
|
14
|
+
* without the namespace prefix (e.g. "card", not "Sample.card").
|
|
15
|
+
* Hamlet registers them as "<namespace>.<name>" automatically.
|
|
16
|
+
* Usage in templates: {{> Sample.card}}
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* - helpers: An object of Handlebars helpers. Use short camelCase
|
|
19
|
+
* names without the namespace prefix (e.g. "format", not "SampleFormat").
|
|
20
|
+
* Hamlet registers them as "<namespace><Name>" automatically.
|
|
21
|
+
* Usage in templates: {{SampleFormat value}}
|
|
20
22
|
*
|
|
21
|
-
* @param {object} options - Options from hamlet.config.js.
|
|
22
23
|
* @return {{namespace: string, partials: object, helpers: object}}
|
|
23
24
|
*/
|
|
24
|
-
export default function hamletPlugin(
|
|
25
|
-
const { greeting = 'Hello World' } = options
|
|
26
|
-
|
|
25
|
+
export default function hamletPlugin() {
|
|
27
26
|
return {
|
|
28
|
-
namespace: '
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// Usage in a .hbs file: {{> myPlugin.hello}}
|
|
32
|
-
'myPlugin.hello': `MyPlugin says: {{myPluginShout greeting}}`,
|
|
33
|
-
},
|
|
34
|
-
helpers: {
|
|
35
|
-
// Usage in a .hbs file: {{myPluginShout "Hello World"}}
|
|
36
|
-
myPluginShout: text => `${text ?? greeting}!`.toUpperCase(),
|
|
37
|
-
},
|
|
27
|
+
namespace: 'Sample',
|
|
28
|
+
partials,
|
|
29
|
+
helpers: {},
|
|
38
30
|
}
|
|
39
31
|
}
|
package/lib/partials.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// This file is auto-generated. Do not edit it manually.
|
|
2
|
+
export const partials = {
|
|
3
|
+
"hello": "<p>Hello World!</p>\n",
|
|
4
|
+
"card": "<div{{#if className}} class=\"{{className}}\"{{/if}}>\r\n {{#if title}}<h2>{{title}}</h2>{{/if}}\r\n {{#if description}}<p>{{description}}</p>{{/if}}\r\n</div>\n"
|
|
5
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hamlet-plugin-template",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"description": "A plugin template for hamlet",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -11,16 +11,22 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": "./index.js"
|
|
13
13
|
},
|
|
14
|
-
"
|
|
14
|
+
"files": [
|
|
15
|
+
"index.js",
|
|
16
|
+
"lib"
|
|
17
|
+
],
|
|
15
18
|
"scripts": {
|
|
19
|
+
"build:partials": "node ./scripts/build-partials.js",
|
|
20
|
+
"prepublishOnly": "npm run build:partials",
|
|
16
21
|
"test": "vitest run",
|
|
17
22
|
"lint": "eslint .",
|
|
18
23
|
"lint:fix": "eslint . --fix"
|
|
19
24
|
},
|
|
20
25
|
"devDependencies": {
|
|
21
26
|
"@antfu/eslint-config": "^9.1.0",
|
|
22
|
-
"eslint": "^10.
|
|
27
|
+
"eslint": "^10.7.0",
|
|
28
|
+
"glob": "^13.0.0",
|
|
23
29
|
"handlebars": "^4.7.9",
|
|
24
|
-
"vitest": "^4.1.
|
|
30
|
+
"vitest": "^4.1.10"
|
|
25
31
|
}
|
|
26
32
|
}
|
package/.editorconfig
DELETED
package/eslint.config.js
DELETED
package/test/Plugin.test.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict'
|
|
2
|
-
import Handlebars from 'handlebars'
|
|
3
|
-
import { it } from 'vitest'
|
|
4
|
-
import plugin from '../index.js'
|
|
5
|
-
|
|
6
|
-
// Reserved names exposed natively by hamlet.
|
|
7
|
-
const RESERVED_HELPERS = new Set([
|
|
8
|
-
'asset',
|
|
9
|
-
'currentYear',
|
|
10
|
-
'helperMissing',
|
|
11
|
-
'blockHelperMissing',
|
|
12
|
-
'switch',
|
|
13
|
-
'case',
|
|
14
|
-
'default',
|
|
15
|
-
'eq',
|
|
16
|
-
'ne',
|
|
17
|
-
'lt',
|
|
18
|
-
'gt',
|
|
19
|
-
'and',
|
|
20
|
-
'or',
|
|
21
|
-
'not',
|
|
22
|
-
'concat',
|
|
23
|
-
'includes',
|
|
24
|
-
'capitalize',
|
|
25
|
-
'first',
|
|
26
|
-
'last',
|
|
27
|
-
])
|
|
28
|
-
|
|
29
|
-
const isHamletReserved = name => name.startsWith('hamlet.')
|
|
30
|
-
|
|
31
|
-
const PARTIAL_NAME_PATTERN = /^[A-Z][A-Z0-9]*(?:[._-][A-Z][A-Z0-9]*)*$/i
|
|
32
|
-
const HELPER_NAME_PATTERN = /^[A-Z][A-Z0-9]*(?:[-_][A-Z][A-Z0-9]*)*$/i
|
|
33
|
-
const BLOCKED_NAMES = new Set(['__proto__', 'constructor', 'prototype'])
|
|
34
|
-
|
|
35
|
-
it('plugin exports a function (factory)', () => {
|
|
36
|
-
assert.equal(typeof plugin, 'function', 'default export must be a function that returns { partials, helpers }')
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('plugin() returns an object with partials/helpers', () => {
|
|
40
|
-
const result = plugin({})
|
|
41
|
-
assert.equal(typeof result, 'object')
|
|
42
|
-
assert.ok(result.partials === undefined || typeof result.partials === 'object')
|
|
43
|
-
assert.ok(result.helpers === undefined || typeof result.helpers === 'object')
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('partials do not collide with reserved hamlet names', () => {
|
|
47
|
-
const { partials = {} } = plugin({})
|
|
48
|
-
|
|
49
|
-
for (const name of Object.keys(partials)) {
|
|
50
|
-
assert.ok(
|
|
51
|
-
!isHamletReserved(name),
|
|
52
|
-
`Partial "${name}" collides with a built-in hamlet partial`,
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('helpers do not collide with reserved hamlet helpers', () => {
|
|
58
|
-
const { helpers = {} } = plugin({})
|
|
59
|
-
|
|
60
|
-
for (const name of Object.keys(helpers)) {
|
|
61
|
-
assert.ok(
|
|
62
|
-
!RESERVED_HELPERS.has(name),
|
|
63
|
-
`Helper "${name}" collides with a built-in hamlet helper ("${name}" is reserved)`,
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('partial names match hamlet\'s naming policy (dots allowed)', () => {
|
|
69
|
-
const { partials = {} } = plugin({})
|
|
70
|
-
|
|
71
|
-
for (const name of Object.keys(partials)) {
|
|
72
|
-
assert.ok(
|
|
73
|
-
PARTIAL_NAME_PATTERN.test(name),
|
|
74
|
-
`Partial "${name}" does not match hamlet's allowed name pattern `
|
|
75
|
-
+ '(letter start, letters/digits, optional ".", "-" or "_" separators)',
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('helper names match hamlet\'s naming policy (no dots allowed)', () => {
|
|
81
|
-
const { helpers = {} } = plugin({})
|
|
82
|
-
|
|
83
|
-
for (const name of Object.keys(helpers)) {
|
|
84
|
-
assert.ok(
|
|
85
|
-
HELPER_NAME_PATTERN.test(name),
|
|
86
|
-
`Helper "${name}" does not match hamlet's allowed name pattern, or contains a dot. `
|
|
87
|
-
+ 'Helpers cannot be dot-namespaced: Handlebars parses "{{a.b}}" as a property path '
|
|
88
|
-
+ 'on the data context, never as a helper name — a dotted helper registers without '
|
|
89
|
-
+ 'error but is unreachable from any template (use camelCase or dashes instead).',
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('helpers are not nested objects (a common attempt at dot-namespacing)', () => {
|
|
95
|
-
const { helpers = {} } = plugin({})
|
|
96
|
-
|
|
97
|
-
for (const [name, value] of Object.entries(helpers)) {
|
|
98
|
-
assert.ok(
|
|
99
|
-
typeof value === 'function',
|
|
100
|
-
`Helper "${name}" is not a function (got ${typeof value}). If this is an attempt to `
|
|
101
|
-
+ 'namespace helpers like { myPlugin: { shout: fn } }, note that Handlebars cannot '
|
|
102
|
-
+ 'call nested helpers this way — "{{myPlugin.shout}}" looks up a property path, '
|
|
103
|
-
+ 'not a nested helper, and would fail with "Missing helper" at render time.',
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
it('partial and helper names are not on hamlet\'s blocked list', () => {
|
|
109
|
-
const { partials = {}, helpers = {} } = plugin({})
|
|
110
|
-
|
|
111
|
-
for (const name of [...Object.keys(partials), ...Object.keys(helpers)]) {
|
|
112
|
-
assert.ok(
|
|
113
|
-
!BLOCKED_NAMES.has(name),
|
|
114
|
-
`"${name}" is a blocked name (${[...BLOCKED_NAMES].join(', ')}) and will always be rejected by hamlet`,
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
it('partials are valid strings and compile without syntax errors', () => {
|
|
120
|
-
const { partials = {} } = plugin({})
|
|
121
|
-
|
|
122
|
-
for (const [name, template] of Object.entries(partials)) {
|
|
123
|
-
assert.equal(typeof template, 'string', `Partial "${name}" must be a string`)
|
|
124
|
-
assert.doesNotThrow(
|
|
125
|
-
() => Handlebars.compile(template),
|
|
126
|
-
`Partial "${name}" has a Handlebars syntax error`,
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it('helpers are functions', () => {
|
|
132
|
-
const { helpers = {} } = plugin({})
|
|
133
|
-
|
|
134
|
-
for (const [name, fn] of Object.entries(helpers)) {
|
|
135
|
-
assert.equal(typeof fn, 'function', `Helper "${name}" must be a function`)
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
it('plugin namespaces its exported names', () => {
|
|
140
|
-
const { namespace, partials = {}, helpers = {} } = plugin({})
|
|
141
|
-
|
|
142
|
-
assert.equal(
|
|
143
|
-
typeof namespace,
|
|
144
|
-
'string',
|
|
145
|
-
'Plugin must export a string "namespace"',
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
assert.match(
|
|
149
|
-
namespace,
|
|
150
|
-
/^[A-Z][A-Z0-9]*$/i,
|
|
151
|
-
'Namespace must start with a letter and contain only letters and digits',
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
for (const name of Object.keys(partials)) {
|
|
155
|
-
assert.ok(
|
|
156
|
-
name.startsWith(`${namespace}.`),
|
|
157
|
-
`Partial "${name}" must be prefixed with "${namespace}."`,
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
for (const name of Object.keys(helpers)) {
|
|
162
|
-
assert.ok(
|
|
163
|
-
new RegExp(`^${namespace}[A-Z]`).test(name),
|
|
164
|
-
`Helper "${name}" must be prefixed with "${namespace}" followed by an uppercase letter (e.g. "${namespace}Format")`,
|
|
165
|
-
)
|
|
166
|
-
}
|
|
167
|
-
})
|