js-build-tools 5.7.0 → 6.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.
Files changed (58) hide show
  1. package/README.md +1 -1
  2. package/dist/build.js +65 -64
  3. package/dist/build.min.js +1 -1
  4. package/dist/bundle.js +40 -40
  5. package/dist/bundleMinify.js +18 -18
  6. package/dist/compileReadme.js +7 -7
  7. package/dist/copyFonts.js +10 -10
  8. package/dist/default.js +12 -12
  9. package/dist/dist.js +7 -7
  10. package/dist/distMinify.js +10 -10
  11. package/dist/images.js +7 -7
  12. package/dist/partials/addToReadme.js +24 -24
  13. package/dist/partials/imagesFor.js +42 -42
  14. package/dist/partials/loadPeer.js +70 -70
  15. package/dist/partials/neostandardLint.js +144 -0
  16. package/dist/partials/tsFor.js +70 -70
  17. package/dist/partials/typeDocsFor.js +202 -202
  18. package/dist/partials.js +136 -136
  19. package/dist/partials.min.js +1 -1
  20. package/dist/sass.js +7 -7
  21. package/dist/sourceLint.js +33 -0
  22. package/dist/sourceLint.min.js +1 -0
  23. package/dist/test-helpers/neostandardLintWithRealNeostandard.js +48 -0
  24. package/dist/test-helpers/setUp.js +94 -94
  25. package/dist/testFull.js +13 -13
  26. package/dist/testHelpers.js +8 -8
  27. package/dist/testQuick.js +13 -13
  28. package/dist/typeDocs.js +9 -9
  29. package/dist/typeScript.js +6 -6
  30. package/dist/utilities/convertMjsFilesForDocs.js +36 -36
  31. package/dist/utilities/esmNamedExportsToCjs.js +18 -18
  32. package/dist/utilities/getBundleConfigs.js +27 -27
  33. package/dist/watchFull.js +7 -7
  34. package/dist/watchTest.js +11 -11
  35. package/functions/build.mjs +9 -8
  36. package/functions/build.test.mjs +18 -25
  37. package/functions/partials/neostandardLint.mjs +118 -0
  38. package/functions/partials/neostandardLint.test.mjs +109 -0
  39. package/functions/partials.mjs +1 -1
  40. package/functions/sourceLint.mjs +24 -0
  41. package/functions/sourceLint.test.mjs +73 -0
  42. package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +38 -0
  43. package/gulpfile.base.js +2 -4
  44. package/gulpfile.base.mjs +1 -2
  45. package/package.json +7 -6
  46. package/dist/bundleLint.js +0 -28
  47. package/dist/bundleLint.min.js +0 -1
  48. package/dist/distLint.js +0 -20
  49. package/dist/distLint.min.js +0 -1
  50. package/dist/partials/standardLint.js +0 -94
  51. package/dist/test-helpers/standardLintWithRealStandard.js +0 -28
  52. package/functions/bundleLint.mjs +0 -18
  53. package/functions/bundleLint.test.mjs +0 -85
  54. package/functions/distLint.mjs +0 -12
  55. package/functions/distLint.test.mjs +0 -62
  56. package/functions/partials/standardLint.mjs +0 -78
  57. package/functions/partials/standardLint.test.mjs +0 -99
  58. package/functions/test-helpers/standardLintWithRealStandard.mjs +0 -21
@@ -1,18 +0,0 @@
1
- import { dest, src } from 'gulp'
2
- import * as gulpConfig from '../gulp.config.mjs'
3
- import { standardLint } from './partials/standardLint.mjs'
4
- import { getBundleConfigs } from './utilities/getBundleConfigs.mjs'
5
-
6
- /**
7
- * Applies Standard code style linting to every bundled file (the primary bundle, plus any
8
- * additional ones from browser.bundles). The lint step itself never varies per bundle, so this is
9
- * one shared src()/dest() pipeline fed every bundle's filename at once, rather than one pipeline
10
- * per bundle - gulp's src()/dest() both accept an array of paths natively.
11
- * @memberOf module:js-build-tools
12
- * @returns {stream.Stream}
13
- */
14
- export const bundleLint = () => src(
15
- getBundleConfigs().map(({ name }) => `${gulpConfig.get('browser.to')}/${name}.js`)
16
- )
17
- .pipe(standardLint({ fix: true }))
18
- .pipe(dest(gulpConfig.get('browser.to')))
@@ -1,85 +0,0 @@
1
- import fs from 'fs'
2
- import * as setUp from './test-helpers/setUp.mjs'
3
- import { bundleLint } from './bundleLint.mjs'
4
- import { countMatches } from 'test-filesystem'
5
-
6
- // Run the real Standard (in a subprocess) - Jest's CommonJS transform can't load the ESM-only package itself.
7
- jest.mock('./partials/standardLint.mjs', () => require('./test-helpers/standardLintWithRealStandard.mjs'))
8
-
9
- setUp.setDefaults('test-bundle-lint')
10
- const gulpConfig = setUp.gulpConfig
11
-
12
- const lintableContents = 'const gulpConfig = require("../gulp.config.js");\n' +
13
- 'const { dest, src } = require("gulp");\n' +
14
- 'const standard = require("gulp-standard");\n' +
15
- '\n' +
16
- '/**\n' +
17
- ' * Applies Standard code style linting to distribution files.\n' +
18
- ' * @returns {*}\n' +
19
- ' */\n' +
20
- 'const bundleLint = () => src(`${gulpConfig.get(\"browserPath\")}/${gulpConfig.get(\"browserName\")}.js`)\n' +
21
- ' .pipe(standard({ fix: true }))\n' +
22
- ' .pipe(standard.reporter("default", {\n' +
23
- ' fix: true,\n' +
24
- ' quiet: true\n' +
25
- ' }))\n' +
26
- ' .pipe(dest(gulpConfig.get("browserPath")));\n' +
27
- '\n' +
28
- 'module.exports = bundleLint;'
29
-
30
- beforeEach(
31
- () => setUp.beforeEach()
32
- .then(
33
- async () => {
34
- const browserPath = gulpConfig.get('browser.to')
35
- const browserName = gulpConfig.get('browser.name')
36
- await fs.mkdirSync(browserPath)
37
- return fs.writeFileSync(`${browserPath}/${browserName}.js`, lintableContents)
38
- }
39
- )
40
- )
41
-
42
- afterEach(setUp.afterEach)
43
-
44
- describe('bundleLint', () => {
45
- test('copies the src directory and babelifies it into the dist directory', done => {
46
- const browserPath = gulpConfig.get('browser.to')
47
- const browserName = gulpConfig.get('browser.name')
48
- const fullPath = `${browserPath}/${browserName}.js`
49
- const oldContents = fs.readFileSync(fullPath).toString()
50
- expect.assertions(4)
51
- expect(countMatches(oldContents, '"')).toEqual(14)
52
- expect(countMatches(oldContents, ';')).toEqual(5)
53
- bundleLint()
54
- .on('finish', () => {
55
- const lintedContents = fs.readFileSync(fullPath).toString()
56
- expect(countMatches(lintedContents, '"')).toEqual(0)
57
- expect(countMatches(lintedContents, ';')).toEqual(0)
58
- done()
59
- })
60
- .on('error', error => {
61
- console.error('Encountered error', error)
62
- done()
63
- })
64
- }, 10000)
65
-
66
- test('lints every additional bundle too, not just the primary one', done => {
67
- const browserPath = gulpConfig.get('browser.to')
68
- const renderOnlyFile = `${browserPath}/renderOnly.js`
69
- fs.writeFileSync(renderOnlyFile, lintableContents)
70
- gulpConfig.set('browser.bundles', [{ name: 'renderOnly' }])
71
- expect.assertions(2)
72
- bundleLint()
73
- .on('finish', () => {
74
- const lintedContents = fs.readFileSync(renderOnlyFile).toString()
75
- expect(countMatches(lintedContents, '"')).toEqual(0)
76
- expect(countMatches(lintedContents, ';')).toEqual(0)
77
- gulpConfig.set('browser.bundles', [])
78
- done()
79
- })
80
- .on('error', error => {
81
- console.error('Encountered error', error)
82
- done(error)
83
- })
84
- }, 10000)
85
- })
@@ -1,12 +0,0 @@
1
- import * as gulpConfig from '../gulp.config.mjs'
2
- import { dest, src } from 'gulp'
3
- import { standardLint } from './partials/standardLint.mjs'
4
-
5
- /**
6
- * Applies Standard code style linting to distribution files.
7
- * @memberOf module:js-build-tools
8
- * @returns {*}
9
- */
10
- export const distLint = () => src(gulpConfig.get('browser.from'))
11
- .pipe(standardLint({ fix: true }))
12
- .pipe(dest(gulpConfig.get('dist.to')))
@@ -1,62 +0,0 @@
1
- import fs from 'fs'
2
- import * as setUp from './test-helpers/setUp.mjs'
3
- import { distLint } from './distLint.mjs'
4
- import { countMatches } from 'test-filesystem'
5
-
6
- // Run the real Standard (in a subprocess) - Jest's CommonJS transform can't load the ESM-only package itself.
7
- jest.mock('./partials/standardLint.mjs', () => require('./test-helpers/standardLintWithRealStandard.mjs'))
8
-
9
- setUp.setDefaults('test-dist-lint')
10
- const gulpConfig = setUp.gulpConfig
11
-
12
- const lintableContents = 'const gulpConfig = require("../gulp.config.js");\n' +
13
- 'const { dest, src } = require("gulp");\n' +
14
- 'const standard = require("gulp-standard");\n' +
15
- '\n' +
16
- '/**\n' +
17
- ' * Applies Standard code style linting to distribution files.\n' +
18
- ' * @returns {*}\n' +
19
- ' */\n' +
20
- 'const distLint = () => src(gulpConfig.get("distSearch"))\n' +
21
- ' .pipe(standard({ fix: true }))\n' +
22
- ' .pipe(standard.reporter("default", {\n' +
23
- ' fix: true,\n' +
24
- ' quiet: true\n' +
25
- ' }))\n' +
26
- ' .pipe(dest(gulpConfig.get("distPath")));\n' +
27
- '\n' +
28
- 'module.exports = distLint;'
29
-
30
- beforeEach(
31
- () => setUp.beforeEach()
32
- .then(
33
- async () => {
34
- const distPath = gulpConfig.get('dist.to')
35
- await fs.mkdirSync(distPath)
36
- return fs.writeFileSync(`${distPath}/distLint.js`, lintableContents)
37
- }
38
- )
39
- )
40
-
41
- afterEach(setUp.afterEach)
42
-
43
- describe('distLint', () => {
44
- test('copies the src directory and babelifies it into the dist directory', done => {
45
- const distPath = gulpConfig.get('dist.to')
46
- const oldContents = fs.readFileSync(`${distPath}/distLint.js`).toString()
47
- expect.assertions(4)
48
- expect(countMatches(oldContents, '"')).toEqual(12)
49
- expect(countMatches(oldContents, ';')).toEqual(5)
50
- distLint()
51
- .on('finish', () => {
52
- const lintedContents = fs.readFileSync(`${distPath}/distLint.js`).toString()
53
- expect(countMatches(lintedContents, '"')).toEqual(0)
54
- expect(countMatches(lintedContents, ';')).toEqual(0)
55
- done()
56
- })
57
- .on('error', error => {
58
- console.error('Encountered error', error)
59
- done()
60
- })
61
- }, 10000)
62
- })
@@ -1,78 +0,0 @@
1
- import path from 'node:path'
2
- import through from 'through2'
3
- import { importModule } from './loadPeer.mjs'
4
-
5
- // `standard` (17+) ships ESM-only, see importModule for how it is imported.
6
- const importStandard = () => importModule('standard')
7
-
8
- /**
9
- * Print a file's lint messages, if it has any.
10
- * @memberOf module:partials
11
- * @param {import('vinyl')} file
12
- * @param {{messages: Array<{line: number, column: number, message: string}>, errorCount: number, warningCount: number}} result
13
- * @returns {undefined}
14
- */
15
- const printFileReport = (file, result) => {
16
- if (!result.messages.length) {
17
- return
18
- }
19
- console.log(path.relative(file.cwd, file.path))
20
- result.messages.forEach(({ line, column, message }) => console.log(`line ${line}:${column}\t${message}`))
21
- console.log(`✖ ${result.errorCount} error\t⚠ ${result.warningCount} warning\n`)
22
- }
23
-
24
- /**
25
- * Lint every file streaming through with JavaScript Standard Style and, unless `fix` is false, apply the automatic
26
- * fixes to the file's contents so a following `dest()` writes the fixed version. Remaining problems are printed
27
- * along with a summary once the stream ends; they never fail the build.
28
- *
29
- * Project-level Standard configuration (the `standard` field in package.json: ignore, env, globals, ...) is honored
30
- * because the file's own path and cwd are handed to Standard.
31
- * @memberOf module:partials
32
- * @param {Object} [options={}]
33
- * @param {boolean} [options.fix=true] - Apply Standard's automatic fixes to the file contents.
34
- * @param {function(): Promise<{lintText: Function}>} [loadStandard] - Resolves the `standard` module. Real callers
35
- * should never need to pass this - it exists so tests can supply a stand-in, since this project's
36
- * CommonJS-transform-based Jest setup cannot execute a real dynamic import() of an ES module.
37
- * @returns {import('stream').Transform}
38
- */
39
- export const standardLint = (
40
- { fix = true } = {},
41
- loadStandard = () => importStandard().then(({ default: standard }) => standard)
42
- ) => {
43
- const totals = { errors: 0, warnings: 0 }
44
- return through.obj(
45
- function (file, enc, callback) {
46
- if (file.isNull()) {
47
- callback(null, file)
48
- return
49
- }
50
- if (file.isStream()) {
51
- callback(new Error('standardLint: streaming file contents are not supported.'))
52
- return
53
- }
54
- loadStandard()
55
- .then(standard => standard.lintText(file.contents.toString(), { filename: file.path, cwd: file.cwd, fix }))
56
- .then(results => {
57
- // No result at all means the file is ignored by the project's Standard configuration.
58
- const [result] = results
59
- if (result) {
60
- if (typeof result.output === 'string') {
61
- file.contents = Buffer.from(result.output)
62
- }
63
- totals.errors += result.errorCount
64
- totals.warnings += result.warningCount
65
- printFileReport(file, result)
66
- }
67
- callback(null, file)
68
- }, callback)
69
- },
70
- function (callback) {
71
- console.log('Standard linter results')
72
- console.log('======================================')
73
- console.log(`✖ Errors total: ${totals.errors}`)
74
- console.log(`⚠ Warnings total: ${totals.warnings}\n`)
75
- callback()
76
- }
77
- )
78
- }
@@ -1,99 +0,0 @@
1
- import Vinyl from 'vinyl'
2
- import { Readable } from 'node:stream'
3
- import { standardLint } from './standardLint.mjs'
4
-
5
- const makeFile = (contents, filePath = '/project/dist/example.js') => new Vinyl({
6
- cwd: '/project',
7
- base: '/project/dist',
8
- path: filePath,
9
- contents
10
- })
11
-
12
- const run = (transform, files) => new Promise((resolve, reject) => {
13
- const out = []
14
- transform.on('data', file => out.push(file)).on('end', () => resolve(out)).on('error', reject)
15
- files.forEach(file => transform.write(file))
16
- transform.end()
17
- })
18
-
19
- const fakeStandard = (resultFor) => ({
20
- lintText: jest.fn((text, options) => Promise.resolve(resultFor(text, options)))
21
- })
22
-
23
- let logSpy
24
-
25
- beforeEach(() => {
26
- logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
27
- })
28
-
29
- afterEach(() => {
30
- logSpy.mockRestore()
31
- })
32
-
33
- describe('standardLint', () => {
34
- test('replaces file contents with the fixed output and hands Standard the file path, cwd and fix option', async () => {
35
- expect.assertions(3)
36
- const standard = fakeStandard((text) => [{ messages: [], errorCount: 0, warningCount: 0, output: text.replace(/"/g, '\'') }])
37
- const [linted] = await run(standardLint({ fix: true }, () => Promise.resolve(standard)), [makeFile(Buffer.from('const a = "b"'))])
38
- expect(linted.contents.toString()).toEqual('const a = \'b\'')
39
- expect(standard.lintText).toHaveBeenCalledWith('const a = "b"', { filename: '/project/dist/example.js', cwd: '/project', fix: true })
40
- expect(linted.path).toEqual('/project/dist/example.js')
41
- })
42
-
43
- test('leaves the contents alone when Standard has no fixed output (nothing needed fixing)', async () => {
44
- expect.assertions(1)
45
- const standard = fakeStandard(() => [{ messages: [], errorCount: 0, warningCount: 0 }])
46
- const [linted] = await run(standardLint({}, () => Promise.resolve(standard)), [makeFile(Buffer.from('const a = 1'))])
47
- expect(linted.contents.toString()).toEqual('const a = 1')
48
- })
49
-
50
- test('passes fix: false through so nothing is rewritten', async () => {
51
- expect.assertions(1)
52
- const standard = fakeStandard(() => [{ messages: [], errorCount: 0, warningCount: 0 }])
53
- await run(standardLint({ fix: false }, () => Promise.resolve(standard)), [makeFile(Buffer.from('x'))])
54
- expect(standard.lintText.mock.calls[0][1].fix).toBe(false)
55
- })
56
-
57
- test('passes a file through untouched when the project ignores it (Standard returns no results)', async () => {
58
- expect.assertions(2)
59
- const standard = fakeStandard(() => [])
60
- const [linted] = await run(standardLint({}, () => Promise.resolve(standard)), [makeFile(Buffer.from('var x=1'))])
61
- expect(linted.contents.toString()).toEqual('var x=1')
62
- expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 0')
63
- })
64
-
65
- test('skips null-content files without linting them', async () => {
66
- expect.assertions(2)
67
- const standard = fakeStandard(() => [])
68
- const [passed] = await run(standardLint({}, () => Promise.resolve(standard)), [makeFile(null)])
69
- expect(passed.isNull()).toBeTruthy()
70
- expect(standard.lintText).not.toHaveBeenCalled()
71
- })
72
-
73
- test('errors on streaming file contents, which cannot be linted', async () => {
74
- expect.assertions(1)
75
- const streamFile = makeFile(Readable.from(['x']))
76
- await expect(run(standardLint({}, () => Promise.resolve(fakeStandard(() => []))), [streamFile])).rejects.toThrow(/streaming/)
77
- })
78
-
79
- test('prints per-file problems and a summary of totals across all files, without failing', async () => {
80
- expect.assertions(5)
81
- const standard = fakeStandard((text, { filename }) => filename.endsWith('a.js')
82
- ? [{ messages: [{ line: 2, column: 7, message: 'unused b' }, { line: 3, column: 1, message: 'bad thing' }], errorCount: 2, warningCount: 0 }]
83
- : [{ messages: [{ line: 1, column: 1, message: 'just a warning' }], errorCount: 0, warningCount: 1 }])
84
- const out = await run(
85
- standardLint({}, () => Promise.resolve(standard)),
86
- [makeFile(Buffer.from('a'), '/project/dist/a.js'), makeFile(Buffer.from('b'), '/project/dist/b.js')]
87
- )
88
- expect(out).toHaveLength(2)
89
- expect(logSpy).toHaveBeenCalledWith('dist/a.js')
90
- expect(logSpy).toHaveBeenCalledWith('line 2:7\tunused b')
91
- expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 2')
92
- expect(logSpy).toHaveBeenCalledWith('⚠ Warnings total: 1\n')
93
- })
94
-
95
- test('surfaces a failure to load or run Standard as a stream error', async () => {
96
- expect.assertions(1)
97
- await expect(run(standardLint({}, () => Promise.reject(new Error('cannot load'))), [makeFile(Buffer.from('x'))])).rejects.toThrow('cannot load')
98
- })
99
- })
@@ -1,21 +0,0 @@
1
- import { execFileSync } from 'node:child_process'
2
-
3
- // Jest's CommonJS transform cannot load `standard` (ESM-only) or run a real dynamic import(), so tests that need
4
- // genuine Standard behavior run the actual `standard` package in a plain Node subprocess instead of faking it.
5
- const script = 'import { readFileSync } from \'node:fs\'\n' +
6
- 'import standard from \'standard\'\n' +
7
- 'const { text, options } = JSON.parse(readFileSync(0, \'utf8\'))\n' +
8
- 'process.stdout.write(JSON.stringify(await standard.lintText(text, options)))\n'
9
-
10
- export const loadStandardViaSubprocess = () => Promise.resolve({
11
- lintText: (text, options) => Promise.resolve().then(() => JSON.parse(execFileSync(
12
- process.execPath,
13
- ['--input-type=module', '--eval', script],
14
- { input: JSON.stringify({ text, options }), encoding: 'utf8', cwd: process.cwd(), maxBuffer: 256 * 1024 * 1024 }
15
- )))
16
- })
17
-
18
- const actual = jest.requireActual('../partials/standardLint.mjs')
19
-
20
- // Drop-in replacement for the partial module (see jest.mock in the lint/build tests): same API, real Standard.
21
- export const standardLint = (options) => actual.standardLint(options, loadStandardViaSubprocess)