From d0a64b869a86e8c1f3a54838c40eeef76574e74b Mon Sep 17 00:00:00 2001 From: Elizabeth Craig Date: Wed, 8 Dec 2021 11:31:15 -0800 Subject: [PATCH 1/2] Fix trimming of filenames --- src/__tests__/trimFileName.ts | 119 ++++++++++++++++++++++++++++++++++ src/__tests__/utils.ts | 21 ------ src/parser.ts | 2 +- src/trimFileName.ts | 40 ++++++++++++ src/utils.ts | 13 ---- 5 files changed, 160 insertions(+), 35 deletions(-) create mode 100644 src/__tests__/trimFileName.ts delete mode 100644 src/__tests__/utils.ts create mode 100644 src/trimFileName.ts delete mode 100644 src/utils.ts diff --git a/src/__tests__/trimFileName.ts b/src/__tests__/trimFileName.ts new file mode 100644 index 00000000..267e624a --- /dev/null +++ b/src/__tests__/trimFileName.ts @@ -0,0 +1,119 @@ +import { assert } from 'chai'; +import { trimFileName } from '../trimFileName'; + +describe.only('trimFileName', () => { + describe('posix', () => { + const cwd = '/home/user/projects/react-docgen-typescript'; + const platform = 'posix'; + + it('works with simple path', () => { + const input = `${cwd}/src/__tests__/data/ExportsPropTypeImport.tsx`; + assert.equal( + trimFileName(input, cwd, platform), + 'react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx' + ); + }); + + it('works with repeated path segments', () => { + const input = `${cwd}/react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx`; + assert.equal( + trimFileName(input, cwd, platform), + 'react-docgen-typescript/react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx' + ); + }); + + it('preserves package name from node_modules', () => { + const input = `${cwd}/node_modules/@types/react/index.d.ts`; + assert.equal( + trimFileName(input, cwd, platform), + 'react-docgen-typescript/node_modules/@types/react/index.d.ts' + ); + }); + + it('preserves package name from node_modules in monorepo', () => { + // This simulates running docgen in an individual package in a monorepo + const monorepoCwd = cwd + '/packages/foo'; + const input = `${cwd}/node_modules/@types/react/index.d.ts`; + assert.equal( + trimFileName(input, monorepoCwd, platform), + 'react-docgen-typescript/node_modules/@types/react/index.d.ts' + ); + }); + + it('returns full path if there is no common root', () => { + const input = '/somewhere/else/foo.d.ts'; + assert.equal(trimFileName(input, cwd, platform), input); + }); + + it('works when run at the root directory', () => { + // This is more of a theoretical edge case + const input = `/src/__tests__/data/ExportsPropTypeImport.tsx`; + assert.equal( + trimFileName(input, '/', platform), + 'src/__tests__/data/ExportsPropTypeImport.tsx' + ); + }); + }); + + describe('windows', () => { + const cwd = 'C:\\Users\\user\\projects\\react-docgen-typescript'; + // typescript uses forward slashes even in windows paths + const cwdForwardSlash = cwd.replace(/\\/g, '/'); + const platform = 'win32'; + + it('works with simple path', () => { + const input = `${cwdForwardSlash}/src/__tests__/data/ExportsPropTypeImport.tsx`; + assert.equal( + trimFileName(input, cwd, platform), + 'react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx' + ); + }); + + it('works with repeated path segments', () => { + const input = `${cwdForwardSlash}/react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx`; + assert.equal( + trimFileName(input, cwd, platform), + 'react-docgen-typescript/react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx' + ); + }); + + it('preserves package name from node_modules', () => { + const input = `${cwdForwardSlash}/node_modules/@types/react/index.d.ts`; + assert.equal( + trimFileName(input, cwd, platform), + 'react-docgen-typescript/node_modules/@types/react/index.d.ts' + ); + }); + + it('preserves package name from node_modules in monorepo', () => { + const monorepoCwd = cwd + '\\packages\\foo'; + const input = `${cwdForwardSlash}/node_modules/@types/react/index.d.ts`; + assert.equal( + trimFileName(input, monorepoCwd, platform), + 'react-docgen-typescript/node_modules/@types/react/index.d.ts' + ); + }); + + it('returns full path if there is no common root', () => { + const input = 'D:/somewhere/else/foo.d.ts'; + assert.equal(trimFileName(input, cwd, platform), input); + }); + + it('works when run at the filesystem root', () => { + const input = `C:/src/__tests__/data/ExportsPropTypeImport.tsx`; + assert.equal( + trimFileName(input, 'C:\\', platform), + 'src/__tests__/data/ExportsPropTypeImport.tsx' + ); + }); + + it('works with backslashes', () => { + // typescript uses forward slashes in file paths, but test with backslashes too + const input = `${cwd}\\src\\__tests__\\data\\ExportsPropTypeImport.tsx`; + assert.equal( + trimFileName(input, cwd, platform), + 'react-docgen-typescript\\src\\__tests__\\data\\ExportsPropTypeImport.tsx' + ); + }); + }); +}); diff --git a/src/__tests__/utils.ts b/src/__tests__/utils.ts deleted file mode 100644 index 99fbdb45..00000000 --- a/src/__tests__/utils.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { assert } from 'chai'; -import { trimFileName } from '../utils'; - -describe('utils', () => { - it('should trim file name for simple path', () => { - const input = - '/home/user/projects/react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx'; - assert.equal( - trimFileName(input), - 'react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx' - ); - }); - it('should trim file name for complex path', () => { - const input = - '/home/user/projects/react-docgen-typescript/react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx'; - assert.equal( - trimFileName(input), - 'react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx' - ); - }); -}); diff --git a/src/parser.ts b/src/parser.ts index d22f26ee..4dea833c 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -4,7 +4,7 @@ import * as ts from 'typescript'; import { buildFilter } from './buildFilter'; import { SymbolDisplayPart } from 'typescript'; -import { trimFileName } from './utils'; +import { trimFileName } from './trimFileName'; type InterfaceOrTypeAliasDeclaration = | ts.TypeAliasDeclaration diff --git a/src/trimFileName.ts b/src/trimFileName.ts new file mode 100644 index 00000000..011853e2 --- /dev/null +++ b/src/trimFileName.ts @@ -0,0 +1,40 @@ +import * as path from 'path'; + +const slashRegex = /[\\/]/g; + +export function trimFileName( + fileName: string, + cwd: string = process.cwd(), + platform?: 'posix' | 'win32' +) { + // This allows tests to run regardless of current platform + const pathLib = platform ? path[platform] : path; + + // Typescript formats Windows paths with forward slashes. For easier use of + // the path utilities, normalize to platform-standard slashes, then restore + // the original slashes when returning the result. + const originalSep = fileName.match(slashRegex)?.[0] || pathLib.sep; + const normalizedFileName = pathLib.normalize(fileName); + const root = pathLib.parse(cwd).root; + + // Walk up paths from the current directory until we find a common ancestor, + // and return the path relative to that. This will work in either a single- + // package repo or a monorepo (where dependencies may be installed at the + // root, but commands may be run in a package folder). + let parent = cwd; + do { + if (normalizedFileName.startsWith(parent)) { + return ( + pathLib + // Preserve the parent directory name to match existing behavior + .relative(pathLib.dirname(parent), normalizedFileName) + // Restore original type of slashes + .replace(slashRegex, originalSep) + ); + } + parent = pathLib.dirname(parent); + } while (parent !== root); + + // No common ancestor, so return the path as-is + return fileName; +} diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index 8806bc72..00000000 --- a/src/utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as path from 'path'; - -export function trimFileName(fileName: string) { - // We'll use the currentDirectoryName to trim parent fileNames - const currentDirectoryPath = process.cwd(); - const currentDirectoryParts = currentDirectoryPath.split(path.sep); - const currentDirectoryName = - currentDirectoryParts[currentDirectoryParts.length - 1]; - - const fileNameParts = fileName.split('/'); - const idx = fileNameParts.lastIndexOf(currentDirectoryName); - return fileNameParts.slice(idx, fileNameParts.length).join('/'); -} From 149c8f7377364beae6100699badf9d7c1c6832a0 Mon Sep 17 00:00:00 2001 From: Elizabeth Craig Date: Thu, 9 Dec 2021 11:11:34 -0800 Subject: [PATCH 2/2] run build on pull request --- .github/workflows/nodejs.yml | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index ad345e85..0e90f1a7 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,10 +1,13 @@ name: Node CI -on: [push] +on: + push: + branches: [master] + pull_request: + branches: [master] jobs: build: - runs-on: ubuntu-latest strategy: @@ -12,16 +15,16 @@ jobs: node-version: [14.x] steps: - - uses: actions/checkout@v1 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: install dependencies - run: npm install - env: - CI: true - - name: test - run: npm test - env: - CI: true + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: install dependencies + run: npm install + env: + CI: true + - name: test + run: npm test + env: + CI: true