Skip to content
This repository has been archived by the owner on Dec 12, 2023. It is now read-only.

Commit

Permalink
Support imports of modules with / in module name
Browse files Browse the repository at this point in the history
  • Loading branch information
blakeembrey committed Apr 1, 2016
1 parent 7276ed7 commit 1a4f616
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/lib/__test__/fixtures/compile/root.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import a from 'a'
import b = require('b')
import b = require('b/b')
export * from './root.import'
export default a
8 changes: 4 additions & 4 deletions src/lib/compile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test('compile', t => {
postmessage: undefined,
ambient: false,
browser: {
b: 'browser'
'b/b': 'browser'
},
dependencies: {},
devDependencies: {},
Expand Down Expand Up @@ -87,7 +87,7 @@ test('compile', t => {
}

;(root as any).dependencies.a = a
;(root as any).dependencies.b = b
;(root as any).dependencies['b/b'] = b
;(root as any).dependencies.browser = browser
;(a as any).dependencies.dep = dep

Expand Down Expand Up @@ -117,7 +117,7 @@ test('compile', t => {
'',
`// Generated by typings`,
`// Source: __test__/fixtures/compile/typings/b.d.ts`,
'declare module \'~root~b\' {',
'declare module \'~root~b/b\' {',
'export const foo: number',
'}',
'',
Expand All @@ -134,7 +134,7 @@ test('compile', t => {
`// Source: __test__/fixtures/compile/root.d.ts`,
'declare module \'~root/root\' {',
'import a from \'~root~a\'',
'import b = require(\'~root~b\')',
'import b = require(\'~root~b/b\')',
'export * from \'~root/root.import\'',
'export default a',
'}',
Expand Down
52 changes: 34 additions & 18 deletions src/lib/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,16 @@ export default function compile (tree: DependencyTree, options: Options): Promis

// Re-use "reads" over all compilations, created separate "imported" instances.
return Promise.all([
compileDependencyTree(tree, extend(options, { browser: false, readFiles, imported: {} as ts.Map<boolean> })),
compileDependencyTree(tree, extend(options, { browser: true, readFiles, imported: {} as ts.Map<boolean> }))
compileDependencyTree(tree, extend(options, {
browser: false,
readFiles,
imported: {} as ts.Map<boolean>
})),
compileDependencyTree(tree, extend(options, {
browser: true,
readFiles,
imported: {} as ts.Map<boolean>
}))
])
.then(([main, browser]) => {
return {
Expand All @@ -84,10 +92,10 @@ interface CompileOptions extends Options {
/**
* Resolve override paths.
*/
function resolveFromOverride (src: string, to: string | boolean): string {
function resolveFromOverride (src: string, to: string | boolean, tree: DependencyTree): string {
if (typeof to === 'string') {
if (isModuleName(to)) {
const [moduleName, modulePath] = getModuleNameParts(to)
const [moduleName, modulePath] = getModuleNameParts(to, tree)

return modulePath ? normalizeToDefinition(to) : moduleName
}
Expand All @@ -101,9 +109,9 @@ function resolveFromOverride (src: string, to: string | boolean): string {
/**
* Resolve module locations (appending `.d.ts` to paths).
*/
function resolveFromWithModuleName (src: string, to: string): string {
function resolveFromWithModuleName (src: string, to: string, tree: DependencyTree): string {
if (isModuleName(to)) {
const [moduleName, modulePath] = getModuleNameParts(to)
const [moduleName, modulePath] = getModuleNameParts(to, tree)

return modulePath ? toDefinition(to) : moduleName
}
Expand Down Expand Up @@ -132,8 +140,8 @@ function getStringifyOptions (
overrides[mainDefinition] = browserDefinition
} else {
for (const key of Object.keys(browser)) {
const from = resolveFromOverride(tree.src, key) as string
const to = resolveFromOverride(tree.src, browser[key])
const from = resolveFromOverride(tree.src, key, tree) as string
const to = resolveFromOverride(tree.src, browser[key], tree)

overrides[from] = to
}
Expand Down Expand Up @@ -288,7 +296,7 @@ function stringifyDependencyPath (path: string, options: StringifyOptions): Prom

// Load a dependency path.
function loadByModuleName (path: string) {
const [moduleName, modulePath] = getModuleNameParts(path)
const [moduleName, modulePath] = getModuleNameParts(path, tree)
const compileOptions = { cwd, browser, readFiles, imported, emitter, name: moduleName, ambient: false, meta }
const stringifyOptions = cachedStringifyOptions(moduleName, compileOptions, options)

Expand All @@ -315,7 +323,7 @@ function stringifyDependencyPath (path: string, options: StringifyOptions): Prom
return
}

const importedFiles = info.importedFiles.map(x => resolveFromWithModuleName(resolved, x.fileName))
const importedFiles = info.importedFiles.map(x => resolveFromWithModuleName(resolved, x.fileName, tree))
const referencedFiles = info.referencedFiles.map(x => resolveFrom(resolved, x.fileName))

// All dependencies MUST be imported for ambient modules.
Expand Down Expand Up @@ -375,26 +383,34 @@ function stringifyDependencyPath (path: string, options: StringifyOptions): Prom
/**
* Separate the module name into pieces.
*/
function getModuleNameParts (name: string): [string, string] {
const parts = name.split(/[\\\/]/)
const moduleName = parts.shift()
const modulePath = parts.length === 0 ? null : parts.join('/')
function getModuleNameParts (name: string, tree: DependencyTree): [string, string] {
const parts = name.split(/[\\\/]/g)
let len = parts.length

return [moduleName, modulePath]
while (len--) {
const name = parts.slice(0, len).join('/')
const path = parts.slice(len).join('/')

if (tree.dependencies[name]) {
return [name, path]
}
}

return [parts.join('/'), null]
}

/**
* Normalize import paths against the prefix.
*/
function importPath (path: string, name: string, options: StringifyOptions) {
const resolved = getPath(resolveFromWithModuleName(path, name), options)
const { prefix, tree } = options
const resolved = getPath(resolveFromWithModuleName(path, name, tree), options)

if (isModuleName(resolved)) {
const [moduleName, modulePath] = getModuleNameParts(resolved)
const [moduleName, modulePath] = getModuleNameParts(resolved, tree)

// If the dependency is not available, *do not* transform - it's probably ambient.
if (options.dependencies[moduleName] == null) {
if (tree.dependencies[moduleName] == null) {
return name
}

Expand Down

0 comments on commit 1a4f616

Please sign in to comment.