From 85e934d8d2a8f9eb31df3256192874fc2017b4c8 Mon Sep 17 00:00:00 2001 From: Inesh Bose <56732164+ineshbose@users.noreply.github.com> Date: Wed, 15 Feb 2023 16:22:49 +0000 Subject: [PATCH 1/3] feat: providing types for all exports --- src/module.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/module.ts b/src/module.ts index 5ba783ef..c6cfe803 100644 --- a/src/module.ts +++ b/src/module.ts @@ -163,6 +163,8 @@ export default defineNuxtModule({ // Expose resolved tailwind config as an alias // https://tailwindcss.com/docs/configuration/#referencing-in-javascript if (moduleOptions.exposeConfig) { + const dtsContent: string[] = [] + /** * Creates MJS exports for properties of the config * @@ -173,39 +175,45 @@ export default defineNuxtModule({ */ const populateMap = (obj: any, path: string[] = [], level = 1, maxLevel = moduleOptions.exposeLevel) => { Object.entries(obj).forEach(([key, value = {}]) => { + const subpath = path.concat(key).join('/') + if ( level >= maxLevel || // if recursive call is more than desired typeof value !== 'object' || // if its not an object, no more recursion required Array.isArray(value) || // arrays are objects in JS, but we can't break it down Object.keys(value as any).find(k => !k.match(/^[0-9a-z]+$/i)) // object has non-alphanumeric property (unsafe var name) ) { - addTemplate({ - filename: `tailwind.config/${path.concat(key).join('/')}.mjs`, + const t = addTemplate({ + filename: `tailwind.config/${subpath}.mjs`, getContents: () => `export default ${JSON.stringify(value, null, 2)}` }) + dtsContent.push(`declare module "${`.nuxt/tailwind.config/${subpath}` || t.dst}" { const defaultExport: ${JSON.stringify(value)}; export default defaultExport; }`) } else { // recurse through nested objects populateMap(value, path.concat(key), level + 1, maxLevel) const values = Object.keys(value as any) - addTemplate({ - filename: `tailwind.config/${path.concat(key).join('/')}.mjs`, - getContents: () => `${Object.keys(value as any).map(v => `import _${v} from "./${key}/${v}.mjs"`).join('\n')}\nconst config = { ${values.map(k => `"${k}": _${k}`).join(', ')} }\nexport { config as default${values.length > 0 ? ', _' : ''}${values.join(', _')} }` + const t = addTemplate({ + filename: `tailwind.config/${subpath}.mjs`, + getContents: () => `${values.map(v => `import _${v} from "./${key}/${v}.mjs"`).join('\n')}\nconst config = { ${values.map(k => `"${k}": _${k}`).join(', ')} }\nexport { config as default${values.length > 0 ? ', _' : ''}${values.join(', _')} }` }) + dtsContent.push(`declare module "${`.nuxt/tailwind.config/${subpath}` || t.dst}" {${Object.keys(value as any).map(v => ` export const _${v}: typeof import("${join(`.nuxt/tailwind.config/${key}/${subpath}` || t.dst, `../${v}`)}");`).join('')} const defaultExport: { ${values.map(k => `"${k}": typeof _${k}`).join(', ')} }; export default defaultExport; }`) } }) } populateMap(resolvedConfig) - const configOptions = Object.keys(resolvedConfig) + const template = addTemplate({ filename: 'tailwind.config.mjs', getContents: () => `${configOptions.map(v => `import ${v} from "./tailwind.config/${v}.mjs"`).join('\n')}\nconst config = { ${configOptions.join(', ')} }\nexport { config as default, ${configOptions.join(', ')} }` }) + dtsContent.push(`declare module "${'.nuxt/tailwind.config' || template.dst}" {${configOptions.map(v => ` export const ${v}: typeof import("${join('.nuxt/tailwind.config' || template.dst, v)}");`).join('')} const defaultExport: { ${configOptions.map(v => `"${v}": typeof ${v}`)} }; export default defaultExport; }`) + addTemplate({ filename: 'tailwind.config.d.ts', - getContents: () => `type tailwindcssConfig = import("tailwindcss").Config\ndeclare const config: tailwindcssConfig\n${configOptions.map(o => `declare const ${o}: tailwindcssConfig["${o}"]`).join('\n')}\nexport { config as default, ${configOptions.join(', ')} }`, + getContents: () => dtsContent.join('\n'), write: true }) nuxt.options.alias['#tailwind-config'] = template.dst From c0c905995d974b9b8b9aa99869fd74813fe2bb90 Mon Sep 17 00:00:00 2001 From: Inesh Bose <56732164+ineshbose@users.noreply.github.com> Date: Sun, 12 Mar 2023 22:10:51 +0000 Subject: [PATCH 2/3] chore: aiming to wrap this --- docs/content/1.getting-started/2.options.md | 2 +- docs/content/2.tailwind/1.config.md | 6 ++++++ src/module.ts | 22 +++++++++++---------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/content/1.getting-started/2.options.md b/docs/content/1.getting-started/2.options.md index 0c4d5764..e64f5f48 100644 --- a/docs/content/1.getting-started/2.options.md +++ b/docs/content/1.getting-started/2.options.md @@ -109,7 +109,7 @@ This is only relevant when [`exposeConfig`](/getting-started/options#exposeconfi ::alert{type="warning"} -It is unlikely for `exposeLevel` to ever be over 4 - the usual depth of a Tailwind config. A higher value is also likely to increase boot-time and disk space in dev. +It is unlikely for `exposeLevel` to ever be over 4 - the usual depth of a Tailwind config. A higher value is also likely to increase boot-time and disk space in dev. Refer to the [Nuxt Virtual File System](https://nuxt.com/docs/guide/directory-structure/nuxt#virtual-file-system) to see generated files. :: diff --git a/docs/content/2.tailwind/1.config.md b/docs/content/2.tailwind/1.config.md index dbf60707..1adc3433 100644 --- a/docs/content/2.tailwind/1.config.md +++ b/docs/content/2.tailwind/1.config.md @@ -248,3 +248,9 @@ import { _800 as slate800 } from '#tailwind-config/theme/colors/slate' // alias Please be aware this adds `~19.5KB` (`~3.5KB`) to the client bundle size. :: + +::alert{type="info"} + + Import types are only provided through the `#tailwind-config/*` alias. + +:: diff --git a/src/module.ts b/src/module.ts index d3732e6d..a25de8ea 100644 --- a/src/module.ts +++ b/src/module.ts @@ -179,30 +179,30 @@ export default defineNuxtModule({ * @param maxLevel maximum level of depth */ const populateMap = (obj: any, path: string[] = [], level = 1, maxLevel = moduleOptions.exposeLevel) => { - Object.entries(obj).forEach(([key, value = {}]) => { + Object.entries(obj).forEach(([key, value = {} as any]) => { const subpath = path.concat(key).join('/') if ( level >= maxLevel || // if recursive call is more than desired typeof value !== 'object' || // if its not an object, no more recursion required Array.isArray(value) || // arrays are objects in JS, but we can't break it down - Object.keys(value as any).find(k => !k.match(/^[0-9a-z]+$/i)) // object has non-alphanumeric property (unsafe var name) + Object.keys(value).find(k => !k.match(/^[0-9a-z]+$/i)) // object has non-alphanumeric property (unsafe var name) ) { - const t = addTemplate({ + addTemplate({ filename: `tailwind.config/${subpath}.mjs`, getContents: () => `export default ${JSON.stringify(value, null, 2)}` }) - dtsContent.push(`declare module "${`.nuxt/tailwind.config/${subpath}` || t.dst}" { const defaultExport: ${JSON.stringify(value)}; export default defaultExport; }`) + dtsContent.push(`declare module "#tailwind-config/${subpath}" { const defaultExport: ${JSON.stringify(value)}; export default defaultExport; }`) } else { // recurse through nested objects populateMap(value, path.concat(key), level + 1, maxLevel) - const values = Object.keys(value as any) - const t = addTemplate({ + const values = Object.keys(value) + addTemplate({ filename: `tailwind.config/${subpath}.mjs`, getContents: () => `${values.map(v => `import _${v} from "./${key}/${v}.mjs"`).join('\n')}\nconst config = { ${values.map(k => `"${k}": _${k}`).join(', ')} }\nexport { config as default${values.length > 0 ? ', _' : ''}${values.join(', _')} }` }) - dtsContent.push(`declare module "${`.nuxt/tailwind.config/${subpath}` || t.dst}" {${Object.keys(value as any).map(v => ` export const _${v}: typeof import("${join(`.nuxt/tailwind.config/${key}/${subpath}` || t.dst, `../${v}`)}");`).join('')} const defaultExport: { ${values.map(k => `"${k}": typeof _${k}`).join(', ')} }; export default defaultExport; }`) + dtsContent.push(`declare module "#tailwind-config/${subpath}" {${Object.keys(value).map(v => ` export const _${v}: typeof import("#tailwind-config/${join(`${key}/${subpath}`, `../${v}`)}");`).join('')} const defaultExport: { ${values.map(k => `"${k}": typeof _${k}`).join(', ')} }; export default defaultExport; }`) } }) } @@ -215,14 +215,16 @@ export default defineNuxtModule({ getContents: () => `${configOptions.map(v => `import ${v} from "#build/tailwind.config/${v}.mjs"`).join('\n')}\nconst config = { ${configOptions.join(', ')} }\nexport { config as default, ${configOptions.join(', ')} }`, write: true }) - dtsContent.push(`declare module "${'.nuxt/tailwind.config' || template.dst}" {${configOptions.map(v => ` export const ${v}: typeof import("${join('.nuxt/tailwind.config' || template.dst, v)}");`).join('')} const defaultExport: { ${configOptions.map(v => `"${v}": typeof ${v}`)} }; export default defaultExport; }`) - - addTemplate({ + dtsContent.push(`declare module "#tailwind-config" {${configOptions.map(v => ` export const ${v}: typeof import("${join('#tailwind-config', v)}");`).join('')} const defaultExport: { ${configOptions.map(v => `"${v}": typeof ${v}`)} }; export default defaultExport; }`) + const typesTemplate = addTemplate({ filename: 'tailwind.config.d.ts', getContents: () => dtsContent.join('\n'), write: true }) nuxt.options.alias['#tailwind-config'] = dirname(template.dst) + nuxt.hook('prepare:types', (opts) => { + opts.references.push({ path: typesTemplate.dst }) + }) } // Allow extending tailwindcss config by other modules From 6db4111496d650d871ab66226c73cea739d425d3 Mon Sep 17 00:00:00 2001 From: Inesh Bose <56732164+ineshbose@users.noreply.github.com> Date: Sun, 12 Mar 2023 23:24:55 +0000 Subject: [PATCH 3/3] Update docs/content/2.tailwind/1.config.md Co-authored-by: Daniel Roe --- docs/content/2.tailwind/1.config.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/content/2.tailwind/1.config.md b/docs/content/2.tailwind/1.config.md index 1adc3433..4c7b70e3 100644 --- a/docs/content/2.tailwind/1.config.md +++ b/docs/content/2.tailwind/1.config.md @@ -249,8 +249,6 @@ import { _800 as slate800 } from '#tailwind-config/theme/colors/slate' // alias :: -::alert{type="info"} - - Import types are only provided through the `#tailwind-config/*` alias. - +::alert +Import types are only provided through the `#tailwind-config/*` alias. ::