Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: provide options to transform module path #25

Merged
merged 5 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}