├── .editorconfig
├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── .prettierrc
├── BACKERS.md
├── LICENSE
├── README.md
├── circle.yml
├── core
├── dev-utils
│ ├── CHANGELOG.md
│ ├── InlineChunkHtmlPlugin.js
│ ├── WatchMissingNodeModulesPlugin.js
│ ├── clearConsole.js
│ ├── colors.js
│ ├── formatWebpackMessages.js
│ ├── hotDevClient.js
│ ├── launchEditorEndpoint.js
│ ├── open.js
│ ├── openBrowser.js
│ ├── openChrome.applescript
│ ├── package.json
│ ├── prepareProxy.js
│ ├── prettyBytes.js
│ ├── printServeMessage.js
│ ├── refreshOverlayInterop.js
│ ├── runCompiler.js
│ └── skipServiceWorker.js
├── logger
│ ├── index.js
│ └── package.json
├── poi
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __test__
│ │ ├── __snapshots__
│ │ │ └── format.test.js.snap
│ │ └── format.test.js
│ ├── babel.js
│ ├── bin
│ │ └── cli.js
│ ├── lib
│ │ ├── Hooks.js
│ │ ├── WebpackUtils.js
│ │ ├── babel
│ │ │ └── preset.js
│ │ ├── index.js
│ │ ├── plugins
│ │ │ ├── command-options.js
│ │ │ ├── config-babel.js
│ │ │ ├── config-css.js
│ │ │ ├── config-electron.js
│ │ │ ├── config-eval.js
│ │ │ ├── config-font.js
│ │ │ ├── config-html.js
│ │ │ ├── config-image.js
│ │ │ ├── config-jsx-import.js
│ │ │ ├── config-misc-loaders.js
│ │ │ ├── config-react-refresh.js
│ │ │ ├── config-reason.js
│ │ │ ├── config-vue.js
│ │ │ ├── config-yarn-pnp.js
│ │ │ ├── eject-html.js
│ │ │ ├── serve.js
│ │ │ └── watch.js
│ │ ├── utils
│ │ │ ├── PoiError.js
│ │ │ ├── WebpackChain.js
│ │ │ ├── __test__
│ │ │ │ └── plugins.test.js
│ │ │ ├── createConfigLoader.js
│ │ │ ├── getFileNames.js
│ │ │ ├── isLocalPath.js
│ │ │ ├── loadEnvs.js
│ │ │ ├── mergeConfig.js
│ │ │ ├── parseArgs.js
│ │ │ ├── plugins.js
│ │ │ ├── spinner.js
│ │ │ └── validateConfig.js
│ │ └── webpack
│ │ │ ├── PrintStatusPlugin.js
│ │ │ ├── babel-loader.js
│ │ │ ├── default-template.html
│ │ │ ├── eval-loader.js
│ │ │ ├── reason-loader.js
│ │ │ └── webpack.config.js
│ ├── package.json
│ └── webpack.config.js
└── test-utils
│ ├── CHANGELOG.md
│ ├── createProject.js
│ └── package.json
├── create-poi-app
├── CHANGELOG.md
├── README.md
├── bin
│ └── cli.js
├── generator
│ ├── __test__
│ │ └── index.test.js
│ ├── saofile.js
│ └── templates
│ │ ├── js
│ │ └── src
│ │ │ ├── index.js
│ │ │ └── index.test.js
│ │ ├── linter-tslint
│ │ └── tslint.json
│ │ ├── linter-xo
│ │ └── .eslintrc.js
│ │ ├── main
│ │ ├── README.md
│ │ ├── _gitignore
│ │ ├── package.json
│ │ ├── poi.config.js
│ │ ├── public
│ │ │ └── favicon.ico
│ │ └── src
│ │ │ └── assets
│ │ │ └── css
│ │ │ └── style.css
│ │ ├── pwa
│ │ ├── public
│ │ │ ├── img
│ │ │ │ └── icons
│ │ │ │ │ ├── apple-touch-icon-152x152.png
│ │ │ │ │ ├── msapplication-icon-144x144.png
│ │ │ │ │ └── safari-mask-icon.svg
│ │ │ └── manifest.json
│ │ └── src
│ │ │ └── registerServiceWorker.js
│ │ └── ts
│ │ ├── src
│ │ ├── index.test.ts
│ │ └── index.ts
│ │ └── tsconfig.json
└── package.json
├── lerna.json
├── other-packages
├── babel-plugin-assets-named-imports
│ ├── CHANGELOG.md
│ ├── __test__
│ │ └── index.test.js
│ ├── index.js
│ └── package.json
├── pnp-webpack-plugin
│ ├── CHANGELOG.md
│ ├── index.js
│ └── package.json
└── pwa-html-webpack-plugin
│ ├── index.js
│ └── package.json
├── package.json
├── plugins
├── astroturf
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.js
│ ├── index.test.js
│ └── package.json
├── bundle-report
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.js
│ └── package.json
├── eslint
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.js
│ └── package.json
├── html-entry
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── example
│ │ ├── foo.svg
│ │ ├── index.html
│ │ ├── main.js
│ │ ├── meow.png
│ │ └── style.css
│ ├── lib
│ │ ├── html-entry-loader.js
│ │ ├── index.js
│ │ ├── template-settings.js
│ │ └── utils.js
│ └── package.json
├── karma
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── example
│ │ └── index.test.js
│ ├── lib
│ │ ├── index.js
│ │ └── run-karma.js
│ └── package.json
├── puppet
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── example
│ │ ├── mocha.test.js
│ │ └── tape.test.js
│ ├── lib
│ │ ├── index.js
│ │ ├── mocha
│ │ │ ├── after.js
│ │ │ └── before.js
│ │ ├── run.js
│ │ ├── shared
│ │ │ └── before.js
│ │ ├── tape
│ │ │ └── before.js
│ │ └── utils.js
│ └── package.json
├── pwa
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.js
│ └── package.json
├── typescript
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.js
│ └── package.json
└── vue-static
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── example
│ ├── about.vue
│ ├── home.vue
│ ├── index.js
│ └── style.css
│ ├── lib
│ ├── app
│ │ ├── create-app.js
│ │ ├── entry-client.js
│ │ └── entry-server.js
│ ├── generate.js
│ └── index.js
│ └── package.json
├── tasks
└── test.sh
├── test
└── kitchensink
│ ├── .poirc
│ ├── package.json
│ ├── src
│ └── features
│ │ └── webpack
│ │ ├── AssetsNamedImports.test.js
│ │ ├── CssInclusion.js
│ │ ├── CssInclusion.test.js
│ │ ├── CssModulesInclusion.js
│ │ ├── CssModulesInclusion.test.js
│ │ ├── EvalLoader.test.js
│ │ ├── ImageInclusion.js
│ │ ├── ImageInclusion.test.js
│ │ ├── JsonInclusion.js
│ │ ├── JsonInclusion.test.js
│ │ ├── SassInclusion.js
│ │ ├── SassInclusion.test.js
│ │ ├── SassModulesInclusion.js
│ │ ├── SassModulesInclusion.test.js
│ │ ├── ScssInclusion.js
│ │ ├── ScssInclusion.test.js
│ │ ├── ScssModulesInclusion.js
│ │ ├── ScssModulesInclusion.test.js
│ │ ├── SvgInCss.js
│ │ ├── SvgInCss.test.js
│ │ ├── SvgInclusion.js
│ │ ├── SvgInclusion.test.js
│ │ └── assets
│ │ ├── abstract.json
│ │ ├── data.eval.js
│ │ ├── example.md
│ │ ├── index.module.css
│ │ ├── index.module.sass
│ │ ├── index.module.scss
│ │ ├── logo.svg
│ │ ├── sass-styles.module.sass
│ │ ├── sass-styles.sass
│ │ ├── scss-styles.module.scss
│ │ ├── scss-styles.scss
│ │ ├── style.css
│ │ ├── style.module.css
│ │ ├── svg.css
│ │ ├── text.md
│ │ └── tiniest-cat.jpg
│ └── yarn.lock
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: egoist # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | open_collective: # Replace with a single Open Collective username
5 | ko_fi: support_egoist
6 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
7 | custom: # Replace with a single custom sponsorship URL
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | dist
4 | /.changelog
5 | .vscode
6 | .idea
7 | .DS_Store
8 | .test-projects
9 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "bracketSpacing": true
5 | }
6 |
--------------------------------------------------------------------------------
/BACKERS.md:
--------------------------------------------------------------------------------
1 | # Sponsors & Backers
2 |
3 | Poi is an MIT-licensed open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by awesome backers and sponsors. If you'd like to join them, please consider:
4 |
5 | - [Become a backer or sponsor on Patreon](https://patreon.com/egoist)
6 | - [Donate via PayPal](https://paypal.me/egoistian)
7 | - [Donate via AliPay](https://user-images.githubusercontent.com/8784712/38684215-c7b78590-3ea1-11e8-9812-91569ee72eaa.png)
8 | - [Donate via Wechat](https://user-images.githubusercontent.com/8784712/38684192-bceaad18-3ea1-11e8-9a38-a4e0eb79b7a7.png)
9 |
10 | ## Backers
11 |
12 | - Shinya Katayama [@ktsn](https://github.com/ktsn)
13 | - HANATANI Takuma [@potato4d](https://github.com/potato4d)
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) EGOIST <0x142857@gmail.com> (https://egoist.sh)
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 | # ⚠️ Poi has been deprecated, please migrate to [Vite](https://vitejs.dev), contact me personally if you need help.
2 |
3 |
4 |
5 |
6 |
7 |
8 | [](https://npm.im/poi) [](https://circleci.com/gh/egoist/poi/tree/master) [](https://npm.im/poi) [](https://twitter.com/poi__js)
9 |
10 | Poi is a bundler built on the top of webpack, trying to make developing and bundling apps with webpack as easy as possible.
11 |
12 | **The Poi project is supported by our [Backers](./BACKERS.md) and funded through [Patreon](https://patreon.com/egoist).**
13 |
14 | ## Features
15 |
16 | - 📦 Out of box support for JS, CSS, File assets and more.
17 | - ⚛ Framework-agnostic but also support JSX, Vue and more with no configs.
18 | - 🔌 Great extensibility.
19 | - 🐙 Fits most web apps, npm libs.
20 | - 🚨 Great development experience.
21 |
22 | ## Quick Overview
23 |
24 | Before we get started, ensure that you have installed Node.js (>=8) and Yarn (or npm) on your machine.
25 |
26 | ### Get Started Immediately
27 |
28 | ```bash
29 | yarn global add create-poi-app
30 | create-poi-app my-app
31 |
32 | cd my-app
33 | npm run dev
34 | ```
35 |
36 | Then open http://localhost:4000 to see your app.
37 | When you’re ready to deploy to production, create a minified bundle with `npm run build`.
38 |
39 | ### Get Started Manually
40 |
41 | Inside an empty project, run `yarn init` or `npm init` to create a `package.json` and install Poi:
42 |
43 | ```bash
44 | yarn init
45 | yarn add poi --dev
46 | ```
47 |
48 | Now all you need is to create an entry file, like if you're building a website, just create an `index.js`:
49 |
50 | ```js
51 | const el = document.createElement('div')
52 | el.textContent = 'Hello Poi!'
53 |
54 | document.body.appendChild(el)
55 | ```
56 |
57 | Now if you run:
58 |
59 | ```bash
60 | yarn poi --serve
61 | ```
62 |
63 | You will get a URL like `http://localhost:4000` which you can open to preview the app.
64 |
65 | Next let's start adding some dependencies like a CSS file `style.module.css`:
66 |
67 | ```css
68 | .title {
69 | color: pink;
70 | }
71 | ```
72 |
73 | ```js
74 | import styles from './style.module.css'
75 |
76 | const el = document.createElement('div')
77 | el.className = styles.title
78 | el.textContent = 'Hello Poi!'
79 |
80 | document.body.appendChild(el)
81 | ```
82 |
83 | Save it and the browser will automatically reload to apply the changes!
84 |
85 | ## Documentation
86 |
87 | 📚 https://poi.js.org
88 |
89 | You can improve it by sending pull requests to [this repository](https://github.com/poi-bundler/website).
90 |
91 | Check out [this repository](https://github.com/poi-bundler/examples) for more examples.
92 |
93 | ## Community
94 |
95 | All feedback and suggestions are welcome!
96 |
97 | - 💬 Join the community on [Spectrum](https://spectrum.chat/poi).
98 | - 📣 Stay up to date on new features and announcements on [Twitter @poi\_\_js](https://twitter.com/poi__js).
99 |
100 | ## Credits
101 |
102 | Poi v12 wouldn't exist without the inspirations from following projects:
103 |
104 | - Webpack
105 | - Parcel 2
106 | - Poi itself
107 | - Vue CLI 3
108 | - Create React App
109 |
110 | ## License
111 |
112 | MIT © [EGOIST](https://egoist.sh)
113 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | working_directory: ~/repo
5 | docker:
6 | - image: circleci/node:10-browsers
7 | branches:
8 | ignore:
9 | - gh-pages # list of branches to ignore
10 | - /release\/.*/ # or ignore regexes
11 | steps:
12 | - checkout
13 | - restore_cache:
14 | key: dependency-cache-{{ checksum "yarn.lock" }}
15 | - run:
16 | name: install dependences
17 | command: yarn
18 | - save_cache:
19 | key: dependency-cache-{{ checksum "yarn.lock" }}
20 | paths:
21 | - ./node_modules
22 | - run:
23 | name: test
24 | command: yarn test
25 |
--------------------------------------------------------------------------------
/core/dev-utils/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [12.1.6](https://github.com/egoist/poi/compare/@poi/dev-utils@12.1.5...@poi/dev-utils@12.1.6) (2020-08-19)
7 |
8 | ### Bug Fixes
9 |
10 | - make react-refresh work better with error overlay ([e6deed4](https://github.com/egoist/poi/commit/e6deed4))
11 |
12 | ## [12.1.5](https://github.com/egoist/poi/compare/@poi/dev-utils@12.1.4...@poi/dev-utils@12.1.5) (2020-07-13)
13 |
14 | **Note:** Version bump only for package @poi/dev-utils
15 |
16 | ## [12.1.4](https://github.com/egoist/poi/compare/@poi/dev-utils@12.1.3...@poi/dev-utils@12.1.4) (2020-04-30)
17 |
18 | **Note:** Version bump only for package @poi/dev-utils
19 |
20 | ## [12.1.3](https://github.com/egoist/poi/compare/@poi/dev-utils@12.1.2...@poi/dev-utils@12.1.3) (2019-08-09)
21 |
22 | ### Bug Fixes
23 |
24 | - keep the trailing slash of `output.publicUrl` ([#612](https://github.com/egoist/poi/issues/612)) ([56bd612](https://github.com/egoist/poi/commit/56bd612))
25 |
26 | ## [12.1.2](https://github.com/egoist/poi/compare/@poi/dev-utils@12.1.1...@poi/dev-utils@12.1.2) (2019-07-27)
27 |
28 | ### Bug Fixes
29 |
30 | - Append `poi -s` output URLs with `output.publicUrl` ([#587](https://github.com/egoist/poi/issues/587)) ([fcd70f7](https://github.com/egoist/poi/commit/fcd70f7))
31 |
32 | ### Features
33 |
34 | - enable https one the preview URLs ([#611](https://github.com/egoist/poi/issues/611)) ([cda0ec2](https://github.com/egoist/poi/commit/cda0ec2))
35 |
36 | ## [12.1.1](https://github.com/egoist/poi/compare/@poi/dev-utils@12.1.0...@poi/dev-utils@12.1.1) (2019-01-23)
37 |
38 | ### Bug Fixes
39 |
40 | - format build time in human-readable format ([a89ecd0](https://github.com/egoist/poi/commit/a89ecd0))
41 | - use a new port if the port is already used ([62053e5](https://github.com/egoist/poi/commit/62053e5))
42 |
43 | # [12.1.0](https://github.com/egoist/poi/compare/@poi/dev-utils@12.0.3...@poi/dev-utils@12.1.0) (2019-01-09)
44 |
45 | ### Bug Fixes
46 |
47 | - **dev-utils:** refactor hotDevClient to ES5 compat ([#522](https://github.com/egoist/poi/issues/522)) ([480bce5](https://github.com/egoist/poi/commit/480bce5)), closes [#515](https://github.com/egoist/poi/issues/515)
48 |
49 | ### Features
50 |
51 | - show memory usage ([75f1376](https://github.com/egoist/poi/commit/75f1376))
52 |
53 | ## [12.0.3](https://github.com/egoist/poi/compare/@poi/dev-utils@12.0.2...@poi/dev-utils@12.0.3) (2018-12-21)
54 |
55 | ### Bug Fixes
56 |
57 | - **cli:** only open browser on the first successful build ([13b1ac8](https://github.com/egoist/poi/commit/13b1ac8))
58 |
--------------------------------------------------------------------------------
/core/dev-utils/InlineChunkHtmlPlugin.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | 'use strict';
3 |
4 | class InlineChunkHtmlPlugin {
5 | constructor(htmlWebpackPlugin, tests) {
6 | this.htmlWebpackPlugin = htmlWebpackPlugin;
7 | this.tests = tests;
8 | }
9 |
10 | getInlinedTag(publicPath, assets, tag) {
11 | if (tag.tagName !== 'script' || !(tag.attributes && tag.attributes.src)) {
12 | return tag;
13 | }
14 | const scriptName = tag.attributes.src.replace(publicPath, '');
15 | if (!this.tests.some(test => scriptName.match(test))) {
16 | return tag;
17 | }
18 | const asset = assets[scriptName];
19 | if (asset == null) {
20 | return tag;
21 | }
22 | return { tagName: 'script', innerHTML: asset.source(), closeTag: true };
23 | }
24 |
25 | apply(compiler) {
26 | let publicPath = compiler.options.output.publicPath;
27 | if (!publicPath.endsWith('/')) {
28 | publicPath += '/';
29 | }
30 |
31 | compiler.hooks.compilation.tap('InlineChunkHtmlPlugin', compilation => {
32 | const tagFunction = tag =>
33 | this.getInlinedTag(publicPath, compilation.assets, tag);
34 |
35 | const hooks = this.htmlWebpackPlugin.getHooks(compilation);
36 | hooks.alterAssetTagGroups.tap('InlineChunkHtmlPlugin', assets => {
37 | assets.headTags = assets.headTags.map(tagFunction);
38 | assets.bodyTags = assets.bodyTags.map(tagFunction);
39 | });
40 |
41 | // Still emit the runtime chunk for users who do not use our generated
42 | // index.html file.
43 | // hooks.afterEmit.tap('InlineChunkHtmlPlugin', () => {
44 | // Object.keys(compilation.assets).forEach(assetName => {
45 | // if (this.tests.some(test => assetName.match(test))) {
46 | // delete compilation.assets[assetName];
47 | // }
48 | // });
49 | // });
50 | });
51 | }
52 | }
53 |
54 | module.exports = InlineChunkHtmlPlugin;
55 |
--------------------------------------------------------------------------------
/core/dev-utils/WatchMissingNodeModulesPlugin.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // This Webpack plugin ensures `npm install ` forces a project rebuild.
3 | // We’re not sure why this isn't Webpack's default behavior.
4 | // See https://github.com/facebook/create-react-app/issues/186.
5 |
6 | 'use strict'
7 |
8 | class WatchMissingNodeModulesPlugin {
9 | constructor(nodeModulesPath) {
10 | this.nodeModulesPath = nodeModulesPath
11 | }
12 |
13 | apply(compiler) {
14 | compiler.hooks.emit.tap('WatchMissingNodeModulesPlugin', compilation => {
15 | const missingDeps = [...compilation.missingDependencies]
16 | const nodeModulesPath = this.nodeModulesPath
17 |
18 | // If any missing files are expected to appear in node_modules...
19 | if (missingDeps.some(file => file.includes(nodeModulesPath))) {
20 | // ...tell webpack to watch node_modules recursively until they appear.
21 | compilation.contextDependencies.add(nodeModulesPath)
22 | }
23 | })
24 | }
25 | }
26 |
27 | module.exports = WatchMissingNodeModulesPlugin
28 |
--------------------------------------------------------------------------------
/core/dev-utils/clearConsole.js:
--------------------------------------------------------------------------------
1 | function clearConsole() {
2 | process.stdout.write('\u001Bc')
3 | }
4 |
5 | module.exports = clearConsole
6 |
--------------------------------------------------------------------------------
/core/dev-utils/colors.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | /**
3 | * This file should be written in ES5
4 | * Code is taken from https://github.com/jorgebucaran/colorette/blob/master/index.js
5 | * Copy it to https://buble.surge.sh and paste here
6 | */
7 | "use strict"
8 |
9 | var enabled =
10 | process.env.FORCE_COLOR ||
11 | process.platform === "win32" ||
12 | (process.stdout && process.stdout.isTTY && process.env.TERM && process.env.TERM !== "dumb")
13 |
14 | var rawInit = function (open, close, searchRegex, replaceValue) { return function (s) { return enabled
15 | ? open +
16 | (~(s += "").indexOf(close, 4) // skip opening \x1b[
17 | ? s.replace(searchRegex, replaceValue)
18 | : s) +
19 | close
20 | : s; }; }
21 |
22 | var init = function (open, close) {
23 | return rawInit(
24 | ("\u001b[" + open + "m"),
25 | ("\u001b[" + close + "m"),
26 | new RegExp(("\\x1b\\[" + close + "m"), "g"),
27 | ("\u001b[" + open + "m")
28 | )
29 | }
30 |
31 | module.exports = {
32 | options: Object.defineProperty({}, "enabled", {
33 | get: function () { return enabled; },
34 | set: function (value) { return (enabled = value); }
35 | }),
36 | reset: init(0, 0),
37 | bold: rawInit("\x1b[1m", "\x1b[22m", /\x1b\[22m/g, "\x1b[22m\x1b[1m"),
38 | dim: rawInit("\x1b[2m", "\x1b[22m", /\x1b\[22m/g, "\x1b[22m\x1b[2m"),
39 | italic: init(3, 23),
40 | underline: init(4, 24),
41 | inverse: init(7, 27),
42 | hidden: init(8, 28),
43 | strikethrough: init(9, 29),
44 | black: init(30, 39),
45 | red: init(31, 39),
46 | green: init(32, 39),
47 | yellow: init(33, 39),
48 | blue: init(34, 39),
49 | magenta: init(35, 39),
50 | cyan: init(36, 39),
51 | white: init(37, 39),
52 | gray: init(90, 39),
53 | bgBlack: init(40, 49),
54 | bgRed: init(41, 49),
55 | bgGreen: init(42, 49),
56 | bgYellow: init(43, 49),
57 | bgBlue: init(44, 49),
58 | bgMagenta: init(45, 49),
59 | bgCyan: init(46, 49),
60 | bgWhite: init(47, 49),
61 | blackBright: init(90, 39),
62 | redBright: init(91, 39),
63 | greenBright: init(92, 39),
64 | yellowBright: init(93, 39),
65 | blueBright: init(94, 39),
66 | magentaBright: init(95, 39),
67 | cyanBright: init(96, 39),
68 | whiteBright: init(97, 39),
69 | bgBlackBright: init(100, 49),
70 | bgRedBright: init(101, 49),
71 | bgGreenBright: init(102, 49),
72 | bgYellowBright: init(103, 49),
73 | bgBlueBright: init(104, 49),
74 | bgMagentaBright: init(105, 49),
75 | bgCyanBright: init(106, 49),
76 | bgWhiteBright: init(107, 49)
77 | }
78 |
--------------------------------------------------------------------------------
/core/dev-utils/formatWebpackMessages.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | 'use strict';
3 |
4 | // WARNING: this code is untranspiled and is used in browser too.
5 | // Please make sure any changes are in ES5 or contribute a Babel compile step.
6 | var colors = require('./colors')
7 |
8 | // Some custom utilities to prettify Webpack output.
9 | // This is quite hacky and hopefully won't be needed when Webpack fixes this.
10 | // https://github.com/webpack/webpack/issues/2878
11 | var friendlySyntaxErrorLabel = 'Syntax error:';
12 |
13 | function isLikelyASyntaxError(message) {
14 | return message.indexOf(friendlySyntaxErrorLabel) !== -1;
15 | }
16 |
17 | // Cleans up webpack error messages.
18 | // eslint-disable-next-line no-unused-vars
19 | function formatMessage(message, isError) {
20 | var lines = message.split('\n');
21 |
22 | if (lines.length > 2 && lines[1] === '') {
23 | // Remove extra newline.
24 | lines.splice(1, 1);
25 | }
26 |
27 | // Remove webpack-specific loader notation from filename.
28 | // Before:
29 | // ./~/css-loader!./~/postcss-loader!./src/App.css
30 | // After:
31 | // ./src/App.css
32 | if (lines[0].lastIndexOf('!') !== -1) {
33 | lines[0] = lines[0].substr(lines[0].lastIndexOf('!') + 1);
34 | }
35 |
36 | lines = lines.filter(function (line) {
37 | // Webpack adds a list of entry points to warning messages:
38 | // @ ./src/index.js
39 | // @ multi react-scripts/~/react-dev-utils/webpackHotDevClient.js ...
40 | // It is misleading (and unrelated to the warnings) so we clean it up.
41 | // It is only useful for syntax errors but we have beautiful frames for them.
42 | return line.indexOf(' @ ') !== 0;
43 | });
44 |
45 | // line #0 is filename
46 | // line #1 is the main error message
47 | if (!lines[0] || !lines[1]) {
48 | return lines.join('\n');
49 | }
50 |
51 | // Cleans up verbose "module not found" messages for files and packages.
52 | if (lines[1].indexOf('Module not found: ') === 0) {
53 | lines = [lines[0],
54 | // Clean up message because "Module not found: " is descriptive enough.
55 | lines[1].replace('Cannot resolve \'file\' or \'directory\' ', '').replace('Cannot resolve module ', '').replace('Error: ', '').replace('[CaseSensitivePathsPlugin] ', '')];
56 | }
57 |
58 | // Cleans up syntax error messages.
59 | if (lines[1].indexOf('Module build failed: ') === 0) {
60 | lines[1] = lines[1].replace('Module build failed: SyntaxError:', friendlySyntaxErrorLabel);
61 | }
62 |
63 | // Clean up export errors.
64 | // TODO: we should really send a PR to Webpack for this.
65 | var exportError = /\s*(.+?)\s*(")?export '(.+?)' was not found in '(.+?)'/;
66 | if (lines[1].match(exportError)) {
67 | lines[1] = lines[1].replace(exportError, '$1 \'$4\' does not contain an export named \'$3\'.');
68 | }
69 |
70 | lines[0] = colors.inverse(lines[0]);
71 |
72 | // Reassemble the message.
73 | message = lines.map(function (line) {
74 | if (line.indexOf('vue-template-compiler must be installed as a peer dependency') > -1) {
75 | return 'You need to install "vue-template-compiler" alongside "vue" in your project.'
76 | }
77 | return line
78 | }).join('\n');
79 | // Internal stacks are generally useless so we strip them... with the
80 | // exception of:
81 | // 1: stacks containing `webpack:` because they're normally
82 | // from user code generated by WebPack. For more information see
83 | // https://github.com/facebookincubator/create-react-app/pull/1050
84 | // 2: from eval-loader
85 | var isEvalLoaderError = /webpack\/eval-loader\.js/.exec(lines[1])
86 | if (!isEvalLoaderError) {
87 | message = message.replace(/^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm, ''); // at ... ...:x:y
88 | }
89 |
90 | return message.trim();
91 | }
92 |
93 | function formatWebpackMessages(json) {
94 | var formattedErrors = json.errors.map(function (message) {
95 | return formatMessage(message, true);
96 | });
97 | var formattedWarnings = json.warnings.map(function (message) {
98 | return formatMessage(message, false);
99 | });
100 | var result = {
101 | errors: formattedErrors,
102 | warnings: formattedWarnings
103 | };
104 | if (result.errors.some(isLikelyASyntaxError)) {
105 | // If there are any syntax errors, show just them.
106 | // This prevents a confusing ESLint parsing error
107 | // preceding a much more useful Babel syntax error.
108 | result.errors = result.errors.filter(isLikelyASyntaxError);
109 | }
110 | return result;
111 | }
112 |
113 | module.exports = formatWebpackMessages;
114 |
--------------------------------------------------------------------------------
/core/dev-utils/launchEditorEndpoint.js:
--------------------------------------------------------------------------------
1 | module.exports = '/__open-in-editor'
2 |
--------------------------------------------------------------------------------
/core/dev-utils/open.js:
--------------------------------------------------------------------------------
1 | module.exports = require('open')
2 |
--------------------------------------------------------------------------------
/core/dev-utils/openBrowser.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | 'use strict';
3 |
4 | var execSync = require('child_process').execSync;
5 | var spawn = require('cross-spawn');
6 | var open = require('./open');
7 | var colors = require('./colors');
8 |
9 | // https://github.com/sindresorhus/open#app
10 | var OSX_CHROME = 'google chrome';
11 |
12 | const Actions = Object.freeze({
13 | NONE: 0,
14 | BROWSER: 1,
15 | SCRIPT: 2,
16 | });
17 |
18 | function getBrowserEnv() {
19 | // Attempt to honor this environment variable.
20 | // It is specific to the operating system.
21 | // See https://github.com/sindresorhus/open#app for documentation.
22 | const value = process.env.BROWSER;
23 | let action;
24 | if (!value) {
25 | // Default.
26 | action = Actions.BROWSER;
27 | } else if (value.toLowerCase().endsWith('.js')) {
28 | action = Actions.SCRIPT;
29 | } else if (value.toLowerCase() === 'none') {
30 | action = Actions.NONE;
31 | } else {
32 | action = Actions.BROWSER;
33 | }
34 | return { action, value };
35 | }
36 |
37 | function executeNodeScript(scriptPath, url) {
38 | const extraArgs = process.argv.slice(2);
39 | const child = spawn('node', [scriptPath, ...extraArgs, url], {
40 | stdio: 'inherit',
41 | });
42 | child.on('close', code => {
43 | if (code !== 0) {
44 | console.log();
45 | console.log(
46 | colors.red(
47 | 'The script specified as BROWSER environment variable failed.'
48 | )
49 | );
50 | console.log(colors.cyan(scriptPath) + ' exited with code ' + code + '.');
51 | console.log();
52 | return;
53 | }
54 | });
55 | return true;
56 | }
57 |
58 | function startBrowserProcess(browser, url) {
59 | // If we're on OS X, the user hasn't specifically
60 | // requested a different browser, we can try opening
61 | // Chrome with AppleScript. This lets us reuse an
62 | // existing tab when possible instead of creating a new one.
63 | const shouldTryOpenChromeWithAppleScript =
64 | process.platform === 'darwin' &&
65 | (typeof browser !== 'string' || browser === OSX_CHROME);
66 |
67 | if (shouldTryOpenChromeWithAppleScript) {
68 | try {
69 | // Try our best to reuse existing tab
70 | // on OS X Google Chrome with AppleScript
71 | execSync('ps cax | grep "Google Chrome"');
72 | execSync('osascript openChrome.applescript "' + encodeURI(url) + '"', {
73 | cwd: __dirname,
74 | stdio: 'ignore',
75 | });
76 | return true;
77 | } catch (err) {
78 | // Ignore errors.
79 | }
80 | }
81 |
82 | // Another special case: on OS X, check if BROWSER has been set to "open".
83 | // In this case, instead of passing `open` to `open` (which won't work),
84 | // just ignore it (thus ensuring the intended behavior, i.e. opening the system browser):
85 | // https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768
86 | if (process.platform === 'darwin' && browser === 'open') {
87 | browser = undefined;
88 | }
89 |
90 | // Fallback to open
91 | // (It will always open new tab)
92 | try {
93 | var options = { app: browser };
94 | open(url, options).catch(() => {}); // Prevent `unhandledRejection` error.
95 | return true;
96 | } catch (err) {
97 | return false;
98 | }
99 | }
100 |
101 | /**
102 | * Reads the BROWSER evironment variable and decides what to do with it. Returns
103 | * true if it opened a browser or ran a node.js script, otherwise false.
104 | */
105 | function openBrowser(url) {
106 | const { action, value } = getBrowserEnv();
107 | switch (action) {
108 | case Actions.NONE:
109 | // Special case: BROWSER="none" will prevent opening completely.
110 | return false;
111 | case Actions.SCRIPT:
112 | return executeNodeScript(value, url);
113 | case Actions.BROWSER:
114 | return startBrowserProcess(value, url);
115 | default:
116 | throw new Error('Not implemented.');
117 | }
118 | }
119 |
120 | module.exports = openBrowser;
121 |
--------------------------------------------------------------------------------
/core/dev-utils/openChrome.applescript:
--------------------------------------------------------------------------------
1 | (*
2 | Copyright (c) 2015-present, Facebook, Inc.
3 | This source code is licensed under the MIT license found in the
4 | LICENSE file in the root directory of this source tree.
5 | *)
6 |
7 | property targetTab: null
8 | property targetTabIndex: -1
9 | property targetWindow: null
10 |
11 | on run argv
12 | set theURL to item 1 of argv
13 |
14 | tell application "Chrome"
15 |
16 | if (count every window) = 0 then
17 | make new window
18 | end if
19 |
20 | -- 1: Looking for tab running debugger
21 | -- then, Reload debugging tab if found
22 | -- then return
23 | set found to my lookupTabWithUrl(theURL)
24 | if found then
25 | set targetWindow's active tab index to targetTabIndex
26 | tell targetTab to reload
27 | tell targetWindow to activate
28 | set index of targetWindow to 1
29 | return
30 | end if
31 |
32 | -- 2: Looking for Empty tab
33 | -- In case debugging tab was not found
34 | -- We try to find an empty tab instead
35 | set found to my lookupTabWithUrl("chrome://newtab/")
36 | if found then
37 | set targetWindow's active tab index to targetTabIndex
38 | set URL of targetTab to theURL
39 | tell targetWindow to activate
40 | return
41 | end if
42 |
43 | -- 3: Create new tab
44 | -- both debugging and empty tab were not found
45 | -- make a new tab with url
46 | tell window 1
47 | activate
48 | make new tab with properties {URL:theURL}
49 | end tell
50 | end tell
51 | end run
52 |
53 | -- Function:
54 | -- Lookup tab with given url
55 | -- if found, store tab, index, and window in properties
56 | -- (properties were declared on top of file)
57 | on lookupTabWithUrl(lookupUrl)
58 | tell application "Chrome"
59 | -- Find a tab with the given url
60 | set found to false
61 | set theTabIndex to -1
62 | repeat with theWindow in every window
63 | set theTabIndex to 0
64 | repeat with theTab in every tab of theWindow
65 | set theTabIndex to theTabIndex + 1
66 | if (theTab's URL as string) contains lookupUrl then
67 | -- assign tab, tab index, and window to properties
68 | set targetTab to theTab
69 | set targetTabIndex to theTabIndex
70 | set targetWindow to theWindow
71 | set found to true
72 | exit repeat
73 | end if
74 | end repeat
75 |
76 | if found then
77 | exit repeat
78 | end if
79 | end repeat
80 | end tell
81 | return found
82 | end lookupTabWithUrl
--------------------------------------------------------------------------------
/core/dev-utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@poi/dev-utils",
3 | "version": "12.1.6",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "files": [
8 | "*.js",
9 | "openChrome.applescript"
10 | ],
11 | "license": "MIT",
12 | "dependencies": {
13 | "address": "^1.0.3",
14 | "cross-spawn": "^7.0.2",
15 | "open": "^7.0.4",
16 | "react-error-overlay": "^6.0.7",
17 | "sockjs-client": "^1.1.5",
18 | "strip-ansi": "5.2.0"
19 | },
20 | "xo": false
21 | }
22 |
--------------------------------------------------------------------------------
/core/dev-utils/prepareProxy.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const url = require('url')
4 | const address = require('address')
5 | const colors = require('./colors')
6 |
7 | module.exports = function(proxy, appPublicFolder, debug) {
8 | // `proxy` lets you specify alternate servers for specific requests.
9 | if (!/^https?:\/\//.test(proxy)) {
10 | throw new Error(
11 | `When specified \`proxy\` as a string, it must start with http:// or https://`
12 | )
13 | }
14 |
15 | // If proxy is specified, let it handle any request except for files in the public folder.
16 | function mayProxy(pathname) {
17 | const maybePublicPath = path.resolve(appPublicFolder, pathname.slice(1))
18 | return !fs.existsSync(maybePublicPath)
19 | }
20 |
21 | let target
22 | if (process.platform === 'win32') {
23 | target = resolveLoopback(proxy)
24 | } else {
25 | target = proxy
26 | }
27 | return [
28 | {
29 | target,
30 | logLevel: debug ? 'debug' : 'silent',
31 | // For single page apps, we generally want to fallback to /index.html.
32 | // However we also want to respect `proxy` for API calls.
33 | // So if `proxy` is specified as a string, we need to decide which fallback to use.
34 | // We use a heuristic: We want to proxy all the requests that are not meant
35 | // for static assets and as all the requests for static assets will be using
36 | // `GET` method, we can proxy all non-`GET` requests.
37 | // For `GET` requests, if request `accept`s text/html, we pick /index.html.
38 | // Modern browsers include text/html into `accept` header when navigating.
39 | // However API calls like `fetch()` won’t generally accept text/html.
40 | // If this heuristic doesn’t work well for you, use `src/setupProxy.js`.
41 | context(pathname, req) {
42 | // Explict context
43 | if (pathname.startsWith('/api/')) {
44 | return true
45 | }
46 |
47 | return (
48 | req.method !== 'GET' ||
49 | (mayProxy(pathname) &&
50 | req.headers.accept &&
51 | req.headers.accept.indexOf('text/html') === -1)
52 | )
53 | },
54 | onProxyReq: proxyReq => {
55 | // Browsers may send Origin headers even with same-origin
56 | // requests. To prevent CORS issues, we have to change
57 | // the Origin to match the target URL.
58 | if (proxyReq.getHeader('origin')) {
59 | proxyReq.setHeader('origin', target)
60 | }
61 | },
62 | onError: onProxyError(target),
63 | secure: false,
64 | changeOrigin: true,
65 | ws: true,
66 | xfwd: true
67 | }
68 | ]
69 | }
70 |
71 | // We need to provide a custom onError function for httpProxyMiddleware.
72 | // It allows us to log custom error messages on the console.
73 | function onProxyError(proxy) {
74 | return (err, req, res) => {
75 | const host = req.headers && req.headers.host
76 | console.log(
77 | colors.red('Proxy error:') +
78 | ' Could not proxy request ' +
79 | colors.cyan(req.url) +
80 | ' from ' +
81 | colors.cyan(host) +
82 | ' to ' +
83 | colors.cyan(proxy) +
84 | '.'
85 | )
86 | console.log(
87 | 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
88 | colors.cyan(err.code) +
89 | ').'
90 | )
91 | console.log()
92 |
93 | // And immediately send the proper error response to the client.
94 | // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
95 | if (res.writeHead && !res.headersSent) {
96 | res.writeHead(500)
97 | }
98 | res.end(
99 | 'Proxy error: Could not proxy request ' +
100 | req.url +
101 | ' from ' +
102 | host +
103 | ' to ' +
104 | proxy +
105 | ' (' +
106 | err.code +
107 | ').'
108 | )
109 | }
110 | }
111 |
112 | function resolveLoopback(proxy) {
113 | const o = url.parse(proxy)
114 | o.host = undefined
115 | if (o.hostname !== 'localhost') {
116 | return proxy
117 | }
118 | // Unfortunately, many languages (unlike node) do not yet support IPv6.
119 | // This means even though localhost resolves to ::1, the application
120 | // must fall back to IPv4 (on 127.0.0.1).
121 | // We can re-enable this in a few years.
122 | /* try {
123 | o.hostname = address.ipv6() ? '::1' : '127.0.0.1';
124 | } catch (_ignored) {
125 | o.hostname = '127.0.0.1';
126 | } */
127 |
128 | try {
129 | // Check if we're on a network; if we are, chances are we can resolve
130 | // localhost. Otherwise, we can just be safe and assume localhost is
131 | // IPv4 for maximum compatibility.
132 | if (!address.ip()) {
133 | o.hostname = '127.0.0.1'
134 | }
135 | } catch (_) {
136 | o.hostname = '127.0.0.1'
137 | }
138 | return url.format(o)
139 | }
140 |
--------------------------------------------------------------------------------
/core/dev-utils/prettyBytes.js:
--------------------------------------------------------------------------------
1 | // Takens from https://github.com/sindresorhus/pretty-bytes/blob/master/index.js
2 |
3 | const UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
4 |
5 | /*
6 | Formats the given number using `Number#toLocaleString`.
7 | - If locale is a string, the value is expected to be a locale-key (for example: `de`).
8 | - If locale is true, the system default locale is used for translation.
9 | - If no value for locale is specified, the number is returned unmodified.
10 | */
11 | const toLocaleString = (number, locale) => {
12 | let result = number
13 | if (typeof locale === 'string') {
14 | result = number.toLocaleString(locale)
15 | } else if (locale === true) {
16 | result = number.toLocaleString()
17 | }
18 |
19 | return result
20 | }
21 |
22 | module.exports = (number, options) => {
23 | if (!Number.isFinite(number)) {
24 | throw new TypeError(
25 | `Expected a finite number, got ${typeof number}: ${number}`
26 | )
27 | }
28 |
29 | options = Object.assign({}, options)
30 |
31 | if (options.signed && number === 0) {
32 | return ' 0 B'
33 | }
34 |
35 | const isNegative = number < 0
36 | const prefix = isNegative ? '-' : options.signed ? '+' : ''
37 |
38 | if (isNegative) {
39 | number = -number
40 | }
41 |
42 | if (number < 1) {
43 | const numberString = toLocaleString(number, options.locale)
44 | return prefix + numberString + ' B'
45 | }
46 |
47 | const exponent = Math.min(
48 | Math.floor(Math.log10(number) / 3),
49 | UNITS.length - 1
50 | )
51 | number = Number((number / 1000 ** exponent).toPrecision(3))
52 | const numberString = toLocaleString(number, options.locale)
53 |
54 | const unit = UNITS[exponent]
55 |
56 | return prefix + numberString + ' ' + unit
57 | }
58 |
--------------------------------------------------------------------------------
/core/dev-utils/printServeMessage.js:
--------------------------------------------------------------------------------
1 | const url = require('url')
2 | const address = require('address')
3 | const colors = require('./colors')
4 | const prettyBytes = require('./prettyBytes')
5 |
6 | module.exports = ({
7 | https,
8 | host,
9 | port,
10 | expectedPort,
11 | open,
12 | isFirstBuild,
13 | publicUrl
14 | }) => {
15 | const ip = address.ip()
16 |
17 | const protocol = https ? 'https' : 'http'
18 | const isUnspecifiedHost = host === '0.0.0.0' || host === '::'
19 | const prettyHost = isUnspecifiedHost ? 'localhost' : host
20 | const { heapUsed } = process.memoryUsage()
21 |
22 | const urlPort = colors.bold(port)
23 | const urlPath = publicUrl === '/' ? '' : url.resolve('/', publicUrl)
24 |
25 | console.log()
26 | console.log(
27 | `Local: ${protocol}://${prettyHost}:${urlPort}${urlPath}`
28 | )
29 | console.log(`On Your Network: ${protocol}://${ip}:${urlPort}${urlPath}`)
30 | console.log()
31 | if (expectedPort && expectedPort !== port) {
32 | console.log(colors.yellow(`> port ${expectedPort} is used!`))
33 | }
34 | console.log(colors.dim(`> ${prettyBytes(heapUsed)} memory used`))
35 | console.log()
36 |
37 | if (open && isFirstBuild) {
38 | require('./openBrowser')(`${protocol}://${prettyHost}:${port}${urlPath}`)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/dev-utils/refreshOverlayInterop.js:
--------------------------------------------------------------------------------
1 | const {
2 | dismissRuntimeErrors,
3 | reportRuntimeError
4 | } = require('react-error-overlay')
5 |
6 | module.exports = {
7 | clearRuntimeErrors: dismissRuntimeErrors,
8 | handleRuntimeError: reportRuntimeError
9 | }
10 |
--------------------------------------------------------------------------------
/core/dev-utils/runCompiler.js:
--------------------------------------------------------------------------------
1 | module.exports = compiler =>
2 | new Promise((resolve, reject) => {
3 | compiler.run((err, stats) => {
4 | if (err) return reject(err)
5 | resolve(stats)
6 | })
7 | })
8 |
--------------------------------------------------------------------------------
/core/dev-utils/skipServiceWorker.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | const resetScript = `
4 | self.addEventListener('install', function(e) {
5 | self.skipWaiting()
6 | })
7 |
8 | self.addEventListener('activate', function(e) {
9 | self.registration
10 | .unregister()
11 | .then(function() {
12 | return self.clients.matchAll()
13 | })
14 | .then(function(clients) {
15 | clients.forEach(client => client.navigate(client.url))
16 | })
17 | })
18 |
19 | `
20 |
21 | // Express-like middleware
22 | module.exports = swPath => (req, res, next) => {
23 | if (req.url === path.join('/', swPath || 'service-worker.js')) {
24 | res.setHeader('Content-Type', 'text/javascript')
25 | res.send(resetScript)
26 | } else {
27 | next()
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/core/logger/index.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk')
2 |
3 | class Logger {
4 | constructor(options) {
5 | this.setOptions(options)
6 | }
7 |
8 | setOptions(options) {
9 | this.options = Object.assign({}, this.options, options)
10 | }
11 |
12 | log(...args) {
13 | console.log(
14 | ...args.map(arg => {
15 | return typeof arg === 'function' ? arg() : arg
16 | })
17 | )
18 | }
19 |
20 | debug(...args) {
21 | if (!this.options.debug) {
22 | return
23 | }
24 | this.log(chalk.magenta('debug'), ...args)
25 | }
26 |
27 | error(...args) {
28 | this.log(chalk.red('error'), ...args)
29 | process.exitCode = process.exitCode || 1
30 | }
31 |
32 | success(...args) {
33 | this.log(chalk.green('success'), ...args)
34 | }
35 |
36 | done(...args) {
37 | this.log(
38 | chalk.green(process.platform === 'win32' ? '√' : '✔'),
39 | ...args.map(arg => chalk.bold(arg))
40 | )
41 | }
42 |
43 | warn(...args) {
44 | this.log(chalk.yellow('warning'), ...args)
45 | process.exitCode = process.exitCode || 1
46 | }
47 |
48 | tip(...args) {
49 | this.log(chalk.cyan('tip'), ...args)
50 | }
51 | }
52 |
53 | module.exports = new Logger()
54 |
--------------------------------------------------------------------------------
/core/logger/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@poi/logger",
3 | "version": "12.0.0",
4 | "files": [
5 | "index.js"
6 | ],
7 | "main": "index.js",
8 | "publishConfig": {
9 | "access": "public"
10 | },
11 | "dependencies": {
12 | "chalk": "^2.4.1"
13 | },
14 | "xo": false
15 | }
16 |
--------------------------------------------------------------------------------
/core/poi/README.md:
--------------------------------------------------------------------------------
1 | # Poi
2 |
3 | Check out https://poi.js.org
4 |
--------------------------------------------------------------------------------
/core/poi/__test__/__snapshots__/format.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`cjs-format-cli 1`] = `
4 | Array [
5 | "dist/index.js",
6 | "dist/index.js.map",
7 | "index.js",
8 | ]
9 | `;
10 |
11 | exports[`cjs-format-config 1`] = `
12 | Array [
13 | "dist/index.js",
14 | "dist/index.js.map",
15 | "index.js",
16 | "poi.config.js",
17 | ]
18 | `;
19 |
20 | exports[`umd-format-cli 1`] = `
21 | Array [
22 | "dist/index.html",
23 | "dist/index.js",
24 | "dist/index.js.map",
25 | "index.js",
26 | ]
27 | `;
28 |
29 | exports[`umd-format-config 1`] = `
30 | Array [
31 | "dist/index.html",
32 | "dist/index.js",
33 | "dist/index.js.map",
34 | "index.js",
35 | "poi.config.js",
36 | ]
37 | `;
38 |
--------------------------------------------------------------------------------
/core/poi/__test__/format.test.js:
--------------------------------------------------------------------------------
1 | const createProject = require('@poi/test-utils/createProject')
2 |
3 | test('cjs-format-cli', async () => {
4 | const project = await createProject({ name: 'cjs-format-cli' })
5 | await project.write('index.js', 'export default 123')
6 | await project.run('poi --format cjs')
7 | expect(project.files).toMatchSnapshot()
8 | expect(project.require('dist/index.js')).toEqual({ default: 123 })
9 | })
10 |
11 | test('cjs-format-config', async () => {
12 | const project = await createProject({ name: 'cjs-format-config' })
13 | await Promise.all([
14 | project.write('index.js', 'export default 123'),
15 | project.write('poi.config.js', 'exports.output = { format: "cjs" }')
16 | ])
17 | await project.run('poi')
18 | expect(project.files).toMatchSnapshot()
19 | expect(project.require('dist/index.js')).toEqual({ default: 123 })
20 | })
21 |
22 | test('umd-format-cli', async () => {
23 | const project = await createProject({ name: 'umd-format-cli' })
24 | await project.write('index.js', 'export default 123')
25 | await project.run('poi --format umd --module-name Foo')
26 | expect(project.files).toMatchSnapshot()
27 | expect(project.require('dist/index.js')).toEqual({ default: 123 })
28 | })
29 |
30 | test('umd-format-config', async () => {
31 | const project = await createProject({ name: 'umd-format-config' })
32 | await Promise.all([
33 | project.write('index.js', 'export default 123'),
34 | project.write(
35 | 'poi.config.js',
36 | 'exports.output = { format: "umd", moduleName: "Foo" }'
37 | )
38 | ])
39 | await project.run('poi')
40 | expect(project.files).toMatchSnapshot()
41 | expect(project.require('dist/index.js')).toEqual({ default: 123 })
42 | })
43 |
--------------------------------------------------------------------------------
/core/poi/babel.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/babel/preset')
2 |
--------------------------------------------------------------------------------
/core/poi/bin/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | // eslint-disable-next-line import/no-unassigned-import
3 | require('v8-compile-cache')
4 | const Poi = require('..')
5 |
6 | process.on('unhandledRejection', error => {
7 | console.error(error)
8 | process.exit(1)
9 | })
10 |
11 | async function main() {
12 | try {
13 | const poi = new Poi()
14 | await poi.run()
15 | } catch (error) {
16 | require('../lib/utils/spinner').stop()
17 | if (error.poi) {
18 | if (!error.dismiss) {
19 | require('@poi/logger').error(error.message)
20 | }
21 | } else {
22 | console.error(error.stack)
23 | }
24 | process.exit(1)
25 | }
26 | }
27 |
28 | main()
29 |
--------------------------------------------------------------------------------
/core/poi/lib/Hooks.js:
--------------------------------------------------------------------------------
1 | module.exports = class Hooks {
2 | constructor() {
3 | this.hooks = new Map()
4 | }
5 |
6 | add(name, fn) {
7 | const hooks = this.get(name)
8 | hooks.add(fn)
9 | this.hooks.set(name, hooks)
10 | }
11 |
12 | get(name) {
13 | return this.hooks.get(name) || new Set()
14 | }
15 |
16 | invoke(name, ...args) {
17 | for (const hook of this.get(name)) {
18 | hook(...args)
19 | }
20 | }
21 |
22 | async invokePromise(name, ...args) {
23 | for (const hook of this.get(name)) {
24 | await hook(...args)
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/core/poi/lib/WebpackUtils.js:
--------------------------------------------------------------------------------
1 | module.exports = class WebpackUtils {
2 | constructor(api) {
3 | this.api = api
4 | }
5 |
6 | get envs() {
7 | const envs = {
8 | NODE_ENV: this.api.mode === 'production' ? 'production' : 'development'
9 | }
10 |
11 | // Collect variables starting with `POI_APP_` from `process.env`
12 | for (const name of Object.keys(process.env)) {
13 | if (name.startsWith('POI_APP_')) {
14 | envs[name] = process.env[name]
15 | }
16 | }
17 |
18 | Object.assign(envs, this.api.config.envs, {
19 | PUBLIC_URL: this.api.config.output.publicUrl
20 | })
21 |
22 | return envs
23 | }
24 |
25 | get constants() {
26 | return Object.assign({}, this.api.config.constants)
27 | }
28 |
29 | get CopyPlugin() {
30 | return require('copy-webpack-plugin')
31 | }
32 |
33 | addParallelSupport(rule) {
34 | if (this.api.config.parallel) {
35 | rule.use('thread-loader').loader(require.resolve('thread-loader'))
36 | }
37 |
38 | return this
39 | }
40 |
41 | addCacheSupport(rule, getCacheConfig) {
42 | if (this.api.config.cache) {
43 | rule
44 | .use('cache-loader')
45 | .loader(require.resolve('cache-loader'))
46 | .options(getCacheConfig())
47 | }
48 |
49 | return this
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/core/poi/lib/babel/preset.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const merge = require('lodash.merge')
3 |
4 | const env = process.env.BABEL_ENV || process.env.NODE_ENV
5 | const isTest = env === 'test'
6 | const isDevelopment = env === 'development'
7 |
8 | const validateBoolOption = (name, value, defaultValue) => {
9 | if (typeof value === 'undefined') {
10 | value = defaultValue
11 | }
12 |
13 | if (typeof value !== 'boolean') {
14 | throw new TypeError(`Poi babel preset: '${name}' option must be a boolean.`)
15 | }
16 |
17 | return value
18 | }
19 |
20 | module.exports = (
21 | context,
22 | {
23 | jsx = process.env.POI_JSX || 'react',
24 | jsxPragmaFrag,
25 | flow,
26 | typescript,
27 | env,
28 | namedImports = process.env.POI_NAMED_IMPORTS,
29 | reactRefresh = process.env.POI_REACT_REFRESH
30 | } = {}
31 | ) => {
32 | if (typeof namedImports === 'string') {
33 | namedImports = JSON.parse(namedImports)
34 | }
35 | if (typeof reactRefresh === 'string') {
36 | reactRefresh = reactRefresh === 'true'
37 | }
38 |
39 | const isVueJSX = jsx === 'vue'
40 | const isReactJSX = jsx === 'react'
41 | const isPreactJSX = jsx === 'preact'
42 |
43 | // Enable flow and typescript by default at the same time
44 | // typescript transforms will only be applied to .ts .tsx files
45 | const isFlowEnabled = validateBoolOption('flow', flow, true)
46 | const isTypeScriptEnabled = validateBoolOption('typescript', typescript, true)
47 |
48 | const isReactRefreshEnabled = isDevelopment && reactRefresh
49 |
50 | const presets = [
51 | [
52 | require('@babel/preset-env'),
53 | Object.assign(
54 | {
55 | modules: isTest ? 'commonjs' : false,
56 | targets: isTest
57 | ? {
58 | node: 'current'
59 | }
60 | : {
61 | ie: 9
62 | }
63 | },
64 | env
65 | )
66 | ],
67 | !isVueJSX && [
68 | require('@babel/preset-react'),
69 | {
70 | pragma: isReactJSX ? 'React.createElement' : isPreactJSX ? 'h' : jsx,
71 | pragmaFrag: isReactJSX
72 | ? 'React.Fragment'
73 | : isPreactJSX
74 | ? 'Fragment'
75 | : jsxPragmaFrag
76 | }
77 | ],
78 | isTypeScriptEnabled && require('@babel/preset-typescript')
79 | ].filter(Boolean)
80 |
81 | const plugins = [
82 | // Strip flow types before any other transform, emulating the behavior
83 | // order as-if the browser supported all of the succeeding features
84 | isFlowEnabled && require('@babel/plugin-transform-flow-strip-types'),
85 | // JSX config
86 | isVueJSX && require('@babel/plugin-syntax-jsx'),
87 | isVueJSX && require('babel-plugin-transform-vue-jsx'),
88 | // stage-3 features
89 | require('@babel/plugin-syntax-dynamic-import'),
90 | [
91 | require('@babel/plugin-proposal-class-properties'),
92 | {
93 | // Enable loose mode to use assignment instead of defineProperty
94 | loose: true
95 | }
96 | ],
97 | [
98 | require('@babel/plugin-proposal-object-rest-spread'),
99 | {
100 | useBuiltIns: true
101 | }
102 | ],
103 | [
104 | require('babel-plugin-assets-named-imports'),
105 | {
106 | loaderMap: merge(
107 | {
108 | svg: {
109 | ReactComponent: '!@svgr/webpack?-prettier![path]'
110 | },
111 | md: {
112 | ReactComponent: `!babel-loader?${JSON.stringify({
113 | babelrc: false,
114 | configFile: false,
115 | presets: [__filename]
116 | })}!@mdx-js/loader![path]`
117 | }
118 | },
119 | namedImports
120 | )
121 | }
122 | ],
123 | require('babel-plugin-macros'),
124 | [
125 | require('@babel/plugin-transform-runtime'),
126 | {
127 | helpers: false,
128 | regenerator: true,
129 | absoluteRuntime: path.dirname(
130 | require.resolve('@babel/runtime/package.json')
131 | )
132 | }
133 | ],
134 | require('@babel/plugin-proposal-optional-chaining'),
135 | isReactRefreshEnabled && require('react-refresh/babel')
136 | ].filter(Boolean)
137 |
138 | return {
139 | presets,
140 | plugins
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/command-options.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:shared-options'
2 |
3 | exports.cli = ({ command, isProd }) => {
4 | command.option('-d, --out-dir ', 'Output directory', {
5 | default: 'dist'
6 | })
7 |
8 | command.option('--no-progress', 'Disable default progress bar')
9 |
10 | if (isProd) {
11 | command.option('--source-map', 'Enable source map')
12 | } else {
13 | command.option('--no-source-map', 'Disable source map')
14 | }
15 |
16 | command.option('--parallel', 'Enable multicore compilation (experimental)')
17 |
18 | command.option('--no-cache', 'Disable compilation caching')
19 |
20 | command.option('--public-url ', 'Set the public URL to serve on', {
21 | default: '/'
22 | })
23 | command.option('--public-folder ', 'Use a public folder', {
24 | default: 'public'
25 | })
26 | command.option('--no-public-folder', 'Disable public folder')
27 | command.option('--target ', 'Target environment', {
28 | default: 'web'
29 | })
30 | command.option('--format ', 'Output format', { default: 'iife' })
31 | command.option('--module-name ', 'Module name for "umd" format')
32 | command.option('--file-names ', 'Customize output filenames')
33 | command.option('--no-clean', `Don't clean output directory before bundling`)
34 | command.option('--html ', 'Configure generated HTML file')
35 | command.option('--no-html', `Don't generate HTML file`)
36 | command.option('--no-clear-console', `Don't clear console`)
37 |
38 | if (isProd) {
39 | command.option('--no-minimize', 'Disable minimization')
40 | } else {
41 | command.option('--minimize', 'Minimize output')
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-babel.js:
--------------------------------------------------------------------------------
1 | const logger = require('@poi/logger')
2 |
3 | exports.name = 'builtin:config-babel'
4 |
5 | exports.cli = ({ command }) => {
6 | command
7 | .option('--jsx ', 'Set JSX syntax', {
8 | default: 'react'
9 | })
10 | .option('--no-babelrc', `Disable .babelrc files`)
11 | .option('--no-babel-config-file', `Disable babel.config.js`)
12 | .option(
13 | '--named-imports ',
14 | 'Conver specific named imports to use custom loaders'
15 | )
16 | }
17 |
18 | exports.apply = api => {
19 | api.hook('createWebpackChain', config => {
20 | const { transpileModules, jsx, namedImports } = api.config.babel || {}
21 |
22 | process.env.POI_JSX = jsx
23 | if (namedImports) {
24 | process.env.POI_NAMED_IMPORTS =
25 | typeof namedImports === 'string'
26 | ? namedImports
27 | : JSON.stringify(namedImports)
28 | }
29 |
30 | // Handle .mjs
31 | config.module
32 | .rule('mjs')
33 | .test(/\.mjs$/)
34 | .type('javascript/auto')
35 |
36 | // Handle other js files
37 | const rule = config.module.rule('js')
38 |
39 | rule
40 | .test([/\.m?js$/, /\.jsx$/, /\.ts$/, /\.tsx$/])
41 | .include.add(filepath => {
42 | // Ensure there're no back slashes
43 | filepath = filepath.replace(/\\/g, '/')
44 | // Transpile everthing outside node_modules
45 | if (!/node_modules/.test(filepath)) {
46 | return true
47 | }
48 | if (transpileModules) {
49 | const shouldTranspile = []
50 | .concat(transpileModules)
51 | .some(condition => {
52 | return typeof condition === 'string'
53 | ? filepath.includes(`/node_modules/${condition}/`)
54 | : filepath.match(condition)
55 | })
56 | if (shouldTranspile) {
57 | logger.debug(`Babel is transpiling addtional file "${filepath}"`)
58 | return true
59 | }
60 | }
61 | return false
62 | })
63 |
64 | api.webpackUtils.addParallelSupport(rule)
65 |
66 | rule
67 | .use('babel-loader')
68 | .loader(require.resolve('../webpack/babel-loader'))
69 | .options({
70 | cacheDirectory: api.config.cache,
71 | cacheCompression: api.isProd,
72 | cacheIdentifier: `jsx:${process.env.POI_JSX}::namedImports:${
73 | process.env.POI_NAMED_IMPORTS
74 | }`,
75 | babelrc: api.config.babel.babelrc,
76 | configFile: api.config.babel.configFile
77 | })
78 | })
79 | }
80 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-electron.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-electron'
2 |
3 | exports.apply = api => {
4 | api.hook('createWebpackChain', config => {
5 | if (api.config.target !== 'electron') return
6 |
7 | // Force public URL
8 | config.output.publicPath('./')
9 | config.plugin('envs').tap(([options]) => [
10 | Object.assign(options, {
11 | PUBLIC_URL: JSON.stringify('./')
12 | })
13 | ])
14 |
15 | config.target('electron-renderer')
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-eval.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-eval'
2 |
3 | exports.apply = api => {
4 | api.hook('createWebpackChain', config => {
5 | config.module
6 | .rule('eval')
7 | .test([/\.eval\.js$/, /\.eval\.ts$/])
8 | .type('json')
9 | .post()
10 | .use('eval-loader')
11 | .loader(require.resolve('../webpack/eval-loader'))
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-font.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-font'
2 |
3 | exports.apply = api => {
4 | api.hook('createWebpackChain', config => {
5 | config.module
6 | .rule('font')
7 | .test(/\.(eot|otf|ttf|woff|woff2)(\?.*)?$/)
8 | .use('file-loader')
9 | .loader(require.resolve('file-loader'))
10 | .options({
11 | name: api.config.output.fileNames.font
12 | })
13 | })
14 | }
15 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-image.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-image'
2 |
3 | exports.apply = api => {
4 | api.hook('createWebpackChain', config => {
5 | const filename = api.config.output.fileNames.image
6 |
7 | config.module
8 | .rule('image')
9 | .test([/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.webp$/])
10 | .use('url-loader')
11 | .loader(require.resolve('url-loader'))
12 | .options({
13 | name: filename,
14 | // inline the file if smaller than this size
15 | limit: api.config.assets.inlineImageMaxSize
16 | })
17 |
18 | config.module
19 | .rule('svg')
20 | .test(/\.(svg)(\?.*)?$/)
21 | .use('file-loader')
22 | // SVG files use file-loader directly, why?
23 | // See https://github.com/facebookincubator/create-react-app/pull/1180
24 | .loader(require.resolve('file-loader'))
25 | .options({
26 | name: filename
27 | })
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-jsx-import.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-jsx-import'
2 |
3 | exports.apply = api => {
4 | api.hook('createWebpackChain', config => {
5 | const { jsx } = api.config.babel
6 | if (jsx === 'preact') {
7 | // Automatically add `import { h, Fragment } from 'preact'` for free `h` and `Fragment` identifiers
8 | // In the module scope
9 | config.plugin('jsx-import').use(require('webpack').ProvidePlugin, [
10 | {
11 | h: ['preact', 'h'],
12 | Fragment: ['preact', 'Fragment']
13 | }
14 | ])
15 | } else if (jsx === 'react') {
16 | // Automatically add `import React from 'preact'` for free `React` identifier
17 | // In the module scope
18 | config.plugin('jsx-import').use(require('webpack').ProvidePlugin, [
19 | {
20 | React: 'react'
21 | }
22 | ])
23 | }
24 | })
25 | }
26 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-misc-loaders.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-misc-loaders'
2 |
3 | exports.apply = api => {
4 | api.hook('createWebpackChain', config => {
5 | // GraphQL
6 | config.module
7 | .rule('graphql')
8 | .test(/\.(graphql|gql)$/)
9 | .use('graphql-tag')
10 | .loader('graphql-tag/loader')
11 |
12 | config.module
13 | .rule('toml')
14 | .test(/\.toml$/)
15 | .use('toml-loader')
16 | .loader('toml-loader')
17 |
18 | config.module
19 | .rule('yaml')
20 | .test(/\.ya?ml$/)
21 | .merge({
22 | type: 'json'
23 | })
24 | .use('yaml-loader')
25 | .loader('yaml-loader')
26 |
27 | // prettier-ignore
28 | config.module
29 | .rule('pug')
30 | .test([/\.pug$/, /\.jade$/])
31 | // Pug inside Vue template is loaded as raw string
32 | .oneOf('vue-template')
33 | .resourceQuery(/^\?vue/)
34 | .use('pug-plain-loader')
35 | .loader('pug-plain-loader')
36 | .end()
37 | .end()
38 | // Pug inside js file is loaded as a compiled function
39 | .oneOf('normal')
40 | .use('pug-loader')
41 | .loader('pug-loader')
42 | })
43 | }
44 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-react-refresh.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-react-refresh'
2 |
3 | exports.cli = ({ command }) => {
4 | command.option('--react-refresh', 'Enable React Refresh')
5 | }
6 |
7 | exports.when = api => api.config.reactRefresh && api.mode === 'development'
8 |
9 | exports.apply = api => {
10 | api.hook('createWebpackChain', config => {
11 | process.env.POI_REACT_REFRESH = api.hasDependency('react')
12 |
13 | config
14 | .plugin('react-refresh')
15 | .use(require('@pmmmwh/react-refresh-webpack-plugin'), [
16 | {
17 | overlay: {
18 | entry: require.resolve('@poi/dev-utils/hotDevClient'),
19 | // The expected exports are slightly different from what the overlay exports,
20 | // so an interop is included here to enable feedback on module-level errors.
21 | module: require.resolve('@poi/dev-utils/refreshOverlayInterop'),
22 | // Since we ship a custom dev client and overlay integration,
23 | // the bundled socket handling logic can be eliminated.
24 | sockIntegration: false
25 | }
26 | }
27 | ])
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-reason.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:config-reason'
2 |
3 | exports.when = api => api.hasDependency('bs-platform')
4 |
5 | exports.apply = api => {
6 | api.hook('createWebpackChain', config => {
7 | config.module
8 | .rule('reason')
9 | .test(/\.(re|ml)$/)
10 | .use('reason-loader')
11 | .loader(require.resolve('../webpack/reason-loader'))
12 | .options({
13 | watch: api.cli.options.serve || api.cli.options.watch
14 | })
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-vue.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const resolveFrom = require('resolve-from')
3 | const logger = require('@poi/logger')
4 | const PoiError = require('../utils/PoiError')
5 |
6 | exports.name = 'builtin:config-vue'
7 |
8 | exports.apply = api => {
9 | api.hook('createWebpackChain', config => {
10 | const rule = config.module.rule('vue').test(/\.vue$/)
11 |
12 | const vueLoaderPath = path.dirname(
13 | api.localResolve('vue-loader/package.json') ||
14 | require.resolve('vue-loader/package.json')
15 | )
16 | const vueLoaderPkg = require(path.join(vueLoaderPath, 'package.json'))
17 | const vueLoaderMajorVersion = parseInt(vueLoaderPkg.version, 10)
18 | const isVue3 = vueLoaderMajorVersion >= 16
19 |
20 | if (isVue3 && vueLoaderPkg.version.includes('beta')) {
21 | logger.warn(`You are using the beta version of vue-loader, be aware!`)
22 | }
23 |
24 | const getCacheOptions = () => {
25 | if (isVue3) {
26 | const hasSFCCompiler = api.localResolve(
27 | '@vue/compiler-sfc/package.json'
28 | )
29 | if (!hasSFCCompiler) {
30 | throw new PoiError(
31 | `Expect @vue/compiler-sfc to be installed in current project`
32 | )
33 | }
34 | return api.getCacheConfig('vue-loader', {
35 | 'vue-loader': vueLoaderPkg.version,
36 | '@vue/compiler-sfc': hasSFCCompiler
37 | ? api.localRequire('@vue/compiler-sfc/package.json').version
38 | : null
39 | })
40 | }
41 |
42 | const compilerPkg = require(resolveFrom(
43 | vueLoaderPath,
44 | '@vue/component-compiler-utils/package'
45 | ))
46 | return api.getCacheConfig('vue-loader', {
47 | 'vue-loader': vueLoaderPkg.version,
48 | '@vue/component-compiler-utils': compilerPkg.version,
49 | 'vue-template-compiler': api.localResolve(
50 | 'vue-template-compiler/package'
51 | )
52 | ? api.localRequire('vue-template-compiler/package').version
53 | : null
54 | })
55 | }
56 |
57 | api.webpackUtils.addCacheSupport(rule, getCacheOptions)
58 |
59 | rule
60 | .use('vue-loader')
61 | .loader(require.resolve(vueLoaderPath))
62 | .options(
63 | Object.assign(
64 | {
65 | // TODO: error with thread-loader
66 | compiler: isVue3
67 | ? undefined
68 | : api.localRequire('vue-template-compiler')
69 | },
70 | // For Vue templates
71 | api.config.cache && getCacheOptions()
72 | )
73 | )
74 |
75 | config.plugin('vue').use(require(vueLoaderPath).VueLoaderPlugin)
76 | })
77 | }
78 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/config-yarn-pnp.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:yarn-pnp'
2 |
3 | exports.when = api =>
4 | api.pkg.data.installConfig && api.pkg.data.installConfig.pnp
5 |
6 | exports.apply = api => {
7 | api.hook('createWebpackChain', config => {
8 | const { apply, moduleLoader } = require('@poi/pnp-webpack-plugin')
9 |
10 | config.resolve.plugin('pnp').use(
11 | class PnpWebpackPlugin {
12 | apply(...args) {
13 | return apply(...args)
14 | }
15 | }
16 | )
17 |
18 | config.resolveLoader.plugin('pnp').use(
19 | class PnpWebpackPlugin {
20 | apply(...args) {
21 | return moduleLoader(module).apply(...args)
22 | }
23 | }
24 | )
25 | })
26 | }
27 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/eject-html.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | exports.name = 'eject-html'
4 |
5 | exports.cli = api => {
6 | api.cli
7 | .command('eject-html [out-file]', 'Eject the default HTML file')
8 | .option('--overwrite', 'Overwrite exiting file')
9 | .action(async (outFile = 'public/index.html', options) => {
10 | const fs = require('fs-extra')
11 | if (
12 | !options.overwrite &&
13 | (await fs.pathExists(api.resolveCwd(outFile)))
14 | ) {
15 | return api.logger.error(
16 | `${outFile} already existing, try --overwrite flag if you want to update it`
17 | )
18 | }
19 | await fs.copy(
20 | path.join(__dirname, '../webpack/default-template.html'),
21 | api.resolveCwd(outFile)
22 | )
23 | api.logger.done(`Ejected to ${outFile}`)
24 | })
25 | }
26 |
--------------------------------------------------------------------------------
/core/poi/lib/plugins/watch.js:
--------------------------------------------------------------------------------
1 | exports.name = 'builtin:watch'
2 |
3 | exports.cli = api => {
4 | const { command, args } = api
5 |
6 | command.option('-w, --watch', 'Watch and rebuild on file changes')
7 |
8 | if (!args.has('w') && !args.has('watch')) return
9 |
10 | command.action(() => {
11 | const compiler = api.createWebpackCompiler(
12 | api.createWebpackChain().toConfig()
13 | )
14 | compiler.watch({}, err => {
15 | if (err) {
16 | api.logger.error(err)
17 | }
18 | })
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/PoiError.js:
--------------------------------------------------------------------------------
1 | module.exports = class PoiError extends Error {
2 | constructor(message) {
3 | const options = typeof message === 'string' ? { message } : message
4 | super(options.message)
5 | this.dismiss = options.dismiss
6 | this.poi = true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/WebpackChain.js:
--------------------------------------------------------------------------------
1 | const Chain = require('webpack-chain')
2 | const merge = require('webpack-merge')
3 |
4 | module.exports = class WebpackChain extends Chain {
5 | constructor({ configureWebpack, opts }) {
6 | super()
7 | this.configureWebpack = configureWebpack
8 | this.opts = opts
9 | }
10 |
11 | toConfig() {
12 | let config = super.toConfig()
13 | if (typeof this.configureWebpack === 'function') {
14 | config = this.configureWebpack(config, this.opts) || config
15 | } else if (typeof this.configureWebpack === 'object') {
16 | config = merge({}, config, this.configureWebpack)
17 | }
18 | return config
19 | }
20 |
21 | toString(options) {
22 | return Chain.toString(this.toConfig(), options)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/__test__/plugins.test.js:
--------------------------------------------------------------------------------
1 | const { mergePlugins } = require('../plugins')
2 |
3 | test('merge', () => {
4 | expect(
5 | mergePlugins(
6 | [{ resolve: 'foo' }, { resolve: 'bar', options: { foo: 'bar' } }],
7 | [
8 | {
9 | resolve: 'foo'
10 | },
11 | {
12 | resolve: 'baz'
13 | }
14 | ]
15 | )
16 | ).toEqual([
17 | { resolve: 'foo' },
18 | { resolve: 'bar', options: { foo: 'bar' } },
19 | {
20 | resolve: 'baz'
21 | }
22 | ])
23 | })
24 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/createConfigLoader.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const Module = require('module')
4 | const colors = require('chalk')
5 | const JoyCon = require('joycon').default
6 | const PoiError = require('./PoiError')
7 |
8 | const rcLoader = {
9 | name: 'rc',
10 | test: /\.[a-z]+rc$/,
11 | loadSync(filePath) {
12 | return JSON.parse(fs.readFileSync(filePath, 'utf8'))
13 | }
14 | }
15 |
16 | const tsLoader = {
17 | name: 'ts',
18 | test: /\.ts$/,
19 | loadSync(filePath) {
20 | if (!Module._extensions['.ts']) {
21 | throw new PoiError(
22 | `Found ${path.relative(
23 | process.cwd(),
24 | filePath
25 | )}, try installing ${colors.bold(
26 | '`ts-node`'
27 | )} and using CLI flag ${colors.bold(
28 | '`-r ts-node/register`'
29 | )} to support .ts config files. If you don't need type checking, use ${colors.bold(
30 | '`-r ts-node/register/transpile-only`'
31 | )} instead.`
32 | )
33 | }
34 | const result = require(filePath)
35 | return result.default || result
36 | }
37 | }
38 |
39 | module.exports = cwd => {
40 | const configLoader = new JoyCon({ cwd, stopDir: path.dirname(process.cwd()) })
41 |
42 | configLoader.addLoader(rcLoader)
43 | configLoader.addLoader(tsLoader)
44 |
45 | return {
46 | load(opts, noCache) {
47 | if (noCache) {
48 | configLoader.clearCache()
49 | }
50 | return configLoader.loadSync(opts)
51 | },
52 | resolve(opts, noCache) {
53 | if (noCache) {
54 | configLoader.clearCache()
55 | }
56 | return configLoader.resolveSync(opts)
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/getFileNames.js:
--------------------------------------------------------------------------------
1 | module.exports = ({ useHash, format }) => {
2 | let res
3 |
4 | if (format === 'iife') {
5 | res = {
6 | js: useHash ? 'assets/js/[name].[chunkhash:8].js' : 'assets/js/[name].js',
7 | css: useHash
8 | ? 'assets/css/[name].[chunkhash:8].css'
9 | : 'assets/css/[name].css',
10 | font: useHash
11 | ? 'assets/fonts/[path][name].[hash:8].[ext]'
12 | : 'assets/fonts/[path][name].[ext]',
13 | image: useHash
14 | ? 'assets/images/[path][name].[hash:8].[ext]'
15 | : 'assets/images/[path][name].[ext]'
16 | }
17 | } else {
18 | res = {
19 | js: '[name].js',
20 | css: '[name].css',
21 | font: '[path][name].[ext]',
22 | image: '[path][name].[ext]'
23 | }
24 | }
25 |
26 | return res
27 | }
28 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/isLocalPath.js:
--------------------------------------------------------------------------------
1 | module.exports = v => /^[./]|(^[a-zA-Z]:)/.test(v)
2 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/loadEnvs.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const logger = require('@poi/logger')
3 |
4 | module.exports = (mode, dotenvPath) => {
5 | const dotenvFiles = [
6 | `${dotenvPath}.${mode}.local`,
7 | `${dotenvPath}.${mode}`,
8 | // Don't include `.env.local` for `test` mode
9 | // since normally you expect tests to produce the same
10 | // results for everyone
11 | mode !== 'test' && `${dotenvPath}.local`,
12 | dotenvPath
13 | ].filter(Boolean)
14 |
15 | dotenvFiles.forEach(dotenvFile => {
16 | if (fs.existsSync(dotenvFile)) {
17 | logger.debug('Using env file:', dotenvFile)
18 | require('dotenv-expand')(
19 | require('dotenv').config({
20 | path: dotenvFile
21 | })
22 | )
23 | }
24 | })
25 | }
26 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/mergeConfig.js:
--------------------------------------------------------------------------------
1 | const merge = require('lodash.merge')
2 |
3 | module.exports = (config, cliConfig) => {
4 | const devServer = merge({}, config.devServer, cliConfig.devServer, {
5 | proxy: []
6 | .concat((config.devServer && config.devServer.proxy) || [])
7 | .concat(cliConfig.devServer.proxy || [])
8 | })
9 | return merge({}, config, cliConfig, {
10 | devServer
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/parseArgs.js:
--------------------------------------------------------------------------------
1 | const cac = require('cac')
2 |
3 | module.exports = _args => {
4 | const cli = cac()
5 | const { args, options } = cli.parse(_args)
6 |
7 | return {
8 | get(name) {
9 | return options[name]
10 | },
11 |
12 | has(name) {
13 | return this.get(name) !== undefined
14 | },
15 |
16 | options,
17 |
18 | args
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/plugins.js:
--------------------------------------------------------------------------------
1 | const resolveFrom = require('resolve-from')
2 | const logger = require('@poi/logger')
3 | const isLocalPath = require('./isLocalPath')
4 | const PoiError = require('./PoiError')
5 |
6 | const normalizePluginName = (name, cwd) => {
7 | if (isLocalPath(name)) return name
8 |
9 | // @poi/foo => @poi/plugin-foo
10 | // @my-org/hehe => @my-org/poi-plugin-hehe
11 | if (/^@[^/]+\//.test(name)) {
12 | return name.replace(/^@([^/]+)\/(poi-)?(plugin-)?/, (_, m1) => {
13 | return m1 === 'poi' ? `@poi/plugin-` : `@${m1}/poi-plugin-`
14 | })
15 | }
16 |
17 | const prefixedName = name.replace(/^(poi-plugin-)?/, 'poi-plugin-')
18 |
19 | // if a prefixed name exists, use it directly
20 | if (resolveFrom.silent(cwd, prefixedName)) {
21 | return prefixedName
22 | }
23 |
24 | return name
25 | }
26 |
27 | exports.normalizePlugins = (plugins, cwd) => {
28 | return [].concat(plugins || []).map(v => {
29 | if (typeof v === 'string') {
30 | v = { resolve: v }
31 | }
32 | if (typeof v.resolve === 'string') {
33 | const pluginName = normalizePluginName(v.resolve, cwd)
34 | const resolvedPlugin = resolveFrom.silent(cwd, pluginName)
35 | if (!resolvedPlugin) {
36 | const message = `Cannot find plugin \`${pluginName}\` in your project`
37 | logger.error(message)
38 | logger.error(`Did you forget to install it?`)
39 | throw new PoiError({
40 | message,
41 | dismiss: true
42 | })
43 | }
44 | v = Object.assign({}, v, {
45 | resolve: resolvedPlugin
46 | })
47 | }
48 | return v
49 | })
50 | }
51 |
52 | exports.mergePlugins = (configPlugins, cliPlugins) => {
53 | return configPlugins.concat(
54 | cliPlugins.filter(cliPlugin => {
55 | return !configPlugins.find(
56 | configPlugin => configPlugin.resolve === cliPlugin.resolve
57 | )
58 | })
59 | )
60 | }
61 |
--------------------------------------------------------------------------------
/core/poi/lib/utils/spinner.js:
--------------------------------------------------------------------------------
1 | const ora = require('ora')
2 |
3 | module.exports = ora()
4 |
--------------------------------------------------------------------------------
/core/poi/lib/webpack/PrintStatusPlugin.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const chalk = require('chalk')
3 | const textTable = require('text-table')
4 | const gzipSize = require('gzip-size')
5 | const formatWebpackMessages = require('@poi/dev-utils/formatWebpackMessages')
6 | const prettyBytes = require('@poi/dev-utils/prettyBytes')
7 | const logger = require('@poi/logger')
8 | const prettyTime = require('pretty-ms')
9 |
10 | class PrintStatusPlugin {
11 | constructor(opts = {}) {
12 | this.opts = opts
13 | }
14 |
15 | apply(compiler) {
16 | compiler.hooks.invalid.tap('show-rebuild-reason', file => {
17 | const d = new Date()
18 | logger.log(
19 | chalk.dim(
20 | `[${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}] Rebuilding due to changes in ${file}`
21 | )
22 | )
23 | })
24 |
25 | compiler.hooks.done.tapPromise('print-status', async stats => {
26 | if (this.opts.clearConsole !== false && process.env.NODE_ENV !== 'test') {
27 | require('@poi/dev-utils/clearConsole')()
28 | }
29 | if (stats.hasErrors() || stats.hasWarnings()) {
30 | if (stats.hasErrors()) {
31 | process.exitCode = 1
32 | }
33 |
34 | // Print prettified errors and warnings
35 | const messages = formatWebpackMessages(stats.toJson())
36 | if (messages) {
37 | const { errors, warnings } = messages
38 | for (const error of errors) {
39 | console.error(error)
40 | }
41 | for (const warning of warnings) {
42 | console.error(warning)
43 | }
44 | }
45 | // Print full stats in debug mode
46 | logger.debug(() =>
47 | stats.toString({
48 | colors: true
49 | })
50 | )
51 | } else {
52 | if (this.opts.printSucessMessage) {
53 | logger.done(
54 | `Build completed in ${prettyTime(stats.endTime - stats.startTime)}`
55 | )
56 | }
57 | // Print file stats
58 | if (
59 | (this.opts.printFileStats || logger.options.debug) &&
60 | !process.env.CI &&
61 | process.stdout.isTTY
62 | ) {
63 | logger.log()
64 | const assets = await Promise.all(
65 | stats.toJson().assets.map(async asset => {
66 | asset.gzipped = await gzipSize(
67 | stats.compilation.assets[asset.name].source()
68 | )
69 | return asset
70 | })
71 | )
72 | const data = assets.map(asset => {
73 | const filename = path.relative(
74 | process.cwd(),
75 | path.join(compiler.options.output.path, asset.name)
76 | )
77 | return [
78 | path.join(
79 | path.dirname(filename),
80 | chalk.bold(path.basename(filename))
81 | ),
82 | chalk.green(prettyBytes(asset.size)),
83 | chalk.green(prettyBytes(asset.gzipped))
84 | ]
85 | })
86 | data.unshift([
87 | chalk.bold('file'),
88 | chalk.bold('size'),
89 | chalk.bold('gzipped')
90 | ])
91 | data.push([
92 | '(total)',
93 | chalk.green(
94 | prettyBytes(
95 | assets.reduce((result, asset) => result + asset.size, 0)
96 | )
97 | ),
98 | chalk.green(
99 | prettyBytes(
100 | assets.reduce((result, asset) => result + asset.gzipped, 0)
101 | )
102 | )
103 | ])
104 | logger.log(
105 | textTable(data, {
106 | stringLength: require('string-width')
107 | })
108 | )
109 | }
110 | }
111 | })
112 | }
113 | }
114 |
115 | module.exports = PrintStatusPlugin
116 |
--------------------------------------------------------------------------------
/core/poi/lib/webpack/babel-loader.js:
--------------------------------------------------------------------------------
1 | const babelLoader = require('babel-loader')
2 | const logger = require('@poi/logger')
3 | const spinner = require('../utils/spinner')
4 |
5 | const macroCheck = new RegExp('[./]macro')
6 |
7 | module.exports = babelLoader.custom(babel => {
8 | const configs = new Set()
9 | const presetItem = babel.createConfigItem(require('../babel/preset'), {
10 | type: 'preset'
11 | })
12 |
13 | return {
14 | customOptions(opts) {
15 | const custom = opts.customLoaderOptions
16 | delete opts.customLoaderOptions
17 |
18 | return { loader: opts, custom }
19 | },
20 | config(cfg, { source }) {
21 | const options = Object.assign({}, cfg.options, {
22 | caller: Object.assign({}, cfg.options.caller, {
23 | // for babel-plugin-macros it should never be cached
24 | poiInvalidationToken: macroCheck.test(source)
25 | ? require('crypto')
26 | .randomBytes(32)
27 | .toString('hex')
28 | : ''
29 | })
30 | })
31 |
32 | if (cfg.hasFilesystemConfig()) {
33 | for (const file of [cfg.babelrc, cfg.config]) {
34 | if (file && !configs.has(file)) {
35 | configs.add(file)
36 | spinner.stop()
37 | logger.debug(`Using external babel config file: ${file}`)
38 | }
39 | }
40 | } else {
41 | // Add our default preset if the no "babelrc" found.
42 | options.presets = [...options.presets, presetItem]
43 | }
44 |
45 | return options
46 | }
47 | }
48 | })
49 |
--------------------------------------------------------------------------------
/core/poi/lib/webpack/default-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | <%= html.title %>
8 |
9 | <% if (pkg.description) { %>
10 |
11 | <% } %>
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/core/poi/lib/webpack/eval-loader.js:
--------------------------------------------------------------------------------
1 | const NativeModule = require('module')
2 |
3 | module.exports = async function(source, map) {
4 | this.cacheable()
5 | const done = this.async()
6 |
7 | const exec = (code, filename) => {
8 | delete require.cache[filename]
9 | const module = new NativeModule(filename, this)
10 | module.paths = NativeModule._nodeModulePaths(this.context)
11 | module.filename = filename
12 | module._compile(transpileEsModules(code, filename), filename)
13 | return module.exports.default || module.exports
14 | }
15 |
16 | try {
17 | const exported = exec(source, this.resourcePath)
18 | const result = await exported.call(this)
19 | done(null, `${JSON.stringify(result)}`, map)
20 | } catch (error) {
21 | done(error)
22 | }
23 | }
24 |
25 | function transpileEsModules(code, filename) {
26 | const RE = /\b(import|export)\b/
27 | if (!RE.test(code)) {
28 | return code
29 | }
30 | // Use babel-preset-env to transpile potentional `import/export` statements
31 | return require('@babel/core').transform(code, {
32 | filename,
33 | babelrc: false,
34 | configFile: false,
35 | presets: [
36 | [
37 | require.resolve('@babel/preset-env'),
38 | {
39 | targets: {
40 | node: 'current'
41 | }
42 | }
43 | ]
44 | ]
45 | }).code
46 | }
47 |
--------------------------------------------------------------------------------
/core/poi/lib/webpack/reason-loader.js:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | const { watch } = this.query || {}
3 | const outFile = this.resourcePath.replace(/\.(re|ml)$/, '.bs.js')
4 | const fs = this.fs || require('fs')
5 | try {
6 | fs.statSync(outFile)
7 | return `export * from ${JSON.stringify(outFile)}`
8 | } catch (_) {
9 | throw new Error(
10 | `Cannot find ${outFile}\nYou must run \`bsb -make-world${
11 | watch ? ' -w' : ''
12 | }\` first.`
13 | )
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/poi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "poi",
3 | "version": "12.10.3",
4 | "main": "lib/index.js",
5 | "bin": "bin/cli.js",
6 | "description": "A zero-config bundler for JavaScript applications.",
7 | "scripts": {
8 | "test": "jest"
9 | },
10 | "files": [
11 | "lib",
12 | "bin",
13 | "babel.js",
14 | "webpack.config.js",
15 | "!**/__test__/**"
16 | ],
17 | "license": "MIT",
18 | "dependencies": {
19 | "@babel/core": "^7.1.6",
20 | "@babel/plugin-proposal-class-properties": "^7.1.0",
21 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
22 | "@babel/plugin-proposal-optional-chaining": "^7.9.0",
23 | "@babel/plugin-syntax-dynamic-import": "^7.0.0",
24 | "@babel/plugin-syntax-jsx": "^7.0.0",
25 | "@babel/plugin-transform-flow-strip-types": "^7.1.6",
26 | "@babel/plugin-transform-runtime": "^7.1.0",
27 | "@babel/preset-env": "^7.1.6",
28 | "@babel/preset-react": "^7.0.0",
29 | "@babel/preset-typescript": "^7.1.0",
30 | "@babel/runtime": "^7.1.5",
31 | "@intervolga/optimize-cssnano-plugin": "^1.0.6",
32 | "@pmmmwh/react-refresh-webpack-plugin": "^0.4.1",
33 | "@poi/dev-utils": "^12.1.6",
34 | "@poi/logger": "^12.0.0",
35 | "@poi/plugin-html-entry": "^0.2.3",
36 | "@poi/pnp-webpack-plugin": "^0.0.2",
37 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
38 | "babel-loader": "^8.0.4",
39 | "babel-plugin-assets-named-imports": "^0.2.1",
40 | "babel-plugin-macros": "^2.4.2",
41 | "babel-plugin-transform-vue-jsx": "^4.0.0",
42 | "cac": "^6.3.12",
43 | "cache-loader": "^4.1.0",
44 | "case-sensitive-paths-webpack-plugin": "^2.1.2",
45 | "chalk": "^2.4.1",
46 | "copy-webpack-plugin": "^5.1.1",
47 | "css-loader": "^3.0.0",
48 | "cssnano": "^4.1.7",
49 | "dotenv": "^8.1.0",
50 | "dotenv-expand": "^4.2.0",
51 | "extract-css-chunks-webpack-plugin": "^4.7.4",
52 | "file-loader": "^2.0.0",
53 | "fs-extra": "^9.0.0",
54 | "get-port": "^5.0.0",
55 | "gzip-size": "^5.0.0",
56 | "html-webpack-plugin": "^4.0.0-beta.4",
57 | "joycon": "^2.2.1",
58 | "launch-editor-middleware": "^2.2.1",
59 | "lodash.merge": "^4.6.1",
60 | "ora": "^3.0.0",
61 | "postcss-loader": "^3.0.0",
62 | "pretty-ms": "^4.0.0",
63 | "react-refresh": "^0.8.3",
64 | "resolve-from": "^5.0.0",
65 | "string-width": "^4.1.0",
66 | "superstruct": "^0.6.0",
67 | "terser-webpack-plugin": "^2.1.2",
68 | "text-table": "^0.2.0",
69 | "thread-loader": "^1.2.0",
70 | "url-loader": "^4.1.0",
71 | "v8-compile-cache": "^2.0.2",
72 | "vue-loader": "^15.4.2",
73 | "vue-style-loader": "^4.1.2",
74 | "webpack": "^4.26.0",
75 | "webpack-chain": "^6.4.0",
76 | "webpack-dev-server": "^3.11.0",
77 | "webpack-merge": "^4.1.4"
78 | },
79 | "xo": false,
80 | "devDependencies": {
81 | "@poi/test-utils": "^12.0.2",
82 | "vue-template-compiler": "^2.5.21"
83 | },
84 | "keywords": [
85 | "poi",
86 | "webpack",
87 | "zero-config",
88 | "bundler",
89 | "vue-cli",
90 | "parcel",
91 | "create-react-app",
92 | "babel"
93 | ]
94 | }
95 |
--------------------------------------------------------------------------------
/core/poi/webpack.config.js:
--------------------------------------------------------------------------------
1 | const Poi = require('.')
2 |
3 | const poi = new Poi()
4 |
5 | module.exports = poi.createWebpackChain().toConfig()
6 |
--------------------------------------------------------------------------------
/core/test-utils/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [12.0.2](https://github.com/egoist/poi/compare/@poi/test-utils@12.0.1...@poi/test-utils@12.0.2) (2020-04-30)
7 |
8 | **Note:** Version bump only for package @poi/test-utils
9 |
10 |
11 |
12 |
13 |
14 | ## [12.0.1](https://github.com/egoist/poi/compare/@poi/test-utils@12.0.0...@poi/test-utils@12.0.1) (2019-07-27)
15 |
16 | **Note:** Version bump only for package @poi/test-utils
17 |
--------------------------------------------------------------------------------
/core/test-utils/createProject.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const glob = require('fast-glob')
3 | const execa = require('execa')
4 | const fs = require('fs-extra')
5 |
6 | module.exports = async ({ name = Date.now() } = {}) => {
7 | const cwd = path.join(__dirname, `.test-projects/poi-${name}`)
8 | /** @type {string[]} */
9 | let files
10 |
11 | await fs.remove(cwd)
12 |
13 | const run = async cmd => {
14 | const [name, ...args] = cmd.split(' ')
15 | await execa(name, args, { cwd })
16 | files = await glob(['**/*', '!**/node_modules**'], { cwd })
17 | }
18 |
19 | return {
20 | get files() {
21 | return files.sort()
22 | },
23 | run,
24 | has(file) {
25 | return files && files.includes(file)
26 | },
27 | async write(file, content) {
28 | await fs.outputFile(path.join(cwd, file), content, 'utf8')
29 | },
30 | require(file) {
31 | return require(path.join(cwd, file))
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/core/test-utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@poi/test-utils",
3 | "version": "12.0.2",
4 | "files": [
5 | "*.js"
6 | ],
7 | "publishConfig": {
8 | "access": "public"
9 | },
10 | "xo": false,
11 | "dependencies": {
12 | "execa": "^1.0.0",
13 | "fast-glob": "^3.0.4",
14 | "fs-extra": "^9.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/create-poi-app/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [12.2.2](https://github.com/egoist/poi/compare/create-poi-app@12.2.1...create-poi-app@12.2.2) (2020-08-19)
7 |
8 | **Note:** Version bump only for package create-poi-app
9 |
10 | ## [12.2.1](https://github.com/egoist/poi/compare/create-poi-app@12.2.0...create-poi-app@12.2.1) (2020-04-30)
11 |
12 | **Note:** Version bump only for package create-poi-app
13 |
14 | # [12.2.0](https://github.com/egoist/poi/compare/create-poi-app@12.1.2...create-poi-app@12.2.0) (2019-07-03)
15 |
16 | ### Features
17 |
18 | - **create-poi-app:** add update notifier in pwa ([#580](https://github.com/egoist/poi/issues/580)) ([5b4bbaf](https://github.com/egoist/poi/commit/5b4bbaf))
19 |
20 | ## [12.1.2](https://github.com/egoist/poi/compare/create-poi-app@12.1.1...create-poi-app@12.1.2) (2019-01-09)
21 |
22 | ### Bug Fixes
23 |
24 | - properly add pnp plugins ([fdcd9e7](https://github.com/egoist/poi/commit/fdcd9e7))
25 |
26 | ## [12.1.1](https://github.com/egoist/poi/compare/create-poi-app@12.1.0...create-poi-app@12.1.1) (2019-01-09)
27 |
28 | ### Bug Fixes
29 |
30 | - support yarn pnp ([ca61aaa](https://github.com/egoist/poi/commit/ca61aaa))
31 |
32 | # [12.1.0](https://github.com/egoist/poi/compare/create-poi-app@12.0.3...create-poi-app@12.1.0) (2019-01-09)
33 |
34 | ### Features
35 |
36 | - use plugin-karma 13 in create-poi-app ([2b2ae26](https://github.com/egoist/poi/commit/2b2ae26))
37 |
38 | ## [12.0.3](https://github.com/egoist/poi/compare/create-poi-app@12.0.2...create-poi-app@12.0.3) (2018-12-25)
39 |
40 | ### Features
41 |
42 | - add a hook to allow modifing devServer config ([df939e6](https://github.com/egoist/poi/commit/df939e6))
43 |
--------------------------------------------------------------------------------
/create-poi-app/README.md:
--------------------------------------------------------------------------------
1 | # Create Poi App
2 |
3 | ```bash
4 | npm i -g create-poi-app
5 |
6 | cpa my-app
7 | ```
8 |
--------------------------------------------------------------------------------
/create-poi-app/bin/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | const path = require('path')
3 | const cli = require('cac')()
4 |
5 | cli
6 | .command('', 'Generate a new project to target folder')
7 | .option(
8 | '--npm-client ',
9 | `Choose an npm client for installing packages ('yarn' | 'npm' | 'pnpm')`
10 | )
11 | .action(async (targetFolder, { npmClient }) => {
12 | const sao = require('sao')
13 |
14 | const app = sao({
15 | generator: path.join(__dirname, '../generator'),
16 | outDir: targetFolder,
17 | npmClient
18 | })
19 |
20 | await app.run().catch(sao.handleError)
21 | })
22 |
23 | cli.help()
24 | cli.version(require('../package').version)
25 |
26 | cli.parse()
27 |
--------------------------------------------------------------------------------
/create-poi-app/generator/__test__/index.test.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const sao = require('sao')
3 |
4 | const generator = path.join(__dirname, '..')
5 |
6 | test('defaults', async () => {
7 | const stream = await sao.mock(
8 | { generator },
9 | {
10 | features: ['linter'],
11 | linterConfig: 'xo'
12 | }
13 | )
14 | expect(stream.fileList).toContain('.eslintrc.js')
15 | const pkg = JSON.parse(await stream.readFile('package.json'))
16 | const deps = [...Object.keys(pkg.devDependencies)]
17 | expect(deps).toContain('eslint')
18 | expect(deps).toContain('eslint-config-xo')
19 | expect(deps).toContain('@poi/plugin-eslint')
20 | expect(pkg.scripts.lint).toBe('eslint .')
21 | })
22 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/js/src/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-env browser */
2 | import './assets/css/style.css';
3 |
4 | const title = document.createElement('h1');
5 | title.textContent = 'Hello Poi!';
6 | title.className = 'title';
7 |
8 | const tip = document.createElement('div');
9 | tip.textContent = 'Edit src/index.js and save to reload.';
10 | tip.className = 'tip';
11 |
12 | const app = document.getElementById('app');
13 |
14 | if (app) {
15 | app.appendChild(title);
16 | app.appendChild(tip);
17 | }
18 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/js/src/index.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jasmine */
2 | describe('main', () => {
3 | it('works', () => {
4 | expect(1).toBe(1);
5 | });
6 | });
7 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/linter-tslint/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "warning",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "linterOptions": {
7 | "exclude": [
8 | "node_modules/**"
9 | ]
10 | },
11 | "rules": {
12 | "quotemark": [true, "single"],
13 | "indent": [true, "spaces", 2],
14 | "interface-name": false,
15 | "ordered-imports": false,
16 | "object-literal-sort-keys": false,
17 | "no-consecutive-blank-lines": false
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/linter-xo/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | 'xo'
4 | ],
5 | rules: {
6 | indent: ['error', 2]
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/main/README.md:
--------------------------------------------------------------------------------
1 | # <%= context.outFolder %>
2 |
3 | > Created by [create-poi-app](https://poi.js.org).
4 |
5 | ## Project Scripts
6 |
7 | ### `npm run build`
8 |
9 | Build app for production to `./dist` folder.
10 |
11 | ### `npm run dev`
12 |
13 | Start a dev server to preview your app.
14 |
15 | <% if (unit) { %>
16 |
17 | ### `npm run test:unit`
18 |
19 | Run unit tests.
20 | <% } %>
21 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/main/_gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/main/package.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/main/poi.config.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/egoist/poi/25f782797c4bf4e85ab3a23c0a6a040f7843c5db/create-poi-app/generator/templates/main/poi.config.js
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/main/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/egoist/poi/25f782797c4bf4e85ab3a23c0a6a040f7843c5db/create-poi-app/generator/templates/main/public/favicon.ico
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/main/src/assets/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | background: #333;
4 | color: #74d7fd;
5 | text-align: center;
6 | }
7 |
8 | .title {
9 | margin-top: 300px;
10 | font-size: 4rem;
11 | }
12 |
13 | .tip {
14 | font-size: 1.4rem;
15 | }
16 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/pwa/public/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/egoist/poi/25f782797c4bf4e85ab3a23c0a6a040f7843c5db/create-poi-app/generator/templates/pwa/public/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/pwa/public/img/icons/msapplication-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/egoist/poi/25f782797c4bf4e85ab3a23c0a6a040f7843c5db/create-poi-app/generator/templates/pwa/public/img/icons/msapplication-icon-144x144.png
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/pwa/public/img/icons/safari-mask-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/pwa/public/manifest.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/pwa/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
2 | const { Workbox } = require('workbox-window')
3 |
4 | const workbox = new Workbox(`${process.env.PUBLIC_URL}service-worker.js`)
5 |
6 | const addNotifier = () => {
7 | const { createSnackbar } = require('@egoist/snackbar')
8 | require('@egoist/snackbar/dist/snackbar.css')
9 |
10 | const pwaFirstTimeInstallMessage = 'Ready for offline use'
11 | const pwaUpdateReadyMessage = 'A new version of this app is available'
12 | const pwaUpdateButtonMessage = 'UPDATE'
13 | const pwaDismissMessage = 'DISMISS'
14 |
15 | const showUpdateNotifier = () => {
16 | createSnackbar(pwaUpdateReadyMessage, {
17 | position: 'right',
18 | timeout: 20000,
19 | actions: [
20 | {
21 | text: pwaUpdateButtonMessage,
22 | style: {
23 | color: 'pink'
24 | },
25 | callback(button) {
26 | button.innerHTML = ``
27 | button.disabled = true
28 |
29 | workbox.addEventListener('controlling', () => {
30 | window.location.reload()
31 | })
32 |
33 | workbox.messageSW({ type: 'SKIP_WAITING' })
34 | }
35 | }
36 | ]
37 | })
38 | }
39 |
40 | workbox.addEventListener('installed', event => {
41 | if (!event.isUpdate) {
42 | createSnackbar(pwaFirstTimeInstallMessage, {
43 | position: 'right',
44 | timeout: 5000,
45 | actions: [
46 | {
47 | text: pwaDismissMessage
48 | }
49 | ]
50 | })
51 | }
52 | })
53 |
54 | workbox.addEventListener('waiting', () => {
55 | showUpdateNotifier()
56 | })
57 | }
58 |
59 | addNotifier()
60 |
61 | workbox.register()
62 | }
63 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/ts/src/index.test.ts:
--------------------------------------------------------------------------------
1 | describe('main', () => {
2 | it('works', () => {
3 | expect(1).toBe(1);
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/ts/src/index.ts:
--------------------------------------------------------------------------------
1 | import './assets/css/style.css';
2 |
3 | const title = document.createElement('h1');
4 | title.textContent = 'Hello Poi!';
5 | title.className = 'title';
6 |
7 | const tip = document.createElement('div');
8 | tip.textContent = 'Edit src/index.ts and save to reload.';
9 | tip.className = 'tip';
10 |
11 | const app = document.getElementById('app');
12 |
13 | if (app) {
14 | app.appendChild(title);
15 | app.appendChild(tip);
16 | }
17 |
--------------------------------------------------------------------------------
/create-poi-app/generator/templates/ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "esnext",
4 | "target": "es5",
5 | "strict": true,
6 | "moduleResolution": "node"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/create-poi-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-poi-app",
3 | "version": "12.2.2",
4 | "license": "MIT",
5 | "files": [
6 | "bin",
7 | "generator",
8 | "!**/__test__/**"
9 | ],
10 | "scripts": {
11 | "test": "jest"
12 | },
13 | "bin": {
14 | "cpa": "bin/cli.js",
15 | "create-poi-app": "bin/cli.js"
16 | },
17 | "dependencies": {
18 | "cac": "^6.3.12",
19 | "sao": "^1.6.1",
20 | "stringify-object": "^3.3.0"
21 | },
22 | "xo": false,
23 | "jest": {
24 | "testPathIgnorePatterns": [
25 | "/templates/"
26 | ],
27 | "testEnvironment": "node"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "npmClient": "yarn",
3 | "useWorkspaces": true,
4 | "independent": true,
5 | "version": "independent",
6 | "ignoreChanges": ["**/__fixtures__/**", "**/__tests__/**", "**/*.md"],
7 | "command": {
8 | "publish": {
9 | "message": "chore(release): publish"
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/other-packages/babel-plugin-assets-named-imports/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [0.2.1](https://github.com/egoist/poi/compare/babel-plugin-assets-named-imports@0.2.0...babel-plugin-assets-named-imports@0.2.1) (2020-04-30)
7 |
8 | **Note:** Version bump only for package babel-plugin-assets-named-imports
9 |
10 |
11 |
12 |
13 |
14 | # 0.2.0 (2018-12-18)
15 |
16 | ### Features
17 |
18 | - named imports for assets ([#505](https://github.com/egoist/poi/issues/505)) ([32f153a](https://github.com/egoist/poi/commit/32f153a))
19 |
--------------------------------------------------------------------------------
/other-packages/babel-plugin-assets-named-imports/__test__/index.test.js:
--------------------------------------------------------------------------------
1 | const babel = require('@babel/core')
2 | const namedAssetImport = require('..')
3 |
4 | const pluginTester = ({ plugin, pluginOptions, tests }) => {
5 | for (const testTitle of Object.keys(tests)) {
6 | test(testTitle, () => {
7 | const { code, output } = tests[testTitle]
8 | expect(
9 | babel.transform(code, {
10 | plugins: [[plugin, pluginOptions]],
11 | babelrc: false,
12 | configFile: false
13 | }).code
14 | ).toBe(output)
15 | })
16 | }
17 | }
18 |
19 | pluginTester({
20 | plugin: namedAssetImport,
21 | pluginOptions: {
22 | loaderMap: {
23 | svg: {
24 | ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
25 | default: 'default![path]'
26 | }
27 | }
28 | },
29 | pluginName: 'named-asset-import',
30 | tests: {
31 | defaultImport: {
32 | code: 'import logo from "logo";',
33 | output: 'import logo from "logo";'
34 | },
35 | namedImport: {
36 | code: 'import { logo } from "logo";',
37 | output: 'import { logo } from "logo";'
38 | },
39 | namedImportRenamed: {
40 | code: 'import { Url as logo1 } from "logo";',
41 | output: 'import { Url as logo1 } from "logo";'
42 | },
43 | svgDefaultImport: {
44 | code: 'import logo from "logo.svg";',
45 | output: 'import logo from "default!logo.svg";'
46 | },
47 | svgNamedImport: {
48 | code: 'import { logo } from "logo.svg";',
49 | output: 'import { logo } from "logo.svg";'
50 | },
51 | svgReactComponentNamedImport: {
52 | code: 'import { ReactComponent as logo } from "logo.svg";',
53 | output: 'import logo from "@svgr/webpack?-prettier,-svgo!logo.svg";'
54 | },
55 | svgMultipleImport: {
56 | code:
57 | 'import logo, { logoUrl , ReactComponent as Logo } from "logo.svg";',
58 | output:
59 | 'import logo from "default!logo.svg";\n' +
60 | 'import { logoUrl } from "logo.svg";\n' +
61 | 'import Logo from "@svgr/webpack?-prettier,-svgo!logo.svg";'
62 | },
63 | defaultExport: {
64 | code: 'export default logo;',
65 | output: 'export default logo;'
66 | },
67 | constExport: {
68 | code: 'export const token = "token";',
69 | output: 'export const token = "token";'
70 | },
71 | classExport: {
72 | code: 'export class Logo {}',
73 | output: 'export class Logo {}'
74 | },
75 | namedExport: {
76 | code: 'export { logo } from "logo";',
77 | output: 'export { logo } from "logo";'
78 | },
79 | namedExportRenamed: {
80 | code: 'export { Url as logo } from "logo";',
81 | output: 'export { Url as logo } from "logo";'
82 | },
83 | allExport: {
84 | code: 'export * from "logo";',
85 | output: 'export * from "logo";'
86 | },
87 | svgNamedExport: {
88 | code: 'export { logo } from "logo.svg";',
89 | output: 'export { logo } from "logo.svg";'
90 | },
91 | svgAllExport: {
92 | code: 'export * from "logo.svg";',
93 | output: 'export * from "logo.svg";'
94 | },
95 | svgReactComponentNamedExport: {
96 | code: 'export { ReactComponent as Logo } from "logo.svg";',
97 | output:
98 | 'export { default as Logo } from "@svgr/webpack?-prettier,-svgo!logo.svg";'
99 | },
100 | svgReactComponentExport: {
101 | code: 'export { ReactComponent } from "logo.svg";',
102 | output:
103 | 'export { default as ReactComponent } from "@svgr/webpack?-prettier,-svgo!logo.svg";'
104 | },
105 | svgMultipleExport: {
106 | code: 'export { logoUrl , ReactComponent as Logo } from "logo.svg";',
107 | output:
108 | 'export { logoUrl } from "logo.svg";\n' +
109 | 'export { default as Logo } from "@svgr/webpack?-prettier,-svgo!logo.svg";'
110 | }
111 | }
112 | })
113 |
--------------------------------------------------------------------------------
/other-packages/babel-plugin-assets-named-imports/index.js:
--------------------------------------------------------------------------------
1 | const { extname } = require('path')
2 |
3 | /**
4 | * @param {Object} babel
5 | * @param {import('@babel/types')} babel.types
6 | */
7 | function namedAssetImportPlugin({ types: t }) {
8 | const visited = new WeakSet()
9 |
10 | function generateNewSourcePath(loaderMap, moduleName, sourcePath) {
11 | const ext = extname(sourcePath).substr(1)
12 | const extMap = loaderMap[ext]
13 | return extMap[moduleName]
14 | ? extMap[moduleName].replace(/\[path\]/, sourcePath)
15 | : sourcePath
16 | }
17 |
18 | function replaceMatchingSpecifiers(path, loaderMap, callback) {
19 | const sourcePath = path.node.source.value
20 | const ext = extname(sourcePath).substr(1)
21 |
22 | if (visited.has(path.node) || sourcePath.indexOf('!') !== -1) {
23 | return
24 | }
25 |
26 | if (loaderMap[ext]) {
27 | path.replaceWithMultiple(
28 | path.node.specifiers.map(specifier => {
29 | const newSpecifier = callback(specifier, sourcePath)
30 | visited.add(newSpecifier)
31 |
32 | return newSpecifier
33 | })
34 | )
35 | }
36 | }
37 |
38 | return {
39 | visitor: {
40 | ExportNamedDeclaration(
41 | path,
42 | {
43 | opts: { loaderMap }
44 | }
45 | ) {
46 | if (!path.node.source) {
47 | return
48 | }
49 |
50 | replaceMatchingSpecifiers(path, loaderMap, (specifier, sourcePath) => {
51 | if (t.isExportDefaultSpecifier(specifier)) {
52 | return t.exportDeclaration(
53 | [t.exportDefaultSpecifier(t.identifier(specifier.local.name))],
54 | t.stringLiteral(sourcePath)
55 | )
56 | }
57 |
58 | const newSourcePath = generateNewSourcePath(
59 | loaderMap,
60 | specifier.local.name,
61 | sourcePath
62 | )
63 |
64 | if (newSourcePath === sourcePath) {
65 | return t.exportNamedDeclaration(
66 | null,
67 | [specifier],
68 | t.stringLiteral(sourcePath)
69 | )
70 | }
71 |
72 | return t.exportNamedDeclaration(
73 | null,
74 | [
75 | t.exportSpecifier(
76 | t.identifier('default'),
77 | t.identifier(specifier.exported.name)
78 | )
79 | ],
80 | t.stringLiteral(newSourcePath)
81 | )
82 | })
83 | },
84 | ImportDeclaration(
85 | path,
86 | {
87 | opts: { loaderMap }
88 | }
89 | ) {
90 | replaceMatchingSpecifiers(path, loaderMap, (specifier, sourcePath) => {
91 | const isDefaultImport = t.isImportDefaultSpecifier(specifier)
92 | const newSoucePath = generateNewSourcePath(
93 | loaderMap,
94 | isDefaultImport ? 'default' : specifier.imported.name,
95 | sourcePath
96 | )
97 |
98 | if (newSoucePath === sourcePath) {
99 | return t.importDeclaration([specifier], t.stringLiteral(sourcePath))
100 | }
101 |
102 | return t.importDeclaration(
103 | [t.importDefaultSpecifier(t.identifier(specifier.local.name))],
104 | t.stringLiteral(newSoucePath)
105 | )
106 | })
107 | }
108 | }
109 | }
110 | }
111 |
112 | module.exports = namedAssetImportPlugin
113 |
--------------------------------------------------------------------------------
/other-packages/babel-plugin-assets-named-imports/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "babel-plugin-assets-named-imports",
3 | "publishConfig": {
4 | "access": "public"
5 | },
6 | "scripts": {
7 | "test": "jest --env node"
8 | },
9 | "version": "0.2.1",
10 | "main": "index.js",
11 | "files": [
12 | "index.js"
13 | ],
14 | "license": "MIT",
15 | "xo": false,
16 | "devDependencies": {
17 | "@babel/core": "^7.2.2"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/other-packages/pnp-webpack-plugin/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [0.0.2](https://github.com/egoist/poi/compare/@poi/pnp-webpack-plugin@0.0.1...@poi/pnp-webpack-plugin@0.0.2) (2019-01-11)
7 |
8 | ### Bug Fixes
9 |
10 | - remove pnpapi ([ff7f198](https://github.com/egoist/poi/commit/ff7f198))
11 |
12 | ## 0.0.1 (2019-01-09)
13 |
14 | ### Bug Fixes
15 |
16 | - support yarn pnp ([ca61aaa](https://github.com/egoist/poi/commit/ca61aaa))
17 |
--------------------------------------------------------------------------------
/other-packages/pnp-webpack-plugin/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // Forked from https://github.com/arcanis/pnp-webpack-plugin/blob/09cbab561/index.js
3 | // Without ts-pnp
4 |
5 | const path = require(`path`);
6 |
7 | let pnp;
8 |
9 | try {
10 | pnp = require(`pnpapi`);
11 | } catch (error) {
12 | // not in PnP; not a problem
13 | }
14 |
15 | function nothing() {
16 | // ¯\_(ツ)_/¯
17 | }
18 |
19 | function getModuleLocator(module) {
20 | const moduleLocation = module.filename;
21 |
22 | if (!moduleLocation)
23 | throw new Error(`The specified module doesn't seem to exist on the filesystem`);
24 |
25 | const moduleLocator = pnp.findPackageLocator(moduleLocation);
26 |
27 | if (!moduleLocator)
28 | throw new Error(`the specified module doesn't seem to be part of the dependency tree`);
29 |
30 | return moduleLocator;
31 | }
32 |
33 | function getSourceLocation(sourceLocator) {
34 | if (!sourceLocator)
35 | return null;
36 |
37 | const sourceInformation = pnp.getPackageInformation(sourceLocator);
38 |
39 | if (!sourceInformation)
40 | throw new Error(`Couldn't find the package to use as resolution source`);
41 |
42 | if (!sourceInformation.packageLocation)
43 | throw new Error(`The package to use as resolution source seem to not have been installed - maybe it's a devDependency not installed in prod?`);
44 |
45 | return sourceInformation.packageLocation.replace(/\/?$/, `/`);
46 | }
47 |
48 | function makeResolver(sourceLocator) {
49 | const sourceLocation = getSourceLocation(sourceLocator);
50 |
51 | return resolver => {
52 | const MAYBE_BUILTIN = /^[^\/]$/;
53 |
54 | const resolvedHook = resolver.ensureHook(`resolve`);
55 |
56 | // Prevents the SymlinkPlugin from kicking in. We need the symlinks to be preserved because that's how we deal with peer dependencies ambiguities.
57 | resolver.getHook(`file`).intercept({
58 | register: tapInfo => {
59 | return tapInfo.name !== `SymlinkPlugin` ? tapInfo : Object.assign({}, tapInfo, {fn: (request, resolveContext, callback) => {
60 | callback();
61 | }});
62 | }
63 | });
64 |
65 | // Register a plugin that will resolve bare imports into the package location on the filesystem before leaving the rest of the resolution to Webpack
66 | resolver.getHook(`before-module`).tapAsync(`PnpResolver`, (requestContext, resolveContext, callback) => {
67 | let request = requestContext.request;
68 | let issuer = sourceLocation || requestContext.context.issuer;
69 |
70 | // When using require.context, issuer seems to be false (cf https://github.com/webpack/webpack-dev-server/blob/d0725c98fb752d8c0b1e8c9067e526e22b5f5134/client-src/default/index.js#L94)
71 | if (!issuer) {
72 | issuer = `${requestContext.path}/`;
73 | // We only support issuer when they're absolute paths. I'm not sure the opposite can ever happen, but better check here.
74 | } else if (!path.isAbsolute(issuer)) {
75 | throw new Error(`Cannot successfully resolve this dependency - issuer not supported (${issuer})`);
76 | }
77 |
78 | let resolution;
79 |
80 | try {
81 | resolution = pnp.resolveToUnqualified(request, issuer, {considerBuiltins: false});
82 | } catch (error) {
83 | return callback(error);
84 | }
85 |
86 | resolver.doResolve(
87 | resolvedHook,
88 | Object.assign({}, requestContext, {
89 | request: resolution,
90 | }),
91 | null,
92 | resolveContext,
93 | callback
94 | );
95 | });
96 | };
97 | }
98 |
99 | module.exports = pnp ? {
100 | apply: makeResolver(null),
101 | } : {
102 | apply: nothing,
103 | };
104 |
105 | module.exports.moduleLoader = module => pnp ? {
106 | apply: makeResolver(getModuleLocator(module)),
107 | } : {
108 | apply: nothing,
109 | };
110 |
111 | module.exports.topLevelLoader = pnp ? {
112 | apply: makeResolver(pnp.topLevel),
113 | } : {
114 | apply: nothing,
115 | };
116 |
--------------------------------------------------------------------------------
/other-packages/pnp-webpack-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@poi/pnp-webpack-plugin",
3 | "version": "0.0.2",
4 | "files": [
5 | "index.js"
6 | ],
7 | "publishConfig": {
8 | "access": "public"
9 | },
10 | "main": "index.js",
11 | "license": "MIT"
12 | }
13 |
--------------------------------------------------------------------------------
/other-packages/pwa-html-webpack-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pwa-html-webpack-plugin",
3 | "publishConfig": {
4 | "access": "public"
5 | },
6 | "version": "12.0.0",
7 | "main": "index.js",
8 | "files": [
9 | "index.js"
10 | ],
11 | "license": "MIT",
12 | "xo": false
13 | }
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "poi",
4 | "scripts": {
5 | "lint": "xo",
6 | "test": "sh tasks/test.sh",
7 | "commit": "git-cz",
8 | "release": "lerna version --conventional-commits"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git@github.com:egoist/poi.git"
13 | },
14 | "workspaces": [
15 | "core/*",
16 | "plugins/*",
17 | "other-packages/*",
18 | "create-poi-app"
19 | ],
20 | "devDependencies": {
21 | "commitizen": "^3.0.5",
22 | "cz-conventional-changelog": "^2.1.0",
23 | "eslint-config-prettier": "^6.0.0",
24 | "eslint-config-rem": "^4.0.0",
25 | "eslint-plugin-prettier": "^3.0.0",
26 | "husky": "^4.2.5",
27 | "jest": "^25.5.2",
28 | "lerna": "^3.22.1",
29 | "lint-staged": "^8.1.0",
30 | "xo": "^0.23.0"
31 | },
32 | "xo": {
33 | "extends": [
34 | "rem",
35 | "plugin:prettier/recommended"
36 | ],
37 | "rules": {
38 | "unicorn/filename-case": "off",
39 | "no-await-in-loop": "off",
40 | "unicorn/no-abusive-eslint-disable": "off",
41 | "no-multi-assign": "off",
42 | "camelcase": "off"
43 | },
44 | "envs": [
45 | "jest"
46 | ],
47 | "ignores": [
48 | "create-poi-app/generator/templates/**",
49 | "test/kitchensink/**",
50 | "**/example/**"
51 | ]
52 | },
53 | "husky": {
54 | "hooks": {
55 | "pre-commit": "lint-staged"
56 | }
57 | },
58 | "lint-staged": {
59 | "linters": {
60 | "*.js": [
61 | "xo --fix",
62 | "git add"
63 | ],
64 | "*.{md,json}": [
65 | "prettier --write",
66 | "git add"
67 | ]
68 | },
69 | "ignore": [
70 | "create-poi-app/generator/templates/**",
71 | "test/kitchensink/**",
72 | "**/example/**"
73 | ]
74 | },
75 | "config": {
76 | "commitizen": {
77 | "path": "cz-conventional-changelog"
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/plugins/astroturf/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | # [0.2.0](https://github.com/egoist/poi/compare/@poi/plugin-astroturf@0.1.1...@poi/plugin-astroturf@0.2.0) (2020-04-30)
7 |
8 |
9 | ### Features
10 |
11 | * CSS modules should export camelCased names ([#585](https://github.com/egoist/poi/issues/585)) ([5567a8c](https://github.com/egoist/poi/commit/5567a8c))
12 |
13 |
14 |
15 |
16 |
17 | ## [0.1.1](https://github.com/egoist/poi/compare/@poi/plugin-astroturf@0.1.0...@poi/plugin-astroturf@0.1.1) (2019-07-27)
18 |
19 | **Note:** Version bump only for package @poi/plugin-astroturf
20 |
21 | # 0.1.0 (2019-04-03)
22 |
23 | ### Features
24 |
25 | - add plugin astroturf resolve [#548](https://github.com/egoist/poi/issues/548) ([#551](https://github.com/egoist/poi/issues/551)) ([d809c61](https://github.com/egoist/poi/commit/d809c61))
26 |
--------------------------------------------------------------------------------
/plugins/astroturf/README.md:
--------------------------------------------------------------------------------
1 | # @poi/plugin-astroturf
2 |
3 | Use [astroturf](https://github.com/4Catalyzer/astroturf) to write CSS in JS with zero-runtime.
4 |
5 | ## Install
6 |
7 | ```bash
8 | yarn add astroturf @poi/plugin-astroturf --dev
9 | ```
10 |
11 | ## How to use
12 |
13 | In your `poi.config.js`:
14 |
15 | ```js
16 | module.exports = {
17 | plugins: [
18 | {
19 | resolve: '@poi/plugin-astroturf',
20 | options: {}
21 | }
22 | ]
23 | }
24 | ```
25 |
26 | Then write css-in-js:
27 |
28 | ```jsx
29 | import { css } from 'astroturf'
30 |
31 | const style = css`
32 | .title {
33 | font-size: 2em;
34 | }
35 | `
36 | export const App = () => {
37 | return Hello world
38 | }
39 | ```
40 |
41 | Check out [astroturf](https://github.com/4Catalyzer/astroturf/) for more usages.
42 |
43 | ## Options
44 |
45 | - `loaderOptions`: `astroturf/loader` [options](https://github.com/4Catalyzer/astroturf/tree/1741c3e702049f6e75483cd000b439d42e57ef2d#options)
46 | - `loaderOptions.extension`: Default `.module.css`. You can also change it to `.scss` or `.module.scss` etc to use [CSS pre-processors](https://poi.js.org/guide/pre-processing-css.html), but make sure that it ends with `.module.xxx` if you want CSS modules support.
47 |
48 | ## License
49 |
50 | MIT.
51 |
--------------------------------------------------------------------------------
/plugins/astroturf/index.js:
--------------------------------------------------------------------------------
1 | exports.name = 'astroturf'
2 |
3 | /**
4 | * The @poi/astroturf plugin options
5 | * @typedef {Object} AstroturfOptions
6 | * @property {Object} loaderOptions - The `astroturf/loader` options
7 | * See also {@link https://github.com/4Catalyzer/astroturf/tree/1741c3e702049f6e75483cd000b439d42e57ef2d#options}
8 | */
9 |
10 | exports.apply = (api, options = {}) => {
11 | const loaderOptions = Object.assign(
12 | {
13 | extension: '.module.css'
14 | },
15 | options.loaderOptions
16 | )
17 |
18 | const loaderPath = api.localResolve('astroturf/loader')
19 | if (!loaderPath) {
20 | throw new api.PoiError(
21 | `Cannot find module "astroturf/loader" in your project, did you forget to install "astroturf"?`
22 | )
23 | }
24 |
25 | api.hook('createWebpackChain', config => {
26 | const jsRule = config.module.rule('js')
27 |
28 | addAstroturfLoader(jsRule, loaderOptions, loaderPath)
29 | if (config.module.rules.get('ts')) {
30 | addAstroturfLoader(config.module.rule('ts'), loaderOptions, loaderPath)
31 | }
32 | })
33 | }
34 |
35 | /**
36 | * @private
37 | * @param {import('webpack-chain').Rule} rule
38 | * @param {AstroturfOptions.loaderOptions} loaderOptions
39 | * @param {string} loaderPath
40 | */
41 | function addAstroturfLoader(rule, loaderOptions, loaderPath) {
42 | rule
43 | .use('astroturf-loader')
44 | .loader(loaderPath)
45 | .options(loaderOptions)
46 | }
47 |
--------------------------------------------------------------------------------
/plugins/astroturf/index.test.js:
--------------------------------------------------------------------------------
1 | const createProject = require('@poi/test-utils/createProject')
2 |
3 | jest.setTimeout(60000)
4 |
5 | test('astroturf', async () => {
6 | const project = await createProject({ name: 'astroturf' })
7 | await project.write(
8 | '.poirc',
9 | JSON.stringify({
10 | plugins: [require.resolve('.')],
11 | output: {
12 | format: 'cjs',
13 | target: 'node'
14 | }
15 | })
16 | )
17 | await project.write(
18 | 'index.js',
19 | `
20 | import { css } from 'astroturf';
21 |
22 | const margin = 10;
23 | const height = 50;
24 | const bottom = height + margin;
25 |
26 | const styles = css\`
27 | .box {
28 | height: \${height}px;
29 | margin-bottom: \${margin}px;
30 | }
31 |
32 | .footer {
33 | position: absolute;
34 | top: \${bottom}px;
35 | }
36 | \`;
37 |
38 | export default styles;
39 | `
40 | )
41 | await project.run('poi')
42 | expect(project.require('dist/index.js')).toEqual({
43 | default: {
44 | box: 'index-styles.module_box_1SCdY',
45 | footer: 'index-styles.module_footer_1xrFU'
46 | }
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/plugins/astroturf/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@poi/plugin-astroturf",
3 | "version": "0.2.0",
4 | "main": "index.js",
5 | "files": [
6 | "index.js"
7 | ],
8 | "scripts": {
9 | "test": "jest --env node"
10 | },
11 | "publishConfig": {
12 | "access": "public"
13 | },
14 | "license": "MIT",
15 | "devDependencies": {
16 | "@poi/test-utils": "^12.0.2",
17 | "astroturf": "^0.9.2"
18 | },
19 | "peerDependencies": {
20 | "astroturf": "^0.9.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/plugins/bundle-report/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [12.1.2](https://github.com/egoist/poi/compare/@poi/plugin-bundle-report@12.1.1...@poi/plugin-bundle-report@12.1.2) (2019-12-13)
7 |
8 | **Note:** Version bump only for package @poi/plugin-bundle-report
9 |
10 | ## [12.1.1](https://github.com/egoist/poi/compare/@poi/plugin-bundle-report@12.1.0...@poi/plugin-bundle-report@12.1.1) (2019-05-23)
11 |
12 | **Note:** Version bump only for package @poi/plugin-bundle-report
13 |
14 | # 12.1.0 (2019-02-06)
15 |
16 | ### Features
17 |
18 | - bundle report plugin ([#537](https://github.com/egoist/poi/issues/537)) ([318eb79](https://github.com/egoist/poi/commit/318eb79)), closes [/github.com/egoist/poi/issues/507#issuecomment-449032295](https://github.com//github.com/egoist/poi/issues/507/issues/issuecomment-449032295)
19 |
--------------------------------------------------------------------------------
/plugins/bundle-report/README.md:
--------------------------------------------------------------------------------
1 | # @poi/plugin-bundle-report
2 |
3 | This is a preset for adding [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) which could help you:
4 |
5 | 1. Realize what's really inside your bundle
6 | 2. Find out what modules make up the most of it's size
7 | 3. Find modules that got there by mistake
8 | 4. Optimize it!
9 |
10 | ## Install
11 |
12 | ```bash
13 | yarn add @poi/plugin-bundle-report --dev
14 | ```
15 |
16 | ## Usage
17 |
18 | Activate it in config file:
19 |
20 | ```js
21 | // poi.config.js
22 | module.exports = {
23 | plugins: [
24 | {
25 | resolve: '@poi/bundle-report',
26 | options: {}
27 | }
28 | ]
29 | }
30 | ```
31 |
32 | Add `--bundle-report` while building your app in **production mode** to get report:
33 |
34 | ```bash
35 | poi --prod --bundle-report
36 | # then you'll be automatically navigated to http://localhost:8888
37 | ```
38 |
39 | ## Options
40 | Options object for [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) plugin.
41 |
42 | ## LICENSE
43 |
44 | MIT © [EGOIST](https://github.com/egoist)
45 |
--------------------------------------------------------------------------------
/plugins/bundle-report/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // NOTE: This is adapted version of `poi-preset-bundle-report` updated to work
4 | // with poi@12 (original code: https://github.com/egoist/poi/tree/v9.2.0/packages/poi-preset-bundle-report)
5 | exports.name = 'bundle-report'
6 |
7 | exports.cli = api => {
8 | if (!api.isProd) return
9 | api.command.option('--bundle-report', 'View bundle report')
10 | }
11 |
12 | exports.apply = (api, options = {}) => {
13 | api.hook('createWebpackChain', config => {
14 | if (!api.cli.options.bundleReport) return
15 | const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
16 | config.plugin('bundle-report').use(BundleAnalyzerPlugin, [options])
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/plugins/bundle-report/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@poi/plugin-bundle-report",
3 | "version": "12.1.2",
4 | "main": "index.js",
5 | "files": [
6 | "index.js"
7 | ],
8 | "publishConfig": {
9 | "access": "public"
10 | },
11 | "license": "MIT",
12 | "dependencies": {
13 | "webpack-bundle-analyzer": "^3.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/plugins/eslint/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | # [12.1.0](https://github.com/egoist/poi/compare/@poi/plugin-eslint@12.0.1...@poi/plugin-eslint@12.1.0) (2020-04-30)
7 |
8 |
9 | ### Features
10 |
11 | * **eslint:** Pass `loaderOptions` to `eslint-loader` ([#668](https://github.com/egoist/poi/issues/668)) ([9401965](https://github.com/egoist/poi/commit/9401965))
12 |
13 |
14 |
15 |
16 |
17 | ## [12.0.1](https://github.com/egoist/poi/compare/@poi/plugin-eslint@12.0.0...@poi/plugin-eslint@12.0.1) (2019-12-13)
18 |
19 | **Note:** Version bump only for package @poi/plugin-eslint
20 |
--------------------------------------------------------------------------------
/plugins/eslint/README.md:
--------------------------------------------------------------------------------
1 | # @poi/plugin-eslint
2 |
3 | Use ESLint to lint JavaScript.
4 |
5 | ## Install
6 |
7 | ```bash
8 | yarn add @poi/plugin-eslint --dev
9 | ```
10 |
11 | ## How to use
12 |
13 | In your `poi.config.js`:
14 |
15 | ```js
16 | module.exports = {
17 | plugins: [
18 | {
19 | resolve: '@poi/plugin-eslint'
20 | }
21 | ]
22 | }
23 | ```
24 |
25 | Then add a `.eslintrc.js` in your project:
26 |
27 | ```js
28 | module.exports = {
29 | extends: ['eslint:recommended']
30 | }
31 | ```
32 |
33 | Now ESLint will check your JS files at compile time.
34 |
35 |
36 | ## Options
37 |
38 | ### loaderOptions
39 |
40 | - Type: `any`
41 |
42 | Addtional [options](https://github.com/webpack-contrib/eslint-loader#options) for `eslint-loader`.
43 |
--------------------------------------------------------------------------------
/plugins/eslint/index.js:
--------------------------------------------------------------------------------
1 | exports.name = 'eslint'
2 |
3 | exports.apply = (api, options = {}) => {
4 | api.hook('createWebpackChain', config => {
5 | const { cacheIdentifier } = api.getCacheConfig('eslint-loader', {}, [
6 | '.eslintrc.js',
7 | '.eslintrc.yaml',
8 | '.eslintrc.yml',
9 | '.eslintrc.json',
10 | '.eslintrc',
11 | 'package.json'
12 | ])
13 | config.module
14 | .rule('eslint')
15 | .test([/\.jsx?$/, /\.vue$/])
16 | .pre()
17 | .exclude.add(filepath => /node_modules/.test(filepath))
18 | .end()
19 | .use('eslint-loader')
20 | .loader(require.resolve('eslint-loader'))
21 | .options({
22 | formatter: require('eslint/lib/formatters/codeframe'),
23 | eslintPath: api.localResolve('eslint') || require.resolve('eslint'),
24 | ...options.loaderOptions,
25 | cache: api.config.cache,
26 | cacheKey: cacheIdentifier
27 | })
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/plugins/eslint/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@poi/plugin-eslint",
3 | "version": "12.1.0",
4 | "main": "index.js",
5 | "files": [
6 | "index.js"
7 | ],
8 | "publishConfig": {
9 | "access": "public"
10 | },
11 | "license": "MIT",
12 | "dependencies": {
13 | "eslint": "^5.9.0",
14 | "eslint-formatter-pretty": "^2.0.0",
15 | "eslint-loader": "^3.0.2"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/plugins/html-entry/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [0.2.3](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.2.2...@poi/plugin-html-entry@0.2.3) (2020-07-13)
7 |
8 | **Note:** Version bump only for package @poi/plugin-html-entry
9 |
10 | ## [0.2.2](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.2.1...@poi/plugin-html-entry@0.2.2) (2020-04-30)
11 |
12 | **Note:** Version bump only for package @poi/plugin-html-entry
13 |
14 | ## [0.2.1](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.2.0...@poi/plugin-html-entry@0.2.1) (2019-08-09)
15 |
16 | ### Bug Fixes
17 |
18 | - **html-entry:** fix json assets support in html entry ([#619](https://github.com/egoist/poi/issues/619)) ([91dfd21](https://github.com/egoist/poi/commit/91dfd21))
19 |
20 | # [0.2.0](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.1.4...@poi/plugin-html-entry@0.2.0) (2019-05-23)
21 |
22 | ### Bug Fixes
23 |
24 | - **html-entry:** support external css and scripts ([ff65156](https://github.com/egoist/poi/commit/ff65156)), closes [#570](https://github.com/egoist/poi/issues/570) [#571](https://github.com/egoist/poi/issues/571)
25 |
26 | ### Features
27 |
28 | - **html-entry:** a better way to handle static asset ([873cc16](https://github.com/egoist/poi/commit/873cc16))
29 | - **html-entry:** support all link tags([#572](https://github.com/egoist/poi/issues/572)) ([5695f25](https://github.com/egoist/poi/commit/5695f25))
30 |
31 | ## [0.1.4](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.1.3...@poi/plugin-html-entry@0.1.4) (2019-04-08)
32 |
33 | ### Bug Fixes
34 |
35 | - **html-entry:** slash attrs for static assets ([#558](https://github.com/egoist/poi/issues/558)) ([3a2bf0e](https://github.com/egoist/poi/commit/3a2bf0e))
36 |
37 | ## [0.1.3](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.1.2...@poi/plugin-html-entry@0.1.3) (2019-04-06)
38 |
39 | ### Bug Fixes
40 |
41 | - **html-entry:** convert backslash to slash ([b1f581c](https://github.com/egoist/poi/commit/b1f581c)), closes [#555](https://github.com/egoist/poi/issues/555)
42 |
43 | ## [0.1.2](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.1.1...@poi/plugin-html-entry@0.1.2) (2019-03-12)
44 |
45 | ### Bug Fixes
46 |
47 | - **html-entry:** es5-ify generated files ([8df9835](https://github.com/egoist/poi/commit/8df9835))
48 |
49 | ## [0.1.1](https://github.com/egoist/poi/compare/@poi/plugin-html-entry@0.1.0...@poi/plugin-html-entry@0.1.1) (2019-01-24)
50 |
51 | ### Bug Fixes
52 |
53 | - **html-entry:** remove unnecessary dependency ([48eb88f](https://github.com/egoist/poi/commit/48eb88f))
54 |
55 | # 0.1.0 (2019-01-24)
56 |
57 | ### Features
58 |
59 | - support html an entry file ([289468a](https://github.com/egoist/poi/commit/289468a))
60 | - support html file as entrypoint ([bdf5359](https://github.com/egoist/poi/commit/bdf5359))
61 |
--------------------------------------------------------------------------------
/plugins/html-entry/README.md:
--------------------------------------------------------------------------------
1 | # @poi/plugin-html-entry
2 |
3 | This is a built-in Poi plugin which makes Poi support HTML entrypoint.
4 |
5 | ## Features
6 |
7 | ### Process local scripts and styles
8 |
9 | ```html
10 |
11 |
12 | ```
13 |
14 | Note that only relative paths will be processed by webpack, which means you can use absolute paths like `https://...` or `/static/foo.css` to reference external resources.
15 |
16 | ### Process certain HTML attributes
17 |
18 | It processes certain HTML attributes:
19 |
20 | - `
`: `src`
21 | - ``: `xlink:href`
22 | - `