js-build-tools 6.6.0 → 6.7.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/LICENSE +674 -674
- package/README.md +762 -701
- package/babel.config.js +28 -28
- package/dist/build.js +75 -75
- package/dist/bundle.js +19 -19
- package/dist/bundleMinify.js +7 -7
- package/dist/compileReadme.js +4 -4
- package/dist/copyFiles.js +17 -17
- package/dist/copyFonts.js +4 -4
- package/dist/default.js +5 -5
- package/dist/dist.js +4 -4
- package/dist/distMinify.js +4 -4
- package/dist/docs.js +7 -7
- package/dist/images.js +4 -4
- package/dist/jsdocDocs.js +6 -6
- package/dist/lint.js +16 -16
- package/dist/partials/addToReadme.js +9 -9
- package/dist/partials/beginWatcher.js +4 -4
- package/dist/partials/clean.js +5 -5
- package/dist/partials/copyFor.js +9 -9
- package/dist/partials/distFor.js +6 -6
- package/dist/partials/distForSrc.js +5 -5
- package/dist/partials/distSeries.js +7 -7
- package/dist/partials/imagesFor.js +93 -93
- package/dist/partials/jsdocDocsFor.js +46 -46
- package/dist/partials/lintSource.js +51 -51
- package/dist/partials/loadPeer.js +99 -99
- package/dist/partials/loadPlaywright.js +14 -14
- package/dist/partials/minifyFor.js +20 -20
- package/dist/partials/neostandardLint.js +175 -175
- package/dist/partials/readmeTemplate.js +4 -4
- package/dist/partials/removeDirectory.js +11 -11
- package/dist/partials/resolveDocsMethod.js +6 -6
- package/dist/partials/runOnChange.js +31 -31
- package/dist/partials/sassFor.js +6 -6
- package/dist/partials/serveStatic.js +9 -9
- package/dist/partials/tsFor.js +32 -32
- package/dist/partials/typeDocsFor.js +264 -264
- package/dist/partials.js +176 -176
- package/dist/sourceLint.js +18 -18
- package/dist/test-helpers/isolateGulpCache.js +24 -24
- package/dist/test-helpers/setUp.js +4 -4
- package/dist/testFull.js +5 -5
- package/dist/testQuick.js +5 -5
- package/dist/typeDocs.js +5 -5
- package/dist/typeScript.js +4 -4
- package/dist/utilities/convertMjsFilesForDocs.js +12 -12
- package/dist/utilities/dotGet.js +54 -54
- package/dist/utilities/dotNotate.js +79 -79
- package/dist/utilities/dotSet.js +45 -45
- package/dist/utilities/esmNamedExportsToCjs.js +15 -15
- package/dist/utilities/getBundleConfigs.js +9 -9
- package/dist/utilities/isObject.js +6 -6
- package/dist/utilities/strAfter.js +7 -7
- package/dist/utilities/strBefore.js +7 -7
- package/dist/watchFull.js +4 -4
- package/dist/watchTest.js +4 -4
- package/functions/build.mjs +72 -72
- package/functions/build.test.mjs +763 -759
- package/functions/bundle.mjs +44 -44
- package/functions/bundle.test.mjs +219 -219
- package/functions/bundleMinify.mjs +16 -16
- package/functions/bundleMinify.test.mjs +37 -37
- package/functions/compileReadme.mjs +9 -9
- package/functions/compileReadme.test.mjs +18 -18
- package/functions/copyFiles.mjs +32 -32
- package/functions/copyFiles.test.mjs +78 -78
- package/functions/copyFonts.mjs +9 -9
- package/functions/copyFonts.test.mjs +32 -32
- package/functions/default.mjs +12 -12
- package/functions/default.test.mjs +33 -33
- package/functions/dist.mjs +8 -8
- package/functions/dist.test.mjs +44 -44
- package/functions/distMinify.mjs +9 -9
- package/functions/distMinify.test.mjs +15 -15
- package/functions/docs.mjs +13 -13
- package/functions/docs.test.mjs +45 -45
- package/functions/gulpConfigEntries.test.mjs +23 -23
- package/functions/images.mjs +8 -8
- package/functions/images.test.mjs +142 -142
- package/functions/jsdocDocs.mjs +10 -10
- package/functions/jsdocEsmExports.test.mjs +24 -24
- package/functions/lint.mjs +9 -9
- package/functions/partials/addToReadme.mjs +25 -25
- package/functions/partials/addToReadme.test.mjs +34 -34
- package/functions/partials/beginWatcher.mjs +9 -9
- package/functions/partials/beginWatcher.test.mjs +19 -19
- package/functions/partials/clean.mjs +13 -13
- package/functions/partials/clean.test.mjs +22 -22
- package/functions/partials/copyFor.mjs +15 -15
- package/functions/partials/copyFor.test.mjs +53 -53
- package/functions/partials/distFor.mjs +22 -22
- package/functions/partials/distFor.test.mjs +195 -195
- package/functions/partials/distForSrc.mjs +11 -11
- package/functions/partials/distForSrc.test.mjs +18 -18
- package/functions/partials/distSeries.mjs +21 -21
- package/functions/partials/distSeries.test.mjs +34 -34
- package/functions/partials/imagesFor.mjs +83 -83
- package/functions/partials/imagesFor.test.mjs +287 -287
- package/functions/partials/jsdocDocsFor.mjs +163 -152
- package/functions/partials/jsdocDocsFor.test.mjs +182 -152
- package/functions/partials/lintSource.mjs +41 -41
- package/functions/partials/loadPeer.mjs +76 -76
- package/functions/partials/loadPeer.test.mjs +58 -58
- package/functions/partials/loadPlaywright.mjs +23 -23
- package/functions/partials/loadPlaywright.test.mjs +70 -70
- package/functions/partials/minifyFor.mjs +15 -15
- package/functions/partials/minifyFor.test.mjs +49 -49
- package/functions/partials/neostandardLint.mjs +142 -142
- package/functions/partials/neostandardLint.test.mjs +131 -131
- package/functions/partials/readmeTemplate.mjs +12 -12
- package/functions/partials/readmeTemplate.test.mjs +34 -34
- package/functions/partials/removeDirectory.mjs +34 -34
- package/functions/partials/removeDirectory.test.mjs +72 -72
- package/functions/partials/resolveDocsMethod.mjs +10 -10
- package/functions/partials/resolveDocsMethod.test.mjs +33 -33
- package/functions/partials/runOnChange.mjs +54 -54
- package/functions/partials/runOnChange.test.mjs +95 -95
- package/functions/partials/sassFor.mjs +25 -25
- package/functions/partials/sassFor.test.mjs +81 -81
- package/functions/partials/serveStatic.mjs +47 -47
- package/functions/partials/serveStatic.test.mjs +71 -71
- package/functions/partials/tsFor.mjs +92 -92
- package/functions/partials/tsFor.test.mjs +88 -88
- package/functions/partials/typeDocsFor.mjs +231 -231
- package/functions/partials/typeDocsFor.test.mjs +263 -263
- package/functions/partials.mjs +31 -31
- package/functions/partials.test.mjs +7 -7
- package/functions/sass.mjs +4 -4
- package/functions/sass.test.mjs +31 -31
- package/functions/sourceLint.mjs +13 -13
- package/functions/sourceLint.test.mjs +166 -166
- package/functions/test-helpers/isolateGulpCache.mjs +16 -16
- package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +40 -40
- package/functions/test-helpers/setUp.mjs +100 -100
- package/functions/test-helpers/setUp.test.mjs +19 -19
- package/functions/testFull.mjs +17 -17
- package/functions/testFull.test.mjs +17 -17
- package/functions/testHelpers.mjs +10 -10
- package/functions/testHelpers.test.mjs +7 -7
- package/functions/testQuick.mjs +17 -17
- package/functions/testQuick.test.mjs +17 -17
- package/functions/typeDocs.mjs +9 -9
- package/functions/typeDocs.test.mjs +11 -11
- package/functions/typeScript.mjs +8 -8
- package/functions/typeScript.test.mjs +11 -11
- package/functions/utilities/convertMjsFilesForDocs.mjs +34 -34
- package/functions/utilities/convertMjsFilesForDocs.test.mjs +58 -58
- package/functions/utilities/dotGet.mjs +49 -49
- package/functions/utilities/dotNotate.mjs +73 -73
- package/functions/utilities/dotNotate.test.mjs +41 -41
- package/functions/utilities/dotSet.mjs +40 -40
- package/functions/utilities/esmNamedExportsToCjs.mjs +30 -30
- package/functions/utilities/esmNamedExportsToCjs.test.mjs +47 -47
- package/functions/utilities/getBundleConfigs.mjs +30 -30
- package/functions/utilities/isObject.mjs +8 -8
- package/functions/utilities/strAfter.mjs +12 -12
- package/functions/utilities/strBefore.mjs +12 -12
- package/functions/watchFull.mjs +9 -9
- package/functions/watchFull.test.mjs +41 -41
- package/functions/watchTest.mjs +10 -10
- package/functions/watchTest.test.mjs +49 -49
- package/gulp.config.js +4 -4
- package/gulp.config.mjs +344 -340
- package/gulpfile.base.js +51 -51
- package/gulpfile.base.mjs +29 -29
- package/jsdoc.base.js +16 -16
- package/jsdoc.esmExports.js +17 -17
- package/package.json +146 -145
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import * as setUp from '../test-helpers/setUp.mjs'
|
|
3
|
-
import { sassFor } from './sassFor.mjs'
|
|
4
|
-
import { countMatches } from 'test-filesystem'
|
|
5
|
-
|
|
6
|
-
setUp.setDefaults('test-sass-for')
|
|
7
|
-
const gulpConfig = setUp.gulpConfig
|
|
8
|
-
|
|
9
|
-
const sassContents = 'html\n' +
|
|
10
|
-
' font-size: 62.5%\n' +
|
|
11
|
-
' color: #444\n' +
|
|
12
|
-
' font-size: 1em\n' +
|
|
13
|
-
' line-height: 1.4\n' +
|
|
14
|
-
' background-color: #fff\n' +
|
|
15
|
-
'\n' +
|
|
16
|
-
'html, body\n' +
|
|
17
|
-
' width: 100%\n' +
|
|
18
|
-
' height: 100%\n' +
|
|
19
|
-
' margin: 0\n' +
|
|
20
|
-
' padding: 0\n' +
|
|
21
|
-
' position: absolute\n' +
|
|
22
|
-
' text-align: center\n' +
|
|
23
|
-
'\n' +
|
|
24
|
-
'a\n' +
|
|
25
|
-
' outline: none\n' +
|
|
26
|
-
' text-decoration: none'
|
|
27
|
-
|
|
28
|
-
const sassPath = gulpConfig.get('sass.path')
|
|
29
|
-
|
|
30
|
-
beforeEach(() => setUp.beforeEach().then(() => fs.mkdirSync(sassPath, { recursive: true })))
|
|
31
|
-
|
|
32
|
-
afterEach(setUp.afterEach)
|
|
33
|
-
|
|
34
|
-
describe('sassFor', () => {
|
|
35
|
-
test('copies the sass directory and converts it into css output', done => {
|
|
36
|
-
const sassFile = `${sassPath}/sassFor.sass`
|
|
37
|
-
fs.writeFileSync(sassFile, sassContents)
|
|
38
|
-
expect.assertions(7)
|
|
39
|
-
const oldContents = fs.readFileSync(sassFile).toString()
|
|
40
|
-
expect(countMatches(oldContents, ';')).toEqual(0)
|
|
41
|
-
expect(countMatches(oldContents, ' {')).toEqual(0)
|
|
42
|
-
expect(countMatches(oldContents, '\n' +
|
|
43
|
-
' }')).toEqual(0)
|
|
44
|
-
const cssPath = gulpConfig.get('sass.to')
|
|
45
|
-
sassFor(sassFile)
|
|
46
|
-
.on('finish', () => {
|
|
47
|
-
expect(fs.existsSync(cssPath)).toBeTruthy()
|
|
48
|
-
const cssContents = fs.readFileSync(`${cssPath}/sassFor.css`).toString()
|
|
49
|
-
// Will add braces and semicolons
|
|
50
|
-
expect(countMatches(cssContents, ';')).toEqual(13)
|
|
51
|
-
expect(countMatches(cssContents, '{')).toEqual(3)
|
|
52
|
-
expect(countMatches(cssContents, '}')).toEqual(3)
|
|
53
|
-
done()
|
|
54
|
-
})
|
|
55
|
-
.on('error', error => {
|
|
56
|
-
console.error('Encountered error', error)
|
|
57
|
-
done()
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('also writes a minified .min.css next to the css output', done => {
|
|
62
|
-
const sassFile = `${sassPath}/sassFor.sass`
|
|
63
|
-
fs.writeFileSync(sassFile, sassContents)
|
|
64
|
-
expect.assertions(4)
|
|
65
|
-
const cssPath = gulpConfig.get('sass.to')
|
|
66
|
-
sassFor(sassFile)
|
|
67
|
-
.on('finish', () => {
|
|
68
|
-
const cssContents = fs.readFileSync(`${cssPath}/sassFor.css`).toString()
|
|
69
|
-
const minContents = fs.readFileSync(`${cssPath}/sassFor.min.css`).toString()
|
|
70
|
-
expect(minContents.length).toBeLessThan(cssContents.length)
|
|
71
|
-
expect(countMatches(minContents.trim(), '\n')).toEqual(0)
|
|
72
|
-
expect(minContents).toContain('outline:none')
|
|
73
|
-
expect(minContents).toContain('text-align:center')
|
|
74
|
-
done()
|
|
75
|
-
})
|
|
76
|
-
.on('error', error => {
|
|
77
|
-
console.error('Encountered error', error)
|
|
78
|
-
done()
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
})
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import * as setUp from '../test-helpers/setUp.mjs'
|
|
3
|
+
import { sassFor } from './sassFor.mjs'
|
|
4
|
+
import { countMatches } from 'test-filesystem'
|
|
5
|
+
|
|
6
|
+
setUp.setDefaults('test-sass-for')
|
|
7
|
+
const gulpConfig = setUp.gulpConfig
|
|
8
|
+
|
|
9
|
+
const sassContents = 'html\n' +
|
|
10
|
+
' font-size: 62.5%\n' +
|
|
11
|
+
' color: #444\n' +
|
|
12
|
+
' font-size: 1em\n' +
|
|
13
|
+
' line-height: 1.4\n' +
|
|
14
|
+
' background-color: #fff\n' +
|
|
15
|
+
'\n' +
|
|
16
|
+
'html, body\n' +
|
|
17
|
+
' width: 100%\n' +
|
|
18
|
+
' height: 100%\n' +
|
|
19
|
+
' margin: 0\n' +
|
|
20
|
+
' padding: 0\n' +
|
|
21
|
+
' position: absolute\n' +
|
|
22
|
+
' text-align: center\n' +
|
|
23
|
+
'\n' +
|
|
24
|
+
'a\n' +
|
|
25
|
+
' outline: none\n' +
|
|
26
|
+
' text-decoration: none'
|
|
27
|
+
|
|
28
|
+
const sassPath = gulpConfig.get('sass.path')
|
|
29
|
+
|
|
30
|
+
beforeEach(() => setUp.beforeEach().then(() => fs.mkdirSync(sassPath, { recursive: true })))
|
|
31
|
+
|
|
32
|
+
afterEach(setUp.afterEach)
|
|
33
|
+
|
|
34
|
+
describe('sassFor', () => {
|
|
35
|
+
test('copies the sass directory and converts it into css output', done => {
|
|
36
|
+
const sassFile = `${sassPath}/sassFor.sass`
|
|
37
|
+
fs.writeFileSync(sassFile, sassContents)
|
|
38
|
+
expect.assertions(7)
|
|
39
|
+
const oldContents = fs.readFileSync(sassFile).toString()
|
|
40
|
+
expect(countMatches(oldContents, ';')).toEqual(0)
|
|
41
|
+
expect(countMatches(oldContents, ' {')).toEqual(0)
|
|
42
|
+
expect(countMatches(oldContents, '\n' +
|
|
43
|
+
' }')).toEqual(0)
|
|
44
|
+
const cssPath = gulpConfig.get('sass.to')
|
|
45
|
+
sassFor(sassFile)
|
|
46
|
+
.on('finish', () => {
|
|
47
|
+
expect(fs.existsSync(cssPath)).toBeTruthy()
|
|
48
|
+
const cssContents = fs.readFileSync(`${cssPath}/sassFor.css`).toString()
|
|
49
|
+
// Will add braces and semicolons
|
|
50
|
+
expect(countMatches(cssContents, ';')).toEqual(13)
|
|
51
|
+
expect(countMatches(cssContents, '{')).toEqual(3)
|
|
52
|
+
expect(countMatches(cssContents, '}')).toEqual(3)
|
|
53
|
+
done()
|
|
54
|
+
})
|
|
55
|
+
.on('error', error => {
|
|
56
|
+
console.error('Encountered error', error)
|
|
57
|
+
done()
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('also writes a minified .min.css next to the css output', done => {
|
|
62
|
+
const sassFile = `${sassPath}/sassFor.sass`
|
|
63
|
+
fs.writeFileSync(sassFile, sassContents)
|
|
64
|
+
expect.assertions(4)
|
|
65
|
+
const cssPath = gulpConfig.get('sass.to')
|
|
66
|
+
sassFor(sassFile)
|
|
67
|
+
.on('finish', () => {
|
|
68
|
+
const cssContents = fs.readFileSync(`${cssPath}/sassFor.css`).toString()
|
|
69
|
+
const minContents = fs.readFileSync(`${cssPath}/sassFor.min.css`).toString()
|
|
70
|
+
expect(minContents.length).toBeLessThan(cssContents.length)
|
|
71
|
+
expect(countMatches(minContents.trim(), '\n')).toEqual(0)
|
|
72
|
+
expect(minContents).toContain('outline:none')
|
|
73
|
+
expect(minContents).toContain('text-align:center')
|
|
74
|
+
done()
|
|
75
|
+
})
|
|
76
|
+
.on('error', error => {
|
|
77
|
+
console.error('Encountered error', error)
|
|
78
|
+
done()
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
})
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import http from 'node:http'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
|
|
5
|
-
// A real, previously-undiscovered bug fixed here: without a Content-Type header, a browser enforces strict MIME
|
|
6
|
-
// checking on <script type="module"> and refuses to load it at all - exactly the case this partial exists for.
|
|
7
|
-
const contentTypes = {
|
|
8
|
-
'.css': 'text/css',
|
|
9
|
-
'.gif': 'image/gif',
|
|
10
|
-
'.html': 'text/html',
|
|
11
|
-
'.ico': 'image/x-icon',
|
|
12
|
-
'.jpeg': 'image/jpeg',
|
|
13
|
-
'.jpg': 'image/jpeg',
|
|
14
|
-
'.js': 'text/javascript',
|
|
15
|
-
'.json': 'application/json',
|
|
16
|
-
'.mjs': 'text/javascript',
|
|
17
|
-
'.png': 'image/png',
|
|
18
|
-
'.svg': 'image/svg+xml',
|
|
19
|
-
'.woff': 'font/woff',
|
|
20
|
-
'.woff2': 'font/woff2'
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Serve a directory's real files over plain HTTP, for anything that needs a page loaded from a real URL rather
|
|
25
|
-
* than a bare file:// path - most commonly, a page using root-relative asset paths (/browser/...), which a
|
|
26
|
-
* file:// load resolves against the filesystem root instead of the page's own directory.
|
|
27
|
-
* @memberOf module:partials
|
|
28
|
-
* @param {string} rootDir - The directory to serve.
|
|
29
|
-
* @param {number} [port=0] - The port to listen on; 0 picks any free port.
|
|
30
|
-
* @returns {Promise<{server: http.Server, url: string}>} The running server, and its base URL - close the
|
|
31
|
-
* server yourself (server.close()) once done with it.
|
|
32
|
-
*/
|
|
33
|
-
export const serveStatic = (rootDir, port = 0) => new Promise((resolve, reject) => {
|
|
34
|
-
const server = http.createServer((req, res) => {
|
|
35
|
-
const filePath = path.join(rootDir, decodeURIComponent(req.url.split('?')[0]))
|
|
36
|
-
fs.readFile(filePath, (error, data) => {
|
|
37
|
-
if (error) {
|
|
38
|
-
res.statusCode = 404
|
|
39
|
-
return res.end(`Not found: ${req.url}`)
|
|
40
|
-
}
|
|
41
|
-
res.setHeader('Content-Type', contentTypes[path.extname(filePath)] || 'application/octet-stream')
|
|
42
|
-
res.end(data)
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
server.once('error', reject)
|
|
46
|
-
server.listen(port, '127.0.0.1', () => resolve({ server, url: `http://127.0.0.1:${server.address().port}` }))
|
|
47
|
-
})
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import http from 'node:http'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
// A real, previously-undiscovered bug fixed here: without a Content-Type header, a browser enforces strict MIME
|
|
6
|
+
// checking on <script type="module"> and refuses to load it at all - exactly the case this partial exists for.
|
|
7
|
+
const contentTypes = {
|
|
8
|
+
'.css': 'text/css',
|
|
9
|
+
'.gif': 'image/gif',
|
|
10
|
+
'.html': 'text/html',
|
|
11
|
+
'.ico': 'image/x-icon',
|
|
12
|
+
'.jpeg': 'image/jpeg',
|
|
13
|
+
'.jpg': 'image/jpeg',
|
|
14
|
+
'.js': 'text/javascript',
|
|
15
|
+
'.json': 'application/json',
|
|
16
|
+
'.mjs': 'text/javascript',
|
|
17
|
+
'.png': 'image/png',
|
|
18
|
+
'.svg': 'image/svg+xml',
|
|
19
|
+
'.woff': 'font/woff',
|
|
20
|
+
'.woff2': 'font/woff2'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Serve a directory's real files over plain HTTP, for anything that needs a page loaded from a real URL rather
|
|
25
|
+
* than a bare file:// path - most commonly, a page using root-relative asset paths (/browser/...), which a
|
|
26
|
+
* file:// load resolves against the filesystem root instead of the page's own directory.
|
|
27
|
+
* @memberOf module:partials
|
|
28
|
+
* @param {string} rootDir - The directory to serve.
|
|
29
|
+
* @param {number} [port=0] - The port to listen on; 0 picks any free port.
|
|
30
|
+
* @returns {Promise<{server: http.Server, url: string}>} The running server, and its base URL - close the
|
|
31
|
+
* server yourself (server.close()) once done with it.
|
|
32
|
+
*/
|
|
33
|
+
export const serveStatic = (rootDir, port = 0) => new Promise((resolve, reject) => {
|
|
34
|
+
const server = http.createServer((req, res) => {
|
|
35
|
+
const filePath = path.join(rootDir, decodeURIComponent(req.url.split('?')[0]))
|
|
36
|
+
fs.readFile(filePath, (error, data) => {
|
|
37
|
+
if (error) {
|
|
38
|
+
res.statusCode = 404
|
|
39
|
+
return res.end(`Not found: ${req.url}`)
|
|
40
|
+
}
|
|
41
|
+
res.setHeader('Content-Type', contentTypes[path.extname(filePath)] || 'application/octet-stream')
|
|
42
|
+
res.end(data)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
server.once('error', reject)
|
|
46
|
+
server.listen(port, '127.0.0.1', () => resolve({ server, url: `http://127.0.0.1:${server.address().port}` }))
|
|
47
|
+
})
|
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import * as setUp from '../test-helpers/setUp.mjs'
|
|
4
|
-
import { serveStatic } from './serveStatic.mjs'
|
|
5
|
-
|
|
6
|
-
setUp.setDefaults('test-serve-static')
|
|
7
|
-
const gulpConfig = setUp.gulpConfig
|
|
8
|
-
|
|
9
|
-
const write = (file, contents) => {
|
|
10
|
-
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
11
|
-
fs.writeFileSync(file, contents)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
beforeEach(
|
|
15
|
-
() => setUp.beforeEach().then(() => {
|
|
16
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
17
|
-
write(`${srcPath}/index.html`, '<!doctype html><html><body>hello</body></html>')
|
|
18
|
-
write(`${srcPath}/sub/page.html`, '<!doctype html><html><body>nested</body></html>')
|
|
19
|
-
write(`${srcPath}/module.js`, 'export default 1')
|
|
20
|
-
})
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
afterEach(setUp.afterEach)
|
|
24
|
-
|
|
25
|
-
describe('serveStatic', () => {
|
|
26
|
-
test('serves real files from the given directory over a real local HTTP server', async () => {
|
|
27
|
-
const { server, url } = await serveStatic(gulpConfig.get('srcPath'))
|
|
28
|
-
try {
|
|
29
|
-
expect(url).toMatch(/^http:\/\/127\.0\.0\.1:\d+$/)
|
|
30
|
-
const root = await fetch(`${url}/index.html`)
|
|
31
|
-
expect(await root.text()).toBe('<!doctype html><html><body>hello</body></html>')
|
|
32
|
-
const nested = await fetch(`${url}/sub/page.html`)
|
|
33
|
-
expect(await nested.text()).toBe('<!doctype html><html><body>nested</body></html>')
|
|
34
|
-
} finally {
|
|
35
|
-
server.close()
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
test('sends a real Content-Type, not a blank one - a browser refuses to load a <script type="module"> without one', async () => {
|
|
40
|
-
const { server, url } = await serveStatic(gulpConfig.get('srcPath'))
|
|
41
|
-
try {
|
|
42
|
-
const html = await fetch(`${url}/index.html`)
|
|
43
|
-
expect(html.headers.get('content-type')).toBe('text/html')
|
|
44
|
-
const script = await fetch(`${url}/module.js`)
|
|
45
|
-
expect(script.headers.get('content-type')).toBe('text/javascript')
|
|
46
|
-
} finally {
|
|
47
|
-
server.close()
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('responds 404 for a file that does not exist, rather than hanging or throwing', async () => {
|
|
52
|
-
const { server, url } = await serveStatic(gulpConfig.get('srcPath'))
|
|
53
|
-
try {
|
|
54
|
-
const response = await fetch(`${url}/nothing-here.html`)
|
|
55
|
-
expect(response.status).toBe(404)
|
|
56
|
-
} finally {
|
|
57
|
-
server.close()
|
|
58
|
-
}
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('two servers for the same directory each get their own free port', async () => {
|
|
62
|
-
const first = await serveStatic(gulpConfig.get('srcPath'))
|
|
63
|
-
const second = await serveStatic(gulpConfig.get('srcPath'))
|
|
64
|
-
try {
|
|
65
|
-
expect(first.url).not.toBe(second.url)
|
|
66
|
-
} finally {
|
|
67
|
-
first.server.close()
|
|
68
|
-
second.server.close()
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
})
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import * as setUp from '../test-helpers/setUp.mjs'
|
|
4
|
+
import { serveStatic } from './serveStatic.mjs'
|
|
5
|
+
|
|
6
|
+
setUp.setDefaults('test-serve-static')
|
|
7
|
+
const gulpConfig = setUp.gulpConfig
|
|
8
|
+
|
|
9
|
+
const write = (file, contents) => {
|
|
10
|
+
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
11
|
+
fs.writeFileSync(file, contents)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
beforeEach(
|
|
15
|
+
() => setUp.beforeEach().then(() => {
|
|
16
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
17
|
+
write(`${srcPath}/index.html`, '<!doctype html><html><body>hello</body></html>')
|
|
18
|
+
write(`${srcPath}/sub/page.html`, '<!doctype html><html><body>nested</body></html>')
|
|
19
|
+
write(`${srcPath}/module.js`, 'export default 1')
|
|
20
|
+
})
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
afterEach(setUp.afterEach)
|
|
24
|
+
|
|
25
|
+
describe('serveStatic', () => {
|
|
26
|
+
test('serves real files from the given directory over a real local HTTP server', async () => {
|
|
27
|
+
const { server, url } = await serveStatic(gulpConfig.get('srcPath'))
|
|
28
|
+
try {
|
|
29
|
+
expect(url).toMatch(/^http:\/\/127\.0\.0\.1:\d+$/)
|
|
30
|
+
const root = await fetch(`${url}/index.html`)
|
|
31
|
+
expect(await root.text()).toBe('<!doctype html><html><body>hello</body></html>')
|
|
32
|
+
const nested = await fetch(`${url}/sub/page.html`)
|
|
33
|
+
expect(await nested.text()).toBe('<!doctype html><html><body>nested</body></html>')
|
|
34
|
+
} finally {
|
|
35
|
+
server.close()
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('sends a real Content-Type, not a blank one - a browser refuses to load a <script type="module"> without one', async () => {
|
|
40
|
+
const { server, url } = await serveStatic(gulpConfig.get('srcPath'))
|
|
41
|
+
try {
|
|
42
|
+
const html = await fetch(`${url}/index.html`)
|
|
43
|
+
expect(html.headers.get('content-type')).toBe('text/html')
|
|
44
|
+
const script = await fetch(`${url}/module.js`)
|
|
45
|
+
expect(script.headers.get('content-type')).toBe('text/javascript')
|
|
46
|
+
} finally {
|
|
47
|
+
server.close()
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('responds 404 for a file that does not exist, rather than hanging or throwing', async () => {
|
|
52
|
+
const { server, url } = await serveStatic(gulpConfig.get('srcPath'))
|
|
53
|
+
try {
|
|
54
|
+
const response = await fetch(`${url}/nothing-here.html`)
|
|
55
|
+
expect(response.status).toBe(404)
|
|
56
|
+
} finally {
|
|
57
|
+
server.close()
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('two servers for the same directory each get their own free port', async () => {
|
|
62
|
+
const first = await serveStatic(gulpConfig.get('srcPath'))
|
|
63
|
+
const second = await serveStatic(gulpConfig.get('srcPath'))
|
|
64
|
+
try {
|
|
65
|
+
expect(first.url).not.toBe(second.url)
|
|
66
|
+
} finally {
|
|
67
|
+
first.server.close()
|
|
68
|
+
second.server.close()
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
})
|
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
import { dest, src } from 'gulp'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import * as gulpConfig from '../../gulp.config.mjs'
|
|
4
|
-
import { importModule, requirePeer } from './loadPeer.mjs'
|
|
5
|
-
|
|
6
|
-
// gulp-ts-compile ships ESM-only (no CJS build - see its own package.json), see importModule for how it is imported.
|
|
7
|
-
const importGulpTsCompile = () => importModule('gulp-ts-compile')
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Wrap a stream in a promise that resolves once it finishes writing.
|
|
11
|
-
* @memberOf module:partials
|
|
12
|
-
* @param {stream.Stream} stream
|
|
13
|
-
* @returns {Promise<void>}
|
|
14
|
-
*/
|
|
15
|
-
const installHint = 'Install it in your project with: npm install --save-dev typescript'
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Load the project's own copy of TypeScript (an optional peer dependency, only needed when the typescript task is
|
|
19
|
-
* enabled) from the project being built, so projects which do not use TypeScript never need it installed.
|
|
20
|
-
* @memberOf module:partials
|
|
21
|
-
* @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
|
|
22
|
-
* @returns {Object} The TypeScript compiler API module.
|
|
23
|
-
* @throws {Error} With install instructions when typescript is not installed.
|
|
24
|
-
*/
|
|
25
|
-
export const loadTypescript = (projectPath = process.cwd()) => requirePeer('typescript', { task: 'typescript', installHint, projectPath })
|
|
26
|
-
|
|
27
|
-
const streamToPromise = (stream) => new Promise((resolve, reject) => {
|
|
28
|
-
stream.on('finish', resolve)
|
|
29
|
-
stream.on('error', reject)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Read a tsconfig.json file into real typescript.CompilerOptions values, using only TypeScript's stable, current,
|
|
34
|
-
* public config-reading API (the same one `tsc --project` itself uses internally) - never
|
|
35
|
-
* `ts.convertCompilerOptionsFromJson`, which is exactly the kind of internal/legacy surface that broke
|
|
36
|
-
* gulp-typescript when a removed API call started throwing under TypeScript 7.
|
|
37
|
-
* @memberOf module:partials
|
|
38
|
-
* @param {string} configPath - Path to a tsconfig.json file.
|
|
39
|
-
* @returns {ts.CompilerOptions} TypeScript's compiler options
|
|
40
|
-
*/
|
|
41
|
-
const readCompilerOptions = (ts, configPath) => {
|
|
42
|
-
const configFile = ts.readConfigFile(configPath, ts.sys.readFile)
|
|
43
|
-
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))
|
|
44
|
-
return parsedConfig.options
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Starting at the source directory, find all the ts files and convert them into the distribution directory.
|
|
49
|
-
* @memberOf module:partials
|
|
50
|
-
* @param {string|array} [srcPath='']
|
|
51
|
-
* @param {string} [distPath='']
|
|
52
|
-
* @param {function(): Promise<Function>} [loadTsCompile] - Resolves the `gulp-ts-compile` default export. Real
|
|
53
|
-
* callers should never need to pass this - it exists so tests can inject a stand-in compiler, sidestepping the
|
|
54
|
-
* genuine dynamic `import()` above that this project's current CommonJS-transform-based Jest setup cannot
|
|
55
|
-
* execute without a broader (and riskier) migration to Jest's native ESM support. gulp-ts-compile's own test
|
|
56
|
-
* suite already covers real TypeScript-compile correctness - this function's own tests only need to verify its
|
|
57
|
-
* config resolution and stream wiring.
|
|
58
|
-
* @returns {Function}
|
|
59
|
-
*/
|
|
60
|
-
export const tsFor = (
|
|
61
|
-
srcPath = gulpConfig.get('typescript.from'),
|
|
62
|
-
distPath = gulpConfig.get('typescript.to'),
|
|
63
|
-
loadTsCompile = () => importGulpTsCompile().then(({ default: tsCompile }) => tsCompile)
|
|
64
|
-
) => {
|
|
65
|
-
if (gulpConfig.get('typescript.enabled') === false) {
|
|
66
|
-
return () => {}
|
|
67
|
-
}
|
|
68
|
-
const ts = loadTypescript()
|
|
69
|
-
const configPath = gulpConfig.get('typescript.config')
|
|
70
|
-
// When no tsconfig.json is configured, target/module are pinned explicitly rather than left for TypeScript's
|
|
71
|
-
// own compiler defaults - those defaults have already shifted once across a TypeScript version bump in this
|
|
72
|
-
// project's own history (silently changing whether output keeps `const`/`let` or downlevels to `var`), and
|
|
73
|
-
// pinning them keeps this task's output stable across future TypeScript upgrades too. ES5/CommonJS matches
|
|
74
|
-
// what the downstream babel/browserify bundling pipeline has always assumed it receives.
|
|
75
|
-
const compilerOptions = configPath
|
|
76
|
-
? readCompilerOptions(ts, configPath)
|
|
77
|
-
: { declaration: true, target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS, esModuleInterop: false }
|
|
78
|
-
// Accepts gulp's own callback-style task convention (an optional `done`, called once finished) rather than
|
|
79
|
-
// just returning a Promise, since callers may invoke the returned function directly with a callback instead
|
|
80
|
-
// of relying on gulp's own runner to observe a returned Promise.
|
|
81
|
-
return (done) => {
|
|
82
|
-
const compile = async () => {
|
|
83
|
-
const tsCompile = await loadTsCompile()
|
|
84
|
-
const tsResult = src(srcPath).pipe(tsCompile(compilerOptions))
|
|
85
|
-
await Promise.all([
|
|
86
|
-
streamToPromise(tsResult.dts.pipe(dest(distPath))),
|
|
87
|
-
streamToPromise(tsResult.js.pipe(dest(distPath)))
|
|
88
|
-
])
|
|
89
|
-
}
|
|
90
|
-
return typeof done === 'function' ? compile().then(() => done(), done) : compile()
|
|
91
|
-
}
|
|
92
|
-
}
|
|
1
|
+
import { dest, src } from 'gulp'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import * as gulpConfig from '../../gulp.config.mjs'
|
|
4
|
+
import { importModule, requirePeer } from './loadPeer.mjs'
|
|
5
|
+
|
|
6
|
+
// gulp-ts-compile ships ESM-only (no CJS build - see its own package.json), see importModule for how it is imported.
|
|
7
|
+
const importGulpTsCompile = () => importModule('gulp-ts-compile')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Wrap a stream in a promise that resolves once it finishes writing.
|
|
11
|
+
* @memberOf module:partials
|
|
12
|
+
* @param {stream.Stream} stream
|
|
13
|
+
* @returns {Promise<void>}
|
|
14
|
+
*/
|
|
15
|
+
const installHint = 'Install it in your project with: npm install --save-dev typescript'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Load the project's own copy of TypeScript (an optional peer dependency, only needed when the typescript task is
|
|
19
|
+
* enabled) from the project being built, so projects which do not use TypeScript never need it installed.
|
|
20
|
+
* @memberOf module:partials
|
|
21
|
+
* @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
|
|
22
|
+
* @returns {Object} The TypeScript compiler API module.
|
|
23
|
+
* @throws {Error} With install instructions when typescript is not installed.
|
|
24
|
+
*/
|
|
25
|
+
export const loadTypescript = (projectPath = process.cwd()) => requirePeer('typescript', { task: 'typescript', installHint, projectPath })
|
|
26
|
+
|
|
27
|
+
const streamToPromise = (stream) => new Promise((resolve, reject) => {
|
|
28
|
+
stream.on('finish', resolve)
|
|
29
|
+
stream.on('error', reject)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Read a tsconfig.json file into real typescript.CompilerOptions values, using only TypeScript's stable, current,
|
|
34
|
+
* public config-reading API (the same one `tsc --project` itself uses internally) - never
|
|
35
|
+
* `ts.convertCompilerOptionsFromJson`, which is exactly the kind of internal/legacy surface that broke
|
|
36
|
+
* gulp-typescript when a removed API call started throwing under TypeScript 7.
|
|
37
|
+
* @memberOf module:partials
|
|
38
|
+
* @param {string} configPath - Path to a tsconfig.json file.
|
|
39
|
+
* @returns {ts.CompilerOptions} TypeScript's compiler options
|
|
40
|
+
*/
|
|
41
|
+
const readCompilerOptions = (ts, configPath) => {
|
|
42
|
+
const configFile = ts.readConfigFile(configPath, ts.sys.readFile)
|
|
43
|
+
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))
|
|
44
|
+
return parsedConfig.options
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Starting at the source directory, find all the ts files and convert them into the distribution directory.
|
|
49
|
+
* @memberOf module:partials
|
|
50
|
+
* @param {string|array} [srcPath='']
|
|
51
|
+
* @param {string} [distPath='']
|
|
52
|
+
* @param {function(): Promise<Function>} [loadTsCompile] - Resolves the `gulp-ts-compile` default export. Real
|
|
53
|
+
* callers should never need to pass this - it exists so tests can inject a stand-in compiler, sidestepping the
|
|
54
|
+
* genuine dynamic `import()` above that this project's current CommonJS-transform-based Jest setup cannot
|
|
55
|
+
* execute without a broader (and riskier) migration to Jest's native ESM support. gulp-ts-compile's own test
|
|
56
|
+
* suite already covers real TypeScript-compile correctness - this function's own tests only need to verify its
|
|
57
|
+
* config resolution and stream wiring.
|
|
58
|
+
* @returns {Function}
|
|
59
|
+
*/
|
|
60
|
+
export const tsFor = (
|
|
61
|
+
srcPath = gulpConfig.get('typescript.from'),
|
|
62
|
+
distPath = gulpConfig.get('typescript.to'),
|
|
63
|
+
loadTsCompile = () => importGulpTsCompile().then(({ default: tsCompile }) => tsCompile)
|
|
64
|
+
) => {
|
|
65
|
+
if (gulpConfig.get('typescript.enabled') === false) {
|
|
66
|
+
return () => {}
|
|
67
|
+
}
|
|
68
|
+
const ts = loadTypescript()
|
|
69
|
+
const configPath = gulpConfig.get('typescript.config')
|
|
70
|
+
// When no tsconfig.json is configured, target/module are pinned explicitly rather than left for TypeScript's
|
|
71
|
+
// own compiler defaults - those defaults have already shifted once across a TypeScript version bump in this
|
|
72
|
+
// project's own history (silently changing whether output keeps `const`/`let` or downlevels to `var`), and
|
|
73
|
+
// pinning them keeps this task's output stable across future TypeScript upgrades too. ES5/CommonJS matches
|
|
74
|
+
// what the downstream babel/browserify bundling pipeline has always assumed it receives.
|
|
75
|
+
const compilerOptions = configPath
|
|
76
|
+
? readCompilerOptions(ts, configPath)
|
|
77
|
+
: { declaration: true, target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS, esModuleInterop: false }
|
|
78
|
+
// Accepts gulp's own callback-style task convention (an optional `done`, called once finished) rather than
|
|
79
|
+
// just returning a Promise, since callers may invoke the returned function directly with a callback instead
|
|
80
|
+
// of relying on gulp's own runner to observe a returned Promise.
|
|
81
|
+
return (done) => {
|
|
82
|
+
const compile = async () => {
|
|
83
|
+
const tsCompile = await loadTsCompile()
|
|
84
|
+
const tsResult = src(srcPath).pipe(tsCompile(compilerOptions))
|
|
85
|
+
await Promise.all([
|
|
86
|
+
streamToPromise(tsResult.dts.pipe(dest(distPath))),
|
|
87
|
+
streamToPromise(tsResult.js.pipe(dest(distPath)))
|
|
88
|
+
])
|
|
89
|
+
}
|
|
90
|
+
return typeof done === 'function' ? compile().then(() => done(), done) : compile()
|
|
91
|
+
}
|
|
92
|
+
}
|