diff --git a/.changeset/slow-years-flow.md b/.changeset/slow-years-flow.md new file mode 100644 index 00000000..d46f96e6 --- /dev/null +++ b/.changeset/slow-years-flow.md @@ -0,0 +1,5 @@ +--- +'@devup-ui/next-plugin': patch +--- + +Refactor collecting files diff --git a/apps/landing/src/components/Code.tsx b/apps/landing/src/components/Code.tsx index 3c6ae2c2..a1d5d6ad 100644 --- a/apps/landing/src/components/Code.tsx +++ b/apps/landing/src/components/Code.tsx @@ -32,7 +32,12 @@ export const Code = ({ }} display="none" > - + {value} diff --git a/apps/landing/tsconfig.json b/apps/landing/tsconfig.json index 1513e720..23b738d7 100644 --- a/apps/landing/tsconfig.json +++ b/apps/landing/tsconfig.json @@ -11,7 +11,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { diff --git a/packages/next-plugin/package.json b/packages/next-plugin/package.json index 8f0a625c..feb37d02 100644 --- a/packages/next-plugin/package.json +++ b/packages/next-plugin/package.json @@ -43,7 +43,8 @@ "dependencies": { "@devup-ui/webpack-plugin": "workspace:*", "next": "^16.0", - "@devup-ui/wasm": "workspace:*" + "@devup-ui/wasm": "workspace:*", + "glob": "^11.0" }, "devDependencies": { "vite": "^7.1", diff --git a/packages/next-plugin/src/__tests__/find-root.test.ts b/packages/next-plugin/src/__tests__/find-root.test.ts deleted file mode 100644 index abd468a8..00000000 --- a/packages/next-plugin/src/__tests__/find-root.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { existsSync } from 'node:fs' -import { join } from 'node:path' - -import { findRoot } from '../find-root' - -vi.mock('node:fs') - -describe('findRoot', () => { - beforeEach(() => { - vi.clearAllMocks() - }) - - it('should return the first directory with package.json when found', () => { - const mockDir = '/project/src/components' - const expectedRoot = '/project' - - vi.mocked(existsSync) - .mockReturnValueOnce(false) // /project/src/components/package.json - .mockReturnValueOnce(false) // /project/src/package.json - .mockReturnValueOnce(true) // /project/package.json - .mockReturnValueOnce(false) // /package.json - - const result = findRoot(mockDir) - - expect(result).toBe(expectedRoot) - expect(existsSync).toHaveBeenCalledWith( - join('/project/src/components', 'package.json'), - ) - expect(existsSync).toHaveBeenCalledWith( - join('/project/src', 'package.json'), - ) - expect(existsSync).toHaveBeenCalledWith(join('/project', 'package.json')) - }) - - it('should return process.cwd() when no package.json is found', () => { - const mockDir = '/some/deep/nested/directory' - const originalCwd = process.cwd() - - vi.mocked(existsSync).mockReturnValue(false) - - const result = findRoot(mockDir) - - expect(result).toBe(originalCwd) - }) - - it('should handle root directory correctly', () => { - const mockDir = '/' - - vi.mocked(existsSync).mockReturnValue(false) - - const result = findRoot(mockDir) - - expect(result).toBe(process.cwd()) - }) - - it('should find package.json in current directory', () => { - const mockDir = '/project' - - vi.mocked(existsSync) - .mockReturnValueOnce(true) // /project/package.json - .mockReturnValueOnce(false) // /package.json - - const result = findRoot(mockDir) - - expect(result).toBe('/project') - }) - - it('should handle multiple package.json files and return the deepest one', () => { - const mockDir = '/project/src/components/deep' - const expectedRoot = '/project' // The function returns the last found package.json (closest to root) - - vi.mocked(existsSync) - .mockReturnValueOnce(false) // /project/src/components/deep/package.json - .mockReturnValueOnce(false) // /project/src/components/package.json - .mockReturnValueOnce(true) // /project/src/package.json - .mockReturnValueOnce(true) // /project/package.json - .mockReturnValueOnce(false) // /package.json - - const result = findRoot(mockDir) - - expect(result).toBe(expectedRoot) - }) - - it('should handle paths', () => { - const mockDir = join('a', 'b', 'c', 'd') - const expectedRoot = join('a', 'b') - - vi.mocked(existsSync) - .mockReturnValueOnce(false) // a/b/c/d/package.json - .mockReturnValueOnce(false) // a/b/c/package.json - .mockReturnValueOnce(true) // a/b/package.json - .mockReturnValueOnce(false) // a/package.json - - const result = findRoot(mockDir) - - expect(result).toBe(expectedRoot) - }) - - it('should stop at filesystem root', () => { - const mockDir = join('a', 'b', 'c') - - // Mock existsSync to return false for all calls, simulating no package.json found - vi.mocked(existsSync).mockReturnValue(false) - - const result = findRoot(mockDir) - - expect(result).toBe(process.cwd()) - }) - - it('should handle empty string input', () => { - const mockDir = '' - - vi.mocked(existsSync).mockReturnValue(false) - - const result = findRoot(mockDir) - - expect(result).toBe(process.cwd()) - }) - - it('should handle single character directory', () => { - const mockDir = 'a' - - vi.mocked(existsSync) - .mockReturnValueOnce(false) // a/package.json - .mockReturnValueOnce(false) // ./package.json - - const result = findRoot(mockDir) - - expect(result).toBe(process.cwd()) - }) -}) diff --git a/packages/next-plugin/src/__tests__/preload.test.ts b/packages/next-plugin/src/__tests__/preload.test.ts index 52248489..c8a035fe 100644 --- a/packages/next-plugin/src/__tests__/preload.test.ts +++ b/packages/next-plugin/src/__tests__/preload.test.ts @@ -1,44 +1,41 @@ -import { globSync, writeFileSync } from 'node:fs' +import { writeFileSync } from 'node:fs' import { readFileSync } from 'node:fs' import { existsSync } from 'node:fs' import { join } from 'node:path' import { codeExtract, registerTheme } from '@devup-ui/wasm' +import { globSync } from 'glob' -import { findRoot } from '../find-root' import { preload } from '../preload' // Mock dependencies vi.mock('node:fs') vi.mock('@devup-ui/wasm') -vi.mock('../find-root') +vi.mock('glob') // Mock globSync vi.mock('node:fs', () => ({ - globSync: vi.fn(), readFileSync: vi.fn(), writeFileSync: vi.fn(), mkdirSync: vi.fn(), existsSync: vi.fn(), })) +vi.mock('glob', () => ({ + globSync: vi.fn(), +})) + // Mock @devup-ui/wasm vi.mock('@devup-ui/wasm', () => ({ codeExtract: vi.fn(), registerTheme: vi.fn(), })) -// Mock findRoot -vi.mock('../find-root', () => ({ - findRoot: vi.fn(), -})) - describe('preload', () => { beforeEach(() => { vi.clearAllMocks() // Default mock implementations - vi.mocked(findRoot).mockReturnValue('/project/root') vi.mocked(globSync).mockReturnValue([ 'src/App.tsx', 'src/components/Button.tsx', @@ -67,12 +64,10 @@ describe('preload', () => { preload(excludeRegex, libPackage, singleCss, theme, cssDir) - expect(findRoot).toHaveBeenCalledWith(process.cwd()) expect(globSync).toHaveBeenCalledWith( ['**/*.tsx', '**/*.ts', '**/*.js', '**/*.mjs'], { - cwd: '/project/root', - exclude: expect.any(Function), + follow: true, }, ) }) @@ -86,7 +81,7 @@ describe('preload', () => { }) it('should process each collected file', () => { - const files = ['src/App.tsx', 'src/components/Button.tsx'] + const files = ['src/App.tsx', 'src/components/Button.tsx', '.next/page.tsx'] vi.mocked(globSync).mockReturnValue(files) preload(/node_modules/, '@devup-ui/react', false, {}, '/output/css') @@ -235,25 +230,4 @@ describe('preload', () => { 'utf-8', ) }) - it('should handle exclude regex', () => { - const excludeRegex = /node_modules/ - const libPackage = '@devup-ui/react' - const singleCss = false - const theme = { colors: { primary: 'blue' } } - const cssDir = '/output/css' - - preload(excludeRegex, libPackage, singleCss, theme, cssDir) - expect(globSync).toHaveBeenCalledWith( - ['**/*.tsx', '**/*.ts', '**/*.js', '**/*.mjs'], - { - cwd: '/project/root', - exclude: expect.any(Function), - }, - ) - expect( - (vi.mocked(globSync).mock.calls[0][1].exclude as any)( - '/node_modules/react.tsx', - ), - ).toBe(true) - }) }) diff --git a/packages/next-plugin/src/find-root.ts b/packages/next-plugin/src/find-root.ts deleted file mode 100644 index dfd3e621..00000000 --- a/packages/next-plugin/src/find-root.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { existsSync } from 'node:fs' -import { dirname, join } from 'node:path' - -export function findRoot(dir: string): string { - let root = dir - let prev = null - let result: string = process.cwd() - while (prev === null || root !== prev) { - if (existsSync(join(root, 'package.json'))) { - result = root - } - prev = root - root = dirname(root) - } - return result -} diff --git a/packages/next-plugin/src/preload.ts b/packages/next-plugin/src/preload.ts index 8fb52fc5..819f3ba4 100644 --- a/packages/next-plugin/src/preload.ts +++ b/packages/next-plugin/src/preload.ts @@ -1,9 +1,8 @@ -import { globSync, readFileSync, writeFileSync } from 'node:fs' +import { readFileSync, writeFileSync } from 'node:fs' import { basename, join, relative } from 'node:path' import { codeExtract, registerTheme } from '@devup-ui/wasm' - -import { findRoot } from './find-root' +import { globSync } from 'glob' export function preload( excludeRegex: RegExp, @@ -12,14 +11,19 @@ export function preload( theme: object, cssDir: string, ) { - const projectRoot = findRoot(process.cwd()) + const projectRoot = process.cwd() const collected = globSync(['**/*.tsx', '**/*.ts', '**/*.js', '**/*.mjs'], { - cwd: projectRoot, - exclude: (fileName) => excludeRegex.test(fileName), + follow: true, }) registerTheme(theme) for (const file of collected) { + if ( + /\.(test(-d)?|d|spec)\.(tsx|ts|js|mjs)$/.test(file) || + /^(out|.next)[/\\]/.test(file) || + excludeRegex.test(file) + ) + continue const filePath = relative(process.cwd(), join(projectRoot, file)) const { cssFile, css } = codeExtract( filePath, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2faad63..2476b112 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -760,6 +760,9 @@ importers: '@devup-ui/webpack-plugin': specifier: workspace:* version: link:../webpack-plugin + glob: + specifier: ^11.0 + version: 11.0.3 next: specifier: ^16.0 version: 16.0.0(@babel/core@7.28.4)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)