From 275692d5903b378e0ed9f1cb73017798d3fda63a Mon Sep 17 00:00:00 2001 From: Vasko Date: Thu, 1 Oct 2020 19:55:29 +0300 Subject: [PATCH 1/2] replace relative paths when exporting from d.ts --- index.ts | 54 ++++++++++++++++++++++++++++++++++++++++++++- tests/unit/index.ts | 14 ++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 1b19972..44fdb2e 100644 --- a/index.ts +++ b/index.ts @@ -48,6 +48,9 @@ export interface Options { // declare some constants so we don't have magic integers without explanation const DTSLEN = '.d.ts'.length; +// used to find relative paths to replace with their absolute +const relativePathsRegex = /(?:from\s+|import\s+|require\()['"]((?:\.|\.\.)\/[^'"]*)['"]/g; + const filenameToMid: (filename: string) => string = (function () { if (pathUtil.sep === '/') { return function (filename: string) { @@ -62,6 +65,53 @@ const filenameToMid: (filename: string) => string = (function () { } })(); +/** + * Get the absolute path from base path and relative one + * @param base The base path + * @param relative The relative path inside the base path + */ +function getAbsolutePath(base: string, relative: string) { + let stack: string[] = base.split('/'); + const parts: string[] = relative.split('/'); + + stack.pop(); + // remove current file name (or empty string) + // (omit if "base" is the current folder without trailing slash) + + for (let part of parts) { + if (part === '.') { + continue; + } + if (part === '..') { + stack.pop(); + } else { + stack.push(part); + } + } + // remove empty elements from the array to avoid ending / + stack = stack.filter(function(e) { return e; }); + return stack.join('/'); +} + +/** + * Replace all relative paths in a given content with absolute ones + * @param basePath The base path + * @param content The content to search for relative paths + */ +function replaceRelativePaths(basePath: string, content: string): string { + let match = null; + let resultContent: string = content; + while ((match = relativePathsRegex.exec(content)) != null) { + let relativePath = match[1]; + let absolutePath = getAbsolutePath(basePath, relativePath); + // replace relative paths with absolute + resultContent = resultContent.replace(`'${relativePath}'`, `'${absolutePath}'`); + resultContent = resultContent.replace(`"${relativePath}"`, `"${absolutePath}"`); + } + + return resultContent; +} + /** * A helper function that takes TypeScript diagnostic errors and returns an error * object. @@ -469,7 +519,7 @@ export default function generate(options: Options): Promise { output.write('declare module \'' + resolvedModuleId + '\' {' + eol + indent); - const content = processTree(declarationFile, function (node) { + let content = processTree(declarationFile, function (node) { if (isNodeKindExternalModuleReference(node)) { // TODO figure out if this branch is possible, and if so, write a test // that covers it. @@ -497,6 +547,8 @@ export default function generate(options: Options): Promise { } }); + content = replaceRelativePaths(resolvedModuleId, content); + output.write(content.replace(nonEmptyLineStart, '$&' + indent)); output.write(eol + '}' + eol); } diff --git a/tests/unit/index.ts b/tests/unit/index.ts index 3645d46..8ac6dd9 100644 --- a/tests/unit/index.ts +++ b/tests/unit/index.ts @@ -227,5 +227,19 @@ registerSuite('index', { const contents = fs.readFileSync('tmp/foo.d.ts', { encoding: 'utf8' }); assert.include(contents, `/// `); }); + }, + 'project with relative imports in .d.ts files': function () { + return generate({ + baseDir: 'tests/support/foo-relative-path', + files: [ 'sub/bar.d.ts', 'sub/baz.d.ts' ], + out: 'tmp/foo.d.ts' + }).then(function () { + const contents = fs.readFileSync('tmp/foo.d.ts', { encoding: 'utf8' }); + assert.include(contents, `export * from 'sub/folder/bar/bar'`); + assert.include(contents, `export * from 'sub/baz/baz'`); + + // all relative paths should be replaced with absolute ones so there should be no exports like this + assert.notInclude(contents, `export * from '.`); + }); } }); From 1ddaf577ad1c5839c8614d9fda0df9e97c95a15e Mon Sep 17 00:00:00 2001 From: Vasko Date: Thu, 1 Oct 2020 20:10:47 +0300 Subject: [PATCH 2/2] added forgotten tests files --- tests/support/foo-relative-path/sub/bar.d.ts | 1 + tests/support/foo-relative-path/sub/baz.d.ts | 1 + tests/support/foo-relative-path/sub/baz/baz.d.ts | 1 + tests/support/foo-relative-path/sub/folder/bar/bar.d.ts | 4 ++++ tests/unit/index.ts | 4 ++-- 5 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 tests/support/foo-relative-path/sub/bar.d.ts create mode 100644 tests/support/foo-relative-path/sub/baz.d.ts create mode 100644 tests/support/foo-relative-path/sub/baz/baz.d.ts create mode 100644 tests/support/foo-relative-path/sub/folder/bar/bar.d.ts diff --git a/tests/support/foo-relative-path/sub/bar.d.ts b/tests/support/foo-relative-path/sub/bar.d.ts new file mode 100644 index 0000000..f567f0e --- /dev/null +++ b/tests/support/foo-relative-path/sub/bar.d.ts @@ -0,0 +1 @@ +export * from './folder/bar/bar'; diff --git a/tests/support/foo-relative-path/sub/baz.d.ts b/tests/support/foo-relative-path/sub/baz.d.ts new file mode 100644 index 0000000..ec0a65f --- /dev/null +++ b/tests/support/foo-relative-path/sub/baz.d.ts @@ -0,0 +1 @@ +export * from './baz/baz'; diff --git a/tests/support/foo-relative-path/sub/baz/baz.d.ts b/tests/support/foo-relative-path/sub/baz/baz.d.ts new file mode 100644 index 0000000..9fffddd --- /dev/null +++ b/tests/support/foo-relative-path/sub/baz/baz.d.ts @@ -0,0 +1 @@ +export * from '../folder/bar/bar'; diff --git a/tests/support/foo-relative-path/sub/folder/bar/bar.d.ts b/tests/support/foo-relative-path/sub/folder/bar/bar.d.ts new file mode 100644 index 0000000..7208706 --- /dev/null +++ b/tests/support/foo-relative-path/sub/folder/bar/bar.d.ts @@ -0,0 +1,4 @@ +export declare interface Bar { + bar: string; + foo: number; +} diff --git a/tests/unit/index.ts b/tests/unit/index.ts index 8ac6dd9..b463c99 100644 --- a/tests/unit/index.ts +++ b/tests/unit/index.ts @@ -206,7 +206,7 @@ registerSuite('index', { assert.include(contents, `declare module 'foo/FooImplExportDeclaration'`); }); }, - 'add reference types package dependency ': function () { + 'add reference types package dependency': function () { return generate({ baseDir: 'tests/support/foo', files: [ 'index.ts' ], @@ -217,7 +217,7 @@ registerSuite('index', { assert.include(contents, `/// `); }); }, - 'add external path dependency ': function () { + 'add external path dependency': function () { return generate({ baseDir: 'tests/support/foo', files: [ 'index.ts' ],