├── .eslintignore
├── .eslintrc.js
├── .github
├── CONTRIBUTING.md
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── chore.md
│ ├── feature_request.md
│ └── question.md
├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── bin
└── index.js
├── docs
├── .nojekyll
├── README.md
├── index.html
└── reset.css
├── example
├── package.json
└── src
│ ├── App.svelte
│ ├── index.html
│ └── index.js
├── lib
├── __tests__
│ └── inititalize.test.js
├── build.js
├── constants.js
├── development.js
├── index.js
├── initialize.js
├── modules
│ └── template
│ │ ├── __tests__
│ │ ├── get-template-contents.test.js
│ │ ├── markup.test.js
│ │ ├── read-template.test.js
│ │ ├── report-template-usage.test.js
│ │ └── write-template.test.js
│ │ ├── compile.js
│ │ ├── get-template-contents.js
│ │ ├── index.js
│ │ ├── markup.js
│ │ ├── read-template.js
│ │ ├── report-template-usage.js
│ │ └── write-template.js
├── rollup.js
├── templates
│ └── template.html
└── utils
│ ├── __tests__
│ ├── argument.test.js
│ ├── get-days-in-ms.test.js
│ ├── path-cwd-resolve.test.js
│ └── warn.test.js
│ ├── ensure-argument.js
│ ├── fs.js
│ ├── get-days-in-ms.js
│ ├── path-cwd-resolve.js
│ └── warn.js
├── package.json
└── yarn.lock
/.eslintignore:
--------------------------------------------------------------------------------
1 | coverage/
2 | docs/
3 | node_modules/
4 | example/
5 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | node: true
4 | },
5 | parserOptions: {
6 | ecmaVersion: 2020,
7 | sourceType: 'module'
8 | },
9 | extends: [
10 | 'himynameisdave/configurations/node'
11 | ],
12 | rules: {
13 | 'no-console': 'off',
14 | 'object-property-newline': ['error', { allowAllPropertiesOnSameLine: false }],
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | Thanks for taking the time to contribute to `svb`!!! 🎉 👌 💪
4 |
5 | Feel free to [file issues](https://github.com/himynameisdave/svb/issues/new) if you encounter any bugs, or if you have a good idea for a new feature. Try to include as much information as possible, including details about what versions of Node and this package that you are using.
6 |
7 | If you're feeling more adventurous, a [pull request](https://github.com/himynameisdave/svb/compare) would be very welcomed! In lieu of a formal style, please try to maintain clean code, and include unit tests to cover any new functionality you are adding.
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: "\U0001F41B Help us squash bugs"
4 | title: ''
5 | labels: 'Status: Todo, Type: Bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Versions (please complete the following information):**
27 | - OS: [e.g. macOS 10.14.5]
28 | - `svb` Version: [eg: `0.1.0`]
29 | - NodeJS Version: [eg: `v12.5.0`]
30 |
31 | **Additional context or comments**
32 | Add any other context about the problem here.
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/chore.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Chore
3 | about: "\U0001F3D7 A chore that needs to be done"
4 | title: ''
5 | labels: 'Status: Todo, Type: Chore'
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe what needs to be done**
11 | - [eg: "Fix travis.yml config"]
12 |
13 | **Are there any dependency updates?**
14 | - [eg: "Bump svelte version"]
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: "✨ Suggest new features"
4 | title: ''
5 | labels: 'Type: Feature, Status: Todo'
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: "❓ Question about this project"
4 | title: ''
5 | labels: 'Status: Todo, Type: Question'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # dotenv environment variables file
2 | .env
3 |
4 | # Dependency directories
5 | node_modules/
6 |
7 | # macos annoyance
8 | *.DS_Store
9 |
10 | # Logs
11 | logs
12 | *.log
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 |
17 | # Runtime data
18 | pids
19 | *.pid
20 | *.seed
21 | *.pid.lock
22 |
23 | # Directory for instrumented libs generated by jscoverage/JSCover
24 | lib-cov
25 |
26 | # Coverage directory used by tools like istanbul
27 | coverage
28 |
29 | # TypeScript v1 declaration files
30 | typings/
31 |
32 | # Optional npm cache directory
33 | .npm
34 |
35 | # Optional eslint cache
36 | .eslintcache
37 |
38 | # Optional REPL history
39 | .node_repl_history
40 |
41 | # Output of 'npm pack'
42 | *.tgz
43 |
44 | # Yarn Integrity file
45 | .yarn-integrity
46 |
47 | # Hide stuff in examples
48 | example/yarn.lock
49 | example/dist/
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .github/
2 | coverage/
3 | docs/
4 | example/
5 | node_modules/
6 | *__tests__**/*
7 | .travis.yml
8 | .eslintignore
9 | .eslintrc.js
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8"
4 | - "10"
5 | - "12"
6 | after_success:
7 | - npm run coverage:report
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Dave Lunny
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
svelte-bundler
3 |
📦 A zero-config CLI to bundle Svelte apps.
4 |
18 |
19 |
20 | ---
21 |
22 | This is a (mildly) opinionated and very lightweight Svelte compiler/bundler, which is meant to take some of the headaches out of setting up and configuring simple [Svelte](https://svelte.dev/) projects.
23 |
24 | Differs from [Sapper](https://sapper.svelte.dev), which is more of a fully baked solution which includes SSR, routing and other goodies. This is more akin to the [react-scripts](https://github.com/facebook/create-react-app/tree/master/packages/react-scripts) used in `create-react-app`, where all of the config is hidden away so that you can just focus on building cool Svelte apps.
25 |
26 | **Notice:** This is very much a work in progress right now, so [feel free to contribute](https://github.com/himynameisdave/svb/blob/master/.github/CONTRIBUTING.md)! We'd love to get some feedback and ideas!
27 |
28 | ### Installation
29 |
30 | > _**Note:** Currently requires NodeJS >= 8.16.0_
31 |
32 | ```
33 | yarn add -D svb
34 |
35 | npm i -D svb
36 | ```
37 |
38 | You could also install this globally:
39 |
40 | ```
41 | yarn global add svb
42 |
43 | npm i -g svb
44 | ```
45 |
46 | This provides you with the global `svb` binary (as well as a `svelte-bundler` alias, in case you like typing).
47 |
48 |
49 | ### Documentation
50 |
51 | Please view [the documentation here](https://himynameisdave.github.io/svb/#/)!
52 |
53 | ---
54 |
55 | _Created by [Dave](http://himynameisdave.com) in 2019 ✌️_
56 |
--------------------------------------------------------------------------------
/bin/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | require('../lib')();
4 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/himynameisdave/svb/757b85d1186de49854fd8cde17fe1cdf38bd63c1/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 |
2 |
svelte-bundler
3 |
📦 A zero-config CLI to bundle Svelte apps.
4 |
18 |
19 |
20 | ---
21 |
22 | This is a (mildly) opinionated and very lightweight Svelte compiler/bundler, which is meant to take some of the headaches out of setting up and configuring simple [Svelte](https://svelte.dev/) projects.
23 |
24 | Differs from [Sapper](https://sapper.svelte.dev), which is more of a fully baked solution which includes SSR, routing and other goodies. This is more akin to the [react-scripts](https://github.com/facebook/create-react-app/tree/master/packages/react-scripts) used in `create-react-app`, where all of the config is hidden away so that you can just focus on building cool Svelte apps.
25 |
26 | **Notice:** This is very much a work in progress right now, so [feel free to contribute](https://github.com/himynameisdave/svb/blob/master/.github/CONTRIBUTING.md)! We'd love to get some feedback and ideas!
27 |
28 | ### Features
29 |
30 | - 📄 *Zero-config*, don't ya worry, we'll take care of that.
31 | - 👀 *Watch/dev mode*, with livereloading.
32 | - 🗺 *Sourcemaps*, for easier debugging.
33 |
34 | ## Installation
35 |
36 | > _**Note:** Currently requires NodeJS >= 8.16.0_
37 |
38 | ```
39 | yarn add -D svb
40 |
41 | npm i -D svb
42 | ```
43 |
44 | You could also install this globally:
45 |
46 | ```
47 | yarn global add svb
48 |
49 | npm i -g svb
50 | ```
51 |
52 | This provides you with the global `svb` binary (as well as a `svelte-bundler` alias, in case you like typing).
53 |
54 | ## Usage
55 |
56 | ### Building
57 |
58 | The `svb` command allows you to bundle your Svelte apps. Most likely you will have this package installed in your `devDependencies`, and then include some kind of [npm script](https://css-tricks.com/why-npm-scripts/) which uses it, like so:
59 |
60 | ```json
61 | {
62 | "build": "svb --input src/index.js --output dist/"
63 | }
64 | ```
65 |
66 | You'd then do one of the following to compile your project:
67 |
68 | ```bash
69 | npm run build
70 | yarn run build
71 | ```
72 |
73 | Here's an example using npx instead:
74 |
75 | ```bash
76 | npx svb -i src/index.js -o dist/
77 | ```
78 |
79 | ### Options
80 |
81 | ```
82 | Options:
83 | -i, --input Index/root file to be compiled
84 | -o, --output Bundled file path/name
85 | ```
86 |
87 | An example of what a project might look like can be [found here](https://github.com/himynameisdave/svb/tree/master/example). This is an overview:
88 |
89 | ```
90 | my-svelte-app/
91 | |- package.json
92 | |- dist/
93 | # Your compiled project
94 | |- src/
95 | |- App.svelte
96 | |- index.js
97 | |- index.html
98 | ```
99 |
100 | ### HTML Template
101 |
102 | `svb` will by default output a standard/bare bones `index.html` file for you. If you wish, you can customize this by including an `index.html` (or `template.html`) file in the src directory of your project, next to your `--input` file.
103 |
104 | You can customize where `svb` injects the JS bundle and CSS stylesheets by using the following tags:
105 |
106 | ```
107 | {SVB.js}
108 | {SVB.css}
109 | ```
110 |
111 | Example:
112 |
113 | ```html
114 |
115 |
116 |
117 | My App
118 | {SVB.css}
119 |
120 |
121 | {SVB.js}
122 |
123 |
124 | ```
125 |
126 | ## Project
127 |
128 | ### Goals
129 |
130 | Three main goals for this project:
131 |
132 | - Simplify Svelte projects; provide a solid default for building apps.
133 | - Remain lightweight; this is not [Sapper](https://sapper.svelte.dev).
134 | - Simple to use; [don't make users think](https://en.wikipedia.org/wiki/Don't_Make_Me_Think)!
135 |
136 | ### Roadmap
137 |
138 | This is a work in progress/the project is still in beta. Here's some stuff that we want to add/take care of:
139 |
140 | - [x] Handle generation of a root `index.html` file ([#13](https://github.com/himynameisdave/svb/issues/13))
141 | - [x] Watch/dev mode ([#4](https://github.com/himynameisdave/svb/issues/4))
142 | - [x] Sourcemaps ([#15](https://github.com/himynameisdave/svb/issues/15))
143 | - [ ] ~Allow some more custom configuration of rollup~ This isn't aligned with the goals of this project.
144 | - [ ] _Maybe_ add some kind of `eject` command, allow users to bump out if they choose. ([#18](https://github.com/himynameisdave/svb/issues/18))
145 |
146 | Follow this project's [progress here](https://github.com/himynameisdave/svb/projects/1?fullscreen=true)! We hope to release a v1 soon!
147 |
148 | ### Contributing
149 |
150 | We gladly welcome new issues and pull requests. Please see the [Contributing Guide](https://github.com/himynameisdave/svb/blob/master/.github/CONTRIBUTING.md) for more info!
151 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | svb - 📦 A zero-config CLI to bundle Svelte apps
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
24 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/docs/reset.css:
--------------------------------------------------------------------------------
1 | * {
2 | font-family: 'Lexend Deca', sans-serif;
3 | }
4 |
5 | html,
6 | body {
7 | background-color: #3f3f3f;
8 | }
9 |
10 | hr,
11 | .markdown-section hr {
12 | border-bottom: 1px solid #ea6f5a;
13 | }
14 |
15 | @keyframes loading-dot {
16 | 0% {
17 | opacity: .4;
18 | transform: scale(1, 1);
19 | }
20 |
21 | 50% {
22 | opacity: 1;
23 | transform: scale(1.2, 1.2);
24 | }
25 |
26 | 100% {
27 | opacity: .4;
28 | transform: scale(1, 1);
29 | }
30 | }
31 |
32 | .loading {
33 | margin: 2rem 0;
34 | text-align: center;
35 | width: 100%;
36 | }
37 |
38 | .loading__dot {
39 | animation: loading-dot 1.5s infinite ease-in-out;
40 | background-color: #ea6f5a;
41 | border-radius: 30px;
42 | display: inline-block;
43 | height: 30px;
44 | width: 30px;
45 | }
46 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "my-app",
4 | "scripts": {
5 | "build": "svb --input src/index.js --output dist/",
6 | "dev": "svb --input src/index.js --output dist/ --watch"
7 | },
8 | "dependencies": {
9 | "svb": "*",
10 | "svelte": "*"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/example/src/App.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
32 |
33 |
34 |
Sample SVB App
35 | Behold, the almighty counter app!
36 | The count is currently {count}!
37 |
38 | Increment
39 |
40 |
41 | Decrement
42 |
43 |
44 |
--------------------------------------------------------------------------------
/example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | My Svelte App
7 |
8 |
9 | {SVB.css}
10 |
11 |
12 | {SVB.js}
13 |
14 |
--------------------------------------------------------------------------------
/example/src/index.js:
--------------------------------------------------------------------------------
1 | import App from './App.svelte';
2 |
3 |
4 | const app = new App({
5 | target: document.body,
6 | });
7 |
8 | export default app;
9 |
--------------------------------------------------------------------------------
/lib/__tests__/inititalize.test.js:
--------------------------------------------------------------------------------
1 | const commander = require('commander');
2 | const updateNotifier = require('update-notifier');
3 |
4 | const initialize = require('../initialize.js');
5 |
6 |
7 | jest.mock('commander');
8 | jest.mock('update-notifier');
9 |
10 | describe('initialize', () => {
11 | const mockNotify = jest.fn();
12 | beforeEach(() => {
13 | updateNotifier.mockImplementation(() => ({
14 | notify: mockNotify,
15 | }));
16 | const getOption = (parse = () => { }) => () => ({
17 | option: getOption(),
18 | parse,
19 | });
20 | commander.version.mockReturnValue({
21 | option: getOption(),
22 | });
23 | });
24 | it('calls the update notifier', () => {
25 | initialize();
26 | expect(mockNotify).toHaveBeenCalledTimes(1);
27 | });
28 | // TODO [>=1]: also assert that it calls commander...
29 | });
30 |
--------------------------------------------------------------------------------
/lib/build.js:
--------------------------------------------------------------------------------
1 | const rollup = require('rollup');
2 |
3 | const {
4 | getInputConfig,
5 | getOutputConfig,
6 | } = require('./rollup.js');
7 | const template = require('./modules/template');
8 |
9 |
10 | const build = async ({
11 | input, output, isDevelopmentMode,
12 | }) => {
13 | // Handle the index.html stuff
14 | await template({
15 | input,
16 | output,
17 | });
18 | const bundle = await rollup.rollup(
19 | await getInputConfig({
20 | input,
21 | output,
22 | isDevelopmentMode,
23 | }),
24 | );
25 | return bundle.write(
26 | getOutputConfig({
27 | input,
28 | output,
29 | isDevelopmentMode,
30 | }),
31 | );
32 |
33 | };
34 |
35 | module.exports = build;
36 |
--------------------------------------------------------------------------------
/lib/constants.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | HTML_TEMPLATE_NAMES: ['index.html', 'template.html'],
3 | DEFAULT_TEMPLATE_PATH: '../../templates/template.html',
4 | BUNDLE_FILENAME: {
5 | CSS: 'bundle.css',
6 | JS: 'index.js',
7 | },
8 | HTML_OUTPUT_INDEX: 'index.html',
9 | };
10 |
--------------------------------------------------------------------------------
/lib/development.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const rollup = require('rollup');
4 | const clear = require('console-clear');
5 | const chalk = require('chalk');
6 |
7 | const {
8 | getInputConfig,
9 | getOutputConfig,
10 | } = require('./rollup.js');
11 | const pathCwdResolve = require('./utils/path-cwd-resolve.js');
12 | const template = require('./modules/template');
13 |
14 |
15 | const logger = (string) => console.log(`\n\n${string}`);
16 |
17 | const watchHandlers = {
18 | START: () => logger(chalk.yellow('📦 Bundling your Svelte app!')),
19 | END: () => logger(chalk.green('⚡️ Bundled your Svelte app!')),
20 | ERROR: ({ error }) => logger(chalk.red(`Error: ️${error.message}!\n${error.frame}`)),
21 | };
22 |
23 | const watch = async ({
24 | input,
25 | output,
26 | isDevelopmentMode,
27 | }) => {
28 | const inputFolder = path.dirname(input);
29 | const config = {
30 | ...await getInputConfig({
31 | input,
32 | output,
33 | isDevelopmentMode,
34 | }),
35 | output: getOutputConfig({
36 | output,
37 | }),
38 | watch: {
39 | chokidar: {
40 | cwd: process.cwd(),
41 | paths: [
42 | `${inputFolder}/**`,
43 | `${inputFolder}/*.html`,
44 | ],
45 | },
46 | clearScreen: true,
47 | exclude: ['node_modules/**'],
48 | // paths:
49 | },
50 | };
51 |
52 | // Initial template build
53 | template({
54 | input,
55 | output,
56 | });
57 |
58 | const watcher = rollup.watch(config);
59 | watcher.on('change', (changedPath) => {
60 | /**
61 | * TODO [2019-10-01]: tech-debt This runs on every change event, which is not desirable
62 | * This is not desirable.
63 | *
64 | */
65 | template({
66 | input,
67 | output,
68 | });
69 | // TODO [2019-10-10]: More logs if --debug mode?
70 | clear(true);
71 | logger(chalk.yellow(`📦 ${changedPath} changed!`));
72 | });
73 |
74 | };
75 |
76 | module.exports = watch;
77 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | // Core
2 | const { mkdirp } = require('fs-extra');
3 |
4 | const init = require('./initialize.js');
5 | const build = require('./build.js');
6 | const development = require('./development.js');
7 | // Utils
8 | const ensureArg = require('./utils/ensure-argument.js');
9 | const pathCwdResolve = require('./utils/path-cwd-resolve.js');
10 | const warn = require('./utils/warn.js');
11 |
12 |
13 | const main = async () => {
14 | const {
15 | input,
16 | output,
17 | watch,
18 | } = init();
19 | const config = {
20 | input: pathCwdResolve(input),
21 | output: pathCwdResolve(output),
22 | isDevelopmentMode: !!watch,
23 | };
24 | // Ensure the user has provided the arguments
25 | ensureArg(input, 'input');
26 | ensureArg(output, 'output');
27 |
28 | // Create the output directory
29 | await mkdirp(config.output);
30 |
31 | try {
32 | return config.isDevelopmentMode
33 | ? development(config)
34 | : build(config);
35 | } catch (error) {
36 | warn(error.message, error);
37 | process.exit(1);
38 | }
39 | };
40 |
41 | module.exports = main;
42 |
--------------------------------------------------------------------------------
/lib/initialize.js:
--------------------------------------------------------------------------------
1 | const commander = require('commander');
2 | const updateNotifier = require('update-notifier');
3 |
4 | const pkg = require('../package.json');
5 |
6 | const getDaysInMS = require('./utils/get-days-in-ms.js');
7 |
8 | /**
9 | * Initializes the program, by doing two things:
10 | * 1. Running updateNotifier
11 | * 2. Setting up commander and return the `program`
12 | */
13 | const initialize = () => {
14 | // Update user if newer version exists
15 | updateNotifier({
16 | pkg,
17 | updateCheckInterval: getDaysInMS(4),
18 | }).notify();
19 |
20 | return (
21 | commander
22 | .version(pkg.version, '-v, --version')
23 | .option('-i, --input ', 'Index/root file to be compiled')
24 | .option('-o, --output ', 'Bundled file path/name')
25 | .option('-w, --watch', 'Run in dev/watch mode')
26 | .parse(process.argv)
27 | );
28 | };
29 |
30 | module.exports = initialize;
31 |
--------------------------------------------------------------------------------
/lib/modules/template/__tests__/get-template-contents.test.js:
--------------------------------------------------------------------------------
1 | const getTemplateContents = require('../get-template-contents.js');
2 | const reportTemplateUsage = require('../report-template-usage.js');
3 | const readTemplate = require('../read-template.js');
4 | const { read } = require('../../../utils/fs.js');
5 | const { HTML_TEMPLATE_NAMES } = require('../../../constants.js');
6 |
7 |
8 | jest.mock('../../../utils/fs.js');
9 | jest.mock('../read-template.js');
10 | jest.mock('../report-template-usage.js');
11 | reportTemplateUsage.mockImplementation(() => { });
12 | jest.spyOn(console, 'log').mockImplementation(() => { });
13 |
14 | describe('modules/template/getTemplateContents', () => {
15 | const mockTemplateContents = 'Custom Template';
16 | describe('when a valid html template is provided', () => {
17 | const mockFileName = HTML_TEMPLATE_NAMES[0];
18 | it('should return the contents of the template file', async () => {
19 | readTemplate.mockImplementationOnce(() => Promise.resolve({
20 | contents: mockTemplateContents,
21 | fileName: mockFileName,
22 | }));
23 | const actual = await getTemplateContents('some/input/path/');
24 | expect(actual).toBe(mockTemplateContents);
25 | });
26 | });
27 | describe('when a no valid html template is provided', () => {
28 | it('should return the contents of the default template', async () => {
29 | readTemplate.mockImplementation(() => Promise.resolve({
30 | error: 'Ya done goofed!',
31 | }));
32 | read.mockImplementationOnce(() => Promise.resolve(mockTemplateContents));
33 | const actual = await getTemplateContents('some/input/path/');
34 | expect(actual).toBe(mockTemplateContents);
35 | });
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/lib/modules/template/__tests__/markup.test.js:
--------------------------------------------------------------------------------
1 | const {
2 | getCSS,
3 | getJS,
4 | } = require('../markup.js');
5 |
6 |
7 | describe('modules/template/markup', () => {
8 | describe('getCSS', () => {
9 | it('should return expected CSS tag', () => {
10 | const mockFileName = 'bundle.css';
11 | const expected = ` `;
12 | expect(getCSS(mockFileName)).toBe(expected);
13 | });
14 | });
15 | describe('getJS', () => {
16 | it('should return expected JS tag', () => {
17 | const mockFileName = 'bundle.js';
18 | const expected = ``;
19 | expect(getJS(mockFileName)).toBe(expected);
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/lib/modules/template/__tests__/read-template.test.js:
--------------------------------------------------------------------------------
1 | const readTemplate = require('../read-template.js');
2 | const { read } = require('../../../utils/fs.js');
3 |
4 |
5 | jest.mock('../../../utils/fs.js');
6 |
7 |
8 | describe('modules/template/readTemplate', () => {
9 | const mockFilename = 'some-template.html';
10 | it('should return an contents and fileName', async () => {
11 | const mockTemplateContents = 'template contents';
12 | read.mockImplementationOnce(() => Promise.resolve(mockTemplateContents));
13 | const results = await readTemplate(mockFilename);
14 | expect(results).toHaveProperty('contents', mockTemplateContents);
15 | expect(results).toHaveProperty('fileName', mockFilename);
16 | });
17 | it('should return an error if reading template fails', async () => {
18 | const error = 'Ya done goofed!';
19 | read.mockImplementationOnce(() => Promise.reject(new Error(error)));
20 | const results = await readTemplate(mockFilename);
21 | expect(results).toHaveProperty('error');
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/lib/modules/template/__tests__/report-template-usage.test.js:
--------------------------------------------------------------------------------
1 | const reportTemplateUsage = require('../report-template-usage.js');
2 |
3 |
4 | describe('modules/template/reportTemplateUsage', () => {
5 | jest.spyOn(console, 'log').mockImplementation(() => { });
6 | describe('when hasTemplate is true', () => {
7 | const hasTemplate = true;
8 | it('logs the template which we are using', () => {
9 | const mockFileName = 'template.html';
10 | reportTemplateUsage(hasTemplate, mockFileName);
11 | expect(console.log).toHaveBeenCalledWith(`📄 Using ${mockFileName} template`);
12 | });
13 | it('falls back to saying "Using the provided template" if no filename is provided', () => {
14 | reportTemplateUsage(hasTemplate);
15 | expect(console.log).toHaveBeenCalledWith('📄 Using the provided template');
16 | });
17 | });
18 | describe('when hasTemplate is false', () => {
19 | const hasTemplate = false;
20 | it('logs that the default template is being used instead', () => {
21 | reportTemplateUsage(hasTemplate);
22 | expect(console.log).toHaveBeenCalledWith('📄 Using the default HTML template instead');
23 | });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/lib/modules/template/__tests__/write-template.test.js:
--------------------------------------------------------------------------------
1 | const writeTemplate = require('../write-template.js');
2 | const { write } = require('../../../utils/fs.js');
3 |
4 |
5 | const mockBasePath = 'absolute/path/';
6 |
7 | jest.mock('../../../utils/fs.js');
8 | jest.mock('../../../utils/path-cwd-resolve.js', () => (path) => `${mockBasePath}${path}`); // eslint-disable-line unicorn/consistent-function-scoping
9 |
10 |
11 | describe('modules/template/writeTemplate', () => {
12 | it('calls write with the correct path & data', async () => {
13 | write.mockImplementationOnce(() => Promise.resolve());
14 | const mockOutput = 'some/dist/path';
15 | const mockCompiled = 'some compiled stuff';
16 | await writeTemplate({
17 | output: mockOutput,
18 | compiled: mockCompiled,
19 | });
20 | expect(write).toHaveBeenCalledWith(`${mockBasePath}${mockOutput}`, mockCompiled);
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/lib/modules/template/compile.js:
--------------------------------------------------------------------------------
1 | const pupa = require('pupa');
2 | const { minify } = require('html-minifier');
3 |
4 | // Local
5 | const { BUNDLE_FILENAME } = require('../../constants.js');
6 |
7 | const markup = require('./markup.js');
8 | // Constants
9 |
10 | // Options for html-minify package
11 | // https://github.com/kangax/html-minifier#options-quick-reference
12 | const MINIFY_OPTIONS = {
13 | collapseBooleanAttributes: true,
14 | collapseWhitespace: true,
15 | minifyCSS: true,
16 | minifyJS: true,
17 | removeComments: true,
18 | sortAttributes: true,
19 | sortClassName: true,
20 | useShortDoctype: true,
21 | };
22 |
23 | /**
24 | * Responsible for compiling and minifying the template HTML
25 | *
26 | * @param {object} props
27 | * @param {object} props.title An optional title for the app
28 | * @param {string} props.template The template HTML string
29 | */
30 | const compile = ({
31 | title = 'My App', template,
32 | }) => {
33 | const compiledTemplate = pupa(template, {
34 | SVB: {
35 | title,
36 | css: markup.getCSS(BUNDLE_FILENAME.CSS),
37 | js: markup.getJS(BUNDLE_FILENAME.JS),
38 | },
39 | });
40 | return minify(compiledTemplate, MINIFY_OPTIONS);
41 | };
42 |
43 | module.exports = compile;
44 |
--------------------------------------------------------------------------------
/lib/modules/template/get-template-contents.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | // Local
4 | // Utils
5 | const { read } = require('../../utils/fs.js');
6 | const pathCwdResolve = require('../../utils/path-cwd-resolve.js');
7 | // Constants
8 | const {
9 | HTML_TEMPLATE_NAMES,
10 | DEFAULT_TEMPLATE_PATH,
11 | } = require('../../constants.js');
12 |
13 | const readTemplate = require('./read-template.js');
14 | const reportTemplateUsage = require('./report-template-usage.js');
15 |
16 |
17 | /**
18 | * Resolves the HTML template contents, either provided by the user,
19 | * or generated based on our template.
20 | *
21 | * @param {string} inputFolder The folder path of the input JS file (from path.dirname())
22 | */
23 | const getTemplateContents = async (inputFolder = '') => { // TODO [>=0.5.0]: have a better/different default here
24 | const readTemplatesResults = await Promise.all(
25 | HTML_TEMPLATE_NAMES.map((templateName) => readTemplate(
26 | pathCwdResolve(inputFolder, templateName),
27 | )),
28 | );
29 | const localTemplate = readTemplatesResults.find(template => !template.error);
30 | if (!localTemplate) {
31 | console.log(`📇 No HTML template file found in "${inputFolder}"`);
32 | reportTemplateUsage(false); // "Using the default template"
33 | const templatePath = path.resolve(__dirname, DEFAULT_TEMPLATE_PATH);
34 | return read(templatePath);
35 | }
36 | reportTemplateUsage(true, localTemplate.fileName); // Using your file
37 | return localTemplate.contents;
38 | };
39 |
40 | module.exports = getTemplateContents;
41 |
--------------------------------------------------------------------------------
/lib/modules/template/index.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const readPkgUp = require('read-pkg-up');
4 |
5 | // Local
6 | const compile = require('./compile.js');
7 | const getTemplateContents = require('./get-template-contents.js');
8 | const writeTemplate = require('./write-template.js');
9 |
10 |
11 | /**
12 | * Responsible for writing user-provided/generated
13 | * index HTML template to the output directory
14 | *
15 | * @param {object} param
16 | * @param {string} input The root/input file
17 | * @param {string} output The output directory
18 | */
19 | const main = async ({
20 | input, output,
21 | }) => {
22 | const inputFolder = path.dirname(input);
23 | // Get the title to inject into the template (if neeeded)
24 | const { 'package': { name } } = await readPkgUp();
25 | // Get the contents, either user-provided or generated
26 | const template = await getTemplateContents(inputFolder);
27 | // Compile the template (inserting the variables)
28 | const compiled = compile({
29 | title: name || 'My App',
30 | template,
31 | });
32 | // Write the file to the output directory
33 | await writeTemplate({
34 | output,
35 | compiled,
36 | });
37 | console.log('✍️ Wrote index.html file');
38 | };
39 |
40 | module.exports = main;
41 |
--------------------------------------------------------------------------------
/lib/modules/template/markup.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Gets the code for the CSS import
3 | *
4 | * @param {string} filename The name of the CSS file
5 | */
6 | const getCSS = filename => ` `;
7 |
8 | /**
9 | * Gets the for importing the JS
10 | *
11 | * @param {string} filename The name of the JS bundle file
12 | */
13 | const getJS = filename => ``;
14 |
15 | const markup = {
16 | getCSS,
17 | getJS,
18 | };
19 |
20 | module.exports = markup;
21 |
--------------------------------------------------------------------------------
/lib/modules/template/read-template.js:
--------------------------------------------------------------------------------
1 | // Utils
2 | const { read } = require('../../utils/fs.js');
3 |
4 | /**
5 | * Actually reads the contents of a given HTML template file.
6 | * Like utils.read but with different outputs
7 | *
8 | * @param {string} path Absolute path to the HTML template file
9 | */
10 | const readTemplate = async (path) => {
11 | try {
12 | return {
13 | contents: await read(path),
14 | fileName: path.split(path.sep).pop(),
15 | };
16 | } catch (error) {
17 | return {
18 | error,
19 | };
20 | }
21 | };
22 |
23 | module.exports = readTemplate;
24 |
--------------------------------------------------------------------------------
/lib/modules/template/report-template-usage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Logs the template being used to the console
3 | *
4 | * @param {boolean} hasTemplate If a user-provided template was provided
5 | * @param {string} fileName Name of the user-provided file being used
6 | */
7 | const reportTemplateUsage = (hasTemplate = false, fileName = 'the provided') => console.log(
8 | hasTemplate
9 | ? `📄 Using ${fileName} template`
10 | : '📄 Using the default HTML template instead',
11 | );
12 |
13 | module.exports = reportTemplateUsage;
14 |
--------------------------------------------------------------------------------
/lib/modules/template/write-template.js:
--------------------------------------------------------------------------------
1 | // Utils
2 | const { write } = require('../../utils/fs.js');
3 | const pathCwdResolve = require('../../utils/path-cwd-resolve.js');
4 | const { HTML_OUTPUT_INDEX } = require('../../constants.js');
5 |
6 |
7 | /**
8 | * Function for writing the compiled template HTML file to disk
9 | *
10 | * @param {object} props
11 | * @param {string} props.output The output directory
12 | * @param {string} props.compiled The compiled template
13 | */
14 | const writeTemplate = ({
15 | output, compiled,
16 | }) => write(
17 | pathCwdResolve(output, HTML_OUTPUT_INDEX),
18 | compiled,
19 | );
20 |
21 | module.exports = writeTemplate;
22 |
--------------------------------------------------------------------------------
/lib/rollup.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const svelte = require('rollup-plugin-svelte');
4 | const resolve = require('rollup-plugin-node-resolve');
5 | const commonjs = require('rollup-plugin-commonjs');
6 | const livereload = require('rollup-plugin-livereload');
7 | const serve = require('rollup-plugin-serve');
8 | const sourcemaps = require('rollup-plugin-sourcemaps');
9 | const { terser } = require('rollup-plugin-terser');
10 | const getPort = require('get-port');
11 |
12 | const { BUNDLE_FILENAME } = require('./constants.js');
13 |
14 |
15 | const getPlugins = async ({
16 | input,
17 | output,
18 | isDevelopmentMode,
19 | }) => {
20 | const inputFolder = path.dirname(input);
21 | const port = await getPort({
22 | port: getPort.makeRange(3000, 3100),
23 | });
24 | return isDevelopmentMode
25 | // Dev plugins
26 | ? [
27 | sourcemaps(),
28 | serve({
29 | // Launch in browser
30 | open: true,
31 | contentBase: output,
32 | port,
33 | verbose: true,
34 | }),
35 | livereload({
36 | watch: [
37 | output,
38 | inputFolder,
39 | ],
40 | exts: ['html', 'svelte'], // eslint-disable-line unicorn/prevent-abbreviations
41 | }),
42 | ]
43 | // Prod plugins
44 | : [
45 | terser(),
46 | ];
47 | };
48 |
49 | const getInputConfig = async ({
50 | input, output, isDevelopmentMode,
51 | }) => ({
52 | input,
53 | plugins: [
54 | svelte({
55 | // Extract any component CSS out into a separate file, as it is better for performance
56 | css: css => css.write(`${output}/${BUNDLE_FILENAME.CSS}`, isDevelopmentMode), // 2nd argument is for sourcemaps
57 | }),
58 | // For resolve external NPM dependencies
59 | resolve({
60 | browser: true,
61 | }),
62 | // For convert any CommonJS modules to ES6
63 | commonjs({
64 | include: 'node_modules/**', // TODO [>=1]: is this relative to svb/node_modules?
65 | }),
66 | ].concat(
67 | await getPlugins({
68 | input,
69 | output,
70 | isDevelopmentMode,
71 | }),
72 | ),
73 | });
74 |
75 | const getOutputConfig = ({
76 | output,
77 | isDevelopmentMode,
78 | }) => ({
79 | format: 'iife',
80 | dir: output, // eslint-disable-line unicorn/prevent-abbreviations
81 | name: 'bundle.js',
82 | sourcemap: isDevelopmentMode,
83 | });
84 |
85 | module.exports.getInputConfig = getInputConfig;
86 | module.exports.getOutputConfig = getOutputConfig;
87 |
--------------------------------------------------------------------------------
/lib/templates/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {SVB.title}
7 |
8 |
9 | {SVB.css}
10 |
11 |
12 | {SVB.js}
13 |
14 |
--------------------------------------------------------------------------------
/lib/utils/__tests__/argument.test.js:
--------------------------------------------------------------------------------
1 | const ensureArg = require('../ensure-argument.js');
2 | const warn = require('../warn.js');
3 |
4 |
5 | jest.mock('../warn.js');
6 |
7 | describe('utils/ensureArg', () => {
8 | beforeEach(() => {
9 | warn.mockImplementation(() => { });
10 | });
11 |
12 | describe('when the argument is invalid', () => {
13 | const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => { });
14 | afterAll(() => {
15 | mockExit.mockClear();
16 | warn.mockClear();
17 | });
18 | // Run the fn
19 | ensureArg(undefined, 'input');
20 | it('warns with the proper warning', () => {
21 | expect(warn).toHaveBeenCalledWith(
22 | 'Please provide an input value with the --input flag!',
23 | );
24 | expect(warn).toHaveBeenCalledTimes(1);
25 | });
26 | it('kills the process', () => {
27 | expect(mockExit).toHaveBeenCalledWith(1);
28 | expect(mockExit).toHaveBeenCalledTimes(1);
29 | });
30 | });
31 |
32 | describe('when the argument is valid', () => {
33 | const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => { });
34 | // Run the fn
35 | ensureArg('some-input.js', 'input');
36 | it('does nothing', () => {
37 | expect(warn).not.toHaveBeenCalled();
38 | expect(mockExit).not.toHaveBeenCalled();
39 | });
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/lib/utils/__tests__/get-days-in-ms.test.js:
--------------------------------------------------------------------------------
1 | const getDaysInMS = require('../get-days-in-ms.js');
2 |
3 |
4 | describe('utils/getDaysInMS', () => {
5 | it('returns the correct number of days in MS', () => {
6 | const expected = 172800000; // two days
7 | const actual = getDaysInMS(2);
8 | expect(actual).toBe(expected);
9 | });
10 | it('defaults to 1 day if no day is provided', () => {
11 | const expected = 86400000; // one day
12 | const actual = getDaysInMS();
13 | expect(actual).toBe(expected);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/lib/utils/__tests__/path-cwd-resolve.test.js:
--------------------------------------------------------------------------------
1 | const pathCwdResolve = require('../path-cwd-resolve.js');
2 |
3 |
4 | describe('utils/pathCwdResolve', () => {
5 | const mockCwd = '/some/file/path';
6 | beforeEach(() => {
7 | const mockProcessCwd = jest.spyOn(process, 'cwd');
8 | mockProcessCwd.mockReturnValue(mockCwd);
9 | });
10 |
11 | it('returns the expected path', () => {
12 | const mockAdditionalPath = 'folder/file.js';
13 | const actual = pathCwdResolve(mockAdditionalPath);
14 | const expected = `${mockCwd}/${mockAdditionalPath}`;
15 | expect(actual).toBe(expected);
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/lib/utils/__tests__/warn.test.js:
--------------------------------------------------------------------------------
1 | const warn = require('../warn.js');
2 |
3 |
4 | describe('utils/warn', () => {
5 | beforeEach(() => {
6 | console.warn = jest.fn().mockImplementation(() => { });
7 | });
8 | afterAll(() => {
9 | console.warn.clearMock();
10 | });
11 | it('logs the provided message with a ⚠️ emoji', () => {
12 | const mockMessage = 'Hello world';
13 | warn(mockMessage);
14 | expect(console.warn).toHaveBeenCalledWith(`⚠️ ${mockMessage}`, null);
15 | });
16 | it('defaults to "Uh oh! Something went wrong!" when no message is provided', () => {
17 | warn();
18 | expect(console.warn).toHaveBeenCalledWith(
19 | '⚠️ Uh oh! Something went wrong!',
20 | null,
21 | );
22 | });
23 | it('logs the rest of the error, if provided', () => {
24 | const mockMessage = 'Ya done goofed';
25 | const mockError = {
26 | code: 'ENOENT',
27 | message: mockMessage,
28 | };
29 | warn(mockMessage, mockError);
30 | expect(console.warn).toHaveBeenCalledWith(`⚠️ ${mockMessage}`, mockError);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/lib/utils/ensure-argument.js:
--------------------------------------------------------------------------------
1 | const warn = require('./warn.js');
2 |
3 |
4 | const ERROR_EXIT_CODE = 1;
5 |
6 | /**
7 | * Verifies that the provided arguments are valid/not nullish.
8 | * Warns the user and exits with an error code if invalid.
9 | *
10 | * @param {string} arg The actual argument value
11 | * @param {string} argLabel A label for the argument (ie: what the argument is called)
12 | */
13 | const ensureArgument = (argument, argumentLabel) => {
14 | if (!argument || argument.length === '') {
15 | warn(`Please provide an ${argumentLabel} value with the --${argumentLabel} flag!`);
16 | process.exit(ERROR_EXIT_CODE);
17 | }
18 | };
19 |
20 | module.exports = ensureArgument;
21 |
--------------------------------------------------------------------------------
/lib/utils/fs.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const { promisify } = require('util');
3 |
4 |
5 | const readFile = promisify(fs.readFile);
6 | const writeFile = promisify(fs.writeFile);
7 |
8 | module.exports = {
9 | read: path => readFile(path, 'utf8'),
10 | write: (path, data) => writeFile(path, data, 'utf8'),
11 | };
12 |
--------------------------------------------------------------------------------
/lib/utils/get-days-in-ms.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Returns the number of ms for a given number of days
3 | *
4 | * @param {number} days The number of days in ms (defaults to 1)
5 | */
6 | const getDaysInMS = (days = 1) => 1000 * 60 * 60 * 24 * days;
7 |
8 | module.exports = getDaysInMS;
9 |
--------------------------------------------------------------------------------
/lib/utils/path-cwd-resolve.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | /**
4 | * Wrapper around path.resolve, with process.cwd() as the 1st argument
5 | *
6 | * @param {string | Array} pth The path/path pieces which you want to resolve
7 | */
8 | const pathCwdResolve = (...pth) => path.resolve(process.cwd(), ...pth);
9 |
10 | module.exports = pathCwdResolve;
11 |
--------------------------------------------------------------------------------
/lib/utils/warn.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Log a warning message to the console
3 | *
4 | * @param {string} message The message to be logged to the console
5 | */
6 | const warn = (message = 'Uh oh! Something went wrong!', error = null) => console.warn(`⚠️ ${message}`, error);
7 |
8 | module.exports = warn;
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svb",
3 | "version": "0.4.0-beta.0",
4 | "description": "📦 A zero-config CLI to bundle Svelte apps",
5 | "main": "lib/index.js",
6 | "bin": {
7 | "svelte-bundler": "bin/index.js",
8 | "svb": "bin/index.js"
9 | },
10 | "scripts": {
11 | "build": "rollup -c",
12 | "release": "np --no-yarn",
13 | "lint": "eslint ./ --quiet",
14 | "lint:loud": "eslint ./",
15 | "lint:fix": "eslint ./ --fix",
16 | "test": "jest",
17 | "test:watch": "jest --watch",
18 | "test:coverage": "jest --coverage",
19 | "coverage:report": "jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
20 | "coverage:view": "jest --coverage && open ./coverage/lcov-report/index.html -a \"Google Chrome\""
21 | },
22 | "dependencies": {
23 | "chalk": "^2.4.2",
24 | "chokidar": "^3.1.1",
25 | "commander": "^3.0.1",
26 | "console-clear": "^1.1.1",
27 | "fs-extra": "^8.1.0",
28 | "get-port": "^5.0.0",
29 | "html-minifier": "^4.0.0",
30 | "pupa": "^2.0.1",
31 | "read-pkg-up": "^6.0.0",
32 | "rollup": "^1.21.4",
33 | "rollup-plugin-commonjs": "^10.1.0",
34 | "rollup-plugin-json": "^4.0.0",
35 | "rollup-plugin-livereload": "^1.0.3",
36 | "rollup-plugin-node-resolve": "^5.2.0",
37 | "rollup-plugin-serve": "^1.0.1",
38 | "rollup-plugin-sourcemaps": "^0.4.2",
39 | "rollup-plugin-svelte": "^5.1.0",
40 | "rollup-plugin-terser": "^5.1.2",
41 | "svelte": "^3.12.1",
42 | "update-notifier": "^3.0.1"
43 | },
44 | "devDependencies": {
45 | "coveralls": "^3.0.6",
46 | "eslint": "^6.4.0",
47 | "eslint-config-himynameisdave": "^1.0.0-beta.1",
48 | "eslint-plugin-filenames": "^1.3.2",
49 | "eslint-plugin-import": "^2.18.2",
50 | "eslint-plugin-jest": "^22.17.0",
51 | "eslint-plugin-promise": "^4.2.1",
52 | "eslint-plugin-unicorn": "^11.0.0",
53 | "jest": "^24.9.0",
54 | "np": "^5.1.0"
55 | },
56 | "engines": {
57 | "node": ">= 8.16.0"
58 | },
59 | "repository": {
60 | "type": "git",
61 | "url": "git+https://github.com/himynameisdave/svelte-bundler.git"
62 | },
63 | "keywords": [
64 | "svelte",
65 | "bundler",
66 | "compiler",
67 | "rollup",
68 | "zero-configuration",
69 | "svelte-cli"
70 | ],
71 | "author": {
72 | "name": "Dave Lunny",
73 | "email": "d@velunny.com",
74 | "url": "http://himynameisdave.com/"
75 | },
76 | "license": "MIT",
77 | "bugs": {
78 | "url": "https://github.com/himynameisdave/svelte-bundler/issues"
79 | },
80 | "homepage": "https://himynameisdave.github.io/svb/#/",
81 | "private": false
82 | }
83 |
--------------------------------------------------------------------------------