Skip to content

Commit

Permalink
feat: provide options to transform module path (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
chengjianhua authored Sep 8, 2020
1 parent 90ea0c1 commit db59d16
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 49 deletions.
46 changes: 42 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,23 +145,60 @@ const routes = importAll.deferred('./files/*.js')
↓ ↓ ↓ ↓ ↓ ↓

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

<!-- SNAP_TO_README:END -->

**Configure `importAll` to transform import path before generating imports**

`babel-plugin-macros.config.js`:

```javascript
module.exports = {
importAll: {
transformModulePath(modulePath, importingPath) {
const projectRoot = path.join(__dirname, '../../')
const modulePathWithoutExt = modulePath.replace(/\.js$/, '')
const absolutePath = path.resolve(
path.dirname(importingPath),
modulePathWithoutExt,
)
const pathRelativeToRoot = path.relative(projectRoot, absolutePath)
return pathRelativeToRoot
},
},
}
```

```javascript
import importAll from 'import-all.macro'
const a = importAll.sync('./files/*.js')
↓ ↓ ↓ ↓ ↓ ↓
import * as _filesA from './files/a'
import * as _filesB from './files/b'
import * as _filesC from './files/c'
import * as _filesD from './files/d'
const a = {
'./files/a': _filesA,
'./files/b': _filesB,
'./files/c': _filesC,
'./files/d': _filesD,
}
```

## Caveats

Some static analysis tools (like ESLint, Flow, and Jest) wont like this very
Expand Down Expand Up @@ -215,6 +252,7 @@ Thanks goes to these people ([emoji key][emojis]):

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification.
Expand Down
23 changes: 23 additions & 0 deletions src/__tests__/__snapshots__/macro-transform-import.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`macros README:4 configure \`importAll\` to transform import path before generating imports: README:4 configure \`importAll\` to transform import path before generating imports 1`] = `
import importAll from 'import-all.macro'
const a = importAll.sync('./files/*.js')
↓ ↓ ↓ ↓ ↓ ↓
import * as _src__tests__FixturesA from 'src/__tests__/files/a'
import * as _src__tests__FixturesB from 'src/__tests__/files/b'
import * as _src__tests__FixturesC from 'src/__tests__/files/c'
import * as _src__tests__FixturesD from 'src/__tests__/files/d'
const a = {
'src/__tests__/files/a': _src__tests__FixturesA,
'src/__tests__/files/b': _src__tests__FixturesB,
'src/__tests__/files/c': _src__tests__FixturesC,
'src/__tests__/files/d': _src__tests__FixturesD,
}
`;
29 changes: 29 additions & 0 deletions src/__tests__/helpers/create-macro-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import path from 'path'
import pluginTester from 'babel-plugin-tester'
import prettier from 'prettier'
import {prettier as prettierConfig} from 'kcd-scripts/config'

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

expect.addSnapshotSerializer({
print(val) {
return val
.split(projectRoot)
.join('<PROJECT_ROOT>/')
.replace(/fixtures/g, 'files')
.replace(/..\/macro/, 'import-all.macro')
},
test(val) {
return typeof val === 'string'
},
})

export function createMacroTests(pluginTesterOptions) {
pluginTester({
snapshot: true,
formatResult(result) {
return prettier.format(result, {...prettierConfig, parser: 'babel'})
},
...pluginTesterOptions,
})
}
34 changes: 34 additions & 0 deletions src/__tests__/macro-transform-import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import path from 'path'
import plugin from 'babel-plugin-macros'

import {createMacroTests} from './helpers/create-macro-test'

createMacroTests({
plugin: (babel, options) => {
return plugin(babel, {
importAll: {
transformModulePath(modulePath, importingPath) {
const projectRoot = path.join(__dirname, '../../')
const modulePathWithoutExt = modulePath.replace(/\.js$/, '')
const absolutePath = path.resolve(
path.dirname(importingPath),
modulePathWithoutExt,
)
const pathRelativeToRoot = path.relative(projectRoot, absolutePath)
return pathRelativeToRoot
},
},
...options,
})
},
babelOptions: {
filename: __filename,
},
tests: {
'README:4 configure `importAll` to transform import path before generating imports': `
import importAll from '../macro'
const a = importAll.sync('./fixtures/*.js')
`,
},
})
25 changes: 2 additions & 23 deletions src/__tests__/macro.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,12 @@
import path from 'path'
import pluginTester from 'babel-plugin-tester'
import plugin from 'babel-plugin-macros'
import prettier from 'prettier'
import {prettier as prettierConfig} from 'kcd-scripts/config'

const projectRoot = path.join(__dirname, '../../').replace(/\\/g, '/')
import { createMacroTests } from './helpers/create-macro-test'

expect.addSnapshotSerializer({
print(val) {
return val
.split(projectRoot)
.join('<PROJECT_ROOT>/')
.replace(/fixtures/g, 'files')
.replace(/..\/macro/, 'import-all.macro')
},
test(val) {
return typeof val === 'string'
},
})

pluginTester({
createMacroTests({
plugin,
snapshot: true,
babelOptions: {
filename: __filename,
},
formatResult(result) {
return prettier.format(result, prettierConfig)
},
tests: {
'no usage': `import importAll from '../macro'`,
'incorrect API usage': {
Expand Down
53 changes: 31 additions & 22 deletions src/macro.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ const path = require('path')
const {createMacro} = require('babel-plugin-macros')
const glob = require('glob')

module.exports = createMacro(prevalMacros)
module.exports = createMacro(prevalMacros, {configName: 'importAll'})

function prevalMacros({references, state, babel}) {
function prevalMacros({references, ...macroOptions}) {
const {babel} = macroOptions
references.default.forEach(referencePath => {
if (referencePath.parentPath.type === 'CallExpression') {
asyncVersion({referencePath, state, babel})
asyncVersion({referencePath, ...macroOptions})
} else if (
referencePath.parentPath.type === 'MemberExpression' &&
referencePath.parentPath.node.property.name === 'sync'
) {
syncVersion({referencePath, state, babel})
syncVersion({referencePath, ...macroOptions})
} else if (
referencePath.parentPath.type === 'MemberExpression' &&
referencePath.parentPath.node.property.name === 'deferred'
) {
deferredVersion({referencePath, state, babel})
deferredVersion({referencePath, ...macroOptions})
} else {
throw new Error(
`This is not supported: \`${referencePath
Expand All @@ -29,17 +30,18 @@ function prevalMacros({references, state, babel}) {
})
}

function syncVersion({referencePath, state, babel}) {
function syncVersion({referencePath, state, babel, config}) {
const {types: t} = babel
const {
file: {
opts: {filename},
},
} = state
const importSources = getImportSources(
referencePath.parentPath.parentPath,
path.dirname(filename),
)
const importSources = getImportSources({
callExpressionPath: referencePath.parentPath.parentPath,
filename,
config,
})

const {importNodes, objectProperties} = importSources.reduce(
(all, source) => {
Expand All @@ -63,7 +65,7 @@ function syncVersion({referencePath, state, babel}) {
referencePath.parentPath.parentPath.replaceWith(objectExpression)
}

function asyncVersion({referencePath, state, babel}) {
function asyncVersion({referencePath, state, babel, config}) {
const {types: t, template} = babel
const {
file: {
Expand All @@ -75,10 +77,11 @@ function asyncVersion({referencePath, state, babel}) {
return IMPORT_OBJ
})
`)
const importSources = getImportSources(
referencePath.parentPath,
path.dirname(filename),
)
const importSources = getImportSources({
callExpressionPath: referencePath.parentPath,
filename,
config,
})

const {dynamicImports, objectProperties} = importSources.reduce(
(all, source, index) => {
Expand Down Expand Up @@ -109,17 +112,18 @@ function asyncVersion({referencePath, state, babel}) {
)
}

function deferredVersion({referencePath, state, babel}) {
function deferredVersion({referencePath, state, babel, config}) {
const {types: t} = babel
const {
file: {
opts: {filename},
},
} = state
const importSources = getImportSources(
referencePath.parentPath.parentPath,
path.dirname(filename),
)
const importSources = getImportSources({
callExpressionPath: referencePath.parentPath.parentPath,
filename,
config,
})

const objectProperties = importSources.map(source => {
return t.objectProperty(
Expand All @@ -141,7 +145,7 @@ function deferredVersion({referencePath, state, babel}) {
referencePath.parentPath.parentPath.replaceWith(objectExpression)
}

function getImportSources(callExpressionPath, cwd) {
function getImportSources({callExpressionPath, filename, config}) {
let globValue
try {
globValue = callExpressionPath.get('arguments')[0].evaluate().value
Expand All @@ -156,5 +160,10 @@ function getImportSources(callExpressionPath, cwd) {
)
}

return glob.sync(globValue, {cwd})
const filepaths = glob.sync(globValue, {cwd: path.dirname(filename)})
if (typeof config.transformModulePath === 'function') {
return filepaths.map(p => config.transformModulePath(p, filename))
}

return filepaths
}

0 comments on commit db59d16

Please sign in to comment.