├── .editorconfig
├── .eslintrc.yml
├── .gitattributes
├── .github
└── workflows
│ └── CI-CD.yaml
├── .gitignore
├── .mocharc.yml
├── .nycrc.yml
├── .vscode
├── launch.json
└── tasks.json
├── 404.md
├── CHANGELOG.md
├── LICENSE
├── README.md
├── _config.yml
├── bin
└── simplifyify.js
├── dist
├── index.js
├── package.json
└── simplifyify.js
├── lib
├── expand-globs.js
├── file-set.js
├── fs-cache.js
├── index.js
├── transforms
│ ├── banner.js
│ ├── index.js
│ ├── istanbul.js
│ ├── tsify.js
│ └── uglifyify.js
├── util.js
└── write-bundles.js
├── package-lock.json
├── package.json
└── test
├── fixtures
├── assert.js
├── cli.js
└── mocha.js
├── specs
├── bundle.spec.js
├── cli.spec.js
├── debug.spec.js
├── exclude.spec.js
├── minify.spec.js
├── outfile.spec.js
├── standalone.spec.js
├── test.spec.js
├── transform.spec.js
├── typescript.spec.js
└── watch.spec.js
└── test-apps
├── error
└── error.js
├── es5
├── hello-world.js
├── index.js
├── lib
│ ├── hello-world.js
│ ├── index.js
│ └── say
│ │ └── index.js
├── package.json
└── say
│ └── index.js
├── es6-with-options
├── hello-world.js
├── index.js
├── package.json
├── say
│ └── index.js
└── src
│ ├── hello-world.js
│ ├── index.js
│ └── say
│ └── index.js
├── es6
├── .babelrc
├── hello-world.js
├── index.js
├── package.json
├── say
│ └── index.js
└── src
│ ├── hello-world.js
│ ├── index.js
│ └── say
│ └── index.js
├── hello
├── banner.txt
├── hello-world.js
├── index.js
├── package.json
└── say
│ └── index.js
├── transform-options
├── hello-world.js
├── index.js
├── package.json
├── say
│ └── index.js
└── src
│ ├── hello-world.js
│ ├── index.js
│ └── say
│ └── index.js
├── typescript-error
├── error.ts
└── tsconfig.json
├── typescript-options
├── hello-world.tsx
├── index.ts
├── package.json
├── say
│ └── index.ts
└── src
│ ├── hello-world.tsx
│ ├── index.js
│ ├── index.ts
│ └── say
│ └── index.ts
├── typescript-tsconfig
├── hello-world.tsx
├── index.ts
├── say
│ └── index.ts
├── src
│ ├── hello-world.tsx
│ ├── index.js
│ ├── index.ts
│ └── say
│ │ └── index.ts
└── tsconfig.json
├── typescript
├── hello-world.tsx
├── index.ts
├── say
│ └── index.ts
└── src
│ ├── hello-world.tsx
│ ├── index.js
│ ├── index.ts
│ └── say
│ └── index.ts
└── universal-lib
├── banner.txt
├── bower.json
├── lib
├── browser.js
├── node.js
└── resolve.js
└── package.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor config
2 | # http://EditorConfig.org
3 |
4 | # This EditorConfig overrides any parent EditorConfigs
5 | root = true
6 |
7 | # Default rules applied to all file types
8 | [*]
9 |
10 | # No trailing spaces, newline at EOF
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 | end_of_line = lf
15 |
16 | # 2 space indentation
17 | indent_style = space
18 | indent_size = 2
19 |
20 | # JavaScript-specific settings
21 | [*.{js,ts}]
22 | quote_type = double
23 | continuation_indent_size = 2
24 | curly_bracket_next_line = false
25 | indent_brace_style = BSD
26 | spaces_around_operators = true
27 | spaces_around_brackets = none
28 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | # ESLint config
2 | # http://eslint.org/docs/user-guide/configuring
3 | # https://jstools.dev/eslint-config/
4 |
5 | root: true
6 | extends: "@jsdevtools"
7 | env:
8 | node: true
9 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Git attributes
2 | # https://git-scm.com/docs/gitattributes
3 | # https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes
4 |
5 | # Normalize line endings for all files that git determines to be text.
6 | # https://git-scm.com/docs/gitattributes#gitattributes-Settostringvalueauto
7 | * text=auto
8 |
9 | # Normalize line endings to LF on checkin, and do NOT convert to CRLF when checking-out on Windows.
10 | # https://git-scm.com/docs/gitattributes#gitattributes-Settostringvaluelf
11 | *.txt text eol=lf
12 | *.html text eol=lf
13 | *.md text eol=lf
14 | *.css text eol=lf
15 | *.scss text eol=lf
16 | *.map text eol=lf
17 | *.js text eol=lf
18 | *.jsx text eol=lf
19 | *.ts text eol=lf
20 | *.tsx text eol=lf
21 | *.json text eol=lf
22 | *.yml text eol=lf
23 | *.yaml text eol=lf
24 | *.xml text eol=lf
25 | *.svg text eol=lf
26 |
--------------------------------------------------------------------------------
/.github/workflows/CI-CD.yaml:
--------------------------------------------------------------------------------
1 | # GitHub Actions workflow
2 | # https://help.github.com/en/actions/automating-your-workflow-with-github-actions
3 | # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions
4 | # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions
5 |
6 | name: CI-CD
7 |
8 | on:
9 | push:
10 | branches:
11 | - "*"
12 | tags-ignore:
13 | - "*"
14 |
15 | schedule:
16 | - cron: "0 0 1 * *"
17 |
18 | jobs:
19 | test:
20 | name: Node ${{ matrix.node }} on ${{ matrix.os }}
21 | runs-on: ${{ matrix.os }}
22 | timeout-minutes: 10
23 | strategy:
24 | fail-fast: true
25 | matrix:
26 | os:
27 | - ubuntu-latest
28 | - macos-latest
29 | - windows-latest
30 | node:
31 | - 10
32 | - 12
33 | - 14
34 |
35 | steps:
36 | - name: Checkout source
37 | uses: actions/checkout@v2
38 |
39 | - name: Install Node ${{ matrix.node }}
40 | uses: actions/setup-node@v1
41 | with:
42 | node-version: ${{ matrix.node }}
43 |
44 | - name: Install dependencies
45 | run: npm ci
46 |
47 | - name: Run linters
48 | run: npm run lint
49 |
50 | - name: Run tests
51 | run: npm run coverage
52 |
53 | - name: Send code coverage results to Coveralls
54 | uses: coverallsapp/github-action@v1.1.0
55 | with:
56 | github-token: ${{ secrets.GITHUB_TOKEN }}
57 | parallel: true
58 |
59 | coverage:
60 | name: Code Coverage
61 | runs-on: ubuntu-latest
62 | timeout-minutes: 10
63 | needs: test
64 | steps:
65 | - name: Let Coveralls know that all tests have finished
66 | uses: coverallsapp/github-action@v1.1.0
67 | with:
68 | github-token: ${{ secrets.GITHUB_TOKEN }}
69 | parallel-finished: true
70 |
71 | deploy:
72 | name: Publish to NPM
73 | if: github.ref == 'refs/heads/master'
74 | runs-on: ubuntu-latest
75 | timeout-minutes: 10
76 | needs: test
77 |
78 | steps:
79 | - name: Checkout source
80 | uses: actions/checkout@v2
81 |
82 | - name: Install Node
83 | uses: actions/setup-node@v1
84 |
85 | - name: Install dependencies
86 | run: npm ci
87 |
88 | - name: Publish to NPM
89 | uses: JS-DevTools/npm-publish@v1
90 | with:
91 | token: ${{ secrets.NPM_TOKEN }}
92 |
93 | - name: Prepare the non-scoped packaged
94 | run: |
95 | cp LICENSE *.md dist
96 | VERSION=$(node -e "console.log(require('./package.json').version)")
97 | sed -i "s/X.X.X/${VERSION}/g" dist/package.json
98 |
99 | - name: Publish the non-scoped package to NPM
100 | uses: JS-DevTools/npm-publish@v1
101 | with:
102 | token: ${{ secrets.NPM_TOKEN }}
103 | package: dist/package.json
104 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Git ignore
2 | # https://git-scm.com/docs/gitignore
3 |
4 | # Miscellaneous
5 | *~
6 | *#
7 | .DS_STORE
8 | Thumbs.db
9 | .netbeans
10 | nbproject
11 | .node_history
12 |
13 | # IDEs & Text Editors
14 | .idea
15 | .sublime-*
16 | .vscode/settings.json
17 | .netbeans
18 | nbproject
19 |
20 | # Temporary files
21 | .tmp
22 | .temp
23 | .grunt
24 | .lock-wscript
25 |
26 | # Logs
27 | /logs
28 | *.log
29 |
30 | # Runtime data
31 | pids
32 | *.pid
33 | *.seed
34 |
35 | # Dependencies
36 | node_modules
37 |
38 | # Test output
39 | lib-cov
40 | .nyc_output
41 | /coverage
42 | /test/test-apps/*/dist
43 | /test/test-apps/*/*.bundle.js
44 |
--------------------------------------------------------------------------------
/.mocharc.yml:
--------------------------------------------------------------------------------
1 | # Mocha options
2 | # https://mochajs.org/#configuring-mocha-nodejs
3 | # https://github.com/mochajs/mocha/blob/master/example/config/.mocharc.yml
4 |
5 |
6 | # Test files
7 | spec:
8 | - test/fixtures/**/*.js
9 | - test/specs/**/*.spec.js
10 |
11 | # Abort after first test failure
12 | bail: true
13 | retries: 2
14 | recursive: true
15 | timeout: 10000
16 |
--------------------------------------------------------------------------------
/.nycrc.yml:
--------------------------------------------------------------------------------
1 | # NYC config
2 | # https://github.com/istanbuljs/nyc#configuration-files
3 |
4 | extension:
5 | - .js
6 | - .ts
7 |
8 | reporter:
9 | - text
10 | - lcov
11 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Run Simlifyify",
6 | "type": "node",
7 | "request": "launch",
8 | "program": "${workspaceRoot}/bin/simplifyify.js",
9 | "stopOnEntry": false,
10 | "args": [
11 | "error/error.js",
12 | "--watch",
13 | "--outfile",
14 | "error/dist/error.js",
15 | ],
16 | "cwd": "${workspaceRoot}/test/test-apps",
17 | "preLaunchTask": null,
18 | "runtimeExecutable": null,
19 | "runtimeArgs": [
20 | "--nolazy"
21 | ],
22 | "env": {
23 | "NODE_ENV": "development",
24 | "DEBUG": "true"
25 | },
26 | "console": "internalConsole",
27 | "sourceMaps": false
28 | },
29 | {
30 | "name": "Run tests",
31 | "type": "node",
32 | "request": "launch",
33 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
34 | "stopOnEntry": false,
35 | "args": [
36 | "--timeout=600000",
37 | "--retries=0"
38 | ],
39 | "cwd": "${workspaceRoot}",
40 | "preLaunchTask": null,
41 | "runtimeExecutable": null,
42 | "runtimeArgs": [
43 | "--nolazy"
44 | ],
45 | "env": {
46 | "NODE_ENV": "development"
47 | },
48 | "console": "internalConsole",
49 | "sourceMaps": false
50 | }
51 | ]
52 | }
53 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // Available variables which can be used inside of strings.
2 | // ${workspaceRoot}: the root folder of the team
3 | // ${file}: the current opened file
4 | // ${fileBasename}: the current opened file's basename
5 | // ${fileDirname}: the current opened file's dirname
6 | // ${fileExtname}: the current opened file's extension
7 | // ${cwd}: the current working directory of the spawned process
8 |
9 | {
10 | "version": "0.1.0",
11 | "command": "npm",
12 | "isShellCommand": true,
13 | "suppressTaskName": true,
14 | "tasks": [
15 | {
16 | "taskName": "lint",
17 | "args": ["run", "lint"],
18 | "showOutput": "always",
19 | "problemMatcher": "$eslint-stylish",
20 | "isBuildCommand": true
21 | },
22 | {
23 | "taskName": "test",
24 | "args": ["run", "test"],
25 | "showOutput": "always",
26 | "isTestCommand": true
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/404.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: 404
3 | ---
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Change Log
2 | ====================================================================================================
3 | All notable changes will be documented in this file.
4 | Simplifyify adheres to [Semantic Versioning](http://semver.org/).
5 |
6 |
7 |
8 | [v8.0.0](https://github.com/JS-DevTools/simplifyify/tree/v8.0.0) (2020-02-18)
9 | ----------------------------------------------------------------------------------------------------
10 |
11 | - Moved Simplifyify to the [@JSDevTools scope](https://www.npmjs.com/org/jsdevtools) on NPM
12 |
13 | - The "simplifyify" NPM package is now just a wrapper around the scoped "@jsdevtools/simplifyify" package
14 |
15 |
16 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v7.0.7...v8.0.0)
17 |
18 |
19 |
20 | [v7.0.0](https://github.com/JS-DevTools/simplifyify/tree/v7.0.0) (2018-10-18)
21 | ----------------------------------------------------------------------------------------------------
22 |
23 | #### Breaking Change
24 | - Simplifyify is no longer tested on Node 6 and Node 8. It's now only tested on the latest LTS version of Node (which is currently Node 10). It **currently** still works fine in older versions, but they are no longer officially supported.
25 |
26 | #### Other Changes
27 | - Improved performance by making many operations async and parallelizing them
28 |
29 | - Fixed a bug that caused Simplifyify to crash in watch mode when files contained syntax errors
30 |
31 |
32 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v6.0.0...v7.0.0)
33 |
34 |
35 |
36 | [v6.0.0](https://github.com/JS-DevTools/simplifyify/tree/v6.0.0) (2018-09-29)
37 | ----------------------------------------------------------------------------------------------------
38 |
39 | #### Breaking Changes
40 | - The shorthand argument for the `--exclude` option is now `-x` instead of `-u`
41 |
42 | - The `--test` argument has been replaced with `--coverage` for clarity. The corresponding shorthand argument is `-c`.
43 |
44 | - The `--coverage` argument produces a `.coverage.js` file instead of a `.test.js` file
45 |
46 |
47 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v5.0.0...v6.0.0)
48 |
49 |
50 |
51 | [v5.0.0](https://github.com/JS-DevTools/simplifyify/tree/v5.0.0) (2018-09-17)
52 | ----------------------------------------------------------------------------------------------------
53 |
54 | #### TypeScript Support
55 | - Simplifyify now has built-in support for TypeScript! If your entry file has a `.ts` or `.tsx` extension, then Simplifyify will automatically use [TSify](https://github.com/TypeStrong/tsify/) to transpile your code. You can configure TSify via the `browserify.plugins` field in your package.json, or via a tsconfig.json file. If both exist, then the `browserify.plugins` field overrides any values in tsconfig.json.
56 |
57 | #### Breaking Changes
58 | - Dropped support for Node v4.0 and older (see https://github.com/nodejs/Release)
59 |
60 | - Previously, [browserify-banner](https://github.com/JS-DevTools/browserify-banner) could be configured using the `browserify.transform` field in package.json. But browserify-banner is a Browserify plugin, not a transform. This caused it to be loaded twice - once as a plugin and once as a transform. You should now use the `browserify.plugins` field instead.
61 |
62 | - The `browserify.transform` field in package.json can be used to configure Browserify transforms. Previously, Simplifyify allowed you to _also_ use it to configure Browserify plugins, but that caused plugins to be loaded twice - once as a plugin and once as a transform. This can cause undefined behavior with some plugins. To fix that, Simplifyify now expects you to to configure Browserify plugins using the `browserify.plugins` field instead.
63 |
64 |
65 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v4.0.3...v5.0.0)
66 |
67 |
68 |
69 | [v4.0.0](https://github.com/JS-DevTools/simplifyify/tree/v4.0.0) (2018-01-17)
70 | ----------------------------------------------------------------------------------------------------
71 |
72 | - Updated all dependencies, including major version updates of `browserify`, `babelify`, `browserify-istanbul`, and `exorcist`
73 |
74 | - Switched from UglifyJS to [Uglify-ES](https://www.npmjs.com/package/uglify-es), which supports ES2015+ syntax. This _shouldn't_ break anything, but I'm bumping the major version number just to be safe
75 |
76 |
77 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v3.3.0...v4.0.0)
78 |
79 |
80 |
81 | [v3.3.0](https://github.com/JS-DevTools/simplifyify/tree/v3.3.0) (2018-01-10)
82 | ----------------------------------------------------------------------------------------------------
83 |
84 | - Refactored to use ES6 syntax (Node 4.x compatible)
85 |
86 | - The `--standalone` option now supports a wildcard (e.g. "MyLib.*"). Thanks to [@taye](https://github.com/taye) for [the PR](https://github.com/JS-DevTools/simplifyify/pull/24)
87 |
88 |
89 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v3.2.0...v3.3.0)
90 |
91 |
92 |
93 | [v3.2.0](https://github.com/JS-DevTools/simplifyify/tree/v3.2.0) (2016-11-11)
94 | ----------------------------------------------------------------------------------------------------
95 |
96 | - Fixed several subtle bugs that were introduced in 3.1.0
97 |
98 |
99 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v3.1.0...v3.2.0)
100 |
101 |
102 |
103 | [v3.1.0](https://github.com/JS-DevTools/simplifyify/tree/v3.1.0) (2016-11-06)
104 | ----------------------------------------------------------------------------------------------------
105 |
106 | #### New Feature: [bannerify](https://www.npmjs.com/package/bannerify) support
107 | Just add a `banner.txt` file to your project, and it'll automatically be added to your output bundle(s). The `banner.txt` file can contain [Lodash templates](https://lodash.com/docs/4.16.6#template), which have access to the full [lodash](https://lodash.com/docs/4.16.6) library as well as [moment-js](http://momentjs.com/) for date/time formatting. See [this example](https://github.com/JS-DevTools/simplifyify/blob/master/test/test-apps/hello/banner.txt).
108 |
109 | #### Better performance
110 | File i/o operations have been optimized in this release. Files that are likely to be needed by multiple entry files are cached so they only need to be read once. Other file i/o operations that were previously synchronous are now asynchronous.
111 |
112 |
113 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v3.0.0...v3.1.0)
114 |
115 |
116 |
117 | [v3.0.0](https://github.com/JS-DevTools/simplifyify/tree/v3.0.0) (2016-11-02)
118 | ----------------------------------------------------------------------------------------------------
119 |
120 | #### Major changes in this release:
121 |
122 | ##### 1) Dropped support for Node 0.x
123 | Simplifyify now requires Node 4.0 or greater, which is in-line with the [Node.js LTS schedule](https://github.com/nodejs/LTS). Many other dev tools, including some that `simplifyify` depends on, have also started dropping support for Node 0.x. Time to upgrade, folks.
124 |
125 | ##### 2) Better minification
126 | Simplifyify has always used [uglifyify](https://www.npmjs.com/package/uglifyify) under the hood to minify each module individually, but now it _also_ uses [UglifyJS](https://github.com/mishoo/UglifyJS2#uglifyjs-2) to minify the entire bundle file. This [2-phase process](https://github.com/JS-DevTools/simplifyify/blob/5ab81a30242b585bee21915fe899714404a4e81a/lib/add-transforms.js#L91-L159) produces the [smallest output possible](https://github.com/hughsk/uglifyify#motivationusage).
127 |
128 | ##### 3) Configure Uglifyify and Istanbul options
129 | You can now specify custom options for the built-in Uglifyify and Istanbul transforms via the [`browserify.transform`](https://github.com/substack/node-browserify#browserifytransform) in your `package.json`. See [this example](https://github.com/JS-DevTools/simplifyify#browserify-transforms) in the ReadMe.
130 |
131 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v2.0.4...v3.0.0)
132 |
133 |
134 |
135 | [v2.0.0](https://github.com/JS-DevTools/simplifyify/tree/v2.0.0) (2015-12-28)
136 | ----------------------------------------------------------------------------------------------------
137 |
138 | #### Major changes in this release:
139 |
140 | ##### 1) Support for Browserify transforms
141 | Simplifyify will now check your `package.json` file to see if you have a [browserify.transform](https://github.com/substack/node-browserify#browserifytransform) field. If so, then it will automatically add those transforms. No need to specify them on the command line. See [the readme](https://github.com/JS-DevTools/simplifyify#browserify-transforms) for more details.
142 |
143 | ##### 2) You choose whether the "default" bundle gets created
144 | In previous versions, Simplifyify _always_ created an unminified bundle. This makes sense if you don't specify _any_ output options. But if you _do_ specify output options (such as `--coverage` or `--minify`), then you may not have expected it to _also_ create an unminified bundle. So, in this version, there is now a `--bundle` option that you must use to explicitly specify that you want an unminified bundle. Otherwise, only the bundle(s) that you explicitly specify will be created.
145 |
146 | [Full Changelog](https://github.com/JS-DevTools/simplifyify/compare/v1.6.0...v2.0.0)
147 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 James Messinger
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Simplifyify
2 | ============================
3 | #### A simplified Browserify and Watchify CLI
4 |
5 | [](https://github.com/JS-DevTools/simplifyify/actions)
6 | [](https://github.com/JS-DevTools/simplifyify/actions)
7 |
8 | [](https://coveralls.io/github/JS-DevTools/simplifyify?branch=master)
9 | [](https://david-dm.org/JS-DevTools/simplifyify)
10 |
11 | [](https://www.npmjs.com/package/@jsdevtools/simplifyify)
12 | [](LICENSE)
13 | [](https://plant.treeware.earth/JS-DevTools/simplifyify)
14 |
15 | I constantly find myself using the same Browserify plug-ins and transforms on every project, and I always end up writing pretty much the same Gulp script over and over again. Simplifyify is the solution to that problem.
16 |
17 |
18 |
19 | Features
20 | --------------------------
21 | - Supports [globs](https://github.com/isaacs/node-glob#glob-primer), even on Windows
22 | - Supports Browserify [transforms](#browserify-transforms) and [plugins](#browserify-plugins), such as Babel, CoffeeScript, TypeScript, etc.
23 | - Built-in support for TypeScript. Enabled automatically if the entry file has a `.ts` or `.tsx` extension
24 | - Has a programmatic [API](#api), for use with build tools like Grunt, Gulp, Broccoli, etc.
25 | - Bundle everything into one big file, or create different bundles for each part of your app (see [examples below](#examples))
26 | - Add a banner with version, date, license, etc. via [browserify-banner](https://www.npmjs.com/package/browserify-banner)
27 | - One command creates all the files you need:
28 | - `--bundle` bundles your code and nothing else. Useful during development
29 | - `--debug` creates _external_ source-maps (`.map`) using [exorcist](https://www.npmjs.com/package/exorcist)
30 | - `--minify` shrinks your code using [uglifyify](https://www.npmjs.com/package/uglifyify) _and_ [Uglify-ES](https://github.com/mishoo/UglifyJS2/tree/harmony)
31 | - `--coverage` adds code-coverage instrumentation using [istanbul](https://istanbul.js.org/)
32 | - `--watch` uses [watchify](https://www.npmjs.com/package/watchify) for _fast_ differential re-builds as files change
33 |
34 |
35 | Related Projects
36 | --------------------------
37 | - [globify](https://jstools.dev/globify)
38 | Run browserify and watchify with globs - even on Windows
39 |
40 | - [sourcemapify](https://jstools.dev/sourcemapify)
41 | Sourcemap plugin for Browserify
42 |
43 | - [browserify-banner](https://jstools.dev/browserify-banner)
44 | Add a comment (and/or code) to the top of your Browserify bundle
45 |
46 |
47 |
48 | Installation
49 | --------------------------
50 | Install using [npm](https://docs.npmjs.com/about-npm/):
51 |
52 | ```bash
53 | npm install @jsdevtools/simplifyify
54 | ```
55 |
56 |
57 | Usage
58 | --------------------------
59 | ```
60 | Usage: simplifyify [options]
61 |
62 | Options:
63 |
64 | -b, --bundle Create a non-minified bundle (*.js) for each source file.
65 | This is the default if no other output option is set.
66 |
67 | -m, --minify Create a minified bundle (*.min.js) for each source file.
68 |
69 | -c, --coverage Create a bundle with code-coverage instrumentation
70 | (*.coverage.js) for each source file.
71 |
72 | -d, --debug Create a source map (*.js.map) for each bundle
73 |
74 | -w, --watch Watch source file(s) and rebuild the bundle(s) automatically
75 |
76 | -o, --outfile The output file or directory.
77 | May include a filename pattern (e.g. "*.bundle.js")
78 |
79 | -x, --exclude File path or glob pattern to exclude.
80 | Don't forget to put quotes around glob patterns
81 |
82 | -s, --standalone Export as a named UMD bundle (e.g. "my.cool.module")
83 | May include a wildcard (e.g. "MyLib.*")
84 |
85 | Arguments:
86 |
87 | One or more file paths and/or glob patterns.
88 | Don't forget to put quotes around glob patterns.
89 | A separate Browserify bundle will be created
90 | for each source file.
91 | ```
92 |
93 |
94 | Examples
95 | --------------------------
96 | #### One entry file --> one output file
97 | In the simplest usage, you can use Simplifyify to bundle all of your code into a single file:
98 |
99 | ```bash
100 | simplifyify src/index.js
101 |
102 | src/index.js --> src/index.bundle.js # <-- unminified code
103 | ```
104 |
105 | By default, the output file is at the same path as the entry file, but with a `.bundle.js` extension. You can customize this using the `--outfile` argument:
106 |
107 | ```bash
108 | simplifyify src/index.js --outfile dist/my-package.js
109 |
110 | src/index.js --> dist/my-package.js # <-- unminified code
111 | ```
112 |
113 | If you want the bundled code to be minified, then add the `--minify` flag:
114 |
115 | ```bash
116 | simplifyify src/index.js --outfile dist/my-package.js --minify
117 |
118 | src/index.js --> dist/my-package.js # <-- minified code
119 | ```
120 |
121 | What if you also want a source map (`.map`) file? Just add the `--debug` flag.
122 |
123 | ```bash
124 | simplifyify src/index.js --outfile dist/my-package.js --minify --debug
125 |
126 | src/index.js --> dist/my-package.js # <-- minified code
127 | src/index.js --> dist/my-package.js.map # <-- source map
128 | ```
129 |
130 |
131 |
132 | #### One entry file --> multiple output files
133 | Simplifyify can output multiple bundles of your code in a single command. Let's say you want to create an unminified bundle for development (with a source map), a minified bundle for production (with a source map), and a test bundle (with code-coverage instrumentation) for testing:
134 |
135 | ```bash
136 | simplifyify src/index.js --outfile dist/my-package.js --bundle --debug --minify --coverage
137 |
138 | src/index.js --> dist/my-package.js # <-- unminified code
139 | src/index.js --> dist/my-package.js.map # <-- source map
140 | src/index.js --> dist/my-package.min.js # <-- minified code
141 | src/index.js --> dist/my-package.min.js.map # <-- source map
142 | src/index.js --> dist/my-package.coverage.js # <-- code-coverage
143 | ```
144 |
145 |
146 |
147 | #### Multiple entry files --> multiple output files _for each_
148 | In many applications, it doesn't make sense for _all_ of your code to be bundled into one huge file. Maybe you want to create separate bundles for each folder, or for each component or section of your app. Simplifyify makes this easy. It will create separate bundles for each entry file that you specify. For example:
149 |
150 | ```bash
151 | simplifyify src/store.js src/cart.js src/checkout.js --outfile dist --bundle --minify --debug
152 |
153 | src/store.js --> dist/store.js # <-- unminified code
154 | src/store.js --> dist/store.js.map # <-- source map
155 | src/store.js --> dist/store.min.js # <-- minified code
156 | src/store.js --> dist/store.min.js.map # <-- source map
157 | src/cart.js --> dist/cart.js # <-- unminified code
158 | src/cart.js --> dist/cart.js.map # <-- source map
159 | src/cart.js --> dist/cart.min.js # <-- minified code
160 | src/cart.js --> dist/cart.min.js.map # <-- source map
161 | src/checkout.js --> dist/checkout.js # <-- unminified code
162 | src/checkout.js --> dist/checkout.js.map # <-- source map
163 | src/checkout.js --> dist/checkout.min.js # <-- minified code
164 | src/checkout.js --> dist/checkout.min.js.map # <-- source map
165 | ```
166 |
167 | Specifying each entry file can quickly become cumbersome though. That's where [globs](https://github.com/isaacs/node-glob#glob-primer) come in. You can specify one or more globs, and Simplifyify will create a separate bundle for each file that matches the glob pattern. For example:
168 |
169 | ```bash
170 | simplifyify "src/*/index.js" --outfile "dist/*.bundle.js" --bundle --minify --debug
171 |
172 | src/store/index.js --> dist/store/index.bundle.js # <-- unminified code
173 | src/store/index.js --> dist/store/index.bundle.js.map # <-- source map
174 | src/store/index.js --> dist/store/index.bundle.min.js # <-- minified code
175 | src/store/index.js --> dist/store/index.bundle.min.js.map # <-- source map
176 | src/cart/index.js --> dist/cart/index.bundle.js # <-- unminified code
177 | src/cart/index.js --> dist/cart/index.bundle.js.map # <-- source map
178 | src/cart/index.js --> dist/cart/index.bundle.min.js # <-- minified code
179 | src/cart/index.js --> dist/cart/index.bundle.min.js.map # <-- source map
180 | src/checkout/index.js --> dist/checkout/index.bundle.js # <-- unminified code
181 | src/checkout/index.js --> dist/checkout/index.bundle.js.map # <-- source map
182 | src/checkout/index.js --> dist/checkout/index.bundle.min.js # <-- minified code
183 | src/checkout/index.js --> dist/checkout/index.bundle.min.js.map # <-- source map
184 | ```
185 |
186 | > **TIP:** Don't forget to put quotes around your glob patterns! Otherwise, some shells (e.g. Bash) will try to expand them themselves, which may or may not work
187 |
188 |
189 |
190 | Browserify Transforms
191 | --------------------------
192 | Simplifyify honors the [`browserify.transform`](https://github.com/substack/node-browserify#browserifytransform) field in your `package.json` file. For example, the following configuration uses [Babelify](https://github.com/babel/babelify) to transform your ES6 code to ES5:
193 |
194 | ```json
195 | {
196 | "name": "my-package",
197 | "version": "1.2.3",
198 | "browserify": {
199 | "transform": ["babelify"]
200 | },
201 | "devDependencies": {
202 | "babelify": "^10.0.0"
203 | }
204 | }
205 | ```
206 |
207 | You can also specify options for your transforms. The exact options depend on the transform you're using. Here's an example that configures [Babelify](https://github.com/babel/babelify) and also modifies Simplifyify's default config for [uglifyify](https://www.npmjs.com/package/uglifyify):
208 |
209 | ```json
210 | {
211 | "name": "my-package",
212 | "version": "1.2.3",
213 | "browserify": {
214 | "transform": [
215 | ["babelify", {
216 | "presets": ["@babel/preset-env"]
217 | }],
218 | ["uglifyify", {
219 | "mangle": true,
220 | "compress": {
221 | "sequences": true,
222 | "dead_code": true,
223 | "booleans": true,
224 | "conditionals": true,
225 | "if_return": false,
226 | "drop_console": false,
227 | "keep_fnames": true
228 | },
229 | "output": {
230 | "comments": false
231 | }
232 | }]
233 | ]
234 | },
235 | "devDependencies": {
236 | "@babel/preset-env": "^7.0.0",
237 | "babelify": "^10.0.0"
238 | }
239 | }
240 | ```
241 |
242 |
243 |
244 | Browserify Plugins
245 | --------------------------
246 | The same technique described above for Browserify transforms also works for Browserify plugins. Just add a `browserify.plugins` field to your `package.json` file. For example, the following configuration configures [TSify](https://github.com/TypeStrong/tsify/) to transpile your TypeScript code, and [browserify-banner](https://github.com/JS-DevTools/browserify-banner) to add a banner comment to the top of your output file(s).
247 |
248 | ```json
249 | {
250 | "name": "my-package",
251 | "version": "1.2.3",
252 | "browserify": {
253 | "plugins": [
254 | ["browserify-banner", {
255 | "template": "<%= pkg.name %> v<%= pkg.version %>"
256 | }],
257 | ["tsify", {
258 | "target": "esnext",
259 | "module": "commonjs",
260 | "moduleResolution": "node",
261 | "jsx": "react"
262 | }]
263 | ]
264 | },
265 | "devDependencies": {
266 | "typescript": "^3.0.3"
267 | }
268 | }
269 | ```
270 |
271 |
272 |
273 | API
274 | --------------------------
275 | Simplifyify also has a programmatic API, so you can use it directly in your build scripts (Gulp, Grunt, Broccoli, etc.)
276 |
277 | [Here's the API definition](https://github.com/JS-DevTools/simplifyify/blob/6709bb5bbf59b327b4ced3e833078de8db006b5a/lib/index.js#L9-L28), and [here's a full example](https://github.com/JS-DevTools/simplifyify/blob/6709bb5bbf59b327b4ced3e833078de8db006b5a/bin/simplifyify.js#L71-L102). Just pass an array of strings (file paths and/or glob patterns) and an options param. You get back an [`EventEmitter`](https://nodejs.org/api/events.html#events_class_events_eventemitter), which fires all the Browserify & Watchify events.
278 |
279 | ```javascript
280 | var simplifyify = require("@jsdevtools/simplifyify");
281 |
282 | gulp.task("browserify", function(done) {
283 | simplifyify("lib/*.module.js",
284 | {
285 | outfile: "dist/*.bundle.js",
286 | debug: true,
287 | minify: true
288 | })
289 | .on("end", function() {
290 | // Finished successfully!
291 | done();
292 | })
293 | .on("error", function(err) {
294 | // Something went wrong
295 | done(err);
296 | });
297 | });
298 | ```
299 |
300 |
301 |
302 | Contributing
303 | --------------------------
304 | Contributions, enhancements, and bug-fixes are welcome! [Open an issue](https://github.com/JS-DevTools/simplifyify/issues) on GitHub and [submit a pull request](https://github.com/JS-DevTools/simplifyify/pulls).
305 |
306 | #### Building
307 | To build the project locally on your computer:
308 |
309 | 1. __Clone this repo__
310 | `git clone https://github.com/JS-DevTools/simplifyify.git`
311 |
312 | 2. __Install dependencies__
313 | `npm install`
314 |
315 | 3. __Run the tests__
316 | `npm test`
317 |
318 |
319 |
320 | License
321 | --------------------------
322 | Simplifyify is 100% free and open-source, under the [MIT license](LICENSE). Use it however you want.
323 |
324 | This package is [Treeware](http://treeware.earth). If you use it in production, then we ask that you [**buy the world a tree**](https://plant.treeware.earth/JS-DevTools/simplifyify) to thank us for our work. By contributing to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats.
325 |
326 |
327 |
328 | Big Thanks To
329 | --------------------------
330 | Thanks to these awesome companies for their support of Open Source developers ❤
331 |
332 | [](https://github.com/open-source)
333 | [](https://www.npmjs.com/)
334 | [](https://coveralls.io)
335 | [](https://travis-ci.com)
336 | [](https://saucelabs.com)
337 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | remote_theme: JS-DevTools/gh-pages-theme
2 |
3 | title: Simplifyify
4 | logo: https://jstools.dev/img/logos/logo.png
5 |
6 | author:
7 | twitter: JSDevTools
8 |
9 | google_analytics: UA-68102273-3
10 |
11 | twitter:
12 | username: JSDevTools
13 | card: summary
14 |
15 | defaults:
16 | - scope:
17 | path: ""
18 | values:
19 | image: https://jstools.dev/img/logos/card.png
20 | - scope:
21 | path: "test/**/*"
22 | values:
23 | sitemap: false
24 |
25 | plugins:
26 | - jekyll-sitemap
27 |
--------------------------------------------------------------------------------
/bin/simplifyify.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 |
4 | let program = require("commander");
5 | let path = require("path");
6 | let manifest = require("../package");
7 | let simplifyify = require("../");
8 |
9 | /**
10 | * Parse command-line arguments
11 | */
12 | function parseArguments () {
13 | program
14 | .version(manifest.version)
15 | .description(manifest.description)
16 | .arguments("")
17 | .option("-b, --bundle", "Create a non-minified bundle (*.js) for each source file")
18 | .option("-m, --minify", "Create a minified bundle (*.min.js) for each source file")
19 | .option("-c, --coverage", "Create a bundle with code-coverage instrumentation (*.coverage.js)")
20 | .option("-d, --debug", "Create a source map (*.js.map) for each bundle")
21 | .option("-w, --watch", "Watch source file(s) and rebuild the bundle(s) automatically")
22 | .option("-o, --outfile ", 'The output file or directory. May include a filename pattern (e.g. "*.bundle.js")')
23 | .option("-x, --exclude ", "File path or glob pattern to exclude")
24 | .option("-s, --standalone ", 'Export as a named UMD bundle (e.g. "my.cool.bundle"). May include a wildcard (e.g. "MyLib.*")')
25 | .on("--help", () => {
26 | console.log(
27 | " Arguments:\n" +
28 | "\n" +
29 | " One or more file paths and/or glob patterns.\n" +
30 | " Don't forget to put quotes around glob patterns.\n" +
31 | " A separate Browserify bundle will be created\n" +
32 | " for each source file.\n" +
33 | "\n" +
34 | " Examples:\n" +
35 | "\n" +
36 | " simplifyify src/index.js --outfile dist/bundle.js --bundle --debug --minify --coverage\n" +
37 | "\n" +
38 | " Output Files: \n" +
39 | " dist/bundle.js\n" +
40 | " dist/bundle.js.map\n" +
41 | " dist/bundle.min.js\n" +
42 | " dist/bundle.min.js.map\n" +
43 | " dist/bundle.coverage.js\n" +
44 | "\n" +
45 | "\n" +
46 | ' simplifyify "src/module-*.js" --outfile "dist/*.bundle.js" --bundle --minify\n' +
47 | "\n" +
48 | " Output Files: \n" +
49 | " dist/module-one.bundle.js\n" +
50 | " dist/module-one.bundle.min.js\n" +
51 | " dist/module-two.bundle.js\n" +
52 | " dist/module-two.bundle.min.js\n"
53 | );
54 | })
55 | .parse(process.argv);
56 |
57 | // Show help if no options were given
58 | if (program.args.length === 0) {
59 | program.outputHelp();
60 | process.exit(1);
61 | }
62 | }
63 |
64 | /**
65 | * Program entry point
66 | */
67 | function main () {
68 | parseArguments();
69 |
70 | simplifyify(program.args, program)
71 | .on("update", (file) => {
72 | // Log that a file change has been detected
73 | let relativePath = path.relative(process.cwd(), file);
74 | console.log(`${relativePath} has changed`);
75 | })
76 | .on("log", (msg) => {
77 | // Log # of bytes written & time taken
78 | console.log(msg);
79 | })
80 | .on("end", (fileSet) => {
81 | // Log the output files that were written
82 | console.log(`${fileSet.entryFile} --> ${fileSet.outputFile}`);
83 | if (fileSet.mapFile) {
84 | console.log(`${fileSet.entryFile} --> ${fileSet.mapFile}`);
85 | }
86 | })
87 | .on("error", (err, fileSet) => {
88 | // Log an error
89 | if (fileSet && fileSet.entryFile) {
90 | console.error(`Error bundling ${fileSet.entryFile}`);
91 | }
92 |
93 | if (process.env.DEBUG) {
94 | if (err.annotated) {
95 | // Show the annotated source code where the error occurred
96 | console.error(err.annotated);
97 |
98 | // Also show the stack trace, if there is one
99 | err.stack && console.error(err.stack);
100 | }
101 | else {
102 | // Show the stack trace, or fallback to the error message
103 | console.error(err.stack || err.message);
104 | }
105 | }
106 | else {
107 | console.error(err.message);
108 | }
109 |
110 | // Exit the app with an error code,
111 | // unless we're in "Watchify" mode, in which case, we just keep watching
112 | if (!program.watch) {
113 | process.exit(2);
114 | }
115 | });
116 | }
117 |
118 | main();
119 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | module.exports = require("@jsdevtools/simplifyify");
3 |
--------------------------------------------------------------------------------
/dist/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simplifyify",
3 | "version": "X.X.X",
4 | "description": "A simplified Browserify and Watchify CLI",
5 | "keywords": [
6 | "browserify",
7 | "browserify-plugin",
8 | "watchify",
9 | "cli",
10 | "minify",
11 | "uglify",
12 | "uglifyify",
13 | "sourcemap",
14 | "source-map",
15 | "source map",
16 | "exorcist",
17 | "istanbul"
18 | ],
19 | "author": {
20 | "name": "James Messinger",
21 | "url": "https://jamesmessinger.com"
22 | },
23 | "homepage": "https://jstools.dev/simplifyify",
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/JS-DevTools/simplifyify.git"
27 | },
28 | "license": "MIT",
29 | "main": "index.js",
30 | "bin": {
31 | "simplifyify": "simplifyify.js"
32 | },
33 | "files": [
34 | "simplifyify.js",
35 | "index.js"
36 | ],
37 | "engines": {
38 | "node": ">=10"
39 | },
40 | "dependencies": {
41 | "@jsdevtools/simplifyify": "X.X.X"
42 | },
43 | "peerDependencies": {
44 | "typescript": "*"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/dist/simplifyify.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 | require("@jsdevtools/simplifyify/bin/simplifyify.js");
4 |
--------------------------------------------------------------------------------
/lib/expand-globs.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const globby = require("globby");
4 | const path = require("path");
5 | const FileSet = require("./file-set");
6 | const util = require("./util");
7 |
8 | module.exports = expandGlobs;
9 |
10 | /**
11 | * Expands the given list of file paths and/or globs, and returns an array of {@link FileSet} objects
12 | * that map input files to their corresponding output files.
13 | *
14 | * @param {string[]} globs - Entry file paths and/or glob patterns
15 | * @param {Options} options - Simplifyify CLI options
16 | * @returns {Promise}
17 | */
18 | function expandGlobs (globs, options) {
19 | let outfileIsADirectory = isDirectory(options.outfile);
20 |
21 | return Promise.all(
22 | globs.map((pattern) => {
23 | return expandGlob(pattern, options, outfileIsADirectory);
24 | }))
25 | .then((arraysOfFileSets) => {
26 | // Flatten the array of FileSets
27 | return Array.prototype.concat.apply([], arraysOfFileSets);
28 | });
29 | }
30 |
31 | /**
32 | * Expands the given glob pattern, and returns an array of {@link FileSet} objects that map
33 | * input files to their corresponding output files.
34 | *
35 | * @param {string} pattern - Entry file paths and/or glob pattern
36 | * @param {Options} options - Simplifyify CLI options
37 | * @param {boolean} outfileIsADirectory - Indicates whether the output location is a directory or a file
38 | * @returns {Promise}
39 | */
40 | function expandGlob (pattern, options, outfileIsADirectory) {
41 | let baseDir;
42 |
43 | return Promise.resolve()
44 | .then(() => {
45 | // Determine the common parent directory of all the glob patterns
46 | baseDir = getBaseDir(pattern);
47 |
48 | // Find all files that match this glob pattern
49 | return globby(pattern, {
50 | unique: true, // only return unique matches
51 | onlyFiles: true, // only match files, not directories
52 | ignore: options.exclude ? [options.exclude] : []
53 | });
54 | })
55 | .then(entryFiles => {
56 | let fileSets = [];
57 |
58 | // Create a FileSet for each entry file that was found
59 | for (let entryFile of entryFiles) {
60 | let fileSet = new FileSet();
61 | fileSet.entryFile = entryFile;
62 |
63 | if (outfileIsADirectory) {
64 | fileSet.outputFile = rename(entryFile, baseDir, options.outfile);
65 | }
66 | else if (options.outfile) {
67 | fileSet.outputFile = options.outfile;
68 | }
69 | else {
70 | fileSet.outputFile = util.appendToFileName(entryFile, ".bundle");
71 | }
72 |
73 | if (options.debug) {
74 | fileSet.mapFile = fileSet.outputFile + ".map";
75 | }
76 |
77 | if (options.standalone) {
78 | fileSet.standalone = getStandalone(entryFile, baseDir, options.standalone);
79 | }
80 |
81 | fileSets.push(fileSet);
82 | }
83 |
84 | return fileSets;
85 | });
86 | }
87 |
88 | /**
89 | * Determines the base directory of the given glob pattern.
90 | * This is used to determine the relative paths of matched files.
91 | *
92 | * @param {string} pattern - A glob pattern, such as "dir/subdir/*.js"
93 | * @returns {string}
94 | */
95 | function getBaseDir (pattern) {
96 | // Some examples:
97 | // - *.js => .
98 | // - dir/**/*.js => dir
99 | // - dir/subdir/main-*.js => dir/subdir
100 | // - dir/subdir/index.js => dir/subdir
101 | // - dir/subdir/index.(js|coffee) => dir/subdir
102 |
103 | let wildcard = pattern.indexOf("*");
104 | if (wildcard >= 0) {
105 | pattern = pattern.substr(0, wildcard + 1);
106 | }
107 | return path.dirname(pattern);
108 | }
109 |
110 | /**
111 | * Determines whether the given output filename is a directory.
112 | *
113 | * @param {string} pattern - A file path, a directory path, or a pattern, such as "dist/*.bundle.js"
114 | * @returns {boolean}
115 | */
116 | function isDirectory (pattern) {
117 | if (pattern) {
118 | let basename = path.basename(pattern);
119 | if (basename.includes("*")) {
120 | // The pattern includes a filename pattern (e.g. "dist/*.bundle.js"),
121 | // which counts as a directory path
122 | return true;
123 | }
124 | else if (!basename.includes(".")) {
125 | // The pattern has no file extension, so assume it's a directory
126 | return true;
127 | }
128 | }
129 |
130 | return false;
131 | }
132 |
133 | /**
134 | * Returns the output file name, based on the the entry file name, the base directory,
135 | * and the output path/pattern.
136 | *
137 | * @param {string} file - The source file path and name (e.g. "lib/dir/subdir/my-file.js")
138 | * @param {string} baseDir - The directory to calculate the relative path from (e.g. "lib")
139 | * @param {string} namePattern - The output file path and pattern (e.g. "dest/*.bundle.js")
140 | * @returns {string} - The main output file path and name (e.g. "dest/dir/subdir/my-file.bundle.js")
141 | */
142 | function rename (file, baseDir, namePattern) {
143 | let fileExtName = path.extname(file); // .js
144 | let fileBaseName = path.basename(file, fileExtName); // my-file
145 | let relativeDir = path.dirname(path.relative(baseDir, file)); // dir/subdir
146 |
147 | let patternFileName = path.basename(namePattern); // *.bundle.js
148 | let patternDir;
149 | if (!patternFileName.includes("*")) {
150 | patternDir = namePattern; // dest
151 |
152 | // TypeScript files transpile to JavaScript files
153 | if (util.isTypeScript(file)) {
154 | fileExtName = ".js";
155 | }
156 | }
157 | else {
158 | patternDir = getBaseDir(namePattern); // dest
159 | fileExtName = patternFileName.substr(patternFileName.indexOf("*") + 1); // .bundle.js
160 | }
161 |
162 | let outputDir = path.join(patternDir, relativeDir); // dest/dir/subdir
163 | return path.join(outputDir, fileBaseName + fileExtName); // dest/dir/subdir/my-file.bundle.js
164 | }
165 |
166 | /**
167 | * Returns the output file name, based on the the entry file name, the base directory,
168 | * and the output path/pattern.
169 | *
170 | * @param {string} file - The source file path and name (e.g. "lib/dir/subdir/my-file.js")
171 | * @param {string} baseDir - The directory to calculate the relative path from (e.g. "lib")
172 | * @param {string} standalonePattern - The standalone option pattern (e.g. "MyLib.*")
173 | * @returns {string} - The UMD standalone module name (e.g. "MyLib.dir.subdir.my-file")
174 | */
175 | function getStandalone (file, baseDir, standalonePattern) {
176 | let patternWildcardIndex = standalonePattern.indexOf("*");
177 |
178 | if (patternWildcardIndex === -1) {
179 | // The same standalone name will be used for all bundles
180 | return standalonePattern;
181 | }
182 |
183 | let fileExtName = path.extname(file); // .js
184 | let fileBaseName = path.basename(file, fileExtName); // my-file
185 | let relativeDir = path.dirname(path.relative(baseDir, file)); // dir/subdir
186 |
187 | let standaloneName;
188 | if (relativeDir === ".") {
189 | standaloneName = fileBaseName; // my-file
190 | }
191 | else {
192 | let standaloneNamespace = relativeDir.replace(/[/\\]/g, "."); // dir.subdir
193 | standaloneName = standaloneNamespace + "." + fileBaseName; // dir.subdir.my-file
194 | }
195 |
196 | let standalone = standalonePattern.replace("*", standaloneName); // MyLib.dir.subdir.my-file
197 | return standalone;
198 | }
199 |
--------------------------------------------------------------------------------
/lib/file-set.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /**
4 | * The input & output files for a Browserify bundle
5 | */
6 | class FileSet {
7 | constructor () {
8 | /**
9 | * The entry file for a CommonJS module
10 | * @type {string}
11 | */
12 | this.entryFile = "";
13 |
14 | /**
15 | * The output file for a Browserify bundle
16 | * @type {string}
17 | */
18 | this.outputFile = "";
19 |
20 | /**
21 | * The source map file for a Browserify bundle
22 | * @type {string}
23 | */
24 | this.mapFile = "";
25 |
26 | /**
27 | * The UMD standalone module name for a Browserify bundle
28 | * @type {string}
29 | */
30 | this.standalone = "";
31 | }
32 | }
33 |
34 | module.exports = FileSet;
35 |
--------------------------------------------------------------------------------
/lib/fs-cache.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const fs = require("fs");
4 | const path = require("path");
5 |
6 | const cache = {/*
7 | filePath: {
8 | exists: true|false,
9 | contents: string|object,
10 | }
11 | */};
12 |
13 | /**
14 | * Caches file contents so we don't have to find and read the same files
15 | * for every entry file.
16 | */
17 | module.exports = {
18 | findFile,
19 | readTextFile,
20 | readJsonFile,
21 | };
22 |
23 | /**
24 | * Searches for the given file name, starting in the given directory
25 | * and crawling up from there.
26 | *
27 | * @param {string} startingPath - The file path to start at
28 | * @returns {string|undefined}
29 | */
30 | function findFile (startingPath) {
31 | let cached = cacheFile(startingPath);
32 |
33 | if (cached.exists) {
34 | return startingPath;
35 | }
36 |
37 | let fileName = path.basename(startingPath);
38 | let startingDir = path.dirname(startingPath);
39 | let parentDir = path.dirname(startingDir);
40 | if (parentDir !== startingDir) {
41 | return findFile(path.join(parentDir, fileName));
42 | }
43 | }
44 |
45 | /**
46 | * Returns the contents of the specified file as a string.
47 | *
48 | * @param {string} filePath
49 | * @returns {string}
50 | */
51 | function readTextFile (filePath) {
52 | let cached = cacheFile(filePath);
53 | return cached.contents;
54 | }
55 |
56 | /**
57 | * Returns the contents of the specified file as a JSON object.
58 | *
59 | * @param {string} filePath
60 | * @returns {object}
61 | */
62 | function readJsonFile (filePath) {
63 | let cached = cacheFile(filePath);
64 | if (!cached.contents) {
65 | cached.contents = {};
66 | }
67 | else if (typeof cached.contents === "string") {
68 | cached.contents = JSON.parse(cached.contents);
69 | }
70 | return cached.contents;
71 | }
72 |
73 | /**
74 | * Caches the given file, and returns the cached file.
75 | *
76 | * @param {string} filePath
77 | * @returns {object}
78 | */
79 | function cacheFile (filePath) {
80 | let cached = cache[filePath];
81 |
82 | if (cached) {
83 | return cached;
84 | }
85 |
86 | cached = {};
87 | try {
88 | cached.contents = fs.readFileSync(filePath, "utf8");
89 | cached.exists = true;
90 | }
91 | catch (e) {
92 | cached.exists = false;
93 | cached.contents = undefined;
94 | }
95 |
96 | return cache[filePath] = cached;
97 | }
98 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const expandGlobs = require("./expand-globs");
4 | const writeBundles = require("./write-bundles");
5 | const EventEmitter = require("events").EventEmitter;
6 |
7 | module.exports = simplifyify;
8 |
9 | /**
10 | * @typedef {{
11 | * outfile: string,
12 | * exclude: string,
13 | * standalone: string,
14 | * bundle: boolean,
15 | * debug: boolean,
16 | * minify: boolean,
17 | * coverage: boolean,
18 | * watch: boolean
19 | * }} Options
20 | */
21 |
22 | /**
23 | * The Simplifyify API
24 | *
25 | * @param {string|string[]} globs - One or more file paths and/or glob patterns
26 | * @param {Options} [options] - Simplifyify CLI options
27 | * @returns {EventEmitter}
28 | */
29 | function simplifyify (globs, options) {
30 | options = options || {};
31 |
32 | let events = new EventEmitter();
33 | simplifyifyAsync(globs, options, events);
34 | return events;
35 | }
36 |
37 | /**
38 | * Do everything asynchronously, even parameter validation.
39 | *
40 | * @param {string|string[]} globs - One or more file paths and/or glob patterns
41 | * @param {Options} options - Simplifyify CLI options
42 | * @param {EventEmitter} events - Emits Browserify events
43 | */
44 | function simplifyifyAsync (globs, options, events) {
45 | Promise.resolve()
46 | .then(() => {
47 | // Validate the entry files
48 | if (!globs || globs.length === 0) {
49 | events.emit("error", new Error("No entry files were specified"));
50 | return;
51 | }
52 |
53 | if (!Array.isArray(globs)) {
54 | globs = [globs];
55 | }
56 |
57 | // Expand the glob(s) into a list of entry files and output files
58 | return expandGlobs(globs, options);
59 | })
60 | .then((fileSets) => {
61 | if (fileSets.length === 0) {
62 | events.emit("error", new Error("No matching entry files were found"));
63 | return;
64 | }
65 |
66 | for (let fileSet of fileSets) {
67 | // Do this synchronously, so that files like package.json, bundle.txt, etc.
68 | // are only read once, and cached versions are used for subsequent bundles
69 | writeBundles(fileSet, events, options);
70 | }
71 | })
72 | .catch((error) => {
73 | events.emit("error", error);
74 | });
75 | }
76 |
--------------------------------------------------------------------------------
/lib/transforms/banner.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("path");
4 | const cache = require("../fs-cache");
5 | const banner = require("@jsdevtools/browserify-banner");
6 |
7 | module.exports = applyBanner;
8 |
9 | /**
10 | * Adds the Banner transform to the given Browserify or Watchify instance.
11 | *
12 | * @param {Browserify} browserify - The Browserify or Watchify instance
13 | * @param {object} manifest - The project manifest (package.json file)
14 | * @param {object} [options] - The Banner options, if any
15 | */
16 | function applyBanner (browserify, manifest, options) {
17 | options = options || {};
18 |
19 | if (!options.pkg) {
20 | // Default to the project manifest
21 | options.pkg = manifest;
22 | }
23 |
24 | if (!options.file) {
25 | // If there's a "banner.txt" file, then use it as the banner template
26 | let bannerPath = path.join(path.dirname(browserify.files.entryFile), "banner.txt");
27 | bannerPath = cache.findFile(bannerPath);
28 | if (bannerPath) {
29 | options.template = cache.readTextFile(bannerPath);
30 | }
31 | }
32 |
33 | if (options.file || options.template || options.banner) {
34 | browserify.plugin(banner, options);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/transforms/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const ono = require("@jsdevtools/ono");
4 | const util = require("../util");
5 | const cache = require("../fs-cache");
6 | const applyTSify = require("./tsify");
7 | const applyIstanbul = require("./istanbul");
8 | const applyUglifyify = require("./uglifyify");
9 | const applyBanner = require("./banner");
10 |
11 | /**
12 | * Provides easy access to the Browserify transforms from the project manifest.
13 | */
14 | class Transforms {
15 | /**
16 | * @param {string} startingDir - The directory to start searching for the manifest file
17 | */
18 | constructor (startingDir) {
19 | /**
20 | * The entire project manifest
21 | * @type {object}
22 | */
23 | this.manifest = readProjectManifest(startingDir);
24 |
25 | /**
26 | * The TSify (TypeScript) transform options
27 | * @type {object}
28 | */
29 | this.tsify = getBrowserifyOptions(this.manifest, "plugins", "tsify");
30 |
31 | /**
32 | * The Uglifyify transform options
33 | * @type {object}
34 | */
35 | this.uglifyify = getBrowserifyOptions(this.manifest, "transform", "uglifyify");
36 |
37 | /**
38 | * The Istanbul transform options
39 | * @type {object}
40 | */
41 | this.istanbul = getBrowserifyOptions(this.manifest, "transform", "browserify-istanbul");
42 |
43 | /**
44 | * The Banner transform options
45 | * @type {object}
46 | */
47 | this.banner = getBrowserifyOptions(this.manifest, "plugins", "browserify-banner");
48 |
49 | /**
50 | * All other Browserify transforms from the project manifest
51 | * @type {array}
52 | */
53 | this.otherTransforms = omitBrowserifyOptions(this.manifest, "transform", [
54 | "uglifyify", "browserify-istanbul"]);
55 |
56 | /**
57 | * All other Browserify plugins from the project manifest
58 | * @type {array}
59 | */
60 | this.otherPlugins = omitBrowserifyOptions(this.manifest, "plugins", [
61 | "tsify", "browserify-banner"]);
62 | }
63 |
64 | /**
65 | * Configures the given Browserify or Watchify instance to use these transforms.
66 | *
67 | * @param {Browserify} browserify - The Browserify or Watchify instance
68 | * @param {object} [options]
69 | * @param {boolean} [options.minify] - Whether to include the uglifyify transform
70 | * @param {boolean} [options.coverage] - Whether to include the istanbul transform
71 | */
72 | apply (browserify, options) {
73 | try {
74 | options = options || {};
75 |
76 | // Add any user-defined transforms first
77 | for (let [name, config] of this.otherTransforms) {
78 | browserify.transform(require(name), config);
79 | }
80 |
81 | // Then any user-defined plugins
82 | for (let [name, config] of this.otherPlugins) {
83 | browserify.transform(require(name), config);
84 | }
85 |
86 | // Transpile TypeScript
87 | if (options.typescript) {
88 | applyTSify(browserify, this.tsify);
89 | }
90 |
91 | // Then minify
92 | if (options.minify) {
93 | applyUglifyify(browserify, this.uglifyify);
94 | }
95 |
96 | // Add code-coverage AFTER uglifyify, so it doesn't get mangled
97 | if (options.coverage) {
98 | applyIstanbul(browserify, this.istanbul);
99 | }
100 |
101 | // Add the banner last
102 | applyBanner(browserify, this.manifest, this.banner);
103 | }
104 | catch (e) {
105 | throw ono(e, "Error adding Browserify transforms");
106 | }
107 | }
108 | }
109 |
110 | /**
111 | * Reads the project manifest (package.json file) and returns
112 | * it as a normalized object.
113 | *
114 | * @param {string} manifestPath - The path of the manifest file
115 | */
116 | function readProjectManifest (manifestPath) {
117 | // Find the manifest file by crawling up the directory tree
118 | manifestPath = cache.findFile(manifestPath);
119 |
120 | // Parse the manifest
121 | let manifest = {};
122 | if (manifestPath) {
123 | manifest = cache.readJsonFile(manifestPath);
124 | }
125 |
126 | // Normalize the manifest
127 | manifest.browserify = manifest.browserify || {};
128 | manifest.browserify.transform = manifest.browserify.transform || [];
129 | manifest.browserify.plugins = manifest.browserify.plugins || [];
130 |
131 | return manifest;
132 | }
133 |
134 | /**
135 | * Returns the specified transform's or plugin's options from the project manifest (package.json).
136 | * If no options are set, then undefined is returned.
137 | *
138 | * @param {object} manifest - The project manifest (package.json file)
139 | * @param {string} type - "transform" or "plugins"
140 | * @param {string} name - The name of the transform/plugin whose options are returned
141 | * @returns {object|undefined}
142 | */
143 | function getBrowserifyOptions (manifest, type, name) {
144 | for (let tuple of manifest.browserify[type]) {
145 | if (Array.isArray(tuple)) {
146 | let [_name, config] = tuple;
147 |
148 | if (_name === name) {
149 | return util.deepClone(config);
150 | }
151 | }
152 | }
153 | }
154 |
155 | /**
156 | * Returns all Browserify transform/plugin options, except the omitted ones
157 | *
158 | * @param {object} manifest - The project manifest (package.json file)
159 | * @param {string} type - "transform" or "plugins"
160 | * @param {string[]} omit - The names of the transforms to omit
161 | * @returns {array}
162 | */
163 | function omitBrowserifyOptions (manifest, type, omit) {
164 | let included = [];
165 |
166 | for (let tuple of manifest.browserify[type]) {
167 | let name, config;
168 |
169 | // Each transform can be a string (just the transform name)
170 | // or an array (the transform name and its options)
171 | if (Array.isArray(tuple)) {
172 | [name, config] = tuple;
173 | }
174 | else {
175 | name = tuple;
176 | config = undefined;
177 | }
178 |
179 | // Add the transform, unless it's one of the omitted ones
180 | if (!omit.includes(name)) {
181 | included.push([name, config]);
182 | }
183 | }
184 |
185 | return included;
186 | }
187 |
188 | module.exports = Transforms;
189 |
--------------------------------------------------------------------------------
/lib/transforms/istanbul.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const istanbul = require("browserify-istanbul");
4 |
5 | module.exports = applyIstanbul;
6 |
7 | /**
8 | * Adds the Istanbul transform to the given Browserify or Watchify instance.
9 | *
10 | * @param {Browserify} browserify - The Browserify or Watchify instance
11 | * @param {object} [options] - The Istanbul options, if any
12 | */
13 | function applyIstanbul (browserify, options) {
14 | options = options || {
15 | // Replace Istanbul's default "ignore" list with our own
16 | defaultIgnore: false,
17 | ignore: [
18 | "**/node_modules/**", "**/bower_components/**",
19 | "**/*.json", "**/*.html", "**/*.md", "**/*.txt"
20 | ],
21 | };
22 |
23 | browserify.transform(istanbul(options));
24 | }
25 |
--------------------------------------------------------------------------------
/lib/transforms/tsify.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("path");
4 | const cache = require("../fs-cache");
5 | const tsify = require("tsify");
6 |
7 | module.exports = applyTSify;
8 |
9 | /**
10 | * Adds the TSify plugin to the given Browserify or Watchify instance.
11 | *
12 | * @param {Browserify} browserify - The Browserify or Watchify instance
13 | * @param {object} [options] - The TSify options, if any
14 | */
15 | function applyTSify (browserify, options) {
16 | if (!options) {
17 | // No TypeScript options were set in package.json, so look for a tsconfig.json file
18 | let tsConfigPath = path.join(path.dirname(browserify.files.entryFile), "tsconfig.json");
19 | tsConfigPath = cache.findFile(tsConfigPath);
20 |
21 | if (tsConfigPath) {
22 | // Configure TSify to use the tsconfig.json file
23 | options = { project: tsConfigPath };
24 | }
25 | else {
26 | // Configure TSify with default options
27 | options = {
28 | project: {
29 | compilerOptions: {
30 | target: "esnext",
31 | module: "commonjs",
32 | moduleResolution: "node",
33 | resolveJsonModule: true,
34 | esModuleInterop: true,
35 | jsx: "react",
36 | },
37 |
38 | // An empty files array causes TSify to use the Browserify entry file(s)
39 | files: [],
40 |
41 | // Don't transpile stuff in node_modules
42 | exclude: [
43 | "node_modules"
44 | ],
45 | },
46 | };
47 | }
48 | }
49 |
50 | browserify.plugin(tsify, options);
51 | }
52 |
--------------------------------------------------------------------------------
/lib/transforms/uglifyify.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("path");
4 | const uglify = require("uglify-es");
5 | const uglifyify = require("uglifyify");
6 | const util = require("../util");
7 |
8 | module.exports = applyUglifyify;
9 |
10 | /**
11 | * Adds the Uglifyify transform to the given Browserify or Watchify instance.
12 | *
13 | * Minification is done in two phases, both using UglifyJS:
14 | *
15 | * PHASE 1 - The first phase occurs as a Browserify transform, which minifies each module
16 | * individually. This allows Uglify to eliminate dead code paths within each module.
17 | *
18 | * PHASE 2 - The second phase occurs after Browserify is finished, and minifies the entire
19 | * bundle file. This allows Uglify to achieve the smallest possible file size.
20 | *
21 | * @param {Browserify} browserify - The Browserify or Watchify instance
22 | * @param {object} [options] - The Uglifyify options, if any
23 | */
24 | function applyUglifyify (browserify, options) {
25 | options = options || {};
26 | let hasSourcemap = !!browserify.files.mapFile;
27 | let bundlePath = path.resolve(browserify.files.outputFile);
28 | let sourcemapPath = hasSourcemap && path.resolve(browserify.files.mapFile);
29 |
30 | if (options.global === undefined) {
31 | // Apply uglifyify to ALL modules in the bundle, even third-party ones
32 | options.global = true;
33 | }
34 |
35 | if (options.exts === undefined) {
36 | // Apply uglifyify to all JavaScript, JSON, or TypeScript files
37 | options.exts = [".js", ".json", ".es6", ".esm", ".jsm", ".jsx", ".ts", ".tsx"];
38 | }
39 |
40 | if (options.output === undefined) {
41 | options.output = {
42 | // Keep important comments when minifying
43 | comments: /^!|^\*!|@preserve|@license|@cc_on/,
44 | };
45 | }
46 |
47 | // PHASE 1 - Minify each module individually
48 | browserify.transform(uglifyify, util.deepClone(options));
49 |
50 | // PHASE 2 - Minify the entire bundle file
51 | browserify.postProcessing = function () {
52 | return Promise.all(
53 | [
54 | util.readFile(bundlePath),
55 | hasSourcemap && util.readFile(sourcemapPath),
56 | ])
57 | .then(phase2)
58 | .then(overwriteBundle)
59 | .then(overwriteSourcemap);
60 | };
61 |
62 | // Minify the entire bundle using UglifyJS
63 | function phase2 (code) {
64 | return Promise.resolve()
65 | .then(() => {
66 | let bundleCode = code[0];
67 | let sourcemapCode = code[1];
68 |
69 | // For PHASE 2, we don't need to perform additional mangling, compressing,
70 | // comment-removal, etc., since that has already been done in PHASE 1
71 | options = {
72 | mangle: false,
73 | compress: false,
74 | output: Object.assign({}, options.output, {
75 | comments: true,
76 | }),
77 | };
78 |
79 | // If the bundle has a sourcemap, then UglifyJS needs to modify it
80 | if (hasSourcemap) {
81 | options.sourceMap = {
82 | content: sourcemapCode,
83 | url: path.basename(sourcemapPath),
84 | filename: path.basename(bundlePath),
85 | };
86 | }
87 |
88 | let minified = uglify.minify(bundleCode, options);
89 |
90 | if (minified.error) {
91 | throw minified.error;
92 | }
93 | else {
94 | return minified;
95 | }
96 | });
97 | }
98 |
99 | // Overwrite the bundle file from PHASE 1
100 | function overwriteBundle (minified) {
101 | return util.writeFile(bundlePath, minified.code)
102 | .then(() => minified);
103 | }
104 |
105 | // Overwrite the sourcemap file from PHASE 1
106 | function overwriteSourcemap (minified) {
107 | if (hasSourcemap) {
108 | // Parse the sourcemap so we format it using JSON.stringify()
109 | let map = JSON.parse(minified.map);
110 |
111 | return util.writeFile(sourcemapPath, JSON.stringify(map, null, 2));
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/lib/util.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const mkdirp = require("mkdirp-promise");
4 | const path = require("path");
5 | const fs = require("fs");
6 |
7 | module.exports = {
8 | ensureFileExists,
9 | touchFile,
10 | statFile,
11 | readFile,
12 | writeFile,
13 | deleteFile,
14 | appendToFileName,
15 | isTypeScript,
16 | deepClone,
17 | };
18 |
19 | /**
20 | * Ensures that the given file path exists, since Browserify throws errors if they don't.
21 | *
22 | * @param {string} file - The absolute file path
23 | * @returns {Promise}
24 | */
25 | function ensureFileExists (file) {
26 | return Promise.resolve()
27 | .then(() => {
28 | // Try to access the file
29 | return statFile(file);
30 | })
31 | .catch((error) => {
32 | if (error.code === "ENOENT") {
33 | // The file doesn't exist, so create it
34 | return touchFile(file);
35 | }
36 | else {
37 | throw error;
38 | }
39 | });
40 | }
41 |
42 | /**
43 | * Asynchronously adds a newline to the end of a file, to trigger any file-modification watchers
44 | *
45 | * @param {string} file - The absolute file path
46 | * @returns {Promise} - Resolves with an fs.Stats object
47 | */
48 | function touchFile (file) {
49 | return new Promise((resolve, reject) => {
50 | fs.appendFile(file, "\n", (err, stats) => {
51 | if (err) {
52 | if (err.code === "ENOENT") {
53 | mkdirp(path.dirname(file))
54 | .then(() => {
55 | return touchFile(file);
56 | })
57 | .then((stats2) => {
58 | resolve(stats2);
59 | });
60 | }
61 | else {
62 | reject(err);
63 | }
64 | }
65 | else {
66 | resolve(stats);
67 | }
68 | });
69 | });
70 | }
71 |
72 | /**
73 | * Asynchronously gets the status of a file
74 | *
75 | * @param {string} file - The absolute file path
76 | * @returns {Promise} - Resolves with an fs.Stats object
77 | */
78 | function statFile (file) {
79 | return new Promise((resolve, reject) => {
80 | fs.stat(file, (err, stats) => {
81 | if (err) {
82 | reject(err);
83 | }
84 | else {
85 | resolve(stats);
86 | }
87 | });
88 | });
89 | }
90 |
91 | /**
92 | * Asynchronously reads the contents of a file
93 | *
94 | * @param {string} file - The absolute file path
95 | * @returns {Promise} - Resolves with the contents of the file, as a UTF8 string
96 | */
97 | function readFile (file) {
98 | return new Promise((resolve, reject) => {
99 | fs.readFile(file, { encoding: "utf8" }, (err, data) => {
100 | if (err) {
101 | reject(err);
102 | }
103 | else {
104 | resolve(data);
105 | }
106 | });
107 | });
108 | }
109 |
110 | /**
111 | * Asynchronously writes the given data to the specified file.
112 | * The file and any parent directories are created if necessary.
113 | *
114 | * @param {string} file - The absolute file path
115 | * @param {string} data - The data to write to the file
116 | * @returns {Promise} - Resolves after the file has been written
117 | */
118 | function writeFile (file, data) {
119 | return new Promise((resolve, reject) => {
120 | fs.writeFile(file, data, (err) => {
121 | if (err) {
122 | reject(err);
123 | }
124 | else {
125 | resolve();
126 | }
127 | });
128 | });
129 | }
130 |
131 | /**
132 | * Asynchronously deletes a file
133 | *
134 | * @param {string} file - The absolute file path
135 | * @returns {Promise} - Resolves when the file has been deleted
136 | */
137 | function deleteFile (file) {
138 | return new Promise((resolve, reject) => {
139 | fs.unlink(file, (err) => {
140 | if (err) {
141 | reject(err);
142 | }
143 | else {
144 | resolve();
145 | }
146 | });
147 | });
148 | }
149 |
150 | /**
151 | * Appends the given string to the given file name, without affecting the file extension.
152 | *
153 | * @param {string} file - The original file path and/or name (e.g. "dest/subdir/my-file.js")
154 | * @param {string} append - The string to append to the file name (e.g. ".min")
155 | * @returns {string}
156 | */
157 | function appendToFileName (file, append) {
158 | let ext = path.extname(file);
159 | return file.substr(0, file.length - ext.length) + append + ext;
160 | }
161 |
162 | /**
163 | * Determines whether the specified file has a ".ts" or ".tsx" extension
164 | */
165 | function isTypeScript (file) {
166 | let ext = path.extname(file).toLowerCase();
167 | return ext === ".ts" || ext === ".tsx";
168 | }
169 |
170 | /**
171 | * A simple recursive cloning function for simple JavaScript values.
172 | *
173 | * @param {*} original
174 | * @returns {*}
175 | */
176 | function deepClone (original) {
177 | let clone;
178 |
179 | if (original) {
180 | if (typeof original === "object") {
181 | if (original instanceof RegExp) {
182 | return original;
183 | }
184 | else if (original instanceof Date) {
185 | return new Date(original.getTime());
186 | }
187 | else if (Array.isArray(original)) {
188 | clone = [];
189 | }
190 | else {
191 | clone = {};
192 | }
193 | }
194 | else {
195 | return original;
196 | }
197 | }
198 | else {
199 | return original;
200 | }
201 |
202 | let keys = Object.keys(original);
203 | for (let i = 0; i < keys.length; i++) {
204 | let key = keys[i];
205 | let value = original[key];
206 |
207 | clone[key] = deepClone(value);
208 | }
209 |
210 | return clone;
211 | }
212 |
--------------------------------------------------------------------------------
/lib/write-bundles.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Browserify = require("browserify");
4 | const watchify = require("watchify");
5 | const exorcist = require("exorcist");
6 | const fs = require("fs");
7 | const path = require("path");
8 | const FileSet = require("./file-set");
9 | const Transforms = require("./transforms");
10 | const util = require("./util");
11 |
12 | module.exports = writeBundles;
13 |
14 | /**
15 | * Writes Browserify bundles for the given entry file.
16 | * At least one bundle is created (the outputFile), but additional ones may be
17 | * created, depending on {@link Options.debug}, {@link Options.minify}, and {@link Options.coverage}.
18 | *
19 | * @param {FileSet} mainFiles - The main input & output files (not the minified or coverage files)
20 | * @param {EventEmitter} events - Browserify events will be propagated to this EventEmitter
21 | * @param {Options} options - Bundling options
22 | */
23 | function writeBundles (mainFiles, events, options) {
24 | let bundles = [];
25 |
26 | // Read the Browserify transforms from the project manifest (package.json file)
27 | let manifestPath = path.join(path.dirname(mainFiles.entryFile), "package.json");
28 | let transforms = new Transforms(manifestPath);
29 |
30 | // Determine whether to enable TypeScript
31 | options.typescript = transforms.tsify || util.isTypeScript(mainFiles.entryFile);
32 |
33 | // If no output options are specified, then default to --bundle
34 | if (!options.bundle && !options.minify && !options.coverage) {
35 | options.bundle = true;
36 | }
37 |
38 | if (options.bundle) {
39 | bundles.push(createMainBundle(mainFiles, transforms, events, options));
40 | }
41 |
42 | if (options.minify) {
43 | bundles.push(createMinifiedBundle(mainFiles, transforms, events, options));
44 | }
45 |
46 | if (options.coverage) {
47 | bundles.push(createCoverageBundle(mainFiles, transforms, events, options));
48 | }
49 |
50 | /**
51 | * Build each bundle one-at-a-time, rather than all of them simultaneously.
52 | * This dramatically lowers the total build time, especially on large apps.
53 | *
54 | * @param {number} index - The bundle to build (from the {@link bundles} array)
55 | **/
56 | function writeBundle (index) {
57 | if (bundles[index]) {
58 | // Write this bundle
59 | bundle(bundles[index]);
60 |
61 | // Write the next bundle when this one finishes
62 | bundles[index].once("end", () => {
63 | writeBundle(index + 1);
64 | });
65 | }
66 | }
67 |
68 | writeBundle(0);
69 | }
70 |
71 | /**
72 | * Returns a Browserify instance that outputs the main (non-minified) bundle for the given entry file.
73 | *
74 | * @param {FileSet} mainFiles - The input & output files
75 | * @param {Transforms} transforms - The Browserify transforms, and their options
76 | * @param {EventEmitter} events - Browserify events will be propagated to this EventEmitter
77 | * @param {Options} options - Bundling options
78 | * @returns {Browserify}
79 | */
80 | function createMainBundle (mainFiles, transforms, events, options) {
81 | let browserify = newify(mainFiles, transforms, events, options);
82 | transforms.apply(browserify, { typescript: options.typescript });
83 | return browserify;
84 | }
85 |
86 | /**
87 | * Returns a Browserify instance that outputs the minified bundle for the given entry file.
88 | *
89 | * @param {FileSet} mainFiles - The input & output files
90 | * @param {Transforms} transforms - The Browserify transforms, and their options
91 | * @param {EventEmitter} events - Browserify events will be propagated to this EventEmitter
92 | * @param {Options} options - Bundling options
93 | * @returns {Browserify}
94 | */
95 | function createMinifiedBundle (mainFiles, transforms, events, options) {
96 | let minifiedFiles = new FileSet();
97 |
98 | if (options.bundle || options.coverage) {
99 | // We're creating multiple output files, so append ".min" to the minified file
100 | minifiedFiles.entryFile = mainFiles.entryFile;
101 | minifiedFiles.outputFile = util.appendToFileName(mainFiles.outputFile, ".min");
102 | minifiedFiles.standalone = mainFiles.standalone;
103 | if (options.debug) {
104 | minifiedFiles.mapFile = minifiedFiles.outputFile + ".map";
105 | }
106 | }
107 | else {
108 | // We're ONLY creating a minified file, so this is the main output file
109 | minifiedFiles = mainFiles;
110 | }
111 |
112 | let browserify = newify(minifiedFiles, transforms, events, options);
113 | transforms.apply(browserify, { minify: true, typescript: options.typescript });
114 | return browserify;
115 | }
116 |
117 | /**
118 | * Returns a Browserify instance that outputs the code-coverage bundle for the given entry file.
119 | *
120 | * @param {FileSet} mainFiles - The input & output files
121 | * @param {Transforms} transforms - The Browserify transforms, and their options
122 | * @param {EventEmitter} events - Browserify events will be propagated to this EventEmitter
123 | * @param {Options} options - Bundling options
124 | * @returns {Browserify}
125 | */
126 | function createCoverageBundle (mainFiles, transforms, events, options) {
127 | let coverageFiles = new FileSet();
128 |
129 | if (options.bundle || options.minify) {
130 | // We're creating multiple output files, so append ".coverage" to the code-coverage file
131 | coverageFiles.entryFile = mainFiles.entryFile;
132 | coverageFiles.outputFile = util.appendToFileName(mainFiles.outputFile, ".coverage");
133 | coverageFiles.standalone = mainFiles.standalone;
134 | }
135 | else {
136 | // We're ONLY creating a code-coverage file, so this is the main output file
137 | coverageFiles = mainFiles;
138 |
139 | // Don't produce source maps for code-coverage files (Istanbul doesn't support source maps)
140 | coverageFiles.mapFile = "";
141 | }
142 |
143 | let browserify = newify(coverageFiles, transforms, events, options);
144 | transforms.apply(browserify, { minify: true, coverage: true, typescript: options.typescript });
145 | return browserify;
146 | }
147 |
148 | /**
149 | * Creates a new Browserify or Watchify instance
150 | *
151 | * @param {FileSet} fileSet - The input & output files for this bundle
152 | * @param {Transforms} transforms - The Browserify transforms, and their options
153 | * @param {EventEmitter} events - Browserify events will be propagated to this EventEmitter
154 | * @param {Options} options - Bundling options
155 | * @returns {Browserify}
156 | */
157 | function newify (fileSet, transforms, events, options) {
158 | // We always set these options
159 | let browserifyOptions = {
160 | entries: fileSet.entryFile,
161 | standalone: fileSet.standalone || undefined,
162 | debug: !!fileSet.mapFile,
163 | };
164 |
165 | // These options are only needed for Watchify
166 | if (options.watch) {
167 | browserifyOptions.cache = {};
168 | browserifyOptions.packageCache = {};
169 | }
170 |
171 | // Create the Browserify instance
172 | let browserify = new Browserify(browserifyOptions);
173 |
174 | // Propagate events
175 | browserify.on("error", err => {
176 | events.emit("error", err, fileSet);
177 | });
178 | browserify.on("end", () => {
179 | events.emit("end", fileSet);
180 | });
181 | browserify.on("log", msg => {
182 | events.emit("log", msg, fileSet);
183 | });
184 | browserify.on("update", file => {
185 | events.emit("update", file.toString(), fileSet);
186 | });
187 |
188 | if (options.watch) {
189 | // Enable Watchify
190 | browserify = watchify(browserify);
191 |
192 | // Re-bundle when a file changes
193 | browserify.on("update", () => {
194 | bundle(browserify);
195 | });
196 | }
197 |
198 | // Remember the input/output files for this browserify
199 | browserify.files = fileSet;
200 |
201 | // Some transforms (e.g. uglifyify) require post-processing of the bundle file
202 | browserify.postProcessing = () => Promise.resolve();
203 |
204 | return browserify;
205 | }
206 |
207 | /**
208 | * Writes the output file (and possibly its .map file) for the given Browserify object
209 | *
210 | * @param {Browserify} browserify - The Browserify or Watchify instance to bundle
211 | */
212 | function bundle (browserify) {
213 | let stream = browserify.bundle();
214 | stream.on("error", browserify.emit.bind(browserify, "error"));
215 |
216 | Promise.resolve()
217 | .then(() => {
218 | if (browserify.files.mapFile) {
219 | // Create the map file, if necessary, since Exorcist expects it to already exist
220 | return util.ensureFileExists(browserify.files.mapFile);
221 | }
222 | })
223 | .then(() => {
224 | if (browserify.files.mapFile) {
225 | // Add Exorcist to the pipeline, to extract the sourcemap to a separate file
226 | let dirname = path.dirname(browserify.files.mapFile);
227 | stream = stream.pipe(exorcist(browserify.files.mapFile, null, null, dirname));
228 | }
229 |
230 | // Create the output file, if necessary, since Browserify expects it to already exist
231 | return util.ensureFileExists(browserify.files.outputFile);
232 | })
233 | .then(() => {
234 | // Pipe the Browserify output to the output file
235 | stream.pipe(fs.createWriteStream(browserify.files.outputFile));
236 | })
237 | .then(() => {
238 | return new Promise((resolve) => stream.on("end", resolve));
239 | })
240 | .then(() => {
241 | // The "end" event sometimes gets called before the file(s) have
242 | // been fully-written to disk. So we wait a bit to allow I/O to finish.
243 | return new Promise((resolve) => setTimeout(resolve, 100));
244 | })
245 | .then(() => {
246 | // Perform any post-processing on the output file(s), such as minification
247 | return browserify.postProcessing();
248 | })
249 | .then(() => {
250 | browserify.emit("end");
251 | })
252 | .catch(e => {
253 | browserify.emit("error", e);
254 | });
255 | }
256 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@jsdevtools/simplifyify",
3 | "version": "8.0.4",
4 | "description": "A simplified Browserify and Watchify CLI",
5 | "keywords": [
6 | "browserify",
7 | "browserify-plugin",
8 | "watchify",
9 | "cli",
10 | "minify",
11 | "uglify",
12 | "uglifyify",
13 | "sourcemap",
14 | "source-map",
15 | "source map",
16 | "exorcist",
17 | "istanbul"
18 | ],
19 | "author": {
20 | "name": "James Messinger",
21 | "url": "https://jamesmessinger.com"
22 | },
23 | "homepage": "https://jstools.dev/simplifyify",
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/JS-DevTools/simplifyify.git"
27 | },
28 | "license": "MIT",
29 | "main": "lib/index.js",
30 | "bin": {
31 | "simplifyify": "bin/simplifyify.js"
32 | },
33 | "files": [
34 | "bin",
35 | "lib"
36 | ],
37 | "engines": {
38 | "node": ">=10"
39 | },
40 | "scripts": {
41 | "clean": "shx rm -rf .nyc_output coverage",
42 | "lint": "eslint bin lib test/fixtures test/specs",
43 | "test": "mocha && npm run lint",
44 | "coverage": "nyc node_modules/mocha/bin/mocha",
45 | "upgrade": "npm-check -u && npm audit fix",
46 | "bump": "bump --tag --push --all",
47 | "release": "npm run upgrade && npm run clean && npm test && npm run bump"
48 | },
49 | "dependencies": {
50 | "@jsdevtools/browserify-banner": "^2.0.4",
51 | "@jsdevtools/ono": "^7.1.3",
52 | "browserify": "^17.0.0",
53 | "browserify-istanbul": "^3.0.1",
54 | "commander": "^6.2.1",
55 | "exorcist": "^1.0.0",
56 | "globby": "^11.0.1",
57 | "mkdirp-promise": "^5.0.1",
58 | "shx": "^0.3.3",
59 | "tsify": "^5.0.2",
60 | "uglify-es": "^3.3.7",
61 | "uglifyify": "^5.0.2",
62 | "watchify": "^3.11.1"
63 | },
64 | "devDependencies": {
65 | "@babel/core": "^7.12.10",
66 | "@babel/preset-env": "^7.12.11",
67 | "@jsdevtools/eslint-config": "^1.1.4",
68 | "@jsdevtools/host-environment": "^2.1.2",
69 | "@jsdevtools/version-bump-prompt": "^6.1.0",
70 | "@types/react": "^17.0.0",
71 | "@types/react-dom": "^17.0.0",
72 | "babelify": "^10.0.0",
73 | "chai": "^4.2.0",
74 | "eslint": "^7.17.0",
75 | "mocha": "^8.2.1",
76 | "npm-check": "^5.9.2",
77 | "nyc": "^15.1.0",
78 | "react": "^17.0.1",
79 | "react-dom": "^17.0.1",
80 | "rmfr": "^2.0.0",
81 | "typescript": "^4.1.3"
82 | },
83 | "peerDependencies": {
84 | "typescript": "*"
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/test/fixtures/assert.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const fs = require("fs");
4 | const path = require("path");
5 | const ono = require("@jsdevtools/ono");
6 | const expect = require("chai").expect;
7 | const isWindows = /^win/.test(process.platform);
8 | const testAppsDir = path.resolve(__dirname, "../test-apps");
9 |
10 | /**
11 | * Asserts that the given folder is empty.
12 | *
13 | * @param {string} dir - The directory to check
14 | */
15 | exports.directoryIsEmpty = function (dir) {
16 | let outfiles = ls(dir);
17 | try {
18 | expect(outfiles).to.have.same.members([]);
19 | }
20 | catch (e) {
21 | console.error("Directory is not empty!\nExpected: []\n\nActual: %s", JSON.stringify(outfiles, null, 2));
22 | throw e;
23 | }
24 | };
25 |
26 | /**
27 | * Asserts that the directory contains the given files, and no others.
28 | *
29 | * @param {string} [dir] - The directory to check
30 | * @param {string[]} files - The files to check for
31 | */
32 | exports.directoryContents = function (dir, files) {
33 | if (arguments.length === 1) {
34 | dir = ".";
35 | files = dir;
36 | }
37 | files = Array.isArray(files) ? files : [files];
38 |
39 | let outfiles = ls(dir);
40 | try {
41 | expect(outfiles).to.have.same.members(files);
42 | }
43 | catch (e) {
44 | console.error("Incorrect directory contents!\nExpected: %s\n\nActual: %s",
45 | JSON.stringify(files, null, 2), JSON.stringify(outfiles, null, 2));
46 | throw e;
47 | }
48 | };
49 |
50 | /**
51 | * Calls the given function for the given file(s), passing the contents of the file.
52 | *
53 | * @param {string} [dir]
54 | * @param {string|string[]} files
55 | * @param {function} fn
56 | */
57 | exports.fileContents = function (dir, files, fn) {
58 | if (typeof files === "function") {
59 | fn = files;
60 | files = dir;
61 | dir = ".";
62 | }
63 | dir = resolve(dir);
64 | files = Array.isArray(files) ? files : [files];
65 |
66 | for (let file of files) {
67 | let fullPath = path.join(dir, file);
68 | let contents = fs.readFileSync(fullPath).toString();
69 |
70 | if (file.substr(-4) === ".map") {
71 | // Parse source-map files, and return a POJO instead of a string
72 | contents = JSON.parse(contents);
73 |
74 | if (isWindows) {
75 | // Replace Windows path separators with POSIX separators
76 | contents.sources = contents.sources.map((source) => {
77 | return source.replace(/\\/g, "/");
78 | });
79 | }
80 | }
81 |
82 | try {
83 | fn(contents);
84 | }
85 | catch (e) {
86 | throw ono(e, file, "failed an assertion:");
87 | }
88 | }
89 | };
90 |
91 | /**
92 | * Asserts that the given file contents start with a banner
93 | *
94 | * @param {string} contents
95 | */
96 | exports.hasBanner = function (contents) {
97 | expect(contents).to.match(/^\/\*\!\n \* /, "The file does not start with a banner");
98 | };
99 |
100 | /**
101 | * Asserts that the given file contents do not contain a banner
102 | *
103 | * @param {string} contents
104 | */
105 | exports.noBanner = function (contents) {
106 | expect(contents).not.to.match(/^\/\*\!/, "The file contains a banner, but it shouldn't");
107 | };
108 |
109 | /**
110 | * Asserts that the given file contents contain the Browserify preamble (non-UMD)
111 | *
112 | * @param {string} contents
113 | */
114 | exports.hasPreamble = function (contents) {
115 | expect(contents).to.match(
116 | /var \w\s*=\s*["']function["']\s*==\s*typeof require\s*\&\&\s*require;/,
117 | "The file is missing the Browserify preamble (non-UMD)"
118 | );
119 | };
120 |
121 | /**
122 | * Asserts that the given file contents contain the minified version of the
123 | * Browserify preamble (non-UMD)
124 | *
125 | * @param {string} contents
126 | */
127 | exports.hasMinifiedPreamble = function (contents) {
128 | expect(contents).to.match(
129 | /var \w="function"==typeof require\&\&*require;/,
130 | "The file is missing the Browserify preamble (minified, non-UMD)"
131 | );
132 | };
133 |
134 | /**
135 | * Asserts that the given file contents contain the Browserify UMD preamble
136 | *
137 | * @param {string} contents
138 | */
139 | exports.hasUmdPreamble = function (contents) {
140 | let msg = "The file is missing the Browserify preamble (UMD)";
141 | expect(contents).to.match(/if\(typeof window!=="undefined"\)/, msg);
142 | expect(contents).to.match(/if\(typeof global!=="undefined"\)/, msg);
143 | expect(contents).to.match(/if\(typeof self!=="undefined"\)/, msg);
144 | };
145 |
146 | /**
147 | * Asserts that the given file contents contain the minified version of the
148 | * Browserify UMD preamble
149 | *
150 | * @param {string} contents
151 | */
152 | exports.hasMinifiedUmdPreamble = function (contents) {
153 | let msg = "The file is missing the Browserify preamble (minified, UMD)";
154 | expect(contents).to.match(/if\(typeof window!=="undefined"\)/, msg);
155 | expect(contents).to.match(/if\(typeof global!=="undefined"\)/, msg);
156 | expect(contents).to.match(/if\(typeof self!=="undefined"\)/, msg);
157 | };
158 |
159 | /**
160 | * Asserts that the given file contents contain an external source map
161 | *
162 | * @param {string} contents
163 | */
164 | exports.hasSourceMap = function (contents) {
165 | expect(contents).to.match(
166 | /\/\/\# sourceMappingURL=.*\.map\n?$/,
167 | "The file does not end with a sourcemap comment"
168 | );
169 | };
170 |
171 | /**
172 | * Asserts that the given file contents DO NOT contain a source map
173 | *
174 | * @param {string} contents
175 | */
176 | exports.noSourceMap = function (contents) {
177 | expect(contents).not.to.match(/\/\/\# sourceMap/, "The file has a sourcemap, but it shouldn't");
178 | };
179 |
180 | /**
181 | * Asserts that the given file contents are minified
182 | *
183 | * @param {string} contents
184 | * @param {boolean} stripComments - Whether the contents should include comments or not
185 | * @param {boolean} beautified - Whether the code has been beautified
186 | */
187 | exports.isMinified = function (contents, stripComments, beautified) {
188 | if (beautified) {
189 | // Single-quotes and newlines
190 | expect(contents).to.match(/'use strict';\n/, "The file is not minified + beautified");
191 | }
192 | else {
193 | // Single-quotes become double-quotes, and newline is removed
194 | expect(contents).to.match(/"use strict";\S+/, "The file is not minified");
195 | }
196 |
197 | if (stripComments) {
198 | // All comments are removed
199 | expect(contents).not.to.match(/\/\/ /, "The file has comments, but shouldn't");
200 | }
201 | else {
202 | // Non-important comments are removed
203 | expect(contents).not.to.match(/\* @param \{string\}/, "The file contains non-important comments (@param)");
204 | expect(contents).not.to.match(/\/\/ This is NOT an important comment/, "The file contains non-important inline comments");
205 |
206 | // Important comments are preserved
207 | expect(contents).to.match(/This is an important comment/, "The file does not contain important comments");
208 | }
209 | };
210 |
211 | /**
212 | * Asserts that the given file contents ARE NOT minified
213 | *
214 | * @param {string} contents
215 | */
216 | exports.notMinified = function (contents) {
217 | // Newlines are preserved
218 | expect(contents).to.match(/['"]use strict['"];\r?\n(\s+|\w+)/, "The file has been minified (newlines were removed)");
219 |
220 | // Non-important comments are preserved
221 | expect(contents).to.match(/\* @param \{string\}/, "Comments have been removed from the file (@param)");
222 | expect(contents).to.match(/\/\/ This is NOT an important comment/, "Inline comments have been removed from the file");
223 |
224 | // Important comments are also preserved
225 | expect(contents).to.match(/This is an important comment/, "Important comments have been removed from the file");
226 | };
227 |
228 | /**
229 | * Asserts that the given file contents have been transformed by Babelify
230 | *
231 | * @param {string} contents
232 | */
233 | exports.isBabelified = function (contents) {
234 | expect(contents).to.match(/Object\.defineProperty\(exports,\s*['"]__esModule['"]/, "The file has not been Babelifieid, but it should have been");
235 | };
236 |
237 | /**
238 | * Asserts that the given file contents contain code-coverage instrumentation
239 | *
240 | * @param {string} contents
241 | */
242 | exports.hasCoverage = function (contents) {
243 | // Check for __cov_ wrappers
244 | expect(contents).to.match(/__coverage__/, "The file is missing code-coverage instrumentation");
245 | };
246 |
247 | /**
248 | * Asserts that the given file contents DO NOT contain code-coverage instrumentation
249 | *
250 | * @param {string} contents
251 | */
252 | exports.noCoverage = function (contents) {
253 | expect(contents).not.to.match(/__coverage__/, "The file contains code-coverage instrumentation, but shouldn't");
254 | };
255 |
256 | /**
257 | * Resolves a path, relative to the "test-apps" folder
258 | */
259 | function resolve (fileOrFolder) {
260 | if (path.isAbsolute(fileOrFolder)) {
261 | return fileOrFolder;
262 | }
263 | else {
264 | return path.resolve(testAppsDir, fileOrFolder);
265 | }
266 | }
267 |
268 | /**
269 | * Returns the contents of the given directory.
270 | *
271 | * @param {string} [dir] - The directory to list
272 | */
273 | function ls (dir) {
274 | try {
275 | let contents = [];
276 | dir = resolve(dir);
277 |
278 | let names = fs.readdirSync(dir);
279 |
280 | for (let name of names) {
281 | let fullName = path.join(dir, name);
282 | if (fs.statSync(fullName).isDirectory()) {
283 | let childNames = ls(fullName);
284 |
285 | for (let childName of childNames) {
286 | contents.push(name + "/" + childName); // Don't use path.join() here, because of Windows
287 | }
288 | }
289 | else if (![".DS_Store", "Thumbs.db"].includes(name)) {
290 | contents.push(name);
291 | }
292 | }
293 |
294 | return contents;
295 | }
296 | catch (e) {
297 | if (e.code === "ENOENT") {
298 | // The directory doesn't exist, so return an empty list
299 | return [];
300 | }
301 | throw e;
302 | }
303 | }
304 |
--------------------------------------------------------------------------------
/test/fixtures/cli.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const spawn = require("child_process").spawn;
4 | const globby = require("globby");
5 | const rmfr = require("rmfr");
6 | const path = require("path");
7 | const isWindows = /^win/.test(process.platform);
8 | const cliPath = path.resolve(__dirname, "../../bin/simplifyify");
9 | const testAppsDir = path.resolve(__dirname, "../test-apps");
10 | const mocha = require("./mocha");
11 | const util = require("../../lib/util");
12 |
13 | beforeEach("Delete previous test files", function () {
14 | // Allow plenty of time for files to be deleted. This is especially important on Windows,
15 | // where "rmfr" often has to retry several times due to file locks
16 | mocha.increaseTimeout(this, 10000);
17 |
18 | // Clear the output files before each test
19 | return Promise.resolve()
20 | .then(() => {
21 | return globby("test/test-apps/*/dist", { onlyDirectories: true });
22 | })
23 | .then(distDirs => {
24 | return Promise.all(distDirs.map(dir => rmfr(dir, { maxBusyTries: 10 })));
25 | })
26 | .then(() => {
27 | return globby("test/test-apps/**/*.bundle.*", { onlyFiles: true });
28 | })
29 | .then(bundleFiles => {
30 | return Promise.all(bundleFiles.map(file => util.deleteFile(file)));
31 | })
32 | .then(() => undefined);
33 | });
34 |
35 | /**
36 | * Runs Simplifyify with the given args
37 | *
38 | * @param {string} args
39 | * @param {function} callback
40 | * @returns {ChildProcess}
41 | */
42 | exports.run = function run (args, callback) {
43 | let exited = false, stdout = "", stderr = "";
44 |
45 | // Run simplifyify
46 | args = [cliPath].concat(args ? args.split(" ") : []);
47 | let simplifyify = spawn("node", args, { cwd: testAppsDir });
48 |
49 | // Capture stdout and stderr
50 | simplifyify.stdout.on("data", (data) => {
51 | stdout += data.toString();
52 | });
53 | simplifyify.stderr.on("data", (data) => {
54 | stderr += data.toString();
55 | });
56 |
57 | // Handle exits (successful or failure)
58 | simplifyify.on("exit", onExit);
59 | simplifyify.on("error", onExit);
60 |
61 | function onExit (code) {
62 | // onExit can sometimes fire multiple times, so ignore duplicates
63 | if (exited) {
64 | return;
65 | }
66 | exited = true;
67 |
68 | // TEMPORARY HACK to workaround a deprecation warning in Node 7.
69 | // TODO: Remove this code once all dependencies have been updated to eliminate this warning
70 | if (stderr && process.version.substr(0, 3) === "v7." &&
71 | /^\(node:\d+\) DeprecationWarning: Using Buffer without `new` will soon stop working/.test(stderr)) {
72 | stderr = "";
73 | }
74 |
75 | let err = null;
76 | if (code > 0 || stderr) {
77 | err = new Error(stderr || "Simplifyify exited with code " + code);
78 | err.code = code;
79 | }
80 | else if (code instanceof Error) {
81 | err = code;
82 | }
83 |
84 | if (isWindows) {
85 | // Replace Windows path separators with POSIX separators
86 | stdout = stdout.replace(/\\/g, "/");
87 | stderr = stderr.replace(/\\/g, "/");
88 | }
89 |
90 | callback(err, stdout.trim(), stderr.trim());
91 | }
92 |
93 | return simplifyify;
94 | };
95 |
--------------------------------------------------------------------------------
/test/fixtures/mocha.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const host = require("@jsdevtools/host-environment");
4 |
5 | exports.increaseTimeout = increaseTimeout;
6 |
7 |
8 | /**
9 | * Increases the timeout of a test, if necessary.
10 | */
11 | function increaseTimeout (test, timeout) {
12 | if (host.ci) {
13 | // Increase timeouts when running in CI because slooooow
14 | timeout *= 4;
15 | }
16 |
17 | let currentTimeout = test.timeout();
18 | if (currentTimeout >= timeout) {
19 | return currentTimeout;
20 | }
21 | else {
22 | test.timeout(timeout);
23 | test.slow(timeout * 0.75);
24 | return timeout;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test/specs/bundle.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 |
7 | describe("simplifyify --bundle", () => {
8 | it("should bundle a single file by default", (done) => {
9 | cli.run("hello/index.js", (err, stdout) => {
10 | if (err) {
11 | return done(err);
12 | }
13 |
14 | expect(stdout).to.contain("hello/index.js --> hello/index.bundle.js");
15 |
16 | assert.directoryContents("hello", [
17 | "banner.txt",
18 | "hello-world.js",
19 | "index.js",
20 | "index.bundle.js",
21 | "package.json",
22 | "say/index.js"
23 | ]);
24 |
25 | assert.fileContents("hello/index.bundle.js", (contents) => {
26 | assert.hasBanner(contents);
27 | assert.hasPreamble(contents);
28 | assert.notMinified(contents);
29 | assert.noSourceMap(contents);
30 | assert.noCoverage(contents);
31 | });
32 | done();
33 | });
34 | });
35 |
36 | it("should bundle a single file", (done) => {
37 | cli.run("hello/index.js --bundle", (err, stdout) => {
38 | if (err) {
39 | return done(err);
40 | }
41 |
42 | expect(stdout).to.contain("hello/index.js --> hello/index.bundle.js");
43 |
44 | assert.directoryContents("hello", [
45 | "banner.txt",
46 | "hello-world.js",
47 | "index.js",
48 | "index.bundle.js",
49 | "package.json",
50 | "say/index.js"
51 | ]);
52 |
53 | assert.fileContents("hello/index.bundle.js", (contents) => {
54 | assert.hasBanner(contents);
55 | assert.hasPreamble(contents);
56 | assert.notMinified(contents);
57 | assert.noSourceMap(contents);
58 | assert.noCoverage(contents);
59 | });
60 | done();
61 | });
62 | });
63 |
64 | it("should work with shorthand arguments", (done) => {
65 | cli.run("hello/index.js -b", (err, stdout) => {
66 | if (err) {
67 | return done(err);
68 | }
69 |
70 | expect(stdout).to.contain("hello/index.js --> hello/index.bundle.js");
71 |
72 | assert.directoryContents("hello", [
73 | "banner.txt",
74 | "hello-world.js",
75 | "index.js",
76 | "index.bundle.js",
77 | "package.json",
78 | "say/index.js"
79 | ]);
80 |
81 | assert.fileContents("hello/index.bundle.js", (contents) => {
82 | assert.hasBanner(contents);
83 | assert.hasPreamble(contents);
84 | assert.notMinified(contents);
85 | assert.noSourceMap(contents);
86 | assert.noCoverage(contents);
87 | });
88 | done();
89 | });
90 | });
91 | });
92 |
--------------------------------------------------------------------------------
/test/specs/cli.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 | const version = require("../../package").version;
7 |
8 | describe("simplifyify --help", () => {
9 | it("should show help if called without any args", (done) => {
10 | cli.run("", (err, stdout) => {
11 | expect(err).to.be.an.instanceOf(Error);
12 | expect(stdout).to.match(/^Usage: simplifyify \[options\] /);
13 | assert.directoryIsEmpty("es5/dist");
14 | done();
15 | });
16 | });
17 |
18 | it("should exit with a nonzero if called without any args", (done) => {
19 | cli.run("", (err) => {
20 | expect(err).to.be.an.instanceOf(Error);
21 | expect(err.code).to.equal(1);
22 | done();
23 | });
24 | });
25 |
26 | it("should show help if called with --help", (done) => {
27 | cli.run("--help", (err, stdout) => {
28 | expect(stdout).to.match(/^Usage: simplifyify \[options\] /);
29 | assert.directoryIsEmpty("es5/dist");
30 | done();
31 | });
32 | });
33 |
34 | it("should exit with zero if called with --help", (done) => {
35 | cli.run("--help", (err) => {
36 | expect(err).to.equal(null);
37 | done();
38 | });
39 | });
40 |
41 | it("should show help if called with -h", (done) => {
42 | cli.run("--help", (err, stdout) => {
43 | expect(stdout).to.match(/^Usage: simplifyify \[options\] /);
44 | assert.directoryIsEmpty("es5/dist");
45 | done();
46 | });
47 | });
48 |
49 | it("should exit with zero if called with -h", (done) => {
50 | cli.run("--help", (err) => {
51 | expect(err).to.equal(null);
52 | done();
53 | });
54 | });
55 | });
56 |
57 | describe("simplifyify --version", () => {
58 | it("should output the version number if called --version", (done) => {
59 | cli.run("--version", (err, stdout) => {
60 | if (err) {
61 | return done(err);
62 | }
63 |
64 | expect(stdout).to.equal(version);
65 | assert.directoryIsEmpty("es5/dist");
66 | done();
67 | });
68 | });
69 |
70 | it("should output the version number if called -V", (done) => {
71 | cli.run("-V", (err, stdout) => {
72 | if (err) {
73 | return done(err);
74 | }
75 |
76 | expect(stdout).to.equal(version);
77 | assert.directoryIsEmpty("es5/dist");
78 | done();
79 | });
80 | });
81 | });
82 |
83 | describe("failure tests", () => {
84 | it("should error if called with an unknown option", (done) => {
85 | cli.run("-z", (err, stdout, stderr) => {
86 | expect(err).to.be.an.instanceOf(Error);
87 | expect(stderr).to.contain("unknown option");
88 | assert.directoryIsEmpty("es5/dist");
89 | done();
90 | });
91 | });
92 |
93 | it("should error if the entry file does not exist", (done) => {
94 | cli.run("some/file/that/does/not/exist.js --outfile dist/", (err, stdout, stderr) => {
95 | expect(err).to.be.an.instanceOf(Error);
96 | expect(stderr).to.equal("No matching entry files were found");
97 | assert.directoryIsEmpty("es5/dist");
98 | done();
99 | });
100 | });
101 |
102 | it("should error if the entry file glob does not match any files", (done) => {
103 | cli.run('"lib/**/*-foo-bar.js" --outfile dist/', (err, stdout, stderr) => {
104 | expect(err).to.be.an.instanceOf(Error);
105 | expect(stderr).to.equal("No matching entry files were found");
106 | assert.directoryIsEmpty("es5/dist");
107 | done();
108 | });
109 | });
110 |
111 | it("should error if all matching files are excluded", (done) => {
112 | cli.run('"lib/**/*.js" --exclude **/*.js --outfile dist/', (err, stdout, stderr) => {
113 | expect(err).to.be.an.instanceOf(Error);
114 | expect(stderr).to.equal("No matching entry files were found");
115 | assert.directoryIsEmpty("es5/dist");
116 | done();
117 | });
118 | });
119 |
120 | it("should error if the --standalone param is not given", (done) => {
121 | cli.run("lib/index.js --outfile dist/ --standalone", (err, stdout, stderr) => {
122 | expect(err).to.be.an.instanceOf(Error);
123 | expect(stderr).to.contain("argument missing");
124 | assert.directoryIsEmpty("es5/dist");
125 | done();
126 | });
127 | });
128 | });
129 |
--------------------------------------------------------------------------------
/test/specs/debug.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 |
7 | describe("simplifyify --debug", () => {
8 | it("should create source map for a single file", (done) => {
9 | cli.run("es5/lib/index.js --debug --outfile es5/dist/index.js", (err, stdout) => {
10 | if (err) {
11 | return done(err);
12 | }
13 |
14 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
15 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js.map");
16 |
17 | assert.directoryContents("es5/dist", [
18 | "index.js",
19 | "index.js.map"
20 | ]);
21 |
22 | assert.fileContents("es5/dist/index.js", (contents) => {
23 | assert.noBanner(contents);
24 | assert.hasPreamble(contents);
25 | assert.notMinified(contents);
26 | assert.hasSourceMap(contents);
27 | assert.noCoverage(contents);
28 | });
29 |
30 | assert.fileContents("es5/dist/index.js.map", (contents) => {
31 | expect(contents.sources).to.contain.members([
32 | "../lib/hello-world.js",
33 | "../lib/index.js",
34 | "../lib/say/index.js"
35 | ]);
36 | });
37 | done();
38 | });
39 | });
40 |
41 | it("should create source maps for multiple files", (done) => {
42 | cli.run("es5/lib/**/*.js --debug --outfile es5/dist/", (err, stdout) => {
43 | if (err) {
44 | return done(err);
45 | }
46 |
47 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
48 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js.map");
49 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.js");
50 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.js.map");
51 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
52 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js.map");
53 |
54 | assert.directoryContents("es5/dist", [
55 | "index.js",
56 | "index.js.map",
57 | "hello-world.js",
58 | "hello-world.js.map",
59 | "say/index.js",
60 | "say/index.js.map"
61 | ]);
62 |
63 | assert.fileContents("es5/dist", ["index.js", "hello-world.js", "say/index.js"], (contents) => {
64 | assert.noBanner(contents);
65 | assert.hasPreamble(contents);
66 | assert.notMinified(contents);
67 | assert.hasSourceMap(contents);
68 | assert.noCoverage(contents);
69 | });
70 | assert.fileContents("es5/dist/index.js.map", (contents) => {
71 | expect(contents.sources).to.contain.members([
72 | "../lib/hello-world.js",
73 | "../lib/index.js",
74 | "../lib/say/index.js"
75 | ]);
76 | });
77 | assert.fileContents("es5/dist/hello-world.js.map", (contents) => {
78 | expect(contents.sources).to.contain.members([
79 | "../lib/hello-world.js",
80 | "../lib/say/index.js"
81 | ]);
82 | });
83 | assert.fileContents("es5/dist/say/index.js.map", (contents) => {
84 | expect(contents.sources).to.contain.members([
85 | "../../lib/say/index.js"
86 | ]);
87 | });
88 | done();
89 | });
90 | });
91 |
92 | it("should create source maps for multiple minified files", (done) => {
93 | cli.run("es5/lib/**/index.js --bundle --debug --minify --outfile es5/dist/", (err, stdout) => {
94 | if (err) {
95 | return done(err);
96 | }
97 |
98 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
99 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js.map");
100 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.min.js");
101 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.min.js.map");
102 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
103 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js.map");
104 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.min.js");
105 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.min.js.map");
106 |
107 | assert.directoryContents("es5/dist", [
108 | "index.js",
109 | "index.js.map",
110 | "index.min.js",
111 | "index.min.js.map",
112 | "say/index.js",
113 | "say/index.js.map",
114 | "say/index.min.js",
115 | "say/index.min.js.map"
116 | ]);
117 |
118 | assert.fileContents("es5/dist", ["index.js", "say/index.js"], (contents) => {
119 | assert.noBanner(contents);
120 | assert.hasPreamble(contents);
121 | assert.notMinified(contents);
122 | assert.hasSourceMap(contents);
123 | assert.noCoverage(contents);
124 | });
125 | assert.fileContents("es5/dist", ["index.min.js", "say/index.min.js"], (contents) => {
126 | assert.noBanner(contents);
127 | assert.hasMinifiedPreamble(contents);
128 | assert.isMinified(contents);
129 | assert.hasSourceMap(contents);
130 | assert.noCoverage(contents);
131 | });
132 |
133 | assert.fileContents("es5/dist", ["index.js.map", "index.min.js.map"], (contents) => {
134 | expect(contents.sources).to.contain.members([
135 | "../lib/hello-world.js",
136 | "../lib/index.js",
137 | "../lib/say/index.js"
138 | ]);
139 | });
140 | assert.fileContents("es5/dist", ["say/index.js.map", "say/index.min.js.map"], (contents) => {
141 | expect(contents.sources).to.contain.members([
142 | "../../lib/say/index.js"
143 | ]);
144 | });
145 | done();
146 | });
147 | });
148 |
149 | it('should append ".map" when renaming output files', (done) => {
150 | cli.run("es5/lib/**/*.js --bundle --debug --minify --outfile es5/dist/*.bundle.es", (err, stdout) => {
151 | if (err) {
152 | return done(err);
153 | }
154 |
155 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.bundle.es");
156 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.bundle.es.map");
157 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.bundle.min.es");
158 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.bundle.min.es.map");
159 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.bundle.es");
160 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.bundle.es.map");
161 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.bundle.min.es");
162 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.bundle.min.es.map");
163 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.bundle.es");
164 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.bundle.es.map");
165 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.bundle.min.es");
166 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.bundle.min.es.map");
167 |
168 | assert.directoryContents("es5/dist", [
169 | "index.bundle.es",
170 | "index.bundle.es.map",
171 | "index.bundle.min.es",
172 | "index.bundle.min.es.map",
173 | "hello-world.bundle.es",
174 | "hello-world.bundle.es.map",
175 | "hello-world.bundle.min.es",
176 | "hello-world.bundle.min.es.map",
177 | "say/index.bundle.es",
178 | "say/index.bundle.es.map",
179 | "say/index.bundle.min.es",
180 | "say/index.bundle.min.es.map"
181 | ]);
182 |
183 | assert.fileContents("es5/dist", ["index.bundle.es", "hello-world.bundle.es", "say/index.bundle.es"],
184 | (contents) => {
185 | assert.noBanner(contents);
186 | assert.hasPreamble(contents);
187 | assert.notMinified(contents);
188 | assert.hasSourceMap(contents);
189 | assert.noCoverage(contents);
190 | });
191 | assert.fileContents("es5/dist", ["index.bundle.min.es", "hello-world.bundle.min.es", "say/index.bundle.min.es"],
192 | (contents) => {
193 | assert.noBanner(contents);
194 | assert.hasMinifiedPreamble(contents);
195 | assert.isMinified(contents);
196 | assert.hasSourceMap(contents);
197 | assert.noCoverage(contents);
198 | });
199 |
200 | assert.fileContents("es5/dist", ["index.bundle.es.map", "index.bundle.min.es.map"], (contents) => {
201 | expect(contents.sources).to.contain.members([
202 | "../lib/hello-world.js",
203 | "../lib/index.js",
204 | "../lib/say/index.js"
205 | ]);
206 | });
207 | assert.fileContents("es5/dist", ["hello-world.bundle.es.map", "hello-world.bundle.min.es.map"], (contents) => {
208 | expect(contents.sources).to.contain.members([
209 | "../lib/hello-world.js",
210 | "../lib/say/index.js"
211 | ]);
212 | });
213 | assert.fileContents("es5/dist", ["say/index.bundle.es.map", "say/index.bundle.min.es.map"], (contents) => {
214 | expect(contents.sources).to.contain.members([
215 | "../../lib/say/index.js"
216 | ]);
217 | });
218 | done();
219 | });
220 | });
221 |
222 | it("should create a sourcemap for a bundle with a banner", (done) => {
223 | cli.run("hello/index.js --debug --outfile hello/dist/", (err, stdout) => {
224 | if (err) {
225 | return done(err);
226 | }
227 |
228 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.js");
229 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.js.map");
230 |
231 | assert.directoryContents("hello", [
232 | "banner.txt",
233 | "hello-world.js",
234 | "index.js",
235 | "package.json",
236 | "say/index.js",
237 | "dist/index.js",
238 | "dist/index.js.map",
239 | ]);
240 |
241 | assert.fileContents("hello/dist/index.js", (contents) => {
242 | assert.hasBanner(contents);
243 | assert.hasPreamble(contents);
244 | assert.notMinified(contents);
245 | assert.hasSourceMap(contents);
246 | assert.noCoverage(contents);
247 | });
248 |
249 | assert.fileContents("hello/dist", "index.js.map", (contents) => {
250 | expect(contents.sources).to.contain.members([
251 | "../hello-world.js",
252 | "../index.js",
253 | "../say/index.js"
254 | ]);
255 |
256 | // The first 9 lines of the sourcemap should be blank, since we don't
257 | // have sourcemappings for the banner
258 | expect(contents.mappings).to.match(/^;;;;;;;;;AAAA/);
259 | });
260 |
261 | done();
262 | });
263 | });
264 |
265 | it("should work with shorthand arguments", (done) => {
266 | cli.run("es5/lib/index.js -do es5/dist/index.js", (err, stdout) => {
267 | if (err) {
268 | return done(err);
269 | }
270 |
271 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
272 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js.map");
273 |
274 | assert.directoryContents("es5/dist", [
275 | "index.js",
276 | "index.js.map"
277 | ]);
278 |
279 | assert.fileContents("es5/dist/index.js", (contents) => {
280 | assert.noBanner(contents);
281 | assert.hasPreamble(contents);
282 | assert.notMinified(contents);
283 | assert.hasSourceMap(contents);
284 | assert.noCoverage(contents);
285 | });
286 |
287 | assert.fileContents("es5/dist/index.js.map", (contents) => {
288 | expect(contents.sources).to.contain.members([
289 | "../lib/hello-world.js",
290 | "../lib/index.js",
291 | "../lib/say/index.js"
292 | ]);
293 | });
294 | done();
295 | });
296 | });
297 | });
298 |
--------------------------------------------------------------------------------
/test/specs/exclude.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 |
7 | describe("simplifyify --exclude", () => {
8 | it("should not exclude anything if nothing matches", (done) => {
9 | cli.run("es5/lib/**/*.js --exclude es5/lib/**/*-foo.js --outfile es5/dist/", (err, stdout) => {
10 | if (err) {
11 | return done(err);
12 | }
13 |
14 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
15 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.js");
16 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
17 |
18 | assert.directoryContents("es5/dist", [
19 | "index.js",
20 | "hello-world.js",
21 | "say/index.js"
22 | ]);
23 |
24 | assert.fileContents("es5/dist", ["index.js", "hello-world.js", "say/index.js"], (contents) => {
25 | assert.noBanner(contents);
26 | assert.hasPreamble(contents);
27 | assert.notMinified(contents);
28 | assert.noSourceMap(contents);
29 | assert.noCoverage(contents);
30 | });
31 | done();
32 | });
33 | });
34 |
35 | it("should exclude a single file", (done) => {
36 | cli.run("es5/lib/**/*.js --exclude es5/lib/say/index.js --outfile es5/dist/", (err, stdout) => {
37 | if (err) {
38 | return done(err);
39 | }
40 |
41 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
42 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.js");
43 | expect(stdout).not.to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
44 |
45 | assert.directoryContents("es5/dist", [
46 | "index.js",
47 | "hello-world.js"
48 | ]);
49 |
50 | assert.fileContents("es5/dist", ["index.js", "hello-world.js"], (contents) => {
51 | assert.noBanner(contents);
52 | assert.hasPreamble(contents);
53 | assert.notMinified(contents);
54 | assert.noSourceMap(contents);
55 | assert.noCoverage(contents);
56 | });
57 | done();
58 | });
59 | });
60 |
61 | it("should exclude multiple files", (done) => {
62 | cli.run("es5/lib/**/*.js --exclude es5/lib/**/index.js --outfile es5/dist/", (err, stdout) => {
63 | if (err) {
64 | return done(err);
65 | }
66 |
67 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.js");
68 | expect(stdout).not.to.contain("es5/lib/index.js --> es5/dist/index.js");
69 | expect(stdout).not.to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
70 |
71 | assert.directoryContents("es5/dist", [
72 | "hello-world.js"
73 | ]);
74 |
75 | assert.fileContents("es5/dist", ["hello-world.js"], (contents) => {
76 | assert.noBanner(contents);
77 | assert.hasPreamble(contents);
78 | assert.notMinified(contents);
79 | assert.noSourceMap(contents);
80 | assert.noCoverage(contents);
81 | });
82 | done();
83 | });
84 | });
85 |
86 | it("should work with shorthand arguments", (done) => {
87 | cli.run("es5/lib/**/*.js -x es5/lib/**/index.js -o es5/dist/", (err, stdout) => {
88 | if (err) {
89 | return done(err);
90 | }
91 |
92 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.js");
93 | expect(stdout).not.to.contain("es5/lib/index.js --> es5/dist/index.js");
94 | expect(stdout).not.to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
95 |
96 | assert.directoryContents("es5/dist", [
97 | "hello-world.js"
98 | ]);
99 |
100 | assert.fileContents("es5/dist", ["hello-world.js"], (contents) => {
101 | assert.noBanner(contents);
102 | assert.hasPreamble(contents);
103 | assert.notMinified(contents);
104 | assert.noSourceMap(contents);
105 | assert.noCoverage(contents);
106 | });
107 | done();
108 | });
109 | });
110 | });
111 |
--------------------------------------------------------------------------------
/test/specs/minify.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 |
7 | describe("simplifyify --minify", () => {
8 | it("should minify a single file", (done) => {
9 | cli.run("es5/lib/index.js --minify --outfile es5/dist/", (err, stdout) => {
10 | if (err) {
11 | return done(err);
12 | }
13 |
14 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
15 |
16 | assert.directoryContents("es5/dist", "index.js");
17 |
18 | assert.fileContents("es5/dist/index.js", (contents) => {
19 | assert.noBanner(contents);
20 | assert.hasMinifiedPreamble(contents);
21 | assert.isMinified(contents);
22 | assert.noSourceMap(contents);
23 | assert.noCoverage(contents);
24 | });
25 | done();
26 | });
27 | });
28 |
29 | it("should create a minified and non-minified file", (done) => {
30 | cli.run("es5/lib/index.js --bundle --minify --outfile es5/dist/", (err, stdout) => {
31 | if (err) {
32 | return done(err);
33 | }
34 |
35 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
36 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.min.js");
37 |
38 | assert.directoryContents("es5/dist", [
39 | "index.js",
40 | "index.min.js"
41 | ]);
42 |
43 | assert.fileContents("es5/dist/index.js", (contents) => {
44 | assert.noBanner(contents);
45 | assert.hasPreamble(contents);
46 | assert.notMinified(contents);
47 | assert.noSourceMap(contents);
48 | assert.noCoverage(contents);
49 | });
50 | assert.fileContents("es5/dist/index.min.js", (contents) => {
51 | assert.noBanner(contents);
52 | assert.hasMinifiedPreamble(contents);
53 | assert.isMinified(contents);
54 | assert.noSourceMap(contents);
55 | assert.noCoverage(contents);
56 | });
57 | done();
58 | });
59 | });
60 |
61 | it("should minify multiple files", (done) => {
62 | cli.run("es5/lib/**/index.js --minify --outfile es5/dist/", (err, stdout) => {
63 | if (err) {
64 | return done(err);
65 | }
66 |
67 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
68 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
69 |
70 | assert.directoryContents("es5/dist", [
71 | "index.js",
72 | "say/index.js",
73 | ]);
74 |
75 | assert.fileContents("es5/dist", ["index.js", "say/index.js"], (contents) => {
76 | assert.noBanner(contents);
77 | assert.hasMinifiedPreamble(contents);
78 | assert.isMinified(contents);
79 | assert.noSourceMap(contents);
80 | assert.noCoverage(contents);
81 | });
82 | done();
83 | });
84 | });
85 |
86 | it('should NOT append ".min" when renaming output files', (done) => {
87 | cli.run("es5/lib/**/*.js --minify --outfile es5/dist/*.foo.es5", (err, stdout) => {
88 | if (err) {
89 | return done(err);
90 | }
91 |
92 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.es5");
93 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.es5");
94 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.es5");
95 |
96 | assert.directoryContents("es5/dist", [
97 | "index.foo.es5",
98 | "hello-world.foo.es5",
99 | "say/index.foo.es5",
100 | ]);
101 |
102 | assert.fileContents("es5/dist", ["index.foo.es5", "hello-world.foo.es5", "say/index.foo.es5"], (contents) => {
103 | assert.noBanner(contents);
104 | assert.hasMinifiedPreamble(contents);
105 | assert.isMinified(contents);
106 | assert.noSourceMap(contents);
107 | assert.noCoverage(contents);
108 | });
109 | done();
110 | });
111 | });
112 |
113 | it('should append ".min" when renaming output files and producing multiple bundles', (done) => {
114 | cli.run("es5/lib/**/*.js --bundle --minify --outfile es5/dist/*.foo.es5", (err, stdout) => {
115 | if (err) {
116 | return done(err);
117 | }
118 |
119 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.es5");
120 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.min.es5");
121 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.es5");
122 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.min.es5");
123 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.es5");
124 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.min.es5");
125 |
126 | assert.directoryContents("es5/dist", [
127 | "index.foo.es5",
128 | "index.foo.min.es5",
129 | "hello-world.foo.es5",
130 | "hello-world.foo.min.es5",
131 | "say/index.foo.es5",
132 | "say/index.foo.min.es5"
133 | ]);
134 |
135 | assert.fileContents("es5/dist", ["index.foo.es5", "hello-world.foo.es5", "say/index.foo.es5"], (contents) => {
136 | assert.noBanner(contents);
137 | assert.hasPreamble(contents);
138 | assert.notMinified(contents);
139 | assert.noSourceMap(contents);
140 | assert.noCoverage(contents);
141 | });
142 | assert.fileContents("es5/dist", ["index.foo.min.es5", "hello-world.foo.min.es5", "say/index.foo.min.es5"],
143 | (contents) => {
144 | assert.noBanner(contents);
145 | assert.hasMinifiedPreamble(contents);
146 | assert.isMinified(contents);
147 | assert.noSourceMap(contents);
148 | assert.noCoverage(contents);
149 | });
150 | done();
151 | });
152 | });
153 |
154 | it("should create a minified bundle with a banner", (done) => {
155 | cli.run("hello/index.js --minify --outfile hello/dist/", (err, stdout) => {
156 | if (err) {
157 | return done(err);
158 | }
159 |
160 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.js");
161 |
162 | assert.directoryContents("hello", [
163 | "banner.txt",
164 | "hello-world.js",
165 | "index.js",
166 | "package.json",
167 | "say/index.js",
168 | "dist/index.js",
169 | ]);
170 |
171 | assert.fileContents("hello/dist/index.js", (contents) => {
172 | assert.hasBanner(contents);
173 | assert.hasMinifiedPreamble(contents);
174 | assert.isMinified(contents);
175 | assert.noSourceMap(contents);
176 | assert.noCoverage(contents);
177 | });
178 | done();
179 | });
180 | });
181 |
182 | it("should work with shorthand arguments", (done) => {
183 | cli.run("es5/lib/index.js -bmo es5/dist/", (err, stdout) => {
184 | if (err) {
185 | return done(err);
186 | }
187 |
188 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
189 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.min.js");
190 |
191 | assert.directoryContents("es5/dist", [
192 | "index.js",
193 | "index.min.js"
194 | ]);
195 |
196 | assert.fileContents("es5/dist/index.js", (contents) => {
197 | assert.noBanner(contents);
198 | assert.hasPreamble(contents);
199 | assert.notMinified(contents);
200 | assert.noSourceMap(contents);
201 | assert.noCoverage(contents);
202 | });
203 | assert.fileContents("es5/dist/index.min.js", (contents) => {
204 | assert.noBanner(contents);
205 | assert.hasMinifiedPreamble(contents);
206 | assert.isMinified(contents);
207 | assert.noSourceMap(contents);
208 | assert.noCoverage(contents);
209 | });
210 | done();
211 | });
212 | });
213 | });
214 |
--------------------------------------------------------------------------------
/test/specs/outfile.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 |
7 | describe("simplifyify --outfile", () => {
8 | it("should create a single output file, with the an explicit name", (done) => {
9 | cli.run("es5/lib/index.js --outfile es5/dist/my-file.js", (err, stdout) => {
10 | if (err) {
11 | return done(err);
12 | }
13 |
14 | expect(stdout).to.equal("es5/lib/index.js --> es5/dist/my-file.js");
15 |
16 | assert.directoryContents("es5/dist", "my-file.js");
17 |
18 | assert.fileContents("es5/dist/my-file.js", (contents) => {
19 | assert.noBanner(contents);
20 | assert.hasPreamble(contents);
21 | assert.notMinified(contents);
22 | assert.noSourceMap(contents);
23 | assert.noCoverage(contents);
24 | });
25 | done();
26 | });
27 | });
28 |
29 | it("should create a single output file, with the entry file name", (done) => {
30 | cli.run("es5/lib/index.js --outfile es5/dist", (err, stdout) => {
31 | if (err) {
32 | return done(err);
33 | }
34 |
35 | expect(stdout).to.equal("es5/lib/index.js --> es5/dist/index.js");
36 |
37 | assert.directoryContents("es5/dist", "index.js");
38 |
39 | assert.fileContents("es5/dist/index.js", (contents) => {
40 | assert.noBanner(contents);
41 | assert.hasPreamble(contents);
42 | assert.notMinified(contents);
43 | assert.noSourceMap(contents);
44 | assert.noCoverage(contents);
45 | });
46 | done();
47 | });
48 | });
49 |
50 | it("should create multiple output files, with the entry file names", (done) => {
51 | cli.run("es5/lib/**/index.js --outfile es5/dist", (err, stdout) => {
52 | if (err) {
53 | return done(err);
54 | }
55 |
56 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
57 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
58 |
59 | assert.directoryContents("es5/dist", [
60 | "index.js",
61 | "say/index.js"
62 | ]);
63 |
64 | assert.fileContents("es5/dist/index.js", (contents) => {
65 | assert.noBanner(contents);
66 | assert.hasPreamble(contents);
67 | assert.notMinified(contents);
68 | assert.noSourceMap(contents);
69 | assert.noCoverage(contents);
70 | });
71 | assert.fileContents("es5/dist/say/index.js", (contents) => {
72 | assert.noBanner(contents);
73 | assert.hasPreamble(contents);
74 | assert.notMinified(contents);
75 | assert.noSourceMap(contents);
76 | assert.noCoverage(contents);
77 | });
78 |
79 | done();
80 | });
81 | });
82 |
83 | it("should create a single output file, with a patterned file name", (done) => {
84 | cli.run("es5/lib/index.js --outfile es5/dist/*.foo-bar.es6", (err, stdout) => {
85 | if (err) {
86 | return done(err);
87 | }
88 |
89 | expect(stdout).to.equal("es5/lib/index.js --> es5/dist/index.foo-bar.es6");
90 |
91 | assert.directoryContents("es5/dist", "index.foo-bar.es6");
92 |
93 | assert.fileContents("es5/dist/index.foo-bar.es6", (contents) => {
94 | assert.noBanner(contents);
95 | assert.hasPreamble(contents);
96 | assert.notMinified(contents);
97 | assert.noSourceMap(contents);
98 | assert.noCoverage(contents);
99 | });
100 | done();
101 | });
102 | });
103 |
104 | describe("no --outfile specified", () => {
105 | it("should create a single output file, in the entry file directory", (done) => {
106 | cli.run("es5/lib/index.js", (err, stdout) => {
107 | if (err) {
108 | return done(err);
109 | }
110 |
111 | expect(stdout).to.equal("es5/lib/index.js --> es5/lib/index.bundle.js");
112 |
113 | let filesThatAlreadyExisted = ["hello-world.js", "index.js", "say/index.js"];
114 | assert.directoryContents("es5/lib",
115 | ["index.bundle.js"].concat(filesThatAlreadyExisted));
116 |
117 | assert.fileContents("es5/lib/index.bundle.js", (contents) => {
118 | assert.noBanner(contents);
119 | assert.hasPreamble(contents);
120 | assert.notMinified(contents);
121 | assert.noSourceMap(contents);
122 | assert.noCoverage(contents);
123 | });
124 | done();
125 | });
126 | });
127 |
128 | it("should create multiple output files, in the entry file directories", (done) => {
129 | cli.run("es5/lib/**/*.js --bundle --debug --minify --coverage", (err, stdout) => {
130 | if (err) {
131 | return done(err);
132 | }
133 |
134 | expect(stdout).to.contain("es5/lib/index.js --> es5/lib/index.bundle.js");
135 | expect(stdout).to.contain("es5/lib/index.js --> es5/lib/index.bundle.js.map");
136 | expect(stdout).to.contain("es5/lib/index.js --> es5/lib/index.bundle.min.js");
137 | expect(stdout).to.contain("es5/lib/index.js --> es5/lib/index.bundle.min.js.map");
138 | expect(stdout).to.contain("es5/lib/index.js --> es5/lib/index.bundle.coverage.js");
139 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/lib/hello-world.bundle.js");
140 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/lib/hello-world.bundle.js.map");
141 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/lib/hello-world.bundle.min.js");
142 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/lib/hello-world.bundle.min.js.map");
143 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/lib/hello-world.bundle.coverage.js");
144 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/lib/say/index.bundle.js");
145 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/lib/say/index.bundle.js.map");
146 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/lib/say/index.bundle.min.js");
147 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/lib/say/index.bundle.min.js.map");
148 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/lib/say/index.bundle.coverage.js");
149 |
150 | let filesThatAlreadyExisted = ["hello-world.js", "index.js", "say/index.js"];
151 | assert.directoryContents("es5/lib", [
152 | "index.bundle.js",
153 | "index.bundle.js.map",
154 | "index.bundle.min.js",
155 | "index.bundle.min.js.map",
156 | "index.bundle.coverage.js",
157 | "hello-world.bundle.js",
158 | "hello-world.bundle.js.map",
159 | "hello-world.bundle.min.js",
160 | "hello-world.bundle.min.js.map",
161 | "hello-world.bundle.coverage.js",
162 | "say/index.bundle.js",
163 | "say/index.bundle.js.map",
164 | "say/index.bundle.min.js",
165 | "say/index.bundle.min.js.map",
166 | "say/index.bundle.coverage.js"
167 | ].concat(filesThatAlreadyExisted)
168 | );
169 |
170 | assert.fileContents("es5/lib", [
171 | "index.bundle.js", "hello-world.bundle.js", "say/index.bundle.js"
172 | ],
173 | (contents) => {
174 | assert.noBanner(contents);
175 | assert.hasPreamble(contents);
176 | assert.notMinified(contents);
177 | assert.hasSourceMap(contents);
178 | assert.noCoverage(contents);
179 | }
180 | );
181 | assert.fileContents("es5/lib", [
182 | "index.bundle.min.js", "hello-world.bundle.min.js", "say/index.bundle.min.js"
183 | ],
184 | (contents) => {
185 | assert.noBanner(contents);
186 | assert.hasMinifiedPreamble(contents);
187 | assert.isMinified(contents);
188 | assert.hasSourceMap(contents);
189 | assert.noCoverage(contents);
190 | }
191 | );
192 | assert.fileContents("es5/lib", [
193 | "index.bundle.coverage.js", "hello-world.bundle.coverage.js", "say/index.bundle.coverage.js"
194 | ],
195 | (contents) => {
196 | assert.noBanner(contents);
197 | assert.hasMinifiedPreamble(contents);
198 | assert.isMinified(contents, true);
199 | assert.noSourceMap(contents);
200 | assert.hasCoverage(contents);
201 | }
202 | );
203 |
204 | assert.fileContents("es5/lib", ["index.bundle.js.map", "index.bundle.min.js.map"],
205 | (contents) => {
206 | expect(contents.sources).to.contain.members([
207 | "hello-world.js",
208 | "index.js",
209 | "say/index.js"
210 | ]);
211 | }
212 | );
213 | assert.fileContents("es5/lib", ["hello-world.bundle.js.map", "hello-world.bundle.min.js.map"],
214 | (contents) => {
215 | expect(contents.sources).to.contain.members([
216 | "hello-world.js",
217 | "say/index.js"
218 | ]);
219 | }
220 | );
221 | assert.fileContents("es5/lib", ["say/index.bundle.js.map", "say/index.bundle.min.js.map"],
222 | (contents) => {
223 | expect(contents.sources).to.contain.members([
224 | "index.js"
225 | ]);
226 | }
227 | );
228 |
229 | done();
230 | });
231 | });
232 | });
233 |
234 | it("should work with shorthand arguments", (done) => {
235 | cli.run("es5/lib/index.js -o es5/dist/my-file.js", (err, stdout) => {
236 | if (err) {
237 | return done(err);
238 | }
239 |
240 | expect(stdout).to.equal("es5/lib/index.js --> es5/dist/my-file.js");
241 |
242 | assert.directoryContents("es5/dist", "my-file.js");
243 |
244 | assert.fileContents("es5/dist/my-file.js", (contents) => {
245 | assert.noBanner(contents);
246 | assert.hasPreamble(contents);
247 | assert.notMinified(contents);
248 | assert.noSourceMap(contents);
249 | assert.noCoverage(contents);
250 | });
251 | done();
252 | });
253 | });
254 | });
255 |
--------------------------------------------------------------------------------
/test/specs/standalone.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 |
7 | describe("simplifyify --standalone", () => {
8 | it("should create a UMD module with the given name", (done) => {
9 | cli.run("es5/lib/index.js --standalone FizzBuzz --outfile es5/dist/", (err, stdout) => {
10 | if (err) {
11 | return done(err);
12 | }
13 |
14 | expect(stdout).to.equal("es5/lib/index.js --> es5/dist/index.js");
15 |
16 | assert.directoryContents("es5/dist", "index.js");
17 |
18 | assert.fileContents("es5/dist/index.js", (contents) => {
19 | assert.noBanner(contents);
20 | assert.hasUmdPreamble(contents);
21 | assert.notMinified(contents);
22 | assert.noSourceMap(contents);
23 | assert.noCoverage(contents);
24 | expect(contents).to.match(/\.FizzBuzz = /);
25 | });
26 | done();
27 | });
28 | });
29 |
30 | it("should create a UMD module with a namespaced name", (done) => {
31 | cli.run("es5/lib/index.js --standalone Fizz.Buzz --outfile es5/dist/", (err, stdout) => {
32 | if (err) {
33 | return done(err);
34 | }
35 |
36 | expect(stdout).to.equal("es5/lib/index.js --> es5/dist/index.js");
37 |
38 | assert.directoryContents("es5/dist", "index.js");
39 |
40 | assert.fileContents("es5/dist/index.js", (contents) => {
41 | assert.noBanner(contents);
42 | assert.hasUmdPreamble(contents);
43 | assert.notMinified(contents);
44 | assert.noSourceMap(contents);
45 | assert.noCoverage(contents);
46 | expect(contents).to.match(/\.Fizz = /);
47 | expect(contents).to.match(/\.Buzz = /);
48 | });
49 | done();
50 | });
51 | });
52 |
53 | it("should create a UMD bundle with a banner", (done) => {
54 | cli.run("hello/index.js --standalone Fizz.Buzz --outfile hello/dist/", (err, stdout) => {
55 | if (err) {
56 | return done(err);
57 | }
58 |
59 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.js");
60 |
61 | assert.directoryContents("hello", [
62 | "banner.txt",
63 | "hello-world.js",
64 | "index.js",
65 | "package.json",
66 | "say/index.js",
67 | "dist/index.js",
68 | ]);
69 |
70 | assert.fileContents("hello/dist/index.js", (contents) => {
71 | assert.hasBanner(contents);
72 | assert.hasUmdPreamble(contents);
73 | assert.notMinified(contents);
74 | assert.noSourceMap(contents);
75 | assert.noCoverage(contents);
76 | expect(contents).to.match(/\.Fizz = /);
77 | expect(contents).to.match(/\.Buzz = /);
78 | });
79 | done();
80 | });
81 | });
82 |
83 | it("should create a UMD bundle with all options", (done) => {
84 | cli.run("hello/index.js --bundle --minify --debug --coverage --standalone Fizz.Buzz --outfile hello/dist/", (err, stdout) => {
85 | if (err) {
86 | return done(err);
87 | }
88 |
89 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.js");
90 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.js.map");
91 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.min.js");
92 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.min.js.map");
93 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.coverage.js");
94 |
95 | assert.directoryContents("hello", [
96 | "banner.txt",
97 | "hello-world.js",
98 | "index.js",
99 | "package.json",
100 | "say/index.js",
101 | "dist/index.js",
102 | "dist/index.js.map",
103 | "dist/index.min.js",
104 | "dist/index.min.js.map",
105 | "dist/index.coverage.js",
106 | ]);
107 |
108 | assert.fileContents("hello/dist/index.js", (contents) => {
109 | assert.hasBanner(contents);
110 | assert.hasUmdPreamble(contents);
111 | assert.notMinified(contents);
112 | assert.hasSourceMap(contents);
113 | assert.noCoverage(contents);
114 | expect(contents).to.match(/\.Fizz = /);
115 | expect(contents).to.match(/\.Buzz = /);
116 | });
117 |
118 | assert.fileContents("hello/dist/index.min.js", (contents) => {
119 | assert.hasBanner(contents);
120 | assert.hasMinifiedUmdPreamble(contents);
121 | assert.isMinified(contents);
122 | assert.hasSourceMap(contents);
123 | assert.noCoverage(contents);
124 | expect(contents).to.match(/\.Fizz=/);
125 | expect(contents).to.match(/\.Buzz=/);
126 | });
127 |
128 | assert.fileContents("hello/dist/index.coverage.js", (contents) => {
129 | assert.hasBanner(contents);
130 | assert.hasMinifiedUmdPreamble(contents);
131 | assert.isMinified(contents, true);
132 | assert.noSourceMap(contents);
133 | assert.hasCoverage(contents);
134 | expect(contents).to.match(/\.Fizz=/);
135 | expect(contents).to.match(/\.Buzz=/);
136 | });
137 |
138 | assert.fileContents("hello/dist", ["index.js.map", "index.min.js.map"], (contents) => {
139 | expect(contents.sources).to.contain.members([
140 | "../hello-world.js",
141 | "../index.js",
142 | "../say/index.js"
143 | ]);
144 | });
145 |
146 | done();
147 | });
148 | });
149 |
150 | it("should create multiple UMD bundles with names derived from pattern", (done) => {
151 | cli.run("es5/lib/**/*.js --standalone Fizz.* --outfile es5/dist/", (err, stdout) => {
152 | if (err) {
153 | return done(err);
154 | }
155 |
156 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
157 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.js");
158 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
159 |
160 | assert.directoryContents("es5/dist", [
161 | "index.js",
162 | "hello-world.js",
163 | "say/index.js"
164 | ]);
165 |
166 |
167 | assert.fileContents("es5/dist/index.js", (contents) => {
168 | assert.noBanner(contents);
169 | assert.hasUmdPreamble(contents);
170 | assert.notMinified(contents);
171 | assert.noSourceMap(contents);
172 | assert.noCoverage(contents);
173 | expect(contents).to.match(/\.Fizz = /);
174 | expect(contents).to.match(/\.index = /);
175 | });
176 | assert.fileContents("es5/dist/hello-world.js", (contents) => {
177 | assert.noBanner(contents);
178 | assert.hasUmdPreamble(contents);
179 | assert.notMinified(contents);
180 | assert.noSourceMap(contents);
181 | assert.noCoverage(contents);
182 | expect(contents).to.match(/\.Fizz = /);
183 | expect(contents).to.match(/\.helloWorld = /);
184 | });
185 | assert.fileContents("es5/dist/say/index.js", (contents) => {
186 | assert.noBanner(contents);
187 | assert.hasUmdPreamble(contents);
188 | assert.notMinified(contents);
189 | assert.noSourceMap(contents);
190 | assert.noCoverage(contents);
191 | expect(contents).to.match(/\.Fizz = /);
192 | expect(contents).to.match(/\.say = /);
193 | expect(contents).to.match(/\.index = /);
194 | });
195 |
196 | done();
197 | });
198 | });
199 |
200 | it("should create a bundle and sourcemap for a universal library", (done) => {
201 | cli.run("universal-lib/lib/browser.js --outfile universal-lib/dist/universal-lib.js --standalone universal --bundle --debug --minify", (err, stdout) => {
202 | if (err) {
203 | return done(err);
204 | }
205 |
206 | expect(stdout).to.contain("universal-lib/lib/browser.js --> universal-lib/dist/universal-lib.js");
207 | expect(stdout).to.contain("universal-lib/lib/browser.js --> universal-lib/dist/universal-lib.js.map");
208 |
209 | assert.directoryContents("universal-lib", [
210 | "banner.txt",
211 | "bower.json",
212 | "dist/universal-lib.js",
213 | "dist/universal-lib.js.map",
214 | "dist/universal-lib.min.js",
215 | "dist/universal-lib.min.js.map",
216 | "lib/browser.js",
217 | "lib/node.js",
218 | "lib/resolve.js",
219 | "package.json",
220 | ]);
221 |
222 | assert.fileContents("universal-lib/dist/universal-lib.js", (contents) => {
223 | assert.hasBanner(contents);
224 | assert.hasPreamble(contents);
225 | assert.notMinified(contents);
226 | assert.hasSourceMap(contents);
227 | assert.noCoverage(contents);
228 | });
229 |
230 | assert.fileContents("universal-lib/dist/universal-lib.min.js", (contents) => {
231 | assert.hasBanner(contents);
232 | assert.hasMinifiedUmdPreamble(contents);
233 | assert.isMinified(contents);
234 | assert.hasSourceMap(contents);
235 | assert.noCoverage(contents);
236 | });
237 |
238 | assert.fileContents("universal-lib/dist", ["universal-lib.js.map", "universal-lib.min.js.map"], (contents) => {
239 | expect(contents.sources).to.contain.members([
240 | "../lib/browser.js",
241 | "../lib/resolve.js",
242 | ]);
243 |
244 | // The first 9 lines of the sourcemap should be blank, since we don't
245 | // have sourcemappings for the banner
246 | expect(contents.mappings).to.match(/^;;;;;;;;(C|A)AAA/);
247 | });
248 |
249 | done();
250 | });
251 | });
252 |
253 | it("should work with shorthand arguments", (done) => {
254 | cli.run("es5/lib/index.js -s FizzBuzz -o es5/dist/", (err, stdout) => {
255 | if (err) {
256 | return done(err);
257 | }
258 |
259 | expect(stdout).to.equal("es5/lib/index.js --> es5/dist/index.js");
260 |
261 | assert.directoryContents("es5/dist", "index.js");
262 |
263 | assert.fileContents("es5/dist/index.js", (contents) => {
264 | assert.noBanner(contents);
265 | assert.hasUmdPreamble(contents);
266 | assert.notMinified(contents);
267 | assert.noSourceMap(contents);
268 | assert.noCoverage(contents);
269 | expect(contents).to.match(/\.FizzBuzz = /);
270 | });
271 | done();
272 | });
273 | });
274 |
275 | });
276 |
--------------------------------------------------------------------------------
/test/specs/test.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const assert = require("../fixtures/assert");
5 | const expect = require("chai").expect;
6 |
7 | describe("simplifyify --coverage", () => {
8 | it("should add code-coverage to a single file", (done) => {
9 | cli.run("es5/lib/index.js --coverage --outfile es5/dist/", (err, stdout) => {
10 | if (err) {
11 | return done(err);
12 | }
13 |
14 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
15 |
16 | assert.directoryContents("es5/dist", "index.js");
17 |
18 | assert.fileContents("es5/dist/index.js", (contents) => {
19 | assert.noBanner(contents);
20 | assert.hasMinifiedPreamble(contents);
21 | assert.isMinified(contents, true);
22 | assert.noSourceMap(contents);
23 | assert.hasCoverage(contents);
24 | });
25 | done();
26 | });
27 | });
28 |
29 | it("should create a code-coverage and normal file", (done) => {
30 | cli.run("es5/lib/index.js --bundle --coverage --outfile es5/dist/", (err, stdout) => {
31 | if (err) {
32 | return done(err);
33 | }
34 |
35 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
36 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.coverage.js");
37 |
38 | assert.directoryContents("es5/dist", [
39 | "index.js",
40 | "index.coverage.js"
41 | ]);
42 |
43 | assert.fileContents("es5/dist/index.js", (contents) => {
44 | assert.noBanner(contents);
45 | assert.hasPreamble(contents);
46 | assert.notMinified(contents);
47 | assert.noSourceMap(contents);
48 | assert.noCoverage(contents);
49 | });
50 | assert.fileContents("es5/dist/index.coverage.js", (contents) => {
51 | assert.noBanner(contents);
52 | assert.hasMinifiedPreamble(contents);
53 | assert.isMinified(contents, true);
54 | assert.noSourceMap(contents);
55 | assert.hasCoverage(contents);
56 | });
57 | done();
58 | });
59 | });
60 |
61 | it("should add code-coverage to multiple files", (done) => {
62 | cli.run("es5/lib/**/index.js --coverage --outfile es5/dist/", (err, stdout) => {
63 | if (err) {
64 | return done(err);
65 | }
66 |
67 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
68 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.js");
69 |
70 | assert.directoryContents("es5/dist", [
71 | "index.js",
72 | "say/index.js",
73 | ]);
74 |
75 | assert.fileContents("es5/dist", ["index.js", "say/index.js"], (contents) => {
76 | assert.noBanner(contents);
77 | assert.hasMinifiedPreamble(contents);
78 | assert.isMinified(contents, true);
79 | assert.noSourceMap(contents);
80 | assert.hasCoverage(contents);
81 | });
82 | done();
83 | });
84 | });
85 |
86 | it('should NOT create a ".map" file for test bundles, even if --debug is set', (done) => {
87 | cli.run("es5/lib/**/*.js --coverage --debug --outfile es5/dist/*.foo.es5", (err, stdout) => {
88 | if (err) {
89 | return done(err);
90 | }
91 |
92 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.es5");
93 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.es5");
94 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.es5");
95 |
96 | assert.directoryContents("es5/dist", [
97 | "index.foo.es5",
98 | "hello-world.foo.es5",
99 | "say/index.foo.es5",
100 | ]);
101 |
102 | assert.fileContents("es5/dist", ["index.foo.es5", "hello-world.foo.es5", "say/index.foo.es5"], (contents) => {
103 | assert.noBanner(contents);
104 | assert.hasMinifiedPreamble(contents);
105 | assert.isMinified(contents, true);
106 | assert.noSourceMap(contents);
107 | assert.hasCoverage(contents);
108 | });
109 |
110 | done();
111 | });
112 | });
113 |
114 | it('should NOT append ".test" when renaming output files', (done) => {
115 | cli.run("es5/lib/**/*.js --coverage --outfile es5/dist/*.foo.es5", (err, stdout) => {
116 | if (err) {
117 | return done(err);
118 | }
119 |
120 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.es5");
121 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.es5");
122 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.es5");
123 |
124 | assert.directoryContents("es5/dist", [
125 | "index.foo.es5",
126 | "hello-world.foo.es5",
127 | "say/index.foo.es5",
128 | ]);
129 |
130 | assert.fileContents("es5/dist", ["index.foo.es5", "hello-world.foo.es5", "say/index.foo.es5"], (contents) => {
131 | assert.noBanner(contents);
132 | assert.hasMinifiedPreamble(contents);
133 | assert.isMinified(contents, true);
134 | assert.noSourceMap(contents);
135 | assert.hasCoverage(contents);
136 | });
137 |
138 | done();
139 | });
140 | });
141 |
142 | it('should append ".test" when renaming output files and producing multiple bundles', (done) => {
143 | cli.run("es5/lib/**/*.js --coverage --bundle --minify --debug --outfile es5/dist/*.foo.es5", (err, stdout) => {
144 | if (err) {
145 | return done(err);
146 | }
147 |
148 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.es5");
149 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.es5.map");
150 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.min.es5");
151 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.min.es5.map");
152 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.foo.coverage.es5");
153 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.es5");
154 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.es5.map");
155 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.min.es5");
156 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.min.es5.map");
157 | expect(stdout).to.contain("es5/lib/hello-world.js --> es5/dist/hello-world.foo.coverage.es5");
158 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.es5");
159 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.es5.map");
160 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.min.es5");
161 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.min.es5.map");
162 | expect(stdout).to.contain("es5/lib/say/index.js --> es5/dist/say/index.foo.coverage.es5");
163 |
164 | assert.directoryContents("es5/dist", [
165 | "index.foo.es5",
166 | "index.foo.es5.map",
167 | "index.foo.min.es5",
168 | "index.foo.min.es5.map",
169 | "index.foo.coverage.es5",
170 | "hello-world.foo.es5",
171 | "hello-world.foo.es5.map",
172 | "hello-world.foo.min.es5",
173 | "hello-world.foo.min.es5.map",
174 | "hello-world.foo.coverage.es5",
175 | "say/index.foo.es5",
176 | "say/index.foo.es5.map",
177 | "say/index.foo.min.es5",
178 | "say/index.foo.min.es5.map",
179 | "say/index.foo.coverage.es5"
180 | ]);
181 |
182 | assert.fileContents("es5/dist", ["index.foo.es5", "hello-world.foo.es5", "say/index.foo.es5"], (contents) => {
183 | assert.noBanner(contents);
184 | assert.hasPreamble(contents);
185 | assert.notMinified(contents);
186 | assert.hasSourceMap(contents);
187 | assert.noCoverage(contents);
188 | });
189 | assert.fileContents("es5/dist", ["index.foo.min.es5", "hello-world.foo.min.es5", "say/index.foo.min.es5"],
190 | (contents) => {
191 | assert.noBanner(contents);
192 | assert.hasMinifiedPreamble(contents);
193 | assert.isMinified(contents);
194 | assert.hasSourceMap(contents);
195 | assert.noCoverage(contents);
196 | });
197 | assert.fileContents("es5/dist", ["index.foo.coverage.es5", "hello-world.foo.coverage.es5", "say/index.foo.coverage.es5"],
198 | (contents) => {
199 | assert.noBanner(contents);
200 | assert.hasMinifiedPreamble(contents);
201 | assert.isMinified(contents, true);
202 | assert.noSourceMap(contents);
203 | assert.hasCoverage(contents);
204 | });
205 |
206 | assert.fileContents("es5/dist", ["index.foo.es5.map", "index.foo.min.es5.map"], (contents) => {
207 | expect(contents.sources).to.contain.members([
208 | "../lib/hello-world.js",
209 | "../lib/index.js",
210 | "../lib/say/index.js"
211 | ]);
212 | });
213 | assert.fileContents("es5/dist", ["hello-world.foo.es5.map", "hello-world.foo.min.es5.map"], (contents) => {
214 | expect(contents.sources).to.contain.members([
215 | "../lib/hello-world.js",
216 | "../lib/say/index.js"
217 | ]);
218 | });
219 | assert.fileContents("es5/dist", ["say/index.foo.es5.map", "say/index.foo.min.es5.map"], (contents) => {
220 | expect(contents.sources).to.contain.members([
221 | "../../lib/say/index.js"
222 | ]);
223 | });
224 | done();
225 | });
226 | });
227 |
228 | it("should create a test bundle with a banner", (done) => {
229 | cli.run("hello/index.js --coverage --outfile hello/dist/", (err, stdout) => {
230 | if (err) {
231 | return done(err);
232 | }
233 |
234 | expect(stdout).to.contain("hello/index.js --> hello/dist/index.js");
235 |
236 | assert.directoryContents("hello", [
237 | "banner.txt",
238 | "hello-world.js",
239 | "index.js",
240 | "package.json",
241 | "say/index.js",
242 | "dist/index.js",
243 | ]);
244 |
245 | assert.fileContents("hello/dist/index.js", (contents) => {
246 | assert.hasBanner(contents);
247 | assert.hasMinifiedPreamble(contents);
248 | assert.isMinified(contents, true);
249 | assert.noSourceMap(contents);
250 | assert.hasCoverage(contents);
251 | });
252 | done();
253 | });
254 | });
255 |
256 | it("should work with shorthand arguments", (done) => {
257 | cli.run("es5/lib/index.js -bco es5/dist/", (err, stdout) => {
258 | if (err) {
259 | return done(err);
260 | }
261 |
262 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.js");
263 | expect(stdout).to.contain("es5/lib/index.js --> es5/dist/index.coverage.js");
264 |
265 | assert.directoryContents("es5/dist", [
266 | "index.js",
267 | "index.coverage.js"
268 | ]);
269 |
270 | assert.fileContents("es5/dist/index.js", (contents) => {
271 | assert.noBanner(contents);
272 | assert.hasPreamble(contents);
273 | assert.notMinified(contents);
274 | assert.noSourceMap(contents);
275 | assert.noCoverage(contents);
276 | });
277 | assert.fileContents("es5/dist/index.coverage.js", (contents) => {
278 | assert.noBanner(contents);
279 | assert.hasMinifiedPreamble(contents);
280 | assert.isMinified(contents, true);
281 | assert.noSourceMap(contents);
282 | assert.hasCoverage(contents);
283 | });
284 | done();
285 | });
286 | });
287 | });
288 |
--------------------------------------------------------------------------------
/test/specs/transform.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const mocha = require("../fixtures/mocha");
5 | const assert = require("../fixtures/assert");
6 | const expect = require("chai").expect;
7 |
8 | describe("browserify transforms", () => {
9 | beforeEach(function () {
10 | // Increase the test timeouts to allow sufficient time for Browserify transforms
11 | mocha.increaseTimeout(this.currentTest, 15000);
12 | });
13 |
14 | it("should use the browserify.transform field in package.json", (done) => {
15 | cli.run("es6/src/**/*.js --bundle --minify --debug --coverage --outfile es6/dist/", (err, stdout) => {
16 | if (err) {
17 | return done(err);
18 | }
19 |
20 | expect(stdout).to.contain("es6/src/index.js --> es6/dist/index.js");
21 | expect(stdout).to.contain("es6/src/index.js --> es6/dist/index.js.map");
22 | expect(stdout).to.contain("es6/src/index.js --> es6/dist/index.min.js");
23 | expect(stdout).to.contain("es6/src/index.js --> es6/dist/index.min.js.map");
24 | expect(stdout).to.contain("es6/src/index.js --> es6/dist/index.coverage.js");
25 | expect(stdout).to.contain("es6/src/hello-world.js --> es6/dist/hello-world.js");
26 | expect(stdout).to.contain("es6/src/hello-world.js --> es6/dist/hello-world.js.map");
27 | expect(stdout).to.contain("es6/src/hello-world.js --> es6/dist/hello-world.min.js");
28 | expect(stdout).to.contain("es6/src/hello-world.js --> es6/dist/hello-world.min.js.map");
29 | expect(stdout).to.contain("es6/src/hello-world.js --> es6/dist/hello-world.coverage.js");
30 | expect(stdout).to.contain("es6/src/say/index.js --> es6/dist/say/index.js");
31 | expect(stdout).to.contain("es6/src/say/index.js --> es6/dist/say/index.js.map");
32 | expect(stdout).to.contain("es6/src/say/index.js --> es6/dist/say/index.min.js");
33 | expect(stdout).to.contain("es6/src/say/index.js --> es6/dist/say/index.min.js.map");
34 | expect(stdout).to.contain("es6/src/say/index.js --> es6/dist/say/index.coverage.js");
35 |
36 | assert.directoryContents("es6/dist", [
37 | "index.js",
38 | "index.js.map",
39 | "index.min.js",
40 | "index.min.js.map",
41 | "index.coverage.js",
42 | "hello-world.js",
43 | "hello-world.js.map",
44 | "hello-world.min.js",
45 | "hello-world.min.js.map",
46 | "hello-world.coverage.js",
47 | "say/index.js",
48 | "say/index.js.map",
49 | "say/index.min.js",
50 | "say/index.min.js.map",
51 | "say/index.coverage.js",
52 | ]);
53 |
54 | assert.fileContents("es6/dist", ["index.js", "hello-world.js", "say/index.js"], (contents) => {
55 | assert.noBanner(contents);
56 | assert.notMinified(contents);
57 | assert.hasPreamble(contents);
58 | assert.hasSourceMap(contents);
59 | assert.noCoverage(contents);
60 | assert.isBabelified(contents);
61 | });
62 |
63 | assert.fileContents("es6/dist", ["index.min.js", "hello-world.min.js", "say/index.min.js"], (contents) => {
64 | assert.noBanner(contents);
65 | assert.hasMinifiedPreamble(contents);
66 | assert.isMinified(contents);
67 | assert.hasSourceMap(contents);
68 | assert.noCoverage(contents);
69 | assert.isBabelified(contents);
70 | });
71 |
72 | assert.fileContents("es6/dist", ["index.coverage.js", "hello-world.coverage.js", "say/index.coverage.js"], (contents) => {
73 | assert.noBanner(contents);
74 | assert.hasMinifiedPreamble(contents);
75 | assert.isMinified(contents, true);
76 | assert.noSourceMap(contents);
77 | assert.hasCoverage(contents);
78 | assert.isBabelified(contents);
79 | });
80 |
81 | assert.fileContents("es6/dist", ["index.js.map", "index.min.js.map"], (contents) => {
82 | expect(contents.sources).to.contain.members([
83 | "../src/hello-world.js",
84 | "../src/index.js",
85 | "../src/say/index.js"
86 | ]);
87 | });
88 |
89 | assert.fileContents("es6/dist", ["hello-world.js.map", "hello-world.min.js.map"], (contents) => {
90 | expect(contents.sources).to.contain.members([
91 | "../src/hello-world.js",
92 | "../src/say/index.js"
93 | ]);
94 | });
95 |
96 | assert.fileContents("es6/dist/say", ["index.js.map", "index.min.js.map"], (contents) => {
97 | expect(contents.sources).to.contain.members([
98 | "../../src/say/index.js"
99 | ]);
100 | });
101 |
102 | done();
103 | });
104 | });
105 |
106 | it("should use the transform options in the browserify.transform field", (done) => {
107 | cli.run("es6-with-options/src/**/*.js --bundle --minify --debug --coverage --outfile es6-with-options/dist/", (err, stdout) => {
108 | if (err) {
109 | return done(err);
110 | }
111 |
112 | expect(stdout).to.contain("es6-with-options/src/index.js --> es6-with-options/dist/index.js");
113 | expect(stdout).to.contain("es6-with-options/src/index.js --> es6-with-options/dist/index.js.map");
114 | expect(stdout).to.contain("es6-with-options/src/index.js --> es6-with-options/dist/index.min.js");
115 | expect(stdout).to.contain("es6-with-options/src/index.js --> es6-with-options/dist/index.min.js.map");
116 | expect(stdout).to.contain("es6-with-options/src/index.js --> es6-with-options/dist/index.coverage.js");
117 | expect(stdout).to.contain("es6-with-options/src/hello-world.js --> es6-with-options/dist/hello-world.js");
118 | expect(stdout).to.contain("es6-with-options/src/hello-world.js --> es6-with-options/dist/hello-world.js.map");
119 | expect(stdout).to.contain("es6-with-options/src/hello-world.js --> es6-with-options/dist/hello-world.min.js");
120 | expect(stdout).to.contain("es6-with-options/src/hello-world.js --> es6-with-options/dist/hello-world.min.js.map");
121 | expect(stdout).to.contain("es6-with-options/src/hello-world.js --> es6-with-options/dist/hello-world.coverage.js");
122 | expect(stdout).to.contain("es6-with-options/src/say/index.js --> es6-with-options/dist/say/index.js");
123 | expect(stdout).to.contain("es6-with-options/src/say/index.js --> es6-with-options/dist/say/index.js.map");
124 | expect(stdout).to.contain("es6-with-options/src/say/index.js --> es6-with-options/dist/say/index.min.js");
125 | expect(stdout).to.contain("es6-with-options/src/say/index.js --> es6-with-options/dist/say/index.min.js.map");
126 | expect(stdout).to.contain("es6-with-options/src/say/index.js --> es6-with-options/dist/say/index.coverage.js");
127 |
128 | assert.directoryContents("es6-with-options/dist", [
129 | "index.js",
130 | "index.js.map",
131 | "index.min.js",
132 | "index.min.js.map",
133 | "index.coverage.js",
134 | "hello-world.js",
135 | "hello-world.js.map",
136 | "hello-world.min.js",
137 | "hello-world.min.js.map",
138 | "hello-world.coverage.js",
139 | "say/index.js",
140 | "say/index.js.map",
141 | "say/index.min.js",
142 | "say/index.min.js.map",
143 | "say/index.coverage.js",
144 | ]);
145 |
146 | assert.fileContents("es6-with-options/dist", ["index.js", "hello-world.js", "say/index.js"], (contents) => {
147 | assert.noBanner(contents);
148 | assert.hasPreamble(contents);
149 | assert.notMinified(contents);
150 | assert.hasSourceMap(contents);
151 | assert.noCoverage(contents);
152 | assert.isBabelified(contents);
153 | });
154 |
155 | assert.fileContents("es6-with-options/dist", ["index.min.js", "hello-world.min.js", "say/index.min.js"], (contents) => {
156 | assert.noBanner(contents);
157 | assert.hasMinifiedPreamble(contents);
158 | assert.isMinified(contents);
159 | assert.hasSourceMap(contents);
160 | assert.noCoverage(contents);
161 | assert.isBabelified(contents);
162 | });
163 |
164 | assert.fileContents("es6-with-options/dist", ["index.coverage.js", "hello-world.coverage.js", "say/index.coverage.js"], (contents) => {
165 | assert.noBanner(contents);
166 | assert.hasMinifiedPreamble(contents);
167 | assert.isMinified(contents, true);
168 | assert.noSourceMap(contents);
169 | assert.hasCoverage(contents);
170 | assert.isBabelified(contents);
171 | });
172 |
173 | assert.fileContents("es6-with-options/dist", ["index.js.map", "index.min.js.map"], (contents) => {
174 | expect(contents.sources).to.contain.members([
175 | "../src/hello-world.js",
176 | "../src/index.js",
177 | "../src/say/index.js"
178 | ]);
179 | });
180 |
181 | assert.fileContents("es6-with-options/dist", ["hello-world.js.map", "hello-world.min.js.map"], (contents) => {
182 | expect(contents.sources).to.contain.members([
183 | "../src/hello-world.js",
184 | "../src/say/index.js"
185 | ]);
186 | });
187 |
188 | assert.fileContents("es6-with-options/dist/say", ["index.js.map", "index.min.js.map"], (contents) => {
189 | expect(contents.sources).to.contain.members([
190 | "../../src/say/index.js"
191 | ]);
192 | });
193 |
194 | done();
195 | });
196 | });
197 |
198 | it("should use the browserify.transform field for built-in transforms", (done) => {
199 | cli.run("transform-options/src/**/*.js --bundle --minify --debug --coverage --outfile transform-options/dist/", (err, stdout) => {
200 | if (err) {
201 | return done(err);
202 | }
203 |
204 | expect(stdout).to.contain("transform-options/src/index.js --> transform-options/dist/index.js");
205 | expect(stdout).to.contain("transform-options/src/index.js --> transform-options/dist/index.js.map");
206 | expect(stdout).to.contain("transform-options/src/index.js --> transform-options/dist/index.min.js");
207 | expect(stdout).to.contain("transform-options/src/index.js --> transform-options/dist/index.min.js.map");
208 | expect(stdout).to.contain("transform-options/src/index.js --> transform-options/dist/index.coverage.js");
209 | expect(stdout).to.contain("transform-options/src/hello-world.js --> transform-options/dist/hello-world.js");
210 | expect(stdout).to.contain("transform-options/src/hello-world.js --> transform-options/dist/hello-world.js.map");
211 | expect(stdout).to.contain("transform-options/src/hello-world.js --> transform-options/dist/hello-world.min.js");
212 | expect(stdout).to.contain("transform-options/src/hello-world.js --> transform-options/dist/hello-world.min.js.map");
213 | expect(stdout).to.contain("transform-options/src/hello-world.js --> transform-options/dist/hello-world.coverage.js");
214 | expect(stdout).to.contain("transform-options/src/say/index.js --> transform-options/dist/say/index.js");
215 | expect(stdout).to.contain("transform-options/src/say/index.js --> transform-options/dist/say/index.js.map");
216 | expect(stdout).to.contain("transform-options/src/say/index.js --> transform-options/dist/say/index.min.js");
217 | expect(stdout).to.contain("transform-options/src/say/index.js --> transform-options/dist/say/index.min.js.map");
218 | expect(stdout).to.contain("transform-options/src/say/index.js --> transform-options/dist/say/index.coverage.js");
219 |
220 | assert.directoryContents("transform-options/dist", [
221 | "index.js",
222 | "index.js.map",
223 | "index.min.js",
224 | "index.min.js.map",
225 | "index.coverage.js",
226 | "hello-world.js",
227 | "hello-world.js.map",
228 | "hello-world.min.js",
229 | "hello-world.min.js.map",
230 | "hello-world.coverage.js",
231 | "say/index.js",
232 | "say/index.js.map",
233 | "say/index.min.js",
234 | "say/index.min.js.map",
235 | "say/index.coverage.js",
236 | ]);
237 |
238 | assert.fileContents("transform-options/dist", ["index.js", "hello-world.js", "say/index.js"], (contents) => {
239 | assert.hasBanner(contents);
240 | assert.hasPreamble(contents);
241 | assert.notMinified(contents);
242 | assert.hasSourceMap(contents);
243 | assert.noCoverage(contents);
244 | assert.isBabelified(contents);
245 | });
246 |
247 | assert.fileContents("transform-options/dist", ["index.min.js", "hello-world.min.js", "say/index.min.js"], (contents) => {
248 | assert.hasBanner(contents);
249 | assert.hasPreamble(contents);
250 | assert.notMinified(contents);
251 | assert.hasSourceMap(contents);
252 | assert.noCoverage(contents);
253 | assert.isBabelified(contents);
254 | });
255 |
256 | assert.fileContents("transform-options/dist", ["index.coverage.js", "hello-world.coverage.js", "say/index.coverage.js"], (contents) => {
257 | assert.hasBanner(contents);
258 | assert.hasPreamble(contents);
259 | assert.notMinified(contents);
260 | assert.noSourceMap(contents);
261 | assert.hasCoverage(contents);
262 | assert.isBabelified(contents);
263 | });
264 |
265 | assert.fileContents("transform-options/dist", ["index.js.map", "index.min.js.map"], (contents) => {
266 | expect(contents.sources).to.contain.members([
267 | "../src/hello-world.js",
268 | "../src/index.js",
269 | "../src/say/index.js"
270 | ]);
271 | });
272 |
273 | assert.fileContents("transform-options/dist", ["hello-world.js.map", "hello-world.min.js.map"], (contents) => {
274 | expect(contents.sources).to.contain.members([
275 | "../src/hello-world.js",
276 | "../src/say/index.js"
277 | ]);
278 | });
279 |
280 | assert.fileContents("transform-options/dist/say", ["index.js.map", "index.min.js.map"], (contents) => {
281 | expect(contents.sources).to.contain.members([
282 | "../../src/say/index.js"
283 | ]);
284 | });
285 |
286 | done();
287 | });
288 | });
289 | });
290 |
--------------------------------------------------------------------------------
/test/specs/typescript.spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const cli = require("../fixtures/cli");
4 | const mocha = require("../fixtures/mocha");
5 | const assert = require("../fixtures/assert");
6 | const expect = require("chai").expect;
7 |
8 | describe("TypeScript support", () => {
9 | beforeEach(function () {
10 | // Increase the test timeouts to allow sufficient time for Browserify transforms
11 | mocha.increaseTimeout(this.currentTest, 90000);
12 | });
13 |
14 | it("should automatically enable TypeScript if the entry file has a .ts extenstion", (done) => {
15 | cli.run("typescript/src/index.ts --bundle --minify --debug --coverage --outfile typescript/dist/", (err, stdout) => {
16 | if (err) {
17 | return done(err);
18 | }
19 |
20 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.js");
21 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.js.map");
22 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.min.js");
23 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.min.js.map");
24 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.coverage.js");
25 |
26 | assert.directoryContents("typescript/dist", [
27 | "index.js",
28 | "index.js.map",
29 | "index.min.js",
30 | "index.min.js.map",
31 | "index.coverage.js",
32 | ]);
33 |
34 | assert.fileContents("typescript/dist", "index.js", (contents) => {
35 | assert.noBanner(contents);
36 | assert.notMinified(contents);
37 | assert.hasPreamble(contents);
38 | assert.hasSourceMap(contents);
39 | assert.noCoverage(contents);
40 | assert.isBabelified(contents);
41 | });
42 |
43 | assert.fileContents("typescript/dist", "index.min.js", (contents) => {
44 | assert.noBanner(contents);
45 | assert.hasMinifiedPreamble(contents);
46 | assert.isMinified(contents);
47 | assert.hasSourceMap(contents);
48 | assert.noCoverage(contents);
49 | assert.isBabelified(contents);
50 | });
51 |
52 | assert.fileContents("typescript/dist", "index.coverage.js", (contents) => {
53 | assert.noBanner(contents);
54 | assert.hasMinifiedPreamble(contents);
55 | assert.isMinified(contents, true);
56 | assert.noSourceMap(contents);
57 | assert.hasCoverage(contents);
58 | assert.isBabelified(contents);
59 | });
60 |
61 | assert.fileContents("typescript/dist", ["index.js.map", "index.min.js.map"], (contents) => {
62 | expect(contents.sources).to.contain.members([
63 | "../src/hello-world.tsx",
64 | "../src/index.ts",
65 | "../src/say/index.ts"
66 | ]);
67 | });
68 |
69 | done();
70 | });
71 | });
72 |
73 | it("should automatically enable TypeScript if the entry files has a .tsx extenstion", (done) => {
74 | cli.run("typescript/src/hello-world.tsx --bundle --minify --debug --coverage --outfile typescript/dist/", (err, stdout) => {
75 | if (err) {
76 | return done(err);
77 | }
78 |
79 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.js");
80 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.js.map");
81 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.min.js");
82 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.min.js.map");
83 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.coverage.js");
84 |
85 | assert.directoryContents("typescript/dist", [
86 | "hello-world.js",
87 | "hello-world.js.map",
88 | "hello-world.min.js",
89 | "hello-world.min.js.map",
90 | "hello-world.coverage.js",
91 | ]);
92 |
93 | assert.fileContents("typescript/dist", "hello-world.js", (contents) => {
94 | assert.noBanner(contents);
95 | assert.notMinified(contents);
96 | assert.hasPreamble(contents);
97 | assert.hasSourceMap(contents);
98 | assert.noCoverage(contents);
99 | assert.isBabelified(contents);
100 | });
101 |
102 | assert.fileContents("typescript/dist", "hello-world.min.js", (contents) => {
103 | assert.noBanner(contents);
104 | assert.hasMinifiedPreamble(contents);
105 | assert.isMinified(contents);
106 | assert.hasSourceMap(contents);
107 | assert.noCoverage(contents);
108 | assert.isBabelified(contents);
109 | });
110 |
111 | assert.fileContents("typescript/dist", "hello-world.coverage.js", (contents) => {
112 | assert.noBanner(contents);
113 | assert.hasMinifiedPreamble(contents);
114 | assert.isMinified(contents, true);
115 | assert.noSourceMap(contents);
116 | assert.hasCoverage(contents);
117 | assert.isBabelified(contents);
118 | });
119 |
120 | assert.fileContents("typescript/dist", ["hello-world.js.map", "hello-world.min.js.map"], (contents) => {
121 | expect(contents.sources).to.contain.members([
122 | "../src/hello-world.tsx",
123 | "../src/say/index.ts",
124 | ]);
125 | });
126 |
127 | done();
128 | });
129 | });
130 |
131 | it("should automatically enable TypeScript for all entry files that have a .ts or .tsx extenstion", (done) => {
132 | cli.run("typescript/src/**/*.ts* --bundle --minify --debug --coverage --outfile typescript/dist/", (err, stdout) => {
133 | if (err) {
134 | return done(err);
135 | }
136 |
137 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.js");
138 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.js.map");
139 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.min.js");
140 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.min.js.map");
141 | expect(stdout).to.contain("typescript/src/index.ts --> typescript/dist/index.coverage.js");
142 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.js");
143 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.js.map");
144 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.min.js");
145 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.min.js.map");
146 | expect(stdout).to.contain("typescript/src/hello-world.tsx --> typescript/dist/hello-world.coverage.js");
147 | expect(stdout).to.contain("typescript/src/say/index.ts --> typescript/dist/say/index.js");
148 | expect(stdout).to.contain("typescript/src/say/index.ts --> typescript/dist/say/index.js.map");
149 | expect(stdout).to.contain("typescript/src/say/index.ts --> typescript/dist/say/index.min.js");
150 | expect(stdout).to.contain("typescript/src/say/index.ts --> typescript/dist/say/index.min.js.map");
151 | expect(stdout).to.contain("typescript/src/say/index.ts --> typescript/dist/say/index.coverage.js");
152 |
153 | assert.directoryContents("typescript/dist", [
154 | "hello-world.coverage.js",
155 | "hello-world.js",
156 | "hello-world.js.map",
157 | "hello-world.min.js",
158 | "hello-world.min.js.map",
159 | "index.coverage.js",
160 | "index.js",
161 | "index.js.map",
162 | "index.min.js",
163 | "index.min.js.map",
164 | "say/index.coverage.js",
165 | "say/index.js",
166 | "say/index.js.map",
167 | "say/index.min.js",
168 | "say/index.min.js.map",
169 | ]);
170 |
171 | assert.fileContents("typescript/dist", ["index.js", "hello-world.js", "say/index.js"], (contents) => {
172 | assert.noBanner(contents);
173 | assert.notMinified(contents);
174 | assert.hasPreamble(contents);
175 | assert.hasSourceMap(contents);
176 | assert.noCoverage(contents);
177 | assert.isBabelified(contents);
178 | });
179 |
180 | assert.fileContents("typescript/dist", ["index.min.js", "hello-world.min.js", "say/index.min.js"], (contents) => {
181 | assert.noBanner(contents);
182 | assert.hasMinifiedPreamble(contents);
183 | assert.isMinified(contents);
184 | assert.hasSourceMap(contents);
185 | assert.noCoverage(contents);
186 | assert.isBabelified(contents);
187 | });
188 |
189 | assert.fileContents("typescript/dist", ["index.coverage.js", "hello-world.coverage.js", "say/index.coverage.js"], (contents) => {
190 | assert.noBanner(contents);
191 | assert.hasMinifiedPreamble(contents);
192 | assert.isMinified(contents, true);
193 | assert.noSourceMap(contents);
194 | assert.hasCoverage(contents);
195 | assert.isBabelified(contents);
196 | });
197 |
198 | assert.fileContents("typescript/dist", ["index.js.map", "index.min.js.map"], (contents) => {
199 | expect(contents.sources).to.contain.members([
200 | "../src/index.ts",
201 | "../src/hello-world.tsx",
202 | "../src/say/index.ts",
203 | ]);
204 | });
205 |
206 | assert.fileContents("typescript/dist", ["hello-world.js.map", "hello-world.min.js.map"], (contents) => {
207 | expect(contents.sources).to.contain.members([
208 | "../src/hello-world.tsx",
209 | "../src/say/index.ts",
210 | ]);
211 | });
212 |
213 | assert.fileContents("typescript/dist", ["say/index.js.map", "say/index.min.js.map"], (contents) => {
214 | expect(contents.sources).to.contain.members([
215 | "../../src/say/index.ts",
216 | ]);
217 | });
218 |
219 | done();
220 | });
221 | });
222 |
223 | it("should get TSify options from tsconfig.json", (done) => {
224 | cli.run("typescript-tsconfig/src/index.ts --bundle --minify --debug --coverage --outfile typescript-tsconfig/dist/", (err, stdout) => {
225 | if (err) {
226 | return done(err);
227 | }
228 |
229 | expect(stdout).to.contain("typescript-tsconfig/src/index.ts --> typescript-tsconfig/dist/index.js");
230 | expect(stdout).to.contain("typescript-tsconfig/src/index.ts --> typescript-tsconfig/dist/index.js.map");
231 | expect(stdout).to.contain("typescript-tsconfig/src/index.ts --> typescript-tsconfig/dist/index.min.js");
232 | expect(stdout).to.contain("typescript-tsconfig/src/index.ts --> typescript-tsconfig/dist/index.min.js.map");
233 | expect(stdout).to.contain("typescript-tsconfig/src/index.ts --> typescript-tsconfig/dist/index.coverage.js");
234 |
235 | assert.directoryContents("typescript-tsconfig/dist", [
236 | "index.js",
237 | "index.js.map",
238 | "index.min.js",
239 | "index.min.js.map",
240 | "index.coverage.js",
241 | ]);
242 |
243 | assert.fileContents("typescript-tsconfig/dist", "index.js", (contents) => {
244 | assert.noBanner(contents);
245 | assert.notMinified(contents);
246 | assert.hasPreamble(contents);
247 | assert.hasSourceMap(contents);
248 | assert.noCoverage(contents);
249 | assert.isBabelified(contents);
250 | });
251 |
252 | assert.fileContents("typescript-tsconfig/dist", "index.min.js", (contents) => {
253 | assert.noBanner(contents);
254 | assert.hasMinifiedPreamble(contents);
255 | assert.isMinified(contents);
256 | assert.hasSourceMap(contents);
257 | assert.noCoverage(contents);
258 | assert.isBabelified(contents);
259 | });
260 |
261 | assert.fileContents("typescript-tsconfig/dist", "index.coverage.js", (contents) => {
262 | assert.noBanner(contents);
263 | assert.hasMinifiedPreamble(contents);
264 | assert.isMinified(contents, true);
265 | assert.noSourceMap(contents);
266 | assert.hasCoverage(contents);
267 | assert.isBabelified(contents);
268 | });
269 |
270 | assert.fileContents("typescript-tsconfig/dist", ["index.js.map", "index.min.js.map"], (contents) => {
271 | expect(contents.sources).to.contain.members([
272 | "../src/hello-world.tsx",
273 | "../src/index.ts",
274 | "../src/say/index.ts"
275 | ]);
276 | });
277 |
278 | done();
279 | });
280 | });
281 |
282 | it("should get TSify options from package.json", (done) => {
283 | cli.run("typescript-options/src/index.ts --bundle --minify --debug --coverage --outfile typescript-options/dist/", (err, stdout) => {
284 | if (err) {
285 | return done(err);
286 | }
287 |
288 | expect(stdout).to.contain("typescript-options/src/index.ts --> typescript-options/dist/index.js");
289 | expect(stdout).to.contain("typescript-options/src/index.ts --> typescript-options/dist/index.js.map");
290 | expect(stdout).to.contain("typescript-options/src/index.ts --> typescript-options/dist/index.min.js");
291 | expect(stdout).to.contain("typescript-options/src/index.ts --> typescript-options/dist/index.min.js.map");
292 | expect(stdout).to.contain("typescript-options/src/index.ts --> typescript-options/dist/index.coverage.js");
293 |
294 | assert.directoryContents("typescript-options/dist", [
295 | "index.js",
296 | "index.js.map",
297 | "index.min.js",
298 | "index.min.js.map",
299 | "index.coverage.js",
300 | ]);
301 |
302 | assert.fileContents("typescript-options/dist", "index.js", (contents) => {
303 | assert.hasBanner(contents);
304 | assert.notMinified(contents);
305 | assert.hasPreamble(contents);
306 | assert.hasSourceMap(contents);
307 | assert.noCoverage(contents);
308 | assert.isBabelified(contents);
309 | });
310 |
311 | assert.fileContents("typescript-options/dist", "index.min.js", (contents) => {
312 | assert.hasBanner(contents);
313 | assert.hasMinifiedPreamble(contents);
314 | assert.isMinified(contents);
315 | assert.hasSourceMap(contents);
316 | assert.noCoverage(contents);
317 | assert.isBabelified(contents);
318 | });
319 |
320 | assert.fileContents("typescript-options/dist", "index.coverage.js", (contents) => {
321 | assert.hasBanner(contents);
322 | assert.hasMinifiedPreamble(contents);
323 | assert.isMinified(contents, true);
324 | assert.noSourceMap(contents);
325 | assert.hasCoverage(contents);
326 | assert.isBabelified(contents);
327 | });
328 |
329 | assert.fileContents("typescript-options/dist", ["index.js.map", "index.min.js.map"], (contents) => {
330 | expect(contents.sources).to.contain.members([
331 | "../src/hello-world.tsx",
332 | "../src/index.ts",
333 | "../src/say/index.ts"
334 | ]);
335 | });
336 |
337 | done();
338 | });
339 | });
340 |
341 | });
342 |
--------------------------------------------------------------------------------
/test/test-apps/error/error.js:
--------------------------------------------------------------------------------
1 | console.log('this is an error'))
2 |
--------------------------------------------------------------------------------
/test/test-apps/es5/hello-world.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es5/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es5/lib/hello-world.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var say = require('./say');
4 |
5 | /**
6 | * Says hello.
7 | *
8 | * @param {string} [name] - Who to say hello to
9 | */
10 | module.exports = function hello(name) {
11 | // This is NOT an important comment
12 | say('hello', name || 'world');
13 | };
14 |
--------------------------------------------------------------------------------
/test/test-apps/es5/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @preserve This is an important comment
5 | */
6 | module.exports = {
7 | say: require('./say'),
8 | hello: require('./hello-world')
9 | };
10 |
--------------------------------------------------------------------------------
/test/test-apps/es5/lib/say/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Says something to somebody.
5 | *
6 | * @param {string} what - What to say
7 | * @param {string} [who] - Who to say goodbye to
8 | */
9 | module.exports = function say(what, who) {
10 | //! This is an important comment
11 | // This is NOT an important comment
12 | console.log('%s, %s!', what, who);
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/test/test-apps/es5/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample-package",
3 | "version": "0.0.1",
4 | "main": "lib/index.js"
5 | }
6 |
--------------------------------------------------------------------------------
/test/test-apps/es5/say/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es6-with-options/hello-world.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es6-with-options/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es6-with-options/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample-package",
3 | "version": "0.0.1",
4 | "main": "lib/index.js",
5 | "browser": "src/index.js",
6 | "browserify": {
7 | "transform": [
8 | ["babelify", {
9 | "presets": ["@babel/preset-env"]
10 | }]
11 | ]
12 | },
13 | "devDependencies": {
14 | "@babel/preset-env": "^7.0.0",
15 | "babelify": "^10.0.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/test/test-apps/es6-with-options/say/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es6-with-options/src/hello-world.js:
--------------------------------------------------------------------------------
1 | import say from './say';
2 |
3 | /**
4 | * Says hello.
5 | *
6 | * @param {string} [name] - Who to say hello to
7 | */
8 | export default function hello(name) {
9 | // This is NOT an important comment
10 | let words = ['hello', name || world];
11 | say(...words);
12 | }
13 |
--------------------------------------------------------------------------------
/test/test-apps/es6-with-options/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve This is an important comment
3 | */
4 | import say from './say';
5 | import hello from './hello-world';
6 |
7 | export {say};
8 | export {hello};
9 |
--------------------------------------------------------------------------------
/test/test-apps/es6-with-options/src/say/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Says something to somebody.
3 | *
4 | * @param {string} what - What to say
5 | * @param {string} [who] - Who to say goodbye to
6 | */
7 | export default function say(what, who) {
8 | //! This is an important comment
9 | // This is NOT an important comment
10 | console.log(`${what} ${who}`);
11 | }
12 |
--------------------------------------------------------------------------------
/test/test-apps/es6/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/test/test-apps/es6/hello-world.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es6/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es6/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample-package",
3 | "version": "0.0.1",
4 | "main": "lib/index.js",
5 | "browser": "src/index.js",
6 | "browserify": {
7 | "transform": [
8 | ["babelify", {
9 | "presets": ["@babel/preset-env"]
10 | }]
11 | ]
12 | },
13 | "devDependencies": {
14 | "@babel/preset-env": "^7.0.0",
15 | "babelify": "^10.0.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/test/test-apps/es6/say/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/es6/src/hello-world.js:
--------------------------------------------------------------------------------
1 | import say from './say';
2 |
3 | /**
4 | * Says hello.
5 | *
6 | * @param {string} [name] - Who to say hello to
7 | */
8 | export default function hello(name) {
9 | // This is NOT an important comment
10 | let words = ['hello', name || world];
11 | say(...words);
12 | }
13 |
--------------------------------------------------------------------------------
/test/test-apps/es6/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve This is an important comment
3 | */
4 | import say from './say';
5 | import hello from './hello-world';
6 |
7 | export {say};
8 | export {hello};
9 |
--------------------------------------------------------------------------------
/test/test-apps/es6/src/say/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Says something to somebody.
3 | *
4 | * @param {string} what - What to say
5 | * @param {string} [who] - Who to say goodbye to
6 | */
7 | export default function say(what, who) {
8 | //! This is an important comment
9 | // This is NOT an important comment
10 | console.log(`${what} ${who}`);
11 | }
12 |
--------------------------------------------------------------------------------
/test/test-apps/hello/banner.txt:
--------------------------------------------------------------------------------
1 | <%= _.startCase(pkg.name) %> v<%= pkg.version %> (<%= moment().format('MMMM Do YYYY') %>)
2 | <%= pkg.description %>
3 |
4 | <%= pkg.homepage %>
5 |
6 | @author <%= pkg.author.name %> (<%= pkg.author.url %>)
7 | @license <%= pkg.license %>
8 |
--------------------------------------------------------------------------------
/test/test-apps/hello/hello-world.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var say = require('./say');
4 |
5 | /**
6 | * Says hello.
7 | *
8 | * @param {string} [name] - Who to say hello to
9 | */
10 | module.exports = function hello(name) {
11 | // This is NOT an important comment
12 | say('hello', name || 'world');
13 | };
14 |
--------------------------------------------------------------------------------
/test/test-apps/hello/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @preserve This is an important comment
5 | */
6 | module.exports = {
7 | say: require('./say'),
8 | hello: require('./hello-world')
9 | };
10 |
--------------------------------------------------------------------------------
/test/test-apps/hello/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hello-world",
3 | "version": "1.23.456",
4 | "main": "index.js",
5 | "description": "Says hello... to the whole world",
6 | "author": {
7 | "name": "John Doe",
8 | "url": "http://john-doe-software.com"
9 | },
10 | "license": "MIT",
11 | "homepage": "https://hello-world.com"
12 | }
13 |
--------------------------------------------------------------------------------
/test/test-apps/hello/say/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Says something to somebody.
5 | *
6 | * @param {string} what - What to say
7 | * @param {string} [who] - Who to say goodbye to
8 | */
9 | module.exports = function say(what, who) {
10 | //! This is an important comment
11 | // This is NOT an important comment
12 | console.log('%s, %s!', what, who);
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/test/test-apps/transform-options/hello-world.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/transform-options/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/transform-options/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample-package",
3 | "version": "0.0.1",
4 | "main": "lib/index.js",
5 | "browser": "src/index.js",
6 | "browserify": {
7 | "transform": [
8 | ["babelify", {
9 | "presets": ["@babel/preset-env"]
10 | }],
11 | ["uglifyify", {
12 | "mangle": false,
13 | "compress": false,
14 | "output": {
15 | "beautify": true,
16 | "indent_start": 2,
17 | "indent_level": 2,
18 | "quote_style": 1,
19 | "comments": true
20 | }
21 | }]
22 | ],
23 | "plugins": [
24 | ["browserify-banner", { "template": "<%= pkg.name %> v<%= pkg.version %>" }]
25 | ]
26 | },
27 | "devDependencies": {
28 | "@babel/preset-env": "^7.0.0",
29 | "babelify": "^10.0.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/test/test-apps/transform-options/say/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/transform-options/src/hello-world.js:
--------------------------------------------------------------------------------
1 | import say from './say';
2 |
3 | /**
4 | * Says hello.
5 | *
6 | * @param {string} [name] - Who to say hello to
7 | */
8 | export default function hello(name) {
9 | // This is NOT an important comment
10 | let words = ['hello', name || world];
11 | say(...words);
12 | }
13 |
--------------------------------------------------------------------------------
/test/test-apps/transform-options/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve This is an important comment
3 | */
4 | import say from './say';
5 | import hello from './hello-world';
6 |
7 | export {say};
8 | export {hello};
9 |
--------------------------------------------------------------------------------
/test/test-apps/transform-options/src/say/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Says something to somebody.
3 | *
4 | * @param {string} what - What to say
5 | * @param {string} [who] - Who to say goodbye to
6 | */
7 | export default function say(what, who) {
8 | //! This is an important comment
9 | // This is NOT an important comment
10 | console.log(`${what} ${who}`);
11 | }
12 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-error/error.ts:
--------------------------------------------------------------------------------
1 | // This is a syntax error because the "to" parameter doesn't have a type
2 | // and the "noImplicitAny" option is enabled in tsconfig.json
3 | function say(what: string, to): string {
4 | return `${what}, ${to}`;
5 | }
6 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-error/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "noImplicitAny": true
7 | },
8 | "include": [
9 | "*.ts"
10 | ],
11 | "exclude": [
12 | "node_modules"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/hello-world.tsx:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/index.ts:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample-package",
3 | "version": "0.0.1",
4 | "main": "lib/index.js",
5 | "browser": "src/index.js",
6 | "browserify": {
7 | "plugins": [
8 | ["browserify-banner", { "template": "<%= pkg.name %> v<%= pkg.version %>" }],
9 | ["tsify", {
10 | "target": "esnext",
11 | "module": "commonjs",
12 | "moduleResolution": "node",
13 | "jsx": "react"
14 | }]
15 | ]
16 | },
17 | "devDependencies": {
18 | "@babel/preset-env": "^7.0.0",
19 | "babelify": "^10.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/say/index.ts:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/src/hello-world.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import say from './say';
3 |
4 | /**
5 | * Says hello.
6 | *
7 | * @param {string} [name] - Who to say hello to
8 | */
9 | export function Hello(name: string = 'world') {
10 | // This is NOT an important comment
11 | let hello = say('hello', name);
12 | return {hello}
;
13 | }
14 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/src/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve This is an important comment
3 | */
4 | export { Hello } from './hello-world';
5 | export * from './say';
6 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-options/src/say/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Says something to somebody.
3 | *
4 | * @param {string} [what] - What to say
5 | * @param {string} [who] - Who to say it to
6 | */
7 | export default function say(what: string, who: string): string {
8 | //! This is an important comment
9 | // This is NOT an important comment
10 | return `${what} ${who}`;
11 | }
12 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/hello-world.tsx:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/index.ts:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/say/index.ts:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/src/hello-world.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import say from './say';
3 |
4 | /**
5 | * Says hello.
6 | *
7 | * @param {string} [name] - Who to say hello to
8 | */
9 | export function Hello(name: string = 'world') {
10 | // This is NOT an important comment
11 | let hello = say('hello', name);
12 | return {hello}
;
13 | }
14 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/src/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve This is an important comment
3 | */
4 | export { Hello } from './hello-world';
5 | export * from './say';
6 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/src/say/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Says something to somebody.
3 | *
4 | * @param {string} [what] - What to say
5 | * @param {string} [who] - Who to say it to
6 | */
7 | export default function say(what: string, who: string): string {
8 | //! This is an important comment
9 | // This is NOT an important comment
10 | return `${what} ${who}`;
11 | }
12 |
--------------------------------------------------------------------------------
/test/test-apps/typescript-tsconfig/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "jsx": "react"
7 | },
8 | "include": [
9 | "src/**/*.ts",
10 | "src/**/*.tsx"
11 | ],
12 | "exclude": [
13 | "node_modules"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/test/test-apps/typescript/hello-world.tsx:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript/index.ts:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript/say/index.ts:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript/src/hello-world.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import say from './say';
3 |
4 | /**
5 | * Says hello.
6 | *
7 | * @param {string} [name] - Who to say hello to
8 | */
9 | export function Hello(name: string = 'world') {
10 | // This is NOT an important comment
11 | let hello = say('hello', name);
12 | return {hello}
;
13 | }
14 |
--------------------------------------------------------------------------------
/test/test-apps/typescript/src/index.js:
--------------------------------------------------------------------------------
1 | If simplifyify's glob patterns are working properly,
2 | this file will NOT be included in the bundle
3 |
--------------------------------------------------------------------------------
/test/test-apps/typescript/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve This is an important comment
3 | */
4 | export { Hello } from './hello-world';
5 | export * from './say';
6 |
--------------------------------------------------------------------------------
/test/test-apps/typescript/src/say/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Says something to somebody.
3 | *
4 | * @param {string} [what] - What to say
5 | * @param {string} [who] - Who to say it to
6 | */
7 | export default function say(what: string, who: string): string {
8 | //! This is an important comment
9 | // This is NOT an important comment
10 | return `${what} ${who}`;
11 | }
12 |
--------------------------------------------------------------------------------
/test/test-apps/universal-lib/banner.txt:
--------------------------------------------------------------------------------
1 | <%= _.startCase(pkg.name) %> v<%= pkg.version %> (<%= moment().format('MMMM Do YYYY') %>)
2 |
3 | <%= pkg.homepage %>
4 |
5 | @author <%= pkg.author.name %> (<%= pkg.author.url %>)
6 | @license <%= pkg.license %>
7 |
--------------------------------------------------------------------------------
/test/test-apps/universal-lib/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "universal-lib",
3 | "main": "dist/universal-lib.js",
4 | "description": "A JavaScript library for Node.js and web browsers",
5 | "author": {
6 | "name": "John Doe",
7 | "url": "http://john-doe-software.com"
8 | },
9 | "license": "MIT",
10 | "homepage": "https://hello-world.com"
11 | }
12 |
--------------------------------------------------------------------------------
/test/test-apps/universal-lib/lib/browser.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var resolve = require('./resolve');
4 | var cwd = getCurrentDirectory();
5 |
6 | module.exports = {
7 | resolve: resolve.bind(null, cwd),
8 | };
9 |
10 | /**
11 | * Gets the current directory in the web browser.
12 | *
13 | * @returns {string}
14 | */
15 | function getCurrentDirectory () {
16 | var path = location.href;
17 | var segments = path.split('/');
18 | var lastSegment = segments[segments.length - 1];
19 |
20 | if (/\.\w+$/.test(lastSegment)) {
21 | // The URL is a file path (e.g. "http://example.com/dir/index.html")
22 | // So return all but the last segment (e.g. "http://example.com/dir/")
23 | segments.pop();
24 | return segments.join('/') + '/';
25 | }
26 | else {
27 | // The URL is a directory path (e.g. "http://example.com/dir")
28 | if (path[path.length - 1] === '/') {
29 | return path;
30 | }
31 | else {
32 | return path + '/';
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/test/test-apps/universal-lib/lib/node.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var resolve = require('./resolve');
4 | var cwd = process.cwd() + '/';
5 |
6 | module.exports = {
7 | resolve: resolve.bind(null, cwd),
8 | };
9 |
--------------------------------------------------------------------------------
/test/test-apps/universal-lib/lib/resolve.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = resolve;
4 |
5 | /**
6 | * Resolves a relative path to an absolute path
7 | *
8 | * @param {string} cwd - The current directory path (absolute)
9 | * @param {string} path - The relative path to resolve
10 | * @returns {string}
11 | */
12 | function resolve (cwd, path) {
13 | //! This is an important comment
14 | // This is NOT an important comment
15 | return cwd + path;
16 | }
17 |
--------------------------------------------------------------------------------
/test/test-apps/universal-lib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "universal-lib",
3 | "version": "1.23.456",
4 | "main": "lib/index.js",
5 | "browser": "dist/universal-lib.js",
6 | "description": "A JavaScript library for Node.js and web browsers",
7 | "author": {
8 | "name": "John Doe",
9 | "url": "http://john-doe-software.com"
10 | },
11 | "license": "MIT",
12 | "homepage": "https://hello-world.com"
13 | }
14 |
--------------------------------------------------------------------------------