From 6a6dc4fc4dffefeb2141722cd8058d50ff27038e Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Thu, 8 Sep 2022 22:26:29 +1000 Subject: [PATCH] fix: resolve config paths fully and warn on config errors (#522) --- src/module.ts | 33 +++++++++-------- test/basic.test.ts | 8 +++- test/configs.test.ts | 45 +++++++++++++++++++++++ test/fixture/basic/alt-tailwind.config.js | 12 ++++++ test/fixture/basic/tailwind.config.js | 9 ++++- test/fixture/basic/ts-tailwind.config.ts | 14 +++++++ 6 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 test/configs.test.ts create mode 100644 test/fixture/basic/alt-tailwind.config.js create mode 100644 test/fixture/basic/ts-tailwind.config.ts diff --git a/src/module.ts b/src/module.ts index d980fa86..09b22d4a 100644 --- a/src/module.ts +++ b/src/module.ts @@ -12,8 +12,7 @@ import { createResolver, resolvePath, addVitePlugin, - tryRequireModule, - isNuxt3 + isNuxt3, findPath, requireModule } from '@nuxt/kit' import { Config } from 'tailwindcss' import { name, version } from '../package.json' @@ -39,8 +38,10 @@ export interface ModuleHooks { 'tailwindcss:config': (tailwindConfig: any) => void } +type Arrayable = T | T[] + export interface ModuleOptions { - configPath: string; + configPath: Arrayable; cssPath: string; config: Config; viewer: boolean; @@ -76,17 +77,14 @@ export default defineNuxtModule({ * Push config paths into `configPaths` without extension. * Allows next steps of processing to try both .js / .ts when resolving the config. */ - const addConfigPath = async (path: string | string[]) => { - if (typeof path === 'string') { - path = (await resolvePath(path, { extensions: ['.js', '.ts'] })).split('.').slice(0, -1).join('.') - configPaths.push(path) - return - } - - if (Array.isArray(path)) { - for (let _path of path) { - _path = (await resolvePath(_path, { extensions: ['.js', '.ts'] })).split('.').slice(0, -1).join('.') - configPaths.push() + const addConfigPath = async (path: Arrayable) => { + // filter in case an empty path is provided + const paths = (Array.isArray(path) ? path : [path]).filter(Boolean) + for (const path of paths) { + const resolvedPath = (await findPath(path, { extensions: ['.js', '.mjs', '.ts'] }, 'file')) + // only if the path is found + if (resolvedPath) { + configPaths.push(resolvedPath) } } } @@ -116,7 +114,12 @@ export default defineNuxtModule({ // Recursively resolve each config and merge tailwind configs together. let tailwindConfig: any = {} for (const configPath of configPaths) { - const _tailwindConfig = tryRequireModule(configPath, { clearCache: true }) + let _tailwindConfig + try { + _tailwindConfig = requireModule(configPath, { clearCache: true }) + } catch (e) { + logger.warn(`Failed to load Tailwind config at: \`./${relative(nuxt.options.rootDir, configPath)}\``, e) + } // Transform purge option from Array to object with { content } if (_tailwindConfig && Array.isArray(_tailwindConfig.purge)) { diff --git a/test/basic.test.ts b/test/basic.test.ts index 3c36a7c8..2f65ceae 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -13,7 +13,6 @@ describe('tailwindcss module', async () => { await setupNuxtTailwind({ exposeConfig: true, - configPath: r('tailwind.config.js'), cssPath: r('tailwind.css') }) @@ -39,6 +38,13 @@ describe('tailwindcss module', async () => { expect(nuxt.options.css[0]).toEqual(nuxt.options.tailwindcss.cssPath) }) + test('default js config is merged in', () => { + const nuxt = useTestContext().nuxt + const vfsKey = Object.keys(nuxt.vfs).find(k => k.includes('tailwind.config.')) + // set from default config tailwind.config.js + expect(nuxt.vfs[vfsKey]).contains('"primary": "#f1e05a"') + }) + // @todo re-implement // test('custom paths', () => { // const ctx = useTestContext() diff --git a/test/configs.test.ts b/test/configs.test.ts new file mode 100644 index 00000000..f29edbb1 --- /dev/null +++ b/test/configs.test.ts @@ -0,0 +1,45 @@ +import { describe, test, expect, vi } from 'vitest' +import { mockedWarn } from 'consola' +import { useTestContext } from '@nuxt/test-utils' +import { setupNuxtTailwind } from './util' + +describe('tailwindcss module configs', async () => { + vi.mock('consola', async () => { + const { default: mod } = (await vi.importActual('consola')) + mod.withScope = () => mod + mod.info = vi.fn() + mod.warn = vi.fn() + return { default: mod, info: mod.info, mockedWarn: mod.warn } + }) + + await setupNuxtTailwind({ + exposeConfig: true, + configPath: [ + 'alt-tailwind.config.js', + 'malformed-tailwind.config', + 'ts-tailwind.config' + ], + cssPath: 'tailwind.css' + }) + + test('throws error about malformed config', () => { + expect(mockedWarn.mock.calls[0][0]).toMatchInlineSnapshot('"Failed to load Tailwind config at: `./malformed-tailwind.config.js`"') + expect(mockedWarn.mock.calls[0][0]).contains('Failed to load Tailwind config at: `./malformed-tailwind.config.js`') + + expect(mockedWarn.mock.calls[0].length).toBe(2) + }) + + test('ts config file is loaded and merged', () => { + const nuxt = useTestContext().nuxt + const vfsKey = Object.keys(nuxt.vfs).find(k => k.includes('tailwind.config.')) + // set from ts-tailwind.config.ts + expect(nuxt.vfs[vfsKey]).contains('"typescriptBlue": "#007acc"') + }) + + test('js config file is loaded and merged', () => { + const nuxt = useTestContext().nuxt + const vfsKey = Object.keys(nuxt.vfs).find(k => k.includes('tailwind.config.')) + // set from ts-tailwind.config.ts + expect(nuxt.vfs[vfsKey]).contains('"javascriptYellow": "#f1e05a"') + }) +}) diff --git a/test/fixture/basic/alt-tailwind.config.js b/test/fixture/basic/alt-tailwind.config.js new file mode 100644 index 00000000..4af03f47 --- /dev/null +++ b/test/fixture/basic/alt-tailwind.config.js @@ -0,0 +1,12 @@ +module.exports = { + theme: { + extend: { + colors: { + javascriptYellow: '#f1e05a' + } + } + }, + content: [ + 'content/**/*.md' + ] +} diff --git a/test/fixture/basic/tailwind.config.js b/test/fixture/basic/tailwind.config.js index 7b0a6b42..dd9834a5 100644 --- a/test/fixture/basic/tailwind.config.js +++ b/test/fixture/basic/tailwind.config.js @@ -1,5 +1,12 @@ module.exports = { content: [ 'content/**/*.md' - ] + ], + theme: { + extend: { + colors: { + primary: '#f1e05a' + } + } + } } diff --git a/test/fixture/basic/ts-tailwind.config.ts b/test/fixture/basic/ts-tailwind.config.ts new file mode 100644 index 00000000..095bf3a2 --- /dev/null +++ b/test/fixture/basic/ts-tailwind.config.ts @@ -0,0 +1,14 @@ +import { Config } from 'tailwindcss' + +export default { + content: [ + 'content/**/*.md' + ], + theme: { + extend: { + colors: { + typescriptBlue: '#007acc' + } + } + } +}