Skip to content

Commit

Permalink
docs: add all the docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Kent C. Dodds committed Sep 19, 2017
1 parent 3cb5f39 commit 208cce6
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 60 deletions.
119 changes: 114 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,130 @@ individually.

## This solution

// TODO
This is a [babel-macro][babel-macros] which allows you to import files that
match a glob. It supports `import` statements for synchronous resolution as well
as dynamic `import()` for deferred resolution (for code splitting with react
router for example).

## Installation

This module is distributed via [npm][npm] which is bundled with [node][node] and
should be installed as one of your project's `dependencies`:
should be installed as one of your project's `devDependencies`:

```
npm install --save import-all.macro
npm install --save-dev import-all.macro
```

## Usage

// TODO
Once you've [configured `babel-macros`][babel-macros-user] you can
import/require `import-all.macro`.

The `importAll` functions accept a [`glob`][glob] and will transpile your code
to import statements/dynamic imports for each file that matches the given glob.

Let's imagine you have a directory called `my-files` with the files
`a.js`, `b.js`, `c.js`, and `d.js`.

Here are a few before/after examples:

<!-- SNAP_TO_README:START -->
<!-- This section is generated by the other/snap-to-readme.js script. -->
<!-- Do not edit directly. -->

**`importAll` uses dynamic import**

```javascript
import importAll from 'import-all.macro'

document.getElementById('load-stuff').addEventListener(() => {
importAll('./my-files/*.js').then(all => {
console.log(all)
})
})

↓ ↓ ↓ ↓ ↓ ↓

document.getElementById('load-stuff').addEventListener(() => {
Promise.all([
import('./my-files/a.js'),
import('./my-files/b.js'),
import('./my-files/c.js'),
import('./my-files/d.js'),
])
.then(function importAllHandler(importVals) {
return {
a: importVals[0],
b: importVals[1],
c: importVals[2],
d: importVals[3],
}
})
.then(all => {
console.log(all)
})
})
```

**`importAll.sync` uses static imports**

```javascript
import importAll from 'import-all.macro'

const a = importAll.sync('./my-files/*.js')

↓ ↓ ↓ ↓ ↓ ↓

import * as _a from './my-files/a.js'
import * as _b from './my-files/b.js'
import * as _c from './my-files/c.js'
import * as _d from './my-files/d.js'

const a = {
a: _a,
b: _b,
c: _c,
d: _d,
}
```

**`importAll.deferred` gives an object with dynamic imports**

```javascript
import importAll from 'import-all.macro'

const routes = importAll.deferred('./my-files/*.js')

↓ ↓ ↓ ↓ ↓ ↓

const routes = {
a: function a() {
return import('./my-files/a.js')
},
b: function b() {
return import('./my-files/b.js')
},
c: function c() {
return import('./my-files/c.js')
},
d: function d() {
return import('./my-files/d.js')
},
}
```

<!-- SNAP_TO_README:END -->

## Caveats

Some static analysis tools (like ESLint, Flow, and Jest) wont like this very much
without a little additional work. So Jest's watch mode may not pick up all your
tests that are relevant based on changes and some ESLint plugins
(like `eslint-plugin-import`) will probably fail on this.

## Inspiration

// TODO
[Sunil Pai's tweet][sunil-tweet]

## Other Solutions

Expand Down Expand Up @@ -94,3 +200,6 @@ MIT
[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/kentcdodds/import-all.macro.svg?style=social
[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key
[all-contributors]: https://github.com/kentcdodds/all-contributors
[babel-macros-user]: https://github.com/kentcdodds/babel-macros/blob/master/other/docs/user.md
[glob]: https://www.npmjs.com/package/glob
[sunil-tweet]: https://twitter.com/threepointone/status/908290510225330176
5 changes: 5 additions & 0 deletions lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const lintStagedConfig = require('kcd-scripts/config').lintStaged

module.exports = Object.assign(lintStagedConfig.linters, {
'**/__snapshots__/**': 'node other/snap-to-readme.js',
})
41 changes: 41 additions & 0 deletions other/snap-to-readme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const path = require('path')
const fs = require('fs')

const readmePath = path.join(__dirname, '../README.md')
const readme = fs.readFileSync(readmePath, 'utf8')
const snaps = require('../src/__tests__/__snapshots__/macro.js.snap')

const snapNumberRegex = /^README:(\d+)/
const snapTitleRegex = /^README:\d+(.*) \d+$/
const readmeSnapRegex = /<!-- SNAP_TO_README:START -->[\s\S]*?<!-- SNAP_TO_README:END -->/
const snapsToUse = Object.keys(snaps)
.filter(name => name.startsWith('README'))
.sort(
(nameA, nameB) =>
Number(nameA.match(snapNumberRegex)[1]) >
Number(nameB.match(snapNumberRegex)[1])
? 1
: 0,
)
.reduce((acc, key) => {
const title = key.match(snapTitleRegex)[1].trim()
const contents = snaps[key].trim()
return [acc, `**${title}**`, `~~~javascript\n${contents}\n~~~`]
.join('\n\n')
.replace(/~/g, '`')
}, [])

const newReadme = readme.replace(
readmeSnapRegex,
`
<!-- SNAP_TO_README:START -->
<!-- This section is generated by the other/snap-to-readme.js script. -->
<!-- Do not edit directly. -->
${snapsToUse.trim()}
<!-- SNAP_TO_README:END -->
`.trim(),
)

fs.writeFileSync(readmePath, newReadme)
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"devDependencies": {
"ast-pretty-print": "^2.0.1",
"babel-plugin-tester": "^4.0.0",
"kcd-scripts": "^0.16.0"
"kcd-scripts": "^0.16.0",
"prettier": "^1.7.0"
},
"eslintConfig": {
"extends": "./node_modules/kcd-scripts/eslint.js"
Expand Down
101 changes: 55 additions & 46 deletions src/__tests__/__snapshots__/macro.js.snap
Original file line number Diff line number Diff line change
@@ -1,83 +1,92 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`importAll uses dynamic import 1`] = `
exports[`README:1 \`importAll\` uses dynamic import 1`] = `
import importAll from '../macro'
import importAll from 'import-all.macro'
document.getElementById('load-stuff').addEventListener(() => {
importAll('./fixtures/*.js').then(all => {
importAll('./my-files/*.js').then(all => {
console.log(all)
})
})
↓ ↓ ↓ ↓ ↓ ↓
document.getElementById('load-stuff').addEventListener(() => {
Promise.all([import('./fixtures/a.js'), import('./fixtures/b.js'), import('./fixtures/c.js'), import('./fixtures/d.js')]).then(function importAllHandler(importVals) {
return {
'a': importVals[0],
'b': importVals[1],
'c': importVals[2],
'd': importVals[3]
};
}).then(all => {
console.log(all);
});
});
Promise.all([
import('./my-files/a.js'),
import('./my-files/b.js'),
import('./my-files/c.js'),
import('./my-files/d.js'),
])
.then(function importAllHandler(importVals) {
return {
a: importVals[0],
b: importVals[1],
c: importVals[2],
d: importVals[3],
}
})
.then(all => {
console.log(all)
})
})
`;

exports[`importAll.deferred gives an object with dynamic imports 1`] = `
exports[`README:2 \`importAll.sync\` uses static imports 1`] = `
import importAll from '../macro'
import importAll from 'import-all.macro'
const routes = importAll.deferred('./fixtures/*.js')
const a = importAll.sync('./my-files/*.js')
↓ ↓ ↓ ↓ ↓ ↓
const routes = {
'a': function a() {
return import('./fixtures/a.js');
},
'b': function b() {
return import('./fixtures/b.js');
},
'c': function c() {
return import('./fixtures/c.js');
},
'd': function d() {
return import('./fixtures/d.js');
}
};
import * as _a from './my-files/a.js'
import * as _b from './my-files/b.js'
import * as _c from './my-files/c.js'
import * as _d from './my-files/d.js'
const a = {
a: _a,
b: _b,
c: _c,
d: _d,
}
`;

exports[`importAll.sync uses static imports 1`] = `
exports[`README:3 \`importAll.deferred\` gives an object with dynamic imports 1`] = `
import importAll from '../macro'
import importAll from 'import-all.macro'
const a = importAll.sync('./fixtures/*.js')
const routes = importAll.deferred('./my-files/*.js')
↓ ↓ ↓ ↓ ↓ ↓
import * as _a from './fixtures/a.js';
import * as _b from './fixtures/b.js';
import * as _c from './fixtures/c.js';
import * as _d from './fixtures/d.js';
const routes = {
a: function a() {
return import('./my-files/a.js')
},
b: function b() {
return import('./my-files/b.js')
},
c: function c() {
return import('./my-files/c.js')
},
d: function d() {
return import('./my-files/d.js')
},
}
const a = {
'a': _a,
'b': _b,
'c': _c,
'd': _d
};
`;

exports[`no usage 1`] = `
import importAll from '../macro'
import importAll from 'import-all.macro'
↓ ↓ ↓ ↓ ↓ ↓
Expand Down
28 changes: 20 additions & 8 deletions src/__tests__/macro.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import path from 'path'
import pluginTester from 'babel-plugin-tester'
import plugin from 'babel-macros'
import prettier from 'prettier'
import {prettier as prettierConfig} from 'kcd-scripts/config'

const projectRoot = path.join(__dirname, '../../')

expect.addSnapshotSerializer({
print(val) {
return val.split(projectRoot).join('<PROJECT_ROOT>/')
return val
.split(projectRoot)
.join('<PROJECT_ROOT>/')
.replace(/fixtures/g, 'my-files')
.replace(/..\/macro/, 'import-all.macro')
},
test(val) {
return typeof val === 'string'
Expand All @@ -19,14 +25,15 @@ pluginTester({
babelOptions: {
filename: __filename,
},
formatResult(result) {
return prettier.format(
result,
Object.assign({trailingComma: 'es5'}, prettierConfig),
)
},
tests: {
'no usage': `import importAll from '../macro'`,
'importAll.sync uses static imports': `
import importAll from '../macro'
const a = importAll.sync('./fixtures/*.js')
`,
'importAll uses dynamic import': `
'README:1 `importAll` uses dynamic import': `
import importAll from '../macro'
document.getElementById('load-stuff').addEventListener(() => {
Expand All @@ -35,7 +42,12 @@ pluginTester({
})
})
`,
'importAll.deferred gives an object with dynamic imports': `
'README:2 `importAll.sync` uses static imports': `
import importAll from '../macro'
const a = importAll.sync('./fixtures/*.js')
`,
'README:3 `importAll.deferred` gives an object with dynamic imports': `
import importAll from '../macro'
const routes = importAll.deferred('./fixtures/*.js')
Expand Down

0 comments on commit 208cce6

Please sign in to comment.