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.
Files changed (169) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +762 -701
  3. package/babel.config.js +28 -28
  4. package/dist/build.js +75 -75
  5. package/dist/bundle.js +19 -19
  6. package/dist/bundleMinify.js +7 -7
  7. package/dist/compileReadme.js +4 -4
  8. package/dist/copyFiles.js +17 -17
  9. package/dist/copyFonts.js +4 -4
  10. package/dist/default.js +5 -5
  11. package/dist/dist.js +4 -4
  12. package/dist/distMinify.js +4 -4
  13. package/dist/docs.js +7 -7
  14. package/dist/images.js +4 -4
  15. package/dist/jsdocDocs.js +6 -6
  16. package/dist/lint.js +16 -16
  17. package/dist/partials/addToReadme.js +9 -9
  18. package/dist/partials/beginWatcher.js +4 -4
  19. package/dist/partials/clean.js +5 -5
  20. package/dist/partials/copyFor.js +9 -9
  21. package/dist/partials/distFor.js +6 -6
  22. package/dist/partials/distForSrc.js +5 -5
  23. package/dist/partials/distSeries.js +7 -7
  24. package/dist/partials/imagesFor.js +93 -93
  25. package/dist/partials/jsdocDocsFor.js +46 -46
  26. package/dist/partials/lintSource.js +51 -51
  27. package/dist/partials/loadPeer.js +99 -99
  28. package/dist/partials/loadPlaywright.js +14 -14
  29. package/dist/partials/minifyFor.js +20 -20
  30. package/dist/partials/neostandardLint.js +175 -175
  31. package/dist/partials/readmeTemplate.js +4 -4
  32. package/dist/partials/removeDirectory.js +11 -11
  33. package/dist/partials/resolveDocsMethod.js +6 -6
  34. package/dist/partials/runOnChange.js +31 -31
  35. package/dist/partials/sassFor.js +6 -6
  36. package/dist/partials/serveStatic.js +9 -9
  37. package/dist/partials/tsFor.js +32 -32
  38. package/dist/partials/typeDocsFor.js +264 -264
  39. package/dist/partials.js +176 -176
  40. package/dist/sourceLint.js +18 -18
  41. package/dist/test-helpers/isolateGulpCache.js +24 -24
  42. package/dist/test-helpers/setUp.js +4 -4
  43. package/dist/testFull.js +5 -5
  44. package/dist/testQuick.js +5 -5
  45. package/dist/typeDocs.js +5 -5
  46. package/dist/typeScript.js +4 -4
  47. package/dist/utilities/convertMjsFilesForDocs.js +12 -12
  48. package/dist/utilities/dotGet.js +54 -54
  49. package/dist/utilities/dotNotate.js +79 -79
  50. package/dist/utilities/dotSet.js +45 -45
  51. package/dist/utilities/esmNamedExportsToCjs.js +15 -15
  52. package/dist/utilities/getBundleConfigs.js +9 -9
  53. package/dist/utilities/isObject.js +6 -6
  54. package/dist/utilities/strAfter.js +7 -7
  55. package/dist/utilities/strBefore.js +7 -7
  56. package/dist/watchFull.js +4 -4
  57. package/dist/watchTest.js +4 -4
  58. package/functions/build.mjs +72 -72
  59. package/functions/build.test.mjs +763 -759
  60. package/functions/bundle.mjs +44 -44
  61. package/functions/bundle.test.mjs +219 -219
  62. package/functions/bundleMinify.mjs +16 -16
  63. package/functions/bundleMinify.test.mjs +37 -37
  64. package/functions/compileReadme.mjs +9 -9
  65. package/functions/compileReadme.test.mjs +18 -18
  66. package/functions/copyFiles.mjs +32 -32
  67. package/functions/copyFiles.test.mjs +78 -78
  68. package/functions/copyFonts.mjs +9 -9
  69. package/functions/copyFonts.test.mjs +32 -32
  70. package/functions/default.mjs +12 -12
  71. package/functions/default.test.mjs +33 -33
  72. package/functions/dist.mjs +8 -8
  73. package/functions/dist.test.mjs +44 -44
  74. package/functions/distMinify.mjs +9 -9
  75. package/functions/distMinify.test.mjs +15 -15
  76. package/functions/docs.mjs +13 -13
  77. package/functions/docs.test.mjs +45 -45
  78. package/functions/gulpConfigEntries.test.mjs +23 -23
  79. package/functions/images.mjs +8 -8
  80. package/functions/images.test.mjs +142 -142
  81. package/functions/jsdocDocs.mjs +10 -10
  82. package/functions/jsdocEsmExports.test.mjs +24 -24
  83. package/functions/lint.mjs +9 -9
  84. package/functions/partials/addToReadme.mjs +25 -25
  85. package/functions/partials/addToReadme.test.mjs +34 -34
  86. package/functions/partials/beginWatcher.mjs +9 -9
  87. package/functions/partials/beginWatcher.test.mjs +19 -19
  88. package/functions/partials/clean.mjs +13 -13
  89. package/functions/partials/clean.test.mjs +22 -22
  90. package/functions/partials/copyFor.mjs +15 -15
  91. package/functions/partials/copyFor.test.mjs +53 -53
  92. package/functions/partials/distFor.mjs +22 -22
  93. package/functions/partials/distFor.test.mjs +195 -195
  94. package/functions/partials/distForSrc.mjs +11 -11
  95. package/functions/partials/distForSrc.test.mjs +18 -18
  96. package/functions/partials/distSeries.mjs +21 -21
  97. package/functions/partials/distSeries.test.mjs +34 -34
  98. package/functions/partials/imagesFor.mjs +83 -83
  99. package/functions/partials/imagesFor.test.mjs +287 -287
  100. package/functions/partials/jsdocDocsFor.mjs +163 -152
  101. package/functions/partials/jsdocDocsFor.test.mjs +182 -152
  102. package/functions/partials/lintSource.mjs +41 -41
  103. package/functions/partials/loadPeer.mjs +76 -76
  104. package/functions/partials/loadPeer.test.mjs +58 -58
  105. package/functions/partials/loadPlaywright.mjs +23 -23
  106. package/functions/partials/loadPlaywright.test.mjs +70 -70
  107. package/functions/partials/minifyFor.mjs +15 -15
  108. package/functions/partials/minifyFor.test.mjs +49 -49
  109. package/functions/partials/neostandardLint.mjs +142 -142
  110. package/functions/partials/neostandardLint.test.mjs +131 -131
  111. package/functions/partials/readmeTemplate.mjs +12 -12
  112. package/functions/partials/readmeTemplate.test.mjs +34 -34
  113. package/functions/partials/removeDirectory.mjs +34 -34
  114. package/functions/partials/removeDirectory.test.mjs +72 -72
  115. package/functions/partials/resolveDocsMethod.mjs +10 -10
  116. package/functions/partials/resolveDocsMethod.test.mjs +33 -33
  117. package/functions/partials/runOnChange.mjs +54 -54
  118. package/functions/partials/runOnChange.test.mjs +95 -95
  119. package/functions/partials/sassFor.mjs +25 -25
  120. package/functions/partials/sassFor.test.mjs +81 -81
  121. package/functions/partials/serveStatic.mjs +47 -47
  122. package/functions/partials/serveStatic.test.mjs +71 -71
  123. package/functions/partials/tsFor.mjs +92 -92
  124. package/functions/partials/tsFor.test.mjs +88 -88
  125. package/functions/partials/typeDocsFor.mjs +231 -231
  126. package/functions/partials/typeDocsFor.test.mjs +263 -263
  127. package/functions/partials.mjs +31 -31
  128. package/functions/partials.test.mjs +7 -7
  129. package/functions/sass.mjs +4 -4
  130. package/functions/sass.test.mjs +31 -31
  131. package/functions/sourceLint.mjs +13 -13
  132. package/functions/sourceLint.test.mjs +166 -166
  133. package/functions/test-helpers/isolateGulpCache.mjs +16 -16
  134. package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +40 -40
  135. package/functions/test-helpers/setUp.mjs +100 -100
  136. package/functions/test-helpers/setUp.test.mjs +19 -19
  137. package/functions/testFull.mjs +17 -17
  138. package/functions/testFull.test.mjs +17 -17
  139. package/functions/testHelpers.mjs +10 -10
  140. package/functions/testHelpers.test.mjs +7 -7
  141. package/functions/testQuick.mjs +17 -17
  142. package/functions/testQuick.test.mjs +17 -17
  143. package/functions/typeDocs.mjs +9 -9
  144. package/functions/typeDocs.test.mjs +11 -11
  145. package/functions/typeScript.mjs +8 -8
  146. package/functions/typeScript.test.mjs +11 -11
  147. package/functions/utilities/convertMjsFilesForDocs.mjs +34 -34
  148. package/functions/utilities/convertMjsFilesForDocs.test.mjs +58 -58
  149. package/functions/utilities/dotGet.mjs +49 -49
  150. package/functions/utilities/dotNotate.mjs +73 -73
  151. package/functions/utilities/dotNotate.test.mjs +41 -41
  152. package/functions/utilities/dotSet.mjs +40 -40
  153. package/functions/utilities/esmNamedExportsToCjs.mjs +30 -30
  154. package/functions/utilities/esmNamedExportsToCjs.test.mjs +47 -47
  155. package/functions/utilities/getBundleConfigs.mjs +30 -30
  156. package/functions/utilities/isObject.mjs +8 -8
  157. package/functions/utilities/strAfter.mjs +12 -12
  158. package/functions/utilities/strBefore.mjs +12 -12
  159. package/functions/watchFull.mjs +9 -9
  160. package/functions/watchFull.test.mjs +41 -41
  161. package/functions/watchTest.mjs +10 -10
  162. package/functions/watchTest.test.mjs +49 -49
  163. package/gulp.config.js +4 -4
  164. package/gulp.config.mjs +344 -340
  165. package/gulpfile.base.js +51 -51
  166. package/gulpfile.base.mjs +29 -29
  167. package/jsdoc.base.js +16 -16
  168. package/jsdoc.esmExports.js +17 -17
  169. package/package.json +146 -145
@@ -1,44 +1,44 @@
1
- import browserify from 'browserify'
2
- import { dest } from 'gulp'
3
- import mergeStream from 'merge-stream'
4
- import * as gulpConfig from '../gulp.config.mjs'
5
- import source from 'vinyl-source-stream'
6
- import { getBundleConfigs } from './utilities/getBundleConfigs.mjs'
7
-
8
- /**
9
- * Starting at each bundle's own entry point (dist.main for the primary bundle, or its own
10
- * override from browser.bundles), bundle all the reachable files into a single file per bundle and
11
- * store them in the specified output directory. A project with no browser.bundles entries gets
12
- * exactly the one bundle it always did; each additional entry produces its own separate bundle
13
- * (for example, a render-only variant built from a different entry point than the full bundle).
14
- *
15
- * A bundle's name does double duty: it names the output file (name.js) and, via browserify's
16
- * `standalone` option, is also the name its exports are exposed under - as a global when loaded
17
- * with a bare `<script>` tag, or as the module when required via CommonJS/AMD. Without this, a
18
- * bundle built from a real entry point (one that actually exports something) builds successfully
19
- * but exposes nothing a consumer can reach.
20
- *
21
- * Two escape hatches from browser.config.json keep an unwanted dependency (or a dependency's dependency) out of the
22
- * bundle: 'ignore' replaces it with an empty object (safe when your code never actually calls into it - for example
23
- * a library's default option value you always override with your own) and 'exclude' leaves it out entirely (your
24
- * code must not require it, or provide it another way, such as a separate script tag).
25
- * @memberOf module:js-build-tools
26
- * @returns {stream.Stream}
27
- */
28
- export const bundle = () => mergeStream(
29
- getBundleConfigs().map(({ name, main, ignore, exclude }) => {
30
- const bundler = browserify(main, { standalone: name })
31
- if (ignore.length) {
32
- bundler.ignore(ignore)
33
- }
34
- if (exclude.length) {
35
- bundler.exclude(exclude)
36
- }
37
- return bundler
38
- .bundle()
39
- .pipe(source(`${name}.js`))
40
- })
41
- // One shared dest() for every bundle, not one per bundle - vinyl-fs's dest() races against
42
- // itself (a real "write after end" failure) when two separate dest() streams target the same
43
- // directory concurrently, which every additional bundle's own dest() call otherwise would.
44
- ).pipe(dest(gulpConfig.get('browser.to')))
1
+ import browserify from 'browserify'
2
+ import { dest } from 'gulp'
3
+ import mergeStream from 'merge-stream'
4
+ import * as gulpConfig from '../gulp.config.mjs'
5
+ import source from 'vinyl-source-stream'
6
+ import { getBundleConfigs } from './utilities/getBundleConfigs.mjs'
7
+
8
+ /**
9
+ * Starting at each bundle's own entry point (dist.main for the primary bundle, or its own
10
+ * override from browser.bundles), bundle all the reachable files into a single file per bundle and
11
+ * store them in the specified output directory. A project with no browser.bundles entries gets
12
+ * exactly the one bundle it always did; each additional entry produces its own separate bundle
13
+ * (for example, a render-only variant built from a different entry point than the full bundle).
14
+ *
15
+ * A bundle's name does double duty: it names the output file (name.js) and, via browserify's
16
+ * `standalone` option, is also the name its exports are exposed under - as a global when loaded
17
+ * with a bare `<script>` tag, or as the module when required via CommonJS/AMD. Without this, a
18
+ * bundle built from a real entry point (one that actually exports something) builds successfully
19
+ * but exposes nothing a consumer can reach.
20
+ *
21
+ * Two escape hatches from browser.config.json keep an unwanted dependency (or a dependency's dependency) out of the
22
+ * bundle: 'ignore' replaces it with an empty object (safe when your code never actually calls into it - for example
23
+ * a library's default option value you always override with your own) and 'exclude' leaves it out entirely (your
24
+ * code must not require it, or provide it another way, such as a separate script tag).
25
+ * @memberOf module:js-build-tools
26
+ * @returns {stream.Stream}
27
+ */
28
+ export const bundle = () => mergeStream(
29
+ getBundleConfigs().map(({ name, main, ignore, exclude }) => {
30
+ const bundler = browserify(main, { standalone: name })
31
+ if (ignore.length) {
32
+ bundler.ignore(ignore)
33
+ }
34
+ if (exclude.length) {
35
+ bundler.exclude(exclude)
36
+ }
37
+ return bundler
38
+ .bundle()
39
+ .pipe(source(`${name}.js`))
40
+ })
41
+ // One shared dest() for every bundle, not one per bundle - vinyl-fs's dest() races against
42
+ // itself (a real "write after end" failure) when two separate dest() streams target the same
43
+ // directory concurrently, which every additional bundle's own dest() call otherwise would.
44
+ ).pipe(dest(gulpConfig.get('browser.to')))
@@ -1,219 +1,219 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
- import * as setUp from './test-helpers/setUp.mjs'
4
- import { bundle } from './bundle.mjs'
5
- import { countMatches } from 'test-filesystem'
6
-
7
- setUp.setDefaults('test-bundle')
8
- const gulpConfig = setUp.gulpConfig
9
-
10
- const file1Contents = 'function file1 () {\n' +
11
- ' console.log(\'Hello from file1\')\n' +
12
- '}\n' +
13
- '\n' +
14
- 'module.exports = file1\n'
15
- const file2Contents = 'function file2 () {\n' +
16
- ' console.log(\'Good-bye from file2\')\n' +
17
- '}\n' +
18
- '\n' +
19
- 'module.exports = file2\n'
20
- const mainFileContents = 'const file1 = require(\'./sources/file1\')\n' +
21
- 'const file2 = require(\'./sources/file2\')\n' +
22
- '\n' +
23
- 'module.exports = {\n' +
24
- ' file1,\n' +
25
- ' file2,\n' +
26
- '}\n'
27
-
28
- beforeEach(
29
- () => setUp.beforeEach()
30
- .then(
31
- async () => {
32
- const distPath = gulpConfig.get('dist.to')
33
- const mainFile = gulpConfig.get('dist.main')
34
- const sourcesPath = `${distPath}/sources`
35
- await fs.mkdirSync(distPath)
36
- await fs.mkdirSync(sourcesPath)
37
- await fs.writeFileSync(`${sourcesPath}/file1.js`, file1Contents)
38
- await fs.writeFileSync(`${sourcesPath}/file2.js`, file2Contents)
39
- return fs.writeFileSync(`${mainFile}.js`, mainFileContents)
40
- }
41
- )
42
- )
43
-
44
- afterEach(setUp.afterEach)
45
-
46
- describe('bundle', () => {
47
- test('copies all the dist contents into a single file for browsers', done => {
48
- const distPath = gulpConfig.get('dist.to')
49
- const destFile = `${gulpConfig.get('browser.name')}.js`
50
- const destPath = gulpConfig.get('browser.to')
51
- const bundledFile = `${destPath}/${destFile}`
52
- const sourcesPath = `${distPath}/sources`
53
- const file1Path = `${sourcesPath}/file1.js`
54
- const file2Path = `${sourcesPath}/file2.js`
55
- const oldFile1Contents = fs.readFileSync(file1Path).toString()
56
- const oldFile2Contents = fs.readFileSync(file2Path).toString()
57
- expect.assertions(2)
58
- bundle()
59
- .on('finish', () => {
60
- const bundledContents = fs.readFileSync(bundledFile).toString()
61
- expect(countMatches(bundledContents, oldFile1Contents)).toEqual(1)
62
- expect(countMatches(bundledContents, oldFile2Contents)).toEqual(1)
63
- done()
64
- })
65
- .on('error', error => {
66
- console.error('Encountered error', error)
67
- done()
68
- })
69
- })
70
-
71
- test('exposes browser.name as the standalone export, reachable by a real consumer', done => {
72
- const destPath = gulpConfig.get('browser.to')
73
- const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
74
- expect.assertions(2)
75
- bundle()
76
- .on('finish', () => {
77
- // A UMD bundle (browserify's `standalone` option) resolves to its CommonJS branch when
78
- // required like this, and to a `window.<browser.name>` global when loaded via a bare
79
- // <script> tag in a real browser - both paths hit the same exported value.
80
- const resolved = path.resolve(bundledFile)
81
- delete require.cache[resolved]
82
- const loaded = require(resolved)
83
- expect(typeof loaded.file1).toBe('function')
84
- expect(typeof loaded.file2).toBe('function')
85
- done()
86
- })
87
- .on('error', error => done(error))
88
- })
89
- })
90
-
91
- describe('bundle with additional bundles', () => {
92
- const renderOnlyFileContents = 'const file1 = require(\'./sources/file1\')\n' +
93
- '\n' +
94
- 'module.exports = {\n' +
95
- ' file1,\n' +
96
- '}\n'
97
-
98
- afterEach(() => gulpConfig.set('browser.bundles', []))
99
-
100
- test('produces one file per additional bundle, each from its own entry point', done => {
101
- const distPath = gulpConfig.get('dist.to')
102
- const renderOnlyMain = `${distPath}/renderOnly`
103
- fs.writeFileSync(`${renderOnlyMain}.js`, renderOnlyFileContents)
104
- gulpConfig.set('browser.bundles', [{ name: 'renderOnly', main: renderOnlyMain }])
105
-
106
- const destPath = gulpConfig.get('browser.to')
107
- const primaryFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
108
- const renderOnlyFile = `${destPath}/renderOnly.js`
109
- expect.assertions(4)
110
- bundle()
111
- .on('finish', () => {
112
- // The primary bundle is unaffected - still built from dist.main, still has both files.
113
- const primaryContents = fs.readFileSync(primaryFile).toString()
114
- expect(primaryContents).toContain('Hello from file1')
115
- expect(primaryContents).toContain('Good-bye from file2')
116
-
117
- // The additional bundle came from its own entry point - file1 only, never file2.
118
- const renderOnlyContents = fs.readFileSync(renderOnlyFile).toString()
119
- expect(renderOnlyContents).toContain('Hello from file1')
120
- expect(renderOnlyContents).not.toContain('Good-bye from file2')
121
- done()
122
- })
123
- .on('error', error => done(error))
124
- })
125
-
126
- test('an additional bundle exposes its own name as its standalone export', done => {
127
- const distPath = gulpConfig.get('dist.to')
128
- const renderOnlyMain = `${distPath}/renderOnly`
129
- fs.writeFileSync(`${renderOnlyMain}.js`, renderOnlyFileContents)
130
- gulpConfig.set('browser.bundles', [{ name: 'renderOnly', main: renderOnlyMain }])
131
-
132
- const destPath = gulpConfig.get('browser.to')
133
- const renderOnlyFile = `${destPath}/renderOnly.js`
134
- expect.assertions(2)
135
- bundle()
136
- .on('finish', () => {
137
- const resolved = path.resolve(renderOnlyFile)
138
- delete require.cache[resolved]
139
- const loaded = require(resolved)
140
- expect(typeof loaded.file1).toBe('function')
141
- expect(loaded.file2).toBeUndefined()
142
- done()
143
- })
144
- .on('error', error => done(error))
145
- })
146
- })
147
-
148
- describe('bundle ignore / exclude', () => {
149
- const optionalDepMarker = 'MARKER_FROM_THE_OPTIONAL_DEPENDENCY_CODE'
150
-
151
- beforeEach(() => {
152
- const tempDir = gulpConfig.get('rootPath')
153
- const depDir = `${tempDir}node_modules/optional-dep`
154
- fs.mkdirSync(depDir, { recursive: true })
155
- fs.writeFileSync(`${depDir}/package.json`, JSON.stringify({ name: 'optional-dep', main: 'index.js' }))
156
- fs.writeFileSync(`${depDir}/index.js`, `module.exports = '${optionalDepMarker}'\n`)
157
- const distPath = gulpConfig.get('dist.to')
158
- const mainFile = gulpConfig.get('dist.main')
159
- fs.mkdirSync(distPath, { recursive: true })
160
- // Only reached as a fallback for an option the caller always overrides, the way css-select falls back to its
161
- // own default adapter (domutils) unless one is given - exactly the case ignore / exclude exist for.
162
- fs.writeFileSync(`${mainFile}.js`, 'const optionalDep = require(\'optional-dep\')\n\nmodule.exports = (given) => given || optionalDep\n')
163
- })
164
-
165
- test('without ignore or exclude, the dependency is bundled', done => {
166
- const destPath = gulpConfig.get('browser.to')
167
- const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
168
- expect.assertions(1)
169
- bundle()
170
- .on('finish', () => {
171
- expect(fs.readFileSync(bundledFile).toString()).toContain(optionalDepMarker)
172
- done()
173
- })
174
- .on('error', error => done(error))
175
- })
176
-
177
- test('ignore replaces the dependency with an empty object, but the bundle still finishes', done => {
178
- gulpConfig.set('browser.ignore', ['optional-dep'])
179
- const destPath = gulpConfig.get('browser.to')
180
- const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
181
- expect.assertions(2)
182
- bundle()
183
- .on('finish', () => {
184
- const bundledContents = fs.readFileSync(bundledFile).toString()
185
- // The ignored module is still in the bundle (as an empty stub, so requiring it by name still resolves) -
186
- // it just no longer has the real code that would have pulled in the marker
187
- expect(bundledContents).toContain('optional-dep')
188
- expect(bundledContents).not.toContain(optionalDepMarker)
189
- done()
190
- })
191
- .on('error', error => done(error))
192
- })
193
-
194
- test('exclude leaves the dependency out of the bundle entirely', done => {
195
- gulpConfig.set('browser.exclude', ['optional-dep'])
196
- const destPath = gulpConfig.get('browser.to')
197
- const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
198
- expect.assertions(1)
199
- bundle()
200
- .on('finish', () => {
201
- expect(fs.readFileSync(bundledFile).toString()).not.toContain(optionalDepMarker)
202
- done()
203
- })
204
- .on('error', error => done(error))
205
- })
206
-
207
- test('a single string is accepted the same as a one item array', done => {
208
- gulpConfig.set('browser.ignore', 'optional-dep')
209
- const destPath = gulpConfig.get('browser.to')
210
- const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
211
- expect.assertions(1)
212
- bundle()
213
- .on('finish', () => {
214
- expect(fs.readFileSync(bundledFile).toString()).not.toContain(optionalDepMarker)
215
- done()
216
- })
217
- .on('error', error => done(error))
218
- })
219
- })
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import * as setUp from './test-helpers/setUp.mjs'
4
+ import { bundle } from './bundle.mjs'
5
+ import { countMatches } from 'test-filesystem'
6
+
7
+ setUp.setDefaults('test-bundle')
8
+ const gulpConfig = setUp.gulpConfig
9
+
10
+ const file1Contents = 'function file1 () {\n' +
11
+ ' console.log(\'Hello from file1\')\n' +
12
+ '}\n' +
13
+ '\n' +
14
+ 'module.exports = file1\n'
15
+ const file2Contents = 'function file2 () {\n' +
16
+ ' console.log(\'Good-bye from file2\')\n' +
17
+ '}\n' +
18
+ '\n' +
19
+ 'module.exports = file2\n'
20
+ const mainFileContents = 'const file1 = require(\'./sources/file1\')\n' +
21
+ 'const file2 = require(\'./sources/file2\')\n' +
22
+ '\n' +
23
+ 'module.exports = {\n' +
24
+ ' file1,\n' +
25
+ ' file2,\n' +
26
+ '}\n'
27
+
28
+ beforeEach(
29
+ () => setUp.beforeEach()
30
+ .then(
31
+ async () => {
32
+ const distPath = gulpConfig.get('dist.to')
33
+ const mainFile = gulpConfig.get('dist.main')
34
+ const sourcesPath = `${distPath}/sources`
35
+ await fs.mkdirSync(distPath)
36
+ await fs.mkdirSync(sourcesPath)
37
+ await fs.writeFileSync(`${sourcesPath}/file1.js`, file1Contents)
38
+ await fs.writeFileSync(`${sourcesPath}/file2.js`, file2Contents)
39
+ return fs.writeFileSync(`${mainFile}.js`, mainFileContents)
40
+ }
41
+ )
42
+ )
43
+
44
+ afterEach(setUp.afterEach)
45
+
46
+ describe('bundle', () => {
47
+ test('copies all the dist contents into a single file for browsers', done => {
48
+ const distPath = gulpConfig.get('dist.to')
49
+ const destFile = `${gulpConfig.get('browser.name')}.js`
50
+ const destPath = gulpConfig.get('browser.to')
51
+ const bundledFile = `${destPath}/${destFile}`
52
+ const sourcesPath = `${distPath}/sources`
53
+ const file1Path = `${sourcesPath}/file1.js`
54
+ const file2Path = `${sourcesPath}/file2.js`
55
+ const oldFile1Contents = fs.readFileSync(file1Path).toString()
56
+ const oldFile2Contents = fs.readFileSync(file2Path).toString()
57
+ expect.assertions(2)
58
+ bundle()
59
+ .on('finish', () => {
60
+ const bundledContents = fs.readFileSync(bundledFile).toString()
61
+ expect(countMatches(bundledContents, oldFile1Contents)).toEqual(1)
62
+ expect(countMatches(bundledContents, oldFile2Contents)).toEqual(1)
63
+ done()
64
+ })
65
+ .on('error', error => {
66
+ console.error('Encountered error', error)
67
+ done()
68
+ })
69
+ })
70
+
71
+ test('exposes browser.name as the standalone export, reachable by a real consumer', done => {
72
+ const destPath = gulpConfig.get('browser.to')
73
+ const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
74
+ expect.assertions(2)
75
+ bundle()
76
+ .on('finish', () => {
77
+ // A UMD bundle (browserify's `standalone` option) resolves to its CommonJS branch when
78
+ // required like this, and to a `window.<browser.name>` global when loaded via a bare
79
+ // <script> tag in a real browser - both paths hit the same exported value.
80
+ const resolved = path.resolve(bundledFile)
81
+ delete require.cache[resolved]
82
+ const loaded = require(resolved)
83
+ expect(typeof loaded.file1).toBe('function')
84
+ expect(typeof loaded.file2).toBe('function')
85
+ done()
86
+ })
87
+ .on('error', error => done(error))
88
+ })
89
+ })
90
+
91
+ describe('bundle with additional bundles', () => {
92
+ const renderOnlyFileContents = 'const file1 = require(\'./sources/file1\')\n' +
93
+ '\n' +
94
+ 'module.exports = {\n' +
95
+ ' file1,\n' +
96
+ '}\n'
97
+
98
+ afterEach(() => gulpConfig.set('browser.bundles', []))
99
+
100
+ test('produces one file per additional bundle, each from its own entry point', done => {
101
+ const distPath = gulpConfig.get('dist.to')
102
+ const renderOnlyMain = `${distPath}/renderOnly`
103
+ fs.writeFileSync(`${renderOnlyMain}.js`, renderOnlyFileContents)
104
+ gulpConfig.set('browser.bundles', [{ name: 'renderOnly', main: renderOnlyMain }])
105
+
106
+ const destPath = gulpConfig.get('browser.to')
107
+ const primaryFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
108
+ const renderOnlyFile = `${destPath}/renderOnly.js`
109
+ expect.assertions(4)
110
+ bundle()
111
+ .on('finish', () => {
112
+ // The primary bundle is unaffected - still built from dist.main, still has both files.
113
+ const primaryContents = fs.readFileSync(primaryFile).toString()
114
+ expect(primaryContents).toContain('Hello from file1')
115
+ expect(primaryContents).toContain('Good-bye from file2')
116
+
117
+ // The additional bundle came from its own entry point - file1 only, never file2.
118
+ const renderOnlyContents = fs.readFileSync(renderOnlyFile).toString()
119
+ expect(renderOnlyContents).toContain('Hello from file1')
120
+ expect(renderOnlyContents).not.toContain('Good-bye from file2')
121
+ done()
122
+ })
123
+ .on('error', error => done(error))
124
+ })
125
+
126
+ test('an additional bundle exposes its own name as its standalone export', done => {
127
+ const distPath = gulpConfig.get('dist.to')
128
+ const renderOnlyMain = `${distPath}/renderOnly`
129
+ fs.writeFileSync(`${renderOnlyMain}.js`, renderOnlyFileContents)
130
+ gulpConfig.set('browser.bundles', [{ name: 'renderOnly', main: renderOnlyMain }])
131
+
132
+ const destPath = gulpConfig.get('browser.to')
133
+ const renderOnlyFile = `${destPath}/renderOnly.js`
134
+ expect.assertions(2)
135
+ bundle()
136
+ .on('finish', () => {
137
+ const resolved = path.resolve(renderOnlyFile)
138
+ delete require.cache[resolved]
139
+ const loaded = require(resolved)
140
+ expect(typeof loaded.file1).toBe('function')
141
+ expect(loaded.file2).toBeUndefined()
142
+ done()
143
+ })
144
+ .on('error', error => done(error))
145
+ })
146
+ })
147
+
148
+ describe('bundle ignore / exclude', () => {
149
+ const optionalDepMarker = 'MARKER_FROM_THE_OPTIONAL_DEPENDENCY_CODE'
150
+
151
+ beforeEach(() => {
152
+ const tempDir = gulpConfig.get('rootPath')
153
+ const depDir = `${tempDir}node_modules/optional-dep`
154
+ fs.mkdirSync(depDir, { recursive: true })
155
+ fs.writeFileSync(`${depDir}/package.json`, JSON.stringify({ name: 'optional-dep', main: 'index.js' }))
156
+ fs.writeFileSync(`${depDir}/index.js`, `module.exports = '${optionalDepMarker}'\n`)
157
+ const distPath = gulpConfig.get('dist.to')
158
+ const mainFile = gulpConfig.get('dist.main')
159
+ fs.mkdirSync(distPath, { recursive: true })
160
+ // Only reached as a fallback for an option the caller always overrides, the way css-select falls back to its
161
+ // own default adapter (domutils) unless one is given - exactly the case ignore / exclude exist for.
162
+ fs.writeFileSync(`${mainFile}.js`, 'const optionalDep = require(\'optional-dep\')\n\nmodule.exports = (given) => given || optionalDep\n')
163
+ })
164
+
165
+ test('without ignore or exclude, the dependency is bundled', done => {
166
+ const destPath = gulpConfig.get('browser.to')
167
+ const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
168
+ expect.assertions(1)
169
+ bundle()
170
+ .on('finish', () => {
171
+ expect(fs.readFileSync(bundledFile).toString()).toContain(optionalDepMarker)
172
+ done()
173
+ })
174
+ .on('error', error => done(error))
175
+ })
176
+
177
+ test('ignore replaces the dependency with an empty object, but the bundle still finishes', done => {
178
+ gulpConfig.set('browser.ignore', ['optional-dep'])
179
+ const destPath = gulpConfig.get('browser.to')
180
+ const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
181
+ expect.assertions(2)
182
+ bundle()
183
+ .on('finish', () => {
184
+ const bundledContents = fs.readFileSync(bundledFile).toString()
185
+ // The ignored module is still in the bundle (as an empty stub, so requiring it by name still resolves) -
186
+ // it just no longer has the real code that would have pulled in the marker
187
+ expect(bundledContents).toContain('optional-dep')
188
+ expect(bundledContents).not.toContain(optionalDepMarker)
189
+ done()
190
+ })
191
+ .on('error', error => done(error))
192
+ })
193
+
194
+ test('exclude leaves the dependency out of the bundle entirely', done => {
195
+ gulpConfig.set('browser.exclude', ['optional-dep'])
196
+ const destPath = gulpConfig.get('browser.to')
197
+ const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
198
+ expect.assertions(1)
199
+ bundle()
200
+ .on('finish', () => {
201
+ expect(fs.readFileSync(bundledFile).toString()).not.toContain(optionalDepMarker)
202
+ done()
203
+ })
204
+ .on('error', error => done(error))
205
+ })
206
+
207
+ test('a single string is accepted the same as a one item array', done => {
208
+ gulpConfig.set('browser.ignore', 'optional-dep')
209
+ const destPath = gulpConfig.get('browser.to')
210
+ const bundledFile = `${destPath}/${gulpConfig.get('browser.name')}.js`
211
+ expect.assertions(1)
212
+ bundle()
213
+ .on('finish', () => {
214
+ expect(fs.readFileSync(bundledFile).toString()).not.toContain(optionalDepMarker)
215
+ done()
216
+ })
217
+ .on('error', error => done(error))
218
+ })
219
+ })
@@ -1,16 +1,16 @@
1
- import * as gulpConfig from '../gulp.config.mjs'
2
- import { minifyFor } from './partials/minifyFor.mjs'
3
- import { getBundleConfigs } from './utilities/getBundleConfigs.mjs'
4
-
5
- /**
6
- * Creates the minified file for every bundle (the primary bundle, plus any additional ones from
7
- * browser.bundles). The minify step itself never varies per bundle, so this is one shared
8
- * src()/dest() pipeline (inside minifyFor) fed every bundle's filename at once, rather than one
9
- * pipeline per bundle - gulp's src() accepts an array of paths natively.
10
- * @memberOf module:js-build-tools
11
- * @returns {*}
12
- */
13
- export const bundleMinify = () => minifyFor(
14
- getBundleConfigs().map(({ name }) => `${gulpConfig.get('browser.to')}/${name}.js`),
15
- gulpConfig.get('browser.to')
16
- )
1
+ import * as gulpConfig from '../gulp.config.mjs'
2
+ import { minifyFor } from './partials/minifyFor.mjs'
3
+ import { getBundleConfigs } from './utilities/getBundleConfigs.mjs'
4
+
5
+ /**
6
+ * Creates the minified file for every bundle (the primary bundle, plus any additional ones from
7
+ * browser.bundles). The minify step itself never varies per bundle, so this is one shared
8
+ * src()/dest() pipeline (inside minifyFor) fed every bundle's filename at once, rather than one
9
+ * pipeline per bundle - gulp's src() accepts an array of paths natively.
10
+ * @memberOf module:js-build-tools
11
+ * @returns {*}
12
+ */
13
+ export const bundleMinify = () => minifyFor(
14
+ getBundleConfigs().map(({ name }) => `${gulpConfig.get('browser.to')}/${name}.js`),
15
+ gulpConfig.get('browser.to')
16
+ )
@@ -1,37 +1,37 @@
1
- import { testHelpers } from './testHelpers.mjs'
2
- import { bundleMinify } from './bundleMinify.mjs'
3
- import { minifyFor } from './partials/minifyFor.mjs'
4
-
5
- const gulpConfig = testHelpers.gulpConfig
6
-
7
- jest.mock('./partials/minifyFor.mjs', () => ({ minifyFor: jest.fn(() => Promise.resolve(true)) }))
8
-
9
- describe('bundleMinify', () => {
10
- afterEach(() => {
11
- gulpConfig.set('browser.bundles', [])
12
- minifyFor.mockClear()
13
- })
14
-
15
- test('calls minifyFor with the primary bundle', () => {
16
- expect.assertions(1)
17
- bundleMinify()
18
- expect(minifyFor).toHaveBeenCalledWith(
19
- [`${gulpConfig.get('browser.to')}/${gulpConfig.get('browser.name')}.js`],
20
- gulpConfig.get('browser.to')
21
- )
22
- })
23
-
24
- test('calls minifyFor once, with every additional bundle included in the same array', () => {
25
- gulpConfig.set('browser.bundles', [{ name: 'renderOnly' }])
26
- expect.assertions(2)
27
- bundleMinify()
28
- expect(minifyFor).toHaveBeenCalledTimes(1)
29
- expect(minifyFor).toHaveBeenCalledWith(
30
- [
31
- `${gulpConfig.get('browser.to')}/${gulpConfig.get('browser.name')}.js`,
32
- `${gulpConfig.get('browser.to')}/renderOnly.js`
33
- ],
34
- gulpConfig.get('browser.to')
35
- )
36
- })
37
- })
1
+ import { testHelpers } from './testHelpers.mjs'
2
+ import { bundleMinify } from './bundleMinify.mjs'
3
+ import { minifyFor } from './partials/minifyFor.mjs'
4
+
5
+ const gulpConfig = testHelpers.gulpConfig
6
+
7
+ jest.mock('./partials/minifyFor.mjs', () => ({ minifyFor: jest.fn(() => Promise.resolve(true)) }))
8
+
9
+ describe('bundleMinify', () => {
10
+ afterEach(() => {
11
+ gulpConfig.set('browser.bundles', [])
12
+ minifyFor.mockClear()
13
+ })
14
+
15
+ test('calls minifyFor with the primary bundle', () => {
16
+ expect.assertions(1)
17
+ bundleMinify()
18
+ expect(minifyFor).toHaveBeenCalledWith(
19
+ [`${gulpConfig.get('browser.to')}/${gulpConfig.get('browser.name')}.js`],
20
+ gulpConfig.get('browser.to')
21
+ )
22
+ })
23
+
24
+ test('calls minifyFor once, with every additional bundle included in the same array', () => {
25
+ gulpConfig.set('browser.bundles', [{ name: 'renderOnly' }])
26
+ expect.assertions(2)
27
+ bundleMinify()
28
+ expect(minifyFor).toHaveBeenCalledTimes(1)
29
+ expect(minifyFor).toHaveBeenCalledWith(
30
+ [
31
+ `${gulpConfig.get('browser.to')}/${gulpConfig.get('browser.name')}.js`,
32
+ `${gulpConfig.get('browser.to')}/renderOnly.js`
33
+ ],
34
+ gulpConfig.get('browser.to')
35
+ )
36
+ })
37
+ })