-
Notifications
You must be signed in to change notification settings - Fork 339
/
Copy pathcopy-to-destination.js
154 lines (130 loc) · 4.29 KB
/
copy-to-destination.js
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
143
144
145
146
147
148
149
150
151
152
153
154
const { basename, join } = require('path')
const nunjucks = require('nunjucks')
const gulp = require('gulp')
const postcss = require('gulp-postcss')
const postcssScss = require('postcss-scss')
const autoprefixer = require('autoprefixer')
const yaml = require('js-yaml')
const map = require('map-stream')
const merge = require('merge-stream')
const rename = require('gulp-rename')
const configPaths = require('../../config/paths.js')
const taskArguments = require('../task-arguments')
gulp.task('copy-files', () => {
return merge(
gulp.src([
`${configPaths.src}**/*`,
// Exclude files from copy
'!**/.DS_Store',
'!**/*.mjs',
'!**/*.test.*',
'!**/__snapshots__/',
'!**/__snapshots__/**',
// Preserve destination README when copying to ./package
// https://github.com/alphagov/govuk-frontend/tree/main/package#readme
`!${configPaths.src}README.md`,
// Exclude files from other streams
`!${configPaths.src}**/*.scss`,
`!${configPaths.components}**/*.yaml`
]),
// Add CSS prefixes to Sass
gulp.src(`${configPaths.src}**/*.scss`)
.pipe(postcss([autoprefixer], { syntax: postcssScss })),
// Generate fixtures.json from ${component}.yaml
gulp.src(`${configPaths.components}**/*.yaml`, { base: configPaths.src })
.pipe(map((file, done) =>
generateFixtures(file)
.then((fixture) => done(null, fixture))
.catch(done)
))
.pipe(rename({
basename: 'fixtures',
extname: '.json'
})),
// Generate macro-options.json from ${component}.yaml
gulp.src(`${configPaths.components}**/*.yaml`, { base: configPaths.src })
.pipe(map((file, done) =>
generateMacroOptions(file)
.then((macro) => done(null, macro))
.catch(done)
))
.pipe(rename({
basename: 'macro-options',
extname: '.json'
}))
)
.pipe(gulp.dest(`${taskArguments.destination}/govuk/`))
})
/**
* Replace file content with fixtures.json
*
* @param {import('vinyl')} file - Component data ${component}.yaml
* @returns {Promise<import('vinyl')>} Component fixtures.json
*/
async function generateFixtures (file) {
const json = await convertYamlToJson(file)
if (!json?.examples) {
throw new Error(`${file.relative} is missing "examples"`)
}
// Nunjucks template
const component = basename(file.dirname)
const template = join(configPaths.components, component, 'template.njk')
// 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
html: await new Promise((resolve, reject) => {
return nunjucks.render(template, context, (error, result) => {
return error ? reject(error) : resolve(result.trim())
})
})
}
})
const fixtures = {
component: basename(file.dirname),
fixtures: await Promise.all(examples)
}
file.contents = Buffer.from(JSON.stringify(fixtures, null, 4))
return file
}
gulp.task('js:copy-esm', () => {
return gulp.src([
`${configPaths.src}**/*.mjs`,
`${configPaths.src}**/*.js`,
`!${configPaths.src}**/*.test.*`
])
.pipe(gulp.dest(taskArguments.destination + '/govuk-esm/'))
})
/**
* Replace file content with macro-options.json
*
* @param {import('vinyl')} file - Component data ${component}.yaml
* @returns {Promise<import('vinyl')>} Component macro-options.json
*/
async function generateMacroOptions (file) {
const json = await convertYamlToJson(file)
if (!json?.params) {
throw new Error(`${file.relative} is missing "params"`)
}
file.contents = Buffer.from(JSON.stringify(json.params, null, 4))
return file
}
/**
* Parse YAML file content as JavaScript
*
* @param {import('vinyl')} file - Component data ${component}.yaml
* @returns {Promise<{ examples?: unknown[]; params?: unknown[] }>} Component options
*/
async function convertYamlToJson (file) {
const cache = convertYamlToJson.cache ??= new Map()
// Check cache for component options
if (!cache.has(file.relative)) {
cache.set(file.relative, yaml.load(file.contents.toString(), { json: true }))
}
// Use cached content
return cache.get(file.relative)
}