Skip to content

Commit

Permalink
feat: genExport utils
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe authored and pi0 committed Jan 21, 2022
1 parent d2562df commit 9135548
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 45 deletions.
36 changes: 12 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# knitwork
# 🧶 knitwork

> Utilities to generate JavaScript code.
Expand All @@ -17,43 +17,31 @@ pnpm install knitwork

## Usage

### `genImport`

Generate a static import statement.

```js
import { genImport } from 'knitwork'
import { genImport, genExport } from 'knitwork'

// import { foo } from "pkg"
// import foo from "pkg"
console.log(genImport('pkg', 'foo'))

// import { a, b } from "pkg"
console.log(genImport('pkg', 'foo'))
console.log(genImport('pkg', ['a', 'b']))

// import { foo as bar } from "pkg"
console.log(genImport('pkg', { name: 'foo', as: 'bar' }))
```

### `genDynamicImport`

Generate a dynamic import statement.

```js
import { genDynamicImport } from 'knitwork'

// () => import("pkg")
console.log(genDynamicImport('pkg'))
console.log(genImport('pkg', [{ name: 'foo', as: 'bar' }]))

// () => import("pkg").then(m => m.default || m)
console.log(genDynamicImport('pkg', { interopDefault: true }))
// export foo from "pkg"
console.log(genExport('pkg', 'foo'))

// import("pkg")
console.log(genDynamicImport('pkg', { wrapper: false }))
// export { a, b } from "pkg"
console.log(genExport('pkg', ['a', 'b']))

// () => import("pkg" /* webpackChunkName: "pkg" */)
console.log(genDynamicImport('pkg', { comment: 'webpackChunkName: "pkg"' }))
// export * as bar from "pkg"
console.log(genExport('pkg', { name: '*foo*', as: 'bar' }))
```

## License

MIT. Made with ❤️
MIT. Made with 💛
47 changes: 31 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,15 @@ export interface CodegenOptions {
singleQuotes?: Boolean
}

// genImport
export type Import = string | { name: string, as?: string }
export function genImport (specifier: string, imports?: Import | Import[], opts: CodegenOptions = {}) {
const specifierStr = genString(specifier, opts)
if (!imports) {
return `import ${specifierStr}`
}
// genImport and genExport
export type Name = string | { name: string, as?: string }

const _imports = (Array.isArray(imports) ? imports : [imports]).map((i: Import) => {
if (typeof i === 'string') { return { name: i } }
if (i.name === i.as) { i = { name: i.name } }
// TODO: Ensure `name` and `as` are valid identifiers
// TODO: Ensure `as` is provided for default import
return i
})
export function genImport (specifier: string, imports?: Name | Name[], opts: CodegenOptions = {}) {
return genStatement('import', specifier, imports, opts)
}

const importsStr = _imports.map(i => i.as ? `${i.name} as ${i.as}` : i.name).join(', ')
return `import { ${importsStr} } from ${genString(specifier, opts)}`
export function genExport (specifier: string, imports?: Name | Name[], opts: CodegenOptions = {}) {
return genStatement('export', specifier, imports, opts)
}

// genDynamicImport
Expand All @@ -38,6 +29,30 @@ export function genDynamicImport (specifier: string, opts: DynamicImportOptions
// genImportName

// Internal

function genStatement (type: 'import' | 'export', specifier: string, names?: Name | Name[], opts: CodegenOptions = {}) {
const specifierStr = genString(specifier, opts)
if (!names) {
return `${type} ${specifierStr};`
}

const nameArray = Array.isArray(names)

const _names = (nameArray ? names : [names]).map((i: Name) => {
if (typeof i === 'string') { return { name: i } }
if (i.name === i.as) { i = { name: i.name } }
// TODO: Ensure `name` and `as` are valid identifiers
// TODO: Ensure `as` is provided for default import
return i
})

const namesStr = _names.map(i => i.as ? `${i.name} as ${i.as}` : i.name).join(', ')
if (nameArray) {
return `${type} { ${namesStr} } from ${genString(specifier, opts)};`
}
return `${type} ${namesStr} from ${genString(specifier, opts)};`
}

function genString (input: string, opts: CodegenOptions = {}) {
const str = JSON.stringify(input)
if (!opts.singleQuotes) {
Expand Down
29 changes: 24 additions & 5 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
import { expect, describe, it } from 'vitest'
import { genImport, genDynamicImport } from '../src'
import { genImport, genExport, genDynamicImport } from '../src'

const genImportTests = [
{ imports: 'foo', code: 'import { foo } from "pkg"' },
{ imports: { name: 'foo', as: 'bar' }, code: 'import { foo as bar } from "pkg"' },
{ imports: { name: 'default', as: 'Test' }, code: 'import { default as Test } from "pkg"' }
{ names: 'foo', code: 'import foo from "pkg";' },
{ names: ['foo'], code: 'import { foo } from "pkg";' },
{ names: [{ name: 'foo', as: 'bar' }], code: 'import { foo as bar } from "pkg";' },
{ names: { name: '*', as: 'bar' }, code: 'import * as bar from "pkg";' },
{ names: [{ name: 'default', as: 'Test' }], code: 'import { default as Test } from "pkg";' }
]

describe('genImport', () => {
for (const t of genImportTests) {
it(t.code, () => {
const code = genImport('pkg', t.imports || 'default')
const code = genImport('pkg', t.names)
expect(code).to.equal(t.code)
})
}
})

const genExportTests = [
{ names: 'foo', code: 'export foo from "pkg";' },
{ names: ['foo'], code: 'export { foo } from "pkg";' },
{ names: [{ name: 'foo', as: 'bar' }], code: 'export { foo as bar } from "pkg";' },
{ names: { name: '*', as: 'bar' }, code: 'export * as bar from "pkg";' },
{ names: ['default'], code: 'export { default } from "pkg";' }
]

describe('genExport', () => {
for (const t of genExportTests) {
it(t.code, () => {
const code = genExport('pkg', t.names)
expect(code).to.equal(t.code)
})
}
Expand Down

0 comments on commit 9135548

Please sign in to comment.