-
Notifications
You must be signed in to change notification settings - Fork 334
/
Copy pathcomponents.mjs
142 lines (117 loc) · 4.05 KB
/
components.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { basename, dirname, join } from 'path'
import { getListing, getYaml } from 'govuk-frontend-lib/files'
import nunjucks from 'nunjucks'
import { files } from './index.mjs'
/**
* Generate fixtures.json from component data
*
* @param {AssetEntry[0]} pattern - Path to ${componentName}.yaml
* @param {Pick<AssetEntry[1], "srcPath" | "destPath">} options - Asset options
*/
export async function generateFixtures (pattern, { srcPath, destPath }) {
const componentDataPaths = await getListing(pattern, {
cwd: srcPath
})
// Loop component data paths
const fixtures = componentDataPaths.map(async (componentDataPath) => {
const fixture = await generateFixture(componentDataPath, { srcPath })
// Write to destination
await files.write(componentDataPath, {
destPath,
// Rename to fixtures.json
filePath ({ dir }) {
return join(dir, 'fixtures.json')
},
// Add fixtures as JSON (formatted)
async fileContents () {
return JSON.stringify(fixture, null, 4)
}
})
})
await Promise.all(fixtures)
}
/**
* Generate macro-options.json from component data
*
* @param {AssetEntry[0]} pattern - Path to ${componentName}.yaml
* @param {Pick<AssetEntry[1], "srcPath" | "destPath">} options - Asset options
*/
export async function generateMacroOptions (pattern, { srcPath, destPath }) {
const componentDataPaths = await getListing(pattern, {
cwd: srcPath
})
// Loop component data paths
const macroOptions = componentDataPaths.map(async (componentDataPath) => {
const macroOption = await generateMacroOption(componentDataPath, { srcPath })
// Write to destination
await files.write(componentDataPath, {
destPath,
// Rename to 'macro-options.json'
filePath ({ dir }) {
return join(dir, 'macro-options.json')
},
// Add macro options as JSON (formatted)
async fileContents () {
return JSON.stringify(macroOption, null, 4)
}
})
})
await Promise.all(macroOptions)
}
/**
* Component fixtures YAML to JSON
*
* @param {string} componentDataPath - Path to ${componentName}.yaml
* @param {Pick<AssetEntry[1], "srcPath">} options - Asset options
* @returns {Promise<{ component: string; fixtures: { [key: string]: unknown }[] }>} Component fixtures object
*/
async function generateFixture (componentDataPath, options) {
/** @type {ComponentData} */
const json = await getYaml(join(options.srcPath, componentDataPath))
if (!json?.examples) {
throw new Error(`${componentDataPath} is missing "examples"`)
}
// Nunjucks template
const template = join(options.srcPath, dirname(componentDataPath), 'template.njk')
const componentName = basename(dirname(componentDataPath))
// Loop examples
const examples = json.examples.map(async (example) => {
const context = { params: example.data }
return {
name: example.name,
options: example.data,
hidden: Boolean(example.hidden),
// Wait for render to complete
/** @type {string} */
html: await new Promise((resolve, reject) => {
return nunjucks.render(template, context, (error, result) => {
return error ? reject(error) : resolve(result?.trim() ?? '')
})
})
}
})
return {
component: componentName,
fixtures: await Promise.all(examples)
}
}
/**
* Macro options YAML to JSON
*
* @param {string} componentDataPath - Path to ${componentName}.yaml
* @param {Pick<AssetEntry[1], "srcPath">} options - Asset options
* @returns {Promise<ComponentOption[] | undefined>} Component macro options
*/
async function generateMacroOption (componentDataPath, options) {
/** @type {ComponentData} */
const json = await getYaml(join(options.srcPath, componentDataPath))
if (!json?.params) {
throw new Error(`${componentDataPath} is missing "params"`)
}
return json.params
}
/**
* @typedef {import('./assets.mjs').AssetEntry} AssetEntry
* @typedef {import('govuk-frontend-lib/files').ComponentData} ComponentData
* @typedef {import('govuk-frontend-lib/files').ComponentOption} ComponentOption
*/