js-build-tools 5.6.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.
- package/README.md +98 -3
- package/dist/build.js +65 -64
- package/dist/build.min.js +1 -1
- package/dist/bundle.js +40 -40
- package/dist/bundleMinify.js +18 -18
- package/dist/compileReadme.js +7 -7
- package/dist/copyFonts.js +10 -10
- package/dist/default.js +12 -12
- package/dist/dist.js +7 -7
- package/dist/distMinify.js +10 -10
- package/dist/images.js +7 -7
- package/dist/partials/addToReadme.js +14 -3
- package/dist/partials/imagesFor.js +42 -42
- package/dist/partials/loadPeer.js +70 -70
- package/dist/partials/neostandardLint.js +144 -0
- package/dist/partials/tsFor.js +70 -70
- package/dist/partials/typeDocsFor.js +202 -202
- package/dist/partials.js +136 -136
- package/dist/partials.min.js +1 -1
- package/dist/sass.js +7 -7
- package/dist/sourceLint.js +33 -0
- package/dist/sourceLint.min.js +1 -0
- package/dist/test-helpers/neostandardLintWithRealNeostandard.js +48 -0
- package/dist/test-helpers/setUp.js +5 -0
- package/dist/testFull.js +13 -13
- package/dist/testHelpers.js +8 -8
- package/dist/testQuick.js +13 -13
- package/dist/typeDocs.js +9 -9
- package/dist/typeScript.js +6 -6
- package/dist/utilities/convertMjsFilesForDocs.js +48 -0
- package/dist/utilities/esmNamedExportsToCjs.js +33 -0
- package/dist/utilities/getBundleConfigs.js +27 -27
- package/dist/watchFull.js +7 -7
- package/dist/watchTest.js +11 -11
- package/functions/build.mjs +9 -8
- package/functions/build.test.mjs +18 -25
- package/functions/partials/addToReadme.mjs +14 -5
- package/functions/partials/neostandardLint.mjs +118 -0
- package/functions/partials/neostandardLint.test.mjs +109 -0
- package/functions/partials.mjs +1 -1
- package/functions/sourceLint.mjs +24 -0
- package/functions/sourceLint.test.mjs +73 -0
- package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +38 -0
- package/functions/test-helpers/setUp.mjs +5 -0
- package/functions/utilities/convertMjsFilesForDocs.mjs +33 -0
- package/functions/utilities/convertMjsFilesForDocs.test.mjs +57 -0
- package/functions/utilities/esmNamedExportsToCjs.mjs +29 -0
- package/functions/utilities/esmNamedExportsToCjs.test.mjs +47 -0
- package/gulp.config.mjs +4 -0
- package/gulpfile.base.js +2 -4
- package/gulpfile.base.mjs +1 -2
- package/package.json +7 -6
- package/dist/bundleLint.js +0 -28
- package/dist/bundleLint.min.js +0 -1
- package/dist/distLint.js +0 -20
- package/dist/distLint.min.js +0 -1
- package/dist/partials/standardLint.js +0 -94
- package/dist/test-helpers/standardLintWithRealStandard.js +0 -28
- package/functions/bundleLint.mjs +0 -18
- package/functions/bundleLint.test.mjs +0 -85
- package/functions/distLint.mjs +0 -12
- package/functions/distLint.test.mjs +0 -62
- package/functions/partials/standardLint.mjs +0 -78
- package/functions/partials/standardLint.test.mjs +0 -99
- package/functions/test-helpers/standardLintWithRealStandard.mjs +0 -21
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as gulpConfig from '../gulp.config.mjs'
|
|
2
|
+
import { dest, src } from 'gulp'
|
|
3
|
+
import { neostandardLint } from './partials/neostandardLint.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Applies neostandard linting (js-build-tools' chosen style) to the real, hand-written source - not the compiled
|
|
7
|
+
* dist/browser output, which is generated and so was never going to pass a hand-authored-code style check (every
|
|
8
|
+
* compiler/bundler emits its own boilerplate - import aliasing, interop headers - that only looks like a style
|
|
9
|
+
* violation). Includes test files: there is no reason to hold tests to a lower style bar than the rest of the
|
|
10
|
+
* source. When typescript.enabled, the real TypeScript source is linted too, with type-aware rules.
|
|
11
|
+
* @memberOf module:js-build-tools
|
|
12
|
+
* @returns {*}
|
|
13
|
+
*/
|
|
14
|
+
export const sourceLint = () => {
|
|
15
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
16
|
+
const ts = gulpConfig.get('typescript.enabled')
|
|
17
|
+
const patterns = [`${srcPath}/**/*.js`]
|
|
18
|
+
if (ts) {
|
|
19
|
+
patterns.push(`${srcPath}/**/*.ts`)
|
|
20
|
+
}
|
|
21
|
+
return src(patterns)
|
|
22
|
+
.pipe(neostandardLint({ fix: true, ts }))
|
|
23
|
+
.pipe(dest(srcPath))
|
|
24
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import * as setUp from './test-helpers/setUp.mjs'
|
|
3
|
+
import { sourceLint } from './sourceLint.mjs'
|
|
4
|
+
import { countMatches } from 'test-filesystem'
|
|
5
|
+
|
|
6
|
+
// Run the real neostandard (in a subprocess) - Jest's CommonJS transform can't load the ESM-only package itself.
|
|
7
|
+
jest.mock('./partials/neostandardLint.mjs', () => require('./test-helpers/neostandardLintWithRealNeostandard.mjs'))
|
|
8
|
+
|
|
9
|
+
setUp.setDefaults('test-source-lint')
|
|
10
|
+
const gulpConfig = setUp.gulpConfig
|
|
11
|
+
|
|
12
|
+
const lintableContents = 'const x = "a";\n' +
|
|
13
|
+
'\n' +
|
|
14
|
+
'module.exports = x;\n'
|
|
15
|
+
|
|
16
|
+
const lintableTestContents = 'const y = "b";\n' +
|
|
17
|
+
'\n' +
|
|
18
|
+
'module.exports = y;\n'
|
|
19
|
+
|
|
20
|
+
beforeEach(
|
|
21
|
+
() => setUp.beforeEach()
|
|
22
|
+
.then(
|
|
23
|
+
async () => {
|
|
24
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
25
|
+
await fs.mkdirSync(srcPath, { recursive: true })
|
|
26
|
+
fs.writeFileSync(`${srcPath}/example.js`, lintableContents)
|
|
27
|
+
return fs.writeFileSync(`${srcPath}/example.test.js`, lintableTestContents)
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
afterEach(setUp.afterEach)
|
|
33
|
+
|
|
34
|
+
describe('sourceLint', () => {
|
|
35
|
+
test('fixes the real source in place, including test files', done => {
|
|
36
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
37
|
+
expect.assertions(4)
|
|
38
|
+
sourceLint()
|
|
39
|
+
.on('finish', () => {
|
|
40
|
+
const linted = fs.readFileSync(`${srcPath}/example.js`).toString()
|
|
41
|
+
expect(countMatches(linted, '"')).toEqual(0)
|
|
42
|
+
expect(countMatches(linted, ';')).toEqual(0)
|
|
43
|
+
const lintedTest = fs.readFileSync(`${srcPath}/example.test.js`).toString()
|
|
44
|
+
expect(countMatches(lintedTest, '"')).toEqual(0)
|
|
45
|
+
expect(countMatches(lintedTest, ';')).toEqual(0)
|
|
46
|
+
done()
|
|
47
|
+
})
|
|
48
|
+
.on('error', error => {
|
|
49
|
+
console.error('Encountered error', error)
|
|
50
|
+
done(error)
|
|
51
|
+
})
|
|
52
|
+
}, 20000)
|
|
53
|
+
|
|
54
|
+
test('also lints .ts source when typescript.enabled', done => {
|
|
55
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
56
|
+
gulpConfig.set('typescript.enabled', true)
|
|
57
|
+
fs.writeFileSync(`${srcPath}/example.ts`, 'const z: string = "c";\n\nexport default z;\n')
|
|
58
|
+
expect.assertions(2)
|
|
59
|
+
sourceLint()
|
|
60
|
+
.on('finish', () => {
|
|
61
|
+
gulpConfig.set('typescript.enabled', false)
|
|
62
|
+
const linted = fs.readFileSync(`${srcPath}/example.ts`).toString()
|
|
63
|
+
expect(countMatches(linted, '"')).toEqual(0)
|
|
64
|
+
expect(countMatches(linted, ';')).toEqual(0)
|
|
65
|
+
done()
|
|
66
|
+
})
|
|
67
|
+
.on('error', error => {
|
|
68
|
+
gulpConfig.set('typescript.enabled', false)
|
|
69
|
+
console.error('Encountered error', error)
|
|
70
|
+
done(error)
|
|
71
|
+
})
|
|
72
|
+
}, 20000)
|
|
73
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
// Jest's CommonJS transform cannot load `neostandard` (ESM-only) or run a real dynamic import(), so tests that need
|
|
6
|
+
// genuine neostandard behavior run the actual package in a plain Node subprocess instead of faking it.
|
|
7
|
+
const script = 'import { readFileSync } from \'node:fs\'\n' +
|
|
8
|
+
'import { ESLint } from \'eslint\'\n' +
|
|
9
|
+
'import { neostandard } from \'neostandard\'\n' +
|
|
10
|
+
'const { text, filePath, cwd, fix, ts, env } = JSON.parse(readFileSync(0, \'utf8\'))\n' +
|
|
11
|
+
'const eslint = new ESLint({ cwd, fix, overrideConfigFile: true, baseConfig: neostandard({ ts, env }) })\n' +
|
|
12
|
+
'process.stdout.write(JSON.stringify(await eslint.lintText(text, { filePath })))\n'
|
|
13
|
+
|
|
14
|
+
const readEnv = cwd => {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).standard?.env ?? []
|
|
17
|
+
} catch {
|
|
18
|
+
return []
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const loadEslintViaSubprocess = ({ cwd, ts, fix }) => Promise.resolve({
|
|
23
|
+
lintText: (text, { filePath }) => Promise.resolve().then(() => JSON.parse(execFileSync(
|
|
24
|
+
process.execPath,
|
|
25
|
+
['--input-type=module', '--eval', script],
|
|
26
|
+
{
|
|
27
|
+
input: JSON.stringify({ text, filePath, cwd, fix, ts, env: readEnv(cwd) }),
|
|
28
|
+
encoding: 'utf8',
|
|
29
|
+
cwd,
|
|
30
|
+
maxBuffer: 256 * 1024 * 1024
|
|
31
|
+
}
|
|
32
|
+
)))
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const actual = jest.requireActual('../partials/neostandardLint.mjs')
|
|
36
|
+
|
|
37
|
+
// Drop-in replacement for the partial module (see jest.mock in the lint/build tests): same API, real neostandard.
|
|
38
|
+
export const neostandardLint = (options) => actual.neostandardLint(options, loadEslintViaSubprocess)
|
|
@@ -30,6 +30,11 @@ export const setDefaults = (testDir = 'test-temp') => {
|
|
|
30
30
|
gulpConfig.set('readme.template', `${tempDir}MAIN.md`)
|
|
31
31
|
gulpConfig.set('readme.to', tempDir)
|
|
32
32
|
gulpConfig.set('readme.from', `${srcPath}/**/!(*.test).js`)
|
|
33
|
+
// Reset explicitly: gulpConfig is a process-wide singleton seeded once from this real project's own
|
|
34
|
+
// build-tools.config.json, so without this, this project's own real readme.fromEsm value (gulp.config.mjs)
|
|
35
|
+
// would leak into every test that exercises addToReadme/compileReadme but never sets this path itself -
|
|
36
|
+
// doing real file I/O and a real jsdoc-to-markdown parse of this project's own, much larger, config file.
|
|
37
|
+
gulpConfig.set('readme.fromEsm', [])
|
|
33
38
|
gulpConfig.set('rootPath', tempDir)
|
|
34
39
|
gulpConfig.set('sass.from', `${sassPath}/**/*.+(scss|sass)`)
|
|
35
40
|
gulpConfig.set('sass.path', sassPath)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import os from 'os'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { esmNamedExportsToCjs } from './esmNamedExportsToCjs.mjs'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Writes a rewritten (see {@link esmNamedExportsToCjs}) copy of each given `.mjs` file into a fresh, unique
|
|
8
|
+
* directory under the OS temp directory, with a `.js` extension - jsdoc-to-markdown only recognizes `.js` as a
|
|
9
|
+
* documentable file, regardless of whether its contents are actually CommonJS or ESM (it parses the real ESM
|
|
10
|
+
* syntax of the rest of a file fine; the extension is the only thing it filters on). Writing outside the project
|
|
11
|
+
* tree means there is nothing to gitignore and nothing left behind in the project - call the returned `cleanUp`
|
|
12
|
+
* once done (for example, right after jsdoc-to-markdown has read the files) to remove the temp directory.
|
|
13
|
+
* @memberOf module:utilities
|
|
14
|
+
* @param {Array<string>} mjsFilePaths - Real `.mjs` files to convert. An empty array is a safe, cheap no-op.
|
|
15
|
+
* @returns {{filePaths: Array<string>, cleanUp: function(): void}} The temp `.js` file paths to pass to
|
|
16
|
+
* jsdoc-to-markdown instead of the real `.mjs` ones, and a function to remove the temp directory afterward.
|
|
17
|
+
*/
|
|
18
|
+
export const convertMjsFilesForDocs = (mjsFilePaths = []) => {
|
|
19
|
+
if (mjsFilePaths.length === 0) {
|
|
20
|
+
return { filePaths: [], cleanUp: () => {} }
|
|
21
|
+
}
|
|
22
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'js-build-tools-docs-'))
|
|
23
|
+
const filePaths = mjsFilePaths.map((mjsFilePath) => {
|
|
24
|
+
const tempFilePath = path.join(tempDir, path.basename(mjsFilePath, '.mjs') + '.js')
|
|
25
|
+
const source = fs.readFileSync(mjsFilePath, 'utf8')
|
|
26
|
+
fs.writeFileSync(tempFilePath, esmNamedExportsToCjs(source))
|
|
27
|
+
return tempFilePath
|
|
28
|
+
})
|
|
29
|
+
return {
|
|
30
|
+
filePaths,
|
|
31
|
+
cleanUp: () => fs.rmSync(tempDir, { recursive: true, force: true })
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import * as setUp from '../test-helpers/setUp.mjs'
|
|
3
|
+
import { convertMjsFilesForDocs } from './convertMjsFilesForDocs.mjs'
|
|
4
|
+
|
|
5
|
+
setUp.setDefaults('test-temp-convert-mjs-for-docs')
|
|
6
|
+
const gulpConfig = setUp.gulpConfig
|
|
7
|
+
|
|
8
|
+
const rawContents = '/**\n' +
|
|
9
|
+
' * Say hello with a given name.\n' +
|
|
10
|
+
' * @memberOf module:greet\n' +
|
|
11
|
+
' * @param {string} name\n' +
|
|
12
|
+
' * @returns {string}\n' +
|
|
13
|
+
' */\n' +
|
|
14
|
+
'export const sayHello = name => `Hello from ${name}`\n'
|
|
15
|
+
|
|
16
|
+
beforeEach(() => setUp.beforeEach()
|
|
17
|
+
.then(() => fs.writeFileSync(gulpConfig.get('srcPath') + '/greet.mjs', rawContents)))
|
|
18
|
+
|
|
19
|
+
afterEach(setUp.afterEach)
|
|
20
|
+
|
|
21
|
+
describe('convertMjsFilesForDocs', () => {
|
|
22
|
+
test('returns an empty result, with a safe no-op cleanUp, for an empty list', () => {
|
|
23
|
+
const { filePaths, cleanUp } = convertMjsFilesForDocs([])
|
|
24
|
+
expect(filePaths).toEqual([])
|
|
25
|
+
expect(() => cleanUp()).not.toThrow()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('writes a rewritten, doc-parseable .js copy outside the project tree', () => {
|
|
29
|
+
const mjsFilePath = gulpConfig.get('srcPath') + '/greet.mjs'
|
|
30
|
+
const { filePaths, cleanUp } = convertMjsFilesForDocs([mjsFilePath])
|
|
31
|
+
|
|
32
|
+
expect(filePaths).toHaveLength(1)
|
|
33
|
+
expect(filePaths[0]).toMatch(/greet\.js$/)
|
|
34
|
+
expect(filePaths[0]).not.toContain(process.cwd())
|
|
35
|
+
|
|
36
|
+
const converted = fs.readFileSync(filePaths[0], 'utf8')
|
|
37
|
+
expect(converted).toContain('const sayHello = name => `Hello from ${name}`')
|
|
38
|
+
expect(converted).toContain('module.exports = { sayHello }')
|
|
39
|
+
|
|
40
|
+
cleanUp()
|
|
41
|
+
expect(fs.existsSync(filePaths[0])).toBe(false)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('converts several files into the same temp directory', () => {
|
|
45
|
+
fs.writeFileSync(gulpConfig.get('srcPath') + '/greetAgain.mjs', rawContents.replace('sayHello', 'sayHelloAgain'))
|
|
46
|
+
const { filePaths, cleanUp } = convertMjsFilesForDocs([
|
|
47
|
+
gulpConfig.get('srcPath') + '/greet.mjs',
|
|
48
|
+
gulpConfig.get('srcPath') + '/greetAgain.mjs'
|
|
49
|
+
])
|
|
50
|
+
|
|
51
|
+
expect(filePaths).toHaveLength(2)
|
|
52
|
+
filePaths.forEach(filePath => expect(fs.existsSync(filePath)).toBe(true))
|
|
53
|
+
|
|
54
|
+
cleanUp()
|
|
55
|
+
filePaths.forEach(filePath => expect(fs.existsSync(filePath)).toBe(false))
|
|
56
|
+
})
|
|
57
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rewrites named `export const`/`export function`/`export class` declarations to plain declarations plus a
|
|
3
|
+
* trailing `module.exports = { ... }` - the same shape jsdoc-to-markdown already documents cleanly (a plain
|
|
4
|
+
* declaration with its own `@memberOf` tag, exported all at once at the bottom), rather than the "exports.name"
|
|
5
|
+
* longname jsdoc-to-markdown's own ESM-compat layer produces for an inline `export const name = ...`.
|
|
6
|
+
*
|
|
7
|
+
* This is a narrow, text-level rewrite for documentation purposes only - it does not execute the module, so it
|
|
8
|
+
* only has to look enough like the real thing for jsdoc-to-markdown's parser. It handles the common named-export
|
|
9
|
+
* forms (`export const`, `export function`, `export class`) and leaves everything else (including `export
|
|
10
|
+
* default`, re-exports, and `export { a, b }` lists) untouched in place - a file using one of those keeps its
|
|
11
|
+
* own export line as-is, which jsdoc-to-markdown will document however it already does for ESM.
|
|
12
|
+
* @memberOf module:utilities
|
|
13
|
+
* @param {string} source - The raw ESM source text (never executed, just rewritten as text).
|
|
14
|
+
* @returns {string} The rewritten text, safe to write out with a `.js` extension for jsdoc-to-markdown to read.
|
|
15
|
+
*/
|
|
16
|
+
export const esmNamedExportsToCjs = (source) => {
|
|
17
|
+
const exportedNames = []
|
|
18
|
+
const rewritten = source.replace(
|
|
19
|
+
/^export (const|function|class) (\w+)/gm,
|
|
20
|
+
(match, keyword, name) => {
|
|
21
|
+
exportedNames.push(name)
|
|
22
|
+
return `${keyword} ${name}`
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
if (exportedNames.length === 0) {
|
|
26
|
+
return rewritten
|
|
27
|
+
}
|
|
28
|
+
return `${rewritten}\n\nmodule.exports = { ${exportedNames.join(', ')} }\n`
|
|
29
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { esmNamedExportsToCjs } from './esmNamedExportsToCjs.mjs'
|
|
2
|
+
|
|
3
|
+
describe('esmNamedExportsToCjs', () => {
|
|
4
|
+
test('rewrites a single export const to a plain declaration plus a trailing module.exports', () => {
|
|
5
|
+
const source = 'export const get = (path) => path\n'
|
|
6
|
+
const result = esmNamedExportsToCjs(source)
|
|
7
|
+
expect(result).toContain('const get = (path) => path')
|
|
8
|
+
expect(result).toContain('module.exports = { get }')
|
|
9
|
+
expect(result).not.toContain('export const')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('rewrites multiple export const declarations into one module.exports with all the names', () => {
|
|
13
|
+
const source = 'export const get = () => {}\nexport const set = () => {}\n'
|
|
14
|
+
const result = esmNamedExportsToCjs(source)
|
|
15
|
+
expect(result).toContain('const get = () => {}')
|
|
16
|
+
expect(result).toContain('const set = () => {}')
|
|
17
|
+
expect(result).toContain('module.exports = { get, set }')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('rewrites export function and export class the same way', () => {
|
|
21
|
+
const source = 'export function doThing() {}\nexport class Thing {}\n'
|
|
22
|
+
const result = esmNamedExportsToCjs(source)
|
|
23
|
+
expect(result).toContain('function doThing() {}')
|
|
24
|
+
expect(result).toContain('class Thing {}')
|
|
25
|
+
expect(result).toContain('module.exports = { doThing, Thing }')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('leaves non-export lines and JSDoc comments untouched', () => {
|
|
29
|
+
const source = '/**\n * A function.\n * @memberOf module:gulpConfig\n */\nexport const get = () => {}\n'
|
|
30
|
+
const result = esmNamedExportsToCjs(source)
|
|
31
|
+
expect(result).toContain('/**\n * A function.\n * @memberOf module:gulpConfig\n */\nconst get = () => {}')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('does not add a module.exports block when there is nothing to export', () => {
|
|
35
|
+
const source = 'import { thing } from \'./thing.mjs\'\nconst local = 1\n'
|
|
36
|
+
const result = esmNamedExportsToCjs(source)
|
|
37
|
+
expect(result).toBe(source)
|
|
38
|
+
expect(result).not.toContain('module.exports')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('leaves export default and other export forms untouched', () => {
|
|
42
|
+
const source = 'const value = 1\nexport default value\n'
|
|
43
|
+
const result = esmNamedExportsToCjs(source)
|
|
44
|
+
expect(result).toContain('export default value')
|
|
45
|
+
expect(result).not.toContain('module.exports')
|
|
46
|
+
})
|
|
47
|
+
})
|
package/gulp.config.mjs
CHANGED
|
@@ -101,6 +101,9 @@ import { fileExists } from 'test-filesystem'
|
|
|
101
101
|
* @typedef {Object<string, Setting>} module:gulpConfig~ReadmeConfig
|
|
102
102
|
* @property {StringSetting} file - The name of the output documentation markdown file.
|
|
103
103
|
* @property {StringSetting} from - Location of files to use for compiling documentation into the readme.
|
|
104
|
+
* @property {ArrayableSetting} fromEsm - Additional `.mjs` files to document alongside `from`, converted on the
|
|
105
|
+
* fly since the readme generator only recognizes `.js` files - see 'Configure including ESM files in the
|
|
106
|
+
* generated readme'. Empty by default: a project that never sets this gets exactly the readme it always did.
|
|
104
107
|
* @property {ArrayableSetting} options - Options for formatting the output readme.
|
|
105
108
|
* @property {StringSetting} template - The file which will be pre-fixed to your README.md output.
|
|
106
109
|
* @property {StringSetting} to - The directory to output the readme file in.
|
|
@@ -200,6 +203,7 @@ const setDefaults = {
|
|
|
200
203
|
readme: {
|
|
201
204
|
file: 'README.md',
|
|
202
205
|
from: 'src/**/!(*.test).js',
|
|
206
|
+
fromEsm: [],
|
|
203
207
|
options: 'utf8',
|
|
204
208
|
template: 'MAIN.md',
|
|
205
209
|
to: './'
|
package/gulpfile.base.js
CHANGED
|
@@ -8,18 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|
const build = require('./dist/build.js')
|
|
10
10
|
const bundle = require('./dist/bundle.js')
|
|
11
|
-
const bundleLint = require('./dist/bundleLint.js')
|
|
12
11
|
const bundleMinify = require('./dist/bundleMinify.js')
|
|
13
12
|
const compileReadme = require('./dist/compileReadme.js')
|
|
14
13
|
const copyFonts = require('./dist/copyFonts.js')
|
|
15
14
|
const defaultCmd = require('./dist/default.js')
|
|
16
15
|
const dist = require('./dist/dist.js')
|
|
17
|
-
const distLint = require('./dist/distLint.js')
|
|
18
16
|
const distMinify = require('./dist/distMinify.js')
|
|
19
17
|
const gulpConfig = require('./gulp.config.js')
|
|
20
18
|
const images = require('./dist/images.js')
|
|
21
19
|
const partials = require('./dist/partials.js')
|
|
22
20
|
const sass = require('./dist/sass.js')
|
|
21
|
+
const sourceLint = require('./dist/sourceLint.js')
|
|
23
22
|
const testFull = require('./dist/testFull.js')
|
|
24
23
|
const testHelpers = require('./dist/testHelpers.js')
|
|
25
24
|
const testQuick = require('./dist/testQuick.js')
|
|
@@ -31,19 +30,18 @@ const watchTest = require('./dist/watchTest.js')
|
|
|
31
30
|
module.exports = {
|
|
32
31
|
build,
|
|
33
32
|
bundle,
|
|
34
|
-
bundleLint,
|
|
35
33
|
bundleMinify,
|
|
36
34
|
copyFonts,
|
|
37
35
|
defaultCmd,
|
|
38
36
|
docs: typeDocs,
|
|
39
37
|
dist,
|
|
40
|
-
distLint,
|
|
41
38
|
distMinify,
|
|
42
39
|
gulpConfig,
|
|
43
40
|
images,
|
|
44
41
|
partials,
|
|
45
42
|
readme: compileReadme,
|
|
46
43
|
sass,
|
|
44
|
+
sourceLint,
|
|
47
45
|
testFull,
|
|
48
46
|
testHelpers,
|
|
49
47
|
testQuick,
|
package/gulpfile.base.mjs
CHANGED
|
@@ -7,18 +7,17 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { build } from './functions/build.mjs'
|
|
9
9
|
export { bundle } from './functions/bundle.mjs'
|
|
10
|
-
export { bundleLint } from './functions/bundleLint.mjs'
|
|
11
10
|
export { bundleMinify } from './functions/bundleMinify.mjs'
|
|
12
11
|
export { compileReadme as readme } from './functions/compileReadme.mjs'
|
|
13
12
|
export { copyFonts } from './functions/copyFonts.mjs'
|
|
14
13
|
export { defaultCmd } from './functions/default.mjs'
|
|
15
14
|
export { dist } from './functions/dist.mjs'
|
|
16
|
-
export { distLint } from './functions/distLint.mjs'
|
|
17
15
|
export { distMinify } from './functions/distMinify.mjs'
|
|
18
16
|
export * as gulpConfig from './gulp.config.mjs'
|
|
19
17
|
export { images } from './functions/images.mjs'
|
|
20
18
|
export * as partials from './functions/partials.mjs'
|
|
21
19
|
export { sass } from './functions/sass.mjs'
|
|
20
|
+
export { sourceLint } from './functions/sourceLint.mjs'
|
|
22
21
|
export { testFull } from './functions/testFull.mjs'
|
|
23
22
|
export * as testHelpers from './functions/testHelpers.mjs'
|
|
24
23
|
export { testQuick } from './functions/testQuick.mjs'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-build-tools",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Standardised build process with gulp.",
|
|
5
5
|
"main": "gulpfile.base.js",
|
|
6
6
|
"exports": {
|
|
@@ -50,12 +50,13 @@
|
|
|
50
50
|
"@babel/plugin-transform-modules-commonjs": "^7.29.7",
|
|
51
51
|
"@babel/preset-env": "^7.29.7",
|
|
52
52
|
"@babel/preset-typescript": "^7.29.7",
|
|
53
|
-
"@babel/runtime-corejs3": "^8.0.
|
|
53
|
+
"@babel/runtime-corejs3": "^8.0.7",
|
|
54
54
|
"autoprefixer": "^10.6.1",
|
|
55
55
|
"babel-jest": "^30.5.2",
|
|
56
56
|
"browserify": "^17.0.1",
|
|
57
57
|
"core-js": "^3.50.0",
|
|
58
58
|
"cssnano": "^6.1.2",
|
|
59
|
+
"eslint": "^10.12.0",
|
|
59
60
|
"glob": "^13.0.6",
|
|
60
61
|
"gulp": "^5.0.1",
|
|
61
62
|
"gulp-babel": "^8.1.0",
|
|
@@ -69,11 +70,11 @@
|
|
|
69
70
|
"jest-environment-jsdom": "^30.5.2",
|
|
70
71
|
"jsdoc-to-markdown": "^9.1.3",
|
|
71
72
|
"merge-stream": "^2.0.0",
|
|
72
|
-
"
|
|
73
|
+
"neostandard": "^0.14.1",
|
|
74
|
+
"postcss": "^8.5.30",
|
|
73
75
|
"regenerator-runtime": "^0.14.1",
|
|
74
|
-
"sass": "^1.105.
|
|
75
|
-
"
|
|
76
|
-
"test-filesystem": "^1.5.1",
|
|
76
|
+
"sass": "^1.105.1",
|
|
77
|
+
"test-filesystem": "^2.0.0",
|
|
77
78
|
"through2": "^4.0.2",
|
|
78
79
|
"vinyl-source-stream": "^2.0.0"
|
|
79
80
|
},
|
package/dist/bundleLint.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
require('core-js/modules/esnext.weak-map.delete-all.js')
|
|
4
|
-
Object.defineProperty(exports, '__esModule', {
|
|
5
|
-
value: true
|
|
6
|
-
})
|
|
7
|
-
exports.bundleLint = void 0
|
|
8
|
-
require('core-js/modules/esnext.iterator.constructor.js')
|
|
9
|
-
require('core-js/modules/esnext.iterator.map.js')
|
|
10
|
-
const _gulp = require('gulp')
|
|
11
|
-
const gulpConfig = _interopRequireWildcard(require('../gulp.config.js'))
|
|
12
|
-
const _standardLint = require('./partials/standardLint.js')
|
|
13
|
-
const _getBundleConfigs = require('./utilities/getBundleConfigs.js')
|
|
14
|
-
function _interopRequireWildcard (e, t) { if (typeof WeakMap === 'function') var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; let o; let i; const f = { __proto__: null, default: e }; if (e === null || typeof e !== 'object' && typeof e !== 'function') return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f) } for (const t in e) t !== 'default' && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f })(e, t) }
|
|
15
|
-
/**
|
|
16
|
-
* Applies Standard code style linting to every bundled file (the primary bundle, plus any
|
|
17
|
-
* additional ones from browser.bundles). The lint step itself never varies per bundle, so this is
|
|
18
|
-
* one shared src()/dest() pipeline fed every bundle's filename at once, rather than one pipeline
|
|
19
|
-
* per bundle - gulp's src()/dest() both accept an array of paths natively.
|
|
20
|
-
* @memberOf module:js-build-tools
|
|
21
|
-
* @returns {stream.Stream}
|
|
22
|
-
*/
|
|
23
|
-
const bundleLint = () => (0, _gulp.src)((0, _getBundleConfigs.getBundleConfigs)().map(({
|
|
24
|
-
name
|
|
25
|
-
}) => `${gulpConfig.get('browser.to')}/${name}.js`)).pipe((0, _standardLint.standardLint)({
|
|
26
|
-
fix: true
|
|
27
|
-
})).pipe((0, _gulp.dest)(gulpConfig.get('browser.to')))
|
|
28
|
-
exports.bundleLint = bundleLint
|
package/dist/bundleLint.min.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.bundleLint=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.map.js");var _gulp=require("gulp"),gulpConfig=_interopRequireWildcard(require("../gulp.config.js")),_standardLint=require("./partials/standardLint.js"),_getBundleConfigs=require("./utilities/getBundleConfigs.js");function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap,n=new WeakMap;return(_interopRequireWildcard=function(e,t){if(!t&&e&&e.__esModule)return e;var i,o,u={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return u;if(i=t?n:r){if(i.has(e))return i.get(e);i.set(e,u)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((o=(i=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(o.get||o.set)?i(u,t,o):u[t]=e[t]);return u})(e,t)}const bundleLint=()=>(0,_gulp.src)((0,_getBundleConfigs.getBundleConfigs)().map(({name:e})=>`${gulpConfig.get("browser.to")}/${e}.js`)).pipe((0,_standardLint.standardLint)({fix:!0})).pipe((0,_gulp.dest)(gulpConfig.get("browser.to")));exports.bundleLint=bundleLint;
|
package/dist/distLint.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
require('core-js/modules/esnext.weak-map.delete-all.js')
|
|
4
|
-
Object.defineProperty(exports, '__esModule', {
|
|
5
|
-
value: true
|
|
6
|
-
})
|
|
7
|
-
exports.distLint = void 0
|
|
8
|
-
const gulpConfig = _interopRequireWildcard(require('../gulp.config.js'))
|
|
9
|
-
const _gulp = require('gulp')
|
|
10
|
-
const _standardLint = require('./partials/standardLint.js')
|
|
11
|
-
function _interopRequireWildcard (e, t) { if (typeof WeakMap === 'function') var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; let o; let i; const f = { __proto__: null, default: e }; if (e === null || typeof e !== 'object' && typeof e !== 'function') return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f) } for (const t in e) t !== 'default' && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f })(e, t) }
|
|
12
|
-
/**
|
|
13
|
-
* Applies Standard code style linting to distribution files.
|
|
14
|
-
* @memberOf module:js-build-tools
|
|
15
|
-
* @returns {*}
|
|
16
|
-
*/
|
|
17
|
-
const distLint = () => (0, _gulp.src)(gulpConfig.get('browser.from')).pipe((0, _standardLint.standardLint)({
|
|
18
|
-
fix: true
|
|
19
|
-
})).pipe((0, _gulp.dest)(gulpConfig.get('dist.to')))
|
|
20
|
-
exports.distLint = distLint
|
package/dist/distLint.min.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.distLint=void 0;var gulpConfig=_interopRequireWildcard(require("../gulp.config.js")),_gulp=require("gulp"),_standardLint=require("./partials/standardLint.js");function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap,i=new WeakMap;return(_interopRequireWildcard=function(e,t){if(!t&&e&&e.__esModule)return e;var n,o,s={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return s;if(n=t?i:r){if(n.has(e))return n.get(e);n.set(e,s)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((o=(n=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(o.get||o.set)?n(s,t,o):s[t]=e[t]);return s})(e,t)}const distLint=()=>(0,_gulp.src)(gulpConfig.get("browser.from")).pipe((0,_standardLint.standardLint)({fix:!0})).pipe((0,_gulp.dest)(gulpConfig.get("dist.to")));exports.distLint=distLint;
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.standardLint = void 0;
|
|
7
|
-
require("core-js/modules/esnext.iterator.constructor.js");
|
|
8
|
-
require("core-js/modules/esnext.iterator.for-each.js");
|
|
9
|
-
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
10
|
-
var _through = _interopRequireDefault(require("through2"));
|
|
11
|
-
var _loadPeer = require("./loadPeer.js");
|
|
12
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
-
// `standard` (17+) ships ESM-only, see importModule for how it is imported.
|
|
14
|
-
const importStandard = () => (0, _loadPeer.importModule)('standard');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Print a file's lint messages, if it has any.
|
|
18
|
-
* @memberOf module:partials
|
|
19
|
-
* @param {import('vinyl')} file
|
|
20
|
-
* @param {{messages: Array<{line: number, column: number, message: string}>, errorCount: number, warningCount: number}} result
|
|
21
|
-
* @returns {undefined}
|
|
22
|
-
*/
|
|
23
|
-
const printFileReport = (file, result) => {
|
|
24
|
-
if (!result.messages.length) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
console.log(_nodePath.default.relative(file.cwd, file.path));
|
|
28
|
-
result.messages.forEach(({
|
|
29
|
-
line,
|
|
30
|
-
column,
|
|
31
|
-
message
|
|
32
|
-
}) => console.log(`line ${line}:${column}\t${message}`));
|
|
33
|
-
console.log(`✖ ${result.errorCount} error\t⚠ ${result.warningCount} warning\n`);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Lint every file streaming through with JavaScript Standard Style and, unless `fix` is false, apply the automatic
|
|
38
|
-
* fixes to the file's contents so a following `dest()` writes the fixed version. Remaining problems are printed
|
|
39
|
-
* along with a summary once the stream ends; they never fail the build.
|
|
40
|
-
*
|
|
41
|
-
* Project-level Standard configuration (the `standard` field in package.json: ignore, env, globals, ...) is honored
|
|
42
|
-
* because the file's own path and cwd are handed to Standard.
|
|
43
|
-
* @memberOf module:partials
|
|
44
|
-
* @param {Object} [options={}]
|
|
45
|
-
* @param {boolean} [options.fix=true] - Apply Standard's automatic fixes to the file contents.
|
|
46
|
-
* @param {function(): Promise<{lintText: Function}>} [loadStandard] - Resolves the `standard` module. Real callers
|
|
47
|
-
* should never need to pass this - it exists so tests can supply a stand-in, since this project's
|
|
48
|
-
* CommonJS-transform-based Jest setup cannot execute a real dynamic import() of an ES module.
|
|
49
|
-
* @returns {import('stream').Transform}
|
|
50
|
-
*/
|
|
51
|
-
const standardLint = ({
|
|
52
|
-
fix = true
|
|
53
|
-
} = {}, loadStandard = () => importStandard().then(({
|
|
54
|
-
default: standard
|
|
55
|
-
}) => standard)) => {
|
|
56
|
-
const totals = {
|
|
57
|
-
errors: 0,
|
|
58
|
-
warnings: 0
|
|
59
|
-
};
|
|
60
|
-
return _through.default.obj(function (file, enc, callback) {
|
|
61
|
-
if (file.isNull()) {
|
|
62
|
-
callback(null, file);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (file.isStream()) {
|
|
66
|
-
callback(new Error('standardLint: streaming file contents are not supported.'));
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
loadStandard().then(standard => standard.lintText(file.contents.toString(), {
|
|
70
|
-
filename: file.path,
|
|
71
|
-
cwd: file.cwd,
|
|
72
|
-
fix
|
|
73
|
-
})).then(results => {
|
|
74
|
-
// No result at all means the file is ignored by the project's Standard configuration.
|
|
75
|
-
const [result] = results;
|
|
76
|
-
if (result) {
|
|
77
|
-
if (typeof result.output === 'string') {
|
|
78
|
-
file.contents = Buffer.from(result.output);
|
|
79
|
-
}
|
|
80
|
-
totals.errors += result.errorCount;
|
|
81
|
-
totals.warnings += result.warningCount;
|
|
82
|
-
printFileReport(file, result);
|
|
83
|
-
}
|
|
84
|
-
callback(null, file);
|
|
85
|
-
}, callback);
|
|
86
|
-
}, function (callback) {
|
|
87
|
-
console.log('Standard linter results');
|
|
88
|
-
console.log('======================================');
|
|
89
|
-
console.log(`✖ Errors total: ${totals.errors}`);
|
|
90
|
-
console.log(`⚠ Warnings total: ${totals.warnings}\n`);
|
|
91
|
-
callback();
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
exports.standardLint = standardLint;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.standardLint = exports.loadStandardViaSubprocess = void 0;
|
|
7
|
-
require("core-js/modules/es.json.stringify.js");
|
|
8
|
-
var _nodeChild_process = require("node:child_process");
|
|
9
|
-
// Jest's CommonJS transform cannot load `standard` (ESM-only) or run a real dynamic import(), so tests that need
|
|
10
|
-
// genuine Standard behavior run the actual `standard` package in a plain Node subprocess instead of faking it.
|
|
11
|
-
const script = 'import { readFileSync } from \'node:fs\'\n' + 'import standard from \'standard\'\n' + 'const { text, options } = JSON.parse(readFileSync(0, \'utf8\'))\n' + 'process.stdout.write(JSON.stringify(await standard.lintText(text, options)))\n';
|
|
12
|
-
const loadStandardViaSubprocess = () => Promise.resolve({
|
|
13
|
-
lintText: (text, options) => Promise.resolve().then(() => JSON.parse((0, _nodeChild_process.execFileSync)(process.execPath, ['--input-type=module', '--eval', script], {
|
|
14
|
-
input: JSON.stringify({
|
|
15
|
-
text,
|
|
16
|
-
options
|
|
17
|
-
}),
|
|
18
|
-
encoding: 'utf8',
|
|
19
|
-
cwd: process.cwd(),
|
|
20
|
-
maxBuffer: 256 * 1024 * 1024
|
|
21
|
-
})))
|
|
22
|
-
});
|
|
23
|
-
exports.loadStandardViaSubprocess = loadStandardViaSubprocess;
|
|
24
|
-
const actual = jest.requireActual('../partials/standardLint.js');
|
|
25
|
-
|
|
26
|
-
// Drop-in replacement for the partial module (see jest.mock in the lint/build tests): same API, real Standard.
|
|
27
|
-
const standardLint = options => actual.standardLint(options, loadStandardViaSubprocess);
|
|
28
|
-
exports.standardLint = standardLint;
|
package/functions/bundleLint.mjs
DELETED
|
@@ -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')))
|