Skip to content

Commit 5c26b7a

Browse files
committed
refactor: add support for relative import/export source replacement
1 parent 564ed0d commit 5c26b7a

17 files changed

+240
-21
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { CallExpression, NodePath } from '../types'
2+
import { CompiledReplacement, CompileReplacementOptions } from '.'
3+
import compileRelativeSourceReplacement from './RelativeSource'
4+
import * as t from '@babel/types'
5+
6+
export default function compileCallExpressionReplacement(
7+
path: NodePath<CallExpression, CallExpression>,
8+
compileOptions: CompileReplacementOptions
9+
): CompiledReplacement | void {
10+
const pattern = path.value
11+
const n = compileOptions.backend.t.namedTypes
12+
if (n.Import.check(pattern.callee)) {
13+
const sourceReplacement = compileRelativeSourceReplacement(
14+
path.get('arguments').get(0),
15+
compileOptions
16+
)
17+
if (sourceReplacement) {
18+
return {
19+
generate: (match, options) =>
20+
t.callExpression(t.import(), [
21+
sourceReplacement.generate(match, options) as t.StringLiteral,
22+
]),
23+
}
24+
}
25+
}
26+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { ExportAllDeclaration, NodePath, Node, StringLiteral } from '../types'
2+
import {
3+
CompiledReplacement,
4+
CompileReplacementOptions,
5+
GenerateReplacementOptions,
6+
ReplaceableMatch,
7+
} from '.'
8+
import compileGenericNodeReplacement from './GenericNodeReplacement'
9+
import transferComments from '../util/transferComments'
10+
import compileRelativeSourceReplacement from './RelativeSource'
11+
12+
export default function compileExportAllDeclarationReplacement(
13+
path: NodePath<ExportAllDeclaration, ExportAllDeclaration>,
14+
compileOptions: CompileReplacementOptions
15+
): CompiledReplacement | void {
16+
const replacement = compileGenericNodeReplacement(path, compileOptions)
17+
18+
const sourceReplacement = compileRelativeSourceReplacement(
19+
path.get('source'),
20+
compileOptions
21+
)
22+
23+
return {
24+
generate: (
25+
match: ReplaceableMatch,
26+
options: GenerateReplacementOptions
27+
): Node | Node[] => {
28+
const result: ExportAllDeclaration = replacement.generate(
29+
match,
30+
options
31+
) as any
32+
if (sourceReplacement) {
33+
result.source = sourceReplacement.generate(
34+
match,
35+
options
36+
) as StringLiteral
37+
}
38+
transferComments(path.node, result)
39+
return result
40+
},
41+
}
42+
}

src/compileReplacement/ExportNamedDeclaration.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,41 @@
1-
import { ExportNamedDeclaration, NodePath, Node } from '../types'
1+
import { ExportNamedDeclaration, NodePath, Node, StringLiteral } from '../types'
22
import {
33
CompiledReplacement,
44
CompileReplacementOptions,
5+
GenerateReplacementOptions,
56
ReplaceableMatch,
67
} from '.'
78
import compileGenericNodeReplacement from './GenericNodeReplacement'
89
import transferComments from '../util/transferComments'
10+
import compileRelativeSourceReplacement from './RelativeSource'
911

1012
export default function compileExportNamedDeclarationReplacement(
1113
path: NodePath<ExportNamedDeclaration, ExportNamedDeclaration>,
1214
compileOptions: CompileReplacementOptions
1315
): CompiledReplacement | void {
1416
const n = compileOptions.backend.t.namedTypes
1517
const replacement = compileGenericNodeReplacement(path, compileOptions)
18+
19+
const sourceReplacement = compileRelativeSourceReplacement(
20+
path.get('source'),
21+
compileOptions
22+
)
23+
1624
return {
17-
generate: (match: ReplaceableMatch): Node | Node[] => {
18-
const result: ExportNamedDeclaration = replacement.generate(match) as any
25+
generate: (
26+
match: ReplaceableMatch,
27+
options: GenerateReplacementOptions
28+
): Node | Node[] => {
29+
const result: ExportNamedDeclaration = replacement.generate(
30+
match,
31+
options
32+
) as any
33+
if (sourceReplacement) {
34+
result.source = sourceReplacement.generate(
35+
match,
36+
options
37+
) as StringLiteral
38+
}
1939
if (result.specifiers) {
2040
// move ExportDefaultSpecifier to beginning if necessary
2141
// because @babel/generator craps out otherwise

src/compileReplacement/GenericArrayReplacement.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { NodePath, Node } from '../types'
22
import compileReplacement, {
33
CompiledReplacement,
44
CompileReplacementOptions,
5+
GenerateReplacementOptions,
56
ReplaceableMatch,
67
} from './index'
78
import indentDebug from '../compileMatcher/indentDebug'
@@ -22,10 +23,13 @@ export default function compileGenericArrayReplacement(
2223
)
2324

2425
return {
25-
generate: (match: ReplaceableMatch): Node | Node[] => {
26+
generate: (
27+
match: ReplaceableMatch,
28+
options: GenerateReplacementOptions
29+
): Node | Node[] => {
2630
const result: Node[] = []
2731
for (const elem of elemReplacements) {
28-
const replacement = elem.generate(match)
32+
const replacement = elem.generate(match, options)
2933
if (Array.isArray(replacement)) {
3034
replacement.forEach((elem) => result.push(elem))
3135
} else {

src/compileReplacement/GenericNodeReplacement.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Node, NodePath } from '../types'
22
import compileReplacement, {
33
CompiledReplacement,
44
CompileReplacementOptions,
5+
GenerateReplacementOptions,
56
ReplaceableMatch,
67
} from './index'
78
import indentDebug from '../compileMatcher/indentDebug'
@@ -39,13 +40,16 @@ export default function compileGenericNodeReplacement(
3940
}
4041

4142
return {
42-
generate: (match: ReplaceableMatch): Node | Node[] => {
43+
generate: (
44+
match: ReplaceableMatch,
45+
options: GenerateReplacementOptions
46+
): Node | Node[] => {
4347
const result: any = {
4448
type: pattern.type,
4549
}
4650

4751
for (const [key, replacement] of childReplacements) {
48-
const value = replacement.generate(match)
52+
const value = replacement.generate(match, options)
4953

5054
if (value !== undefined) result[key] = value
5155
}

src/compileReplacement/Identifier.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Node, Identifier, NodePath } from '../types'
22
import {
33
CompiledReplacement,
44
CompileReplacementOptions,
5+
GenerateReplacementOptions,
56
ReplaceableMatch,
67
} from './'
78
import compilePlaceholderReplacement from './Placeholder'
@@ -29,11 +30,14 @@ export default function compileIdentifierReplacement(
2930
)
3031
return {
3132
...placeholderReplacement,
32-
generate: (match: ReplaceableMatch): Node | Node[] => {
33-
const generated = placeholderReplacement.generate(match)
33+
generate: (
34+
match: ReplaceableMatch,
35+
options: GenerateReplacementOptions
36+
): Node | Node[] => {
37+
const generated = placeholderReplacement.generate(match, options)
3438
if (!Array.isArray(generated)) {
3539
;(generated as any).typeAnnotation =
36-
typeAnnotationReplacement.generate(match)
40+
typeAnnotationReplacement.generate(match, options)
3741
}
3842
return generated
3943
},

src/compileReplacement/ImportDeclaration.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,41 @@
1-
import { ImportDeclaration, NodePath, Node } from '../types'
1+
import { ImportDeclaration, NodePath, Node, StringLiteral } from '../types'
22
import {
33
CompiledReplacement,
44
CompileReplacementOptions,
5+
GenerateReplacementOptions,
56
ReplaceableMatch,
67
} from '.'
78
import compileGenericNodeReplacement from './GenericNodeReplacement'
89
import transferComments from '../util/transferComments'
10+
import compileRelativeSourceReplacement from './RelativeSource'
911

1012
export default function compileImportDeclarationReplacement(
1113
path: NodePath<ImportDeclaration, ImportDeclaration>,
1214
compileOptions: CompileReplacementOptions
1315
): CompiledReplacement | void {
1416
const n = compileOptions.backend.t.namedTypes
1517
const replacement = compileGenericNodeReplacement(path, compileOptions)
18+
19+
const sourceReplacement = compileRelativeSourceReplacement(
20+
path.get('source'),
21+
compileOptions
22+
)
23+
1624
return {
17-
generate: (match: ReplaceableMatch): Node | Node[] => {
18-
const result: ImportDeclaration = replacement.generate(match) as any
25+
generate: (
26+
match: ReplaceableMatch,
27+
options: GenerateReplacementOptions
28+
): Node | Node[] => {
29+
const result: ImportDeclaration = replacement.generate(
30+
match,
31+
options
32+
) as any
33+
if (sourceReplacement) {
34+
result.source = sourceReplacement.generate(
35+
match,
36+
options
37+
) as StringLiteral
38+
}
1939
if (result.specifiers) {
2040
// move ImportDefaultSpecifier to beginning if necessary
2141
// because @babel/generator craps out otherwise
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { CompiledReplacement, CompileReplacementOptions } from '.'
2+
import { NodePath } from '../types'
3+
import * as t from '@babel/types'
4+
import Path from 'path'
5+
6+
export default function compileRelativeSourceReplacement(
7+
pattern: NodePath<any, any>,
8+
compileReplacementOptions: CompileReplacementOptions
9+
): CompiledReplacement | void {
10+
const source = pattern.value
11+
const { getResolveAgainstDir } = compileReplacementOptions
12+
if (
13+
source.type === 'StringLiteral' &&
14+
source.value.startsWith('.') &&
15+
getResolveAgainstDir
16+
) {
17+
const target = Path.resolve(getResolveAgainstDir(), source.value)
18+
return {
19+
generate: (match, { filename }) => {
20+
if (!filename) return t.stringLiteral(source.value)
21+
const relative = Path.relative(Path.dirname(filename), target)
22+
return t.stringLiteral(
23+
relative.startsWith('.') ? relative : `./${relative}`
24+
)
25+
},
26+
}
27+
}
28+
}

src/compileReplacement/TemplateLiteral.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ import { unescapeIdentifier } from './Placeholder'
55
import cloneNode from '../util/cloneNode'
66
import * as t from '@babel/types'
77
import transferComments from '../util/transferComments'
8-
9-
function generateValue(cooked: string): { raw: string; cooked: string } {
10-
return { raw: cooked.replace(/\\|`|\${/g, '\\$&'), cooked }
8+
function generateValue(cooked: string): {
9+
raw: string
10+
cooked: string
11+
} {
12+
return {
13+
raw: cooked.replace(/\\|`|\${/g, '\\$&'),
14+
cooked,
15+
}
1116
}
1217

1318
export default function compileTemplateLiteralReplacement(

src/compileReplacement/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { Node, NodePath, Debugger } from '../types'
22
import __debug from 'debug'
33
import compileGenericNodeReplacement from './GenericNodeReplacement'
44
import compileGenericArrayReplacement from './GenericArrayReplacement'
5+
import CallExpression from './CallExpression'
56
import ClassImplements from './ClassImplements'
67
import ClassProperty from './ClassProperty'
8+
import ExportAllDeclaration from './ExportAllDeclaration'
79
import ExportNamedDeclaration from './ExportNamedDeclaration'
810
import ExportDefaultSpecifier from './ExportDefaultSpecifier'
911
import ExportSpecifier from './ExportSpecifier'
@@ -39,18 +41,27 @@ export interface ReplaceableMatch {
3941
stringCaptures?: Record<string, string>
4042
}
4143

44+
export type GenerateReplacementOptions = {
45+
filename?: string
46+
}
47+
4248
export interface CompiledReplacement {
43-
generate: (match: ReplaceableMatch) => Node | Node[]
49+
generate: (
50+
match: ReplaceableMatch,
51+
options: GenerateReplacementOptions
52+
) => Node | Node[]
4453
}
4554

4655
export type RootCompileReplacementOptions = {
4756
debug?: Debugger
4857
backend: Backend
58+
getResolveAgainstDir?: () => string
4959
}
5060

5161
export type CompileReplacementOptions = {
5262
debug: Debugger
5363
backend: Backend
64+
getResolveAgainstDir?: () => string
5465
}
5566

5667
const nodeCompilers: Record<
@@ -60,8 +71,10 @@ const nodeCompilers: Record<
6071
options: CompileReplacementOptions
6172
) => CompiledReplacement | undefined | void
6273
> = {
74+
CallExpression,
6375
ClassImplements,
6476
ClassProperty,
77+
ExportAllDeclaration,
6578
ExportNamedDeclaration,
6679
ExportDefaultSpecifier,
6780
ExportSpecifier,

0 commit comments

Comments
 (0)