Skip to content

Commit

Permalink
chore: implement fixes on viewer and allow exporting (#754)
Browse files Browse the repository at this point in the history
* chore: initial

* chore: progress

* chore: implement some fixes
  • Loading branch information
ineshbose authored Nov 15, 2023
1 parent 58abedf commit 1769e6a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 11 deletions.
14 changes: 10 additions & 4 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ import {
} from './resolvers'
import createTemplates from './templates'
import vitePlugin from './vite-hmr'
import setupViewer from './viewer'
import { setupViewer, exportViewer } from './viewer'
import { name, version, configKey, compatibility } from '../package.json'

import type { ModuleOptions, TWConfig } from './types'
import { withTrailingSlash } from 'ufo'
export type { ModuleOptions } from './types'

const logger = useLogger('nuxt:tailwindcss')
Expand Down Expand Up @@ -132,7 +133,6 @@ export default defineNuxtModule<ModuleOptions>({
await installModule('@nuxt/postcss8')
}


// enabled only in development
if (nuxt.options.dev) {
// Watch the Tailwind config file to restart the server
Expand Down Expand Up @@ -165,16 +165,22 @@ export default defineNuxtModule<ModuleOptions>({
title: 'TailwindCSS',
name: 'tailwindcss',
icon: 'logos-tailwindcss-icon',
category: 'modules',
view: {
type: 'iframe',
src: viewerConfig.endpoint
src: withTrailingSlash(viewerConfig.endpoint)
}
})
})
}
} else {
// production only
if (moduleOptions.viewer) {
const configTemplate = addTemplate({ filename: 'tw-viewer.config.cjs', getContents: () => `module.exports = ${JSON.stringify(tailwindConfig)}`, write: true })
exportViewer(configTemplate.dst, resolveViewerConfig(moduleOptions.viewer))
}
}
}

})

declare module '@nuxt/schema' {
Expand Down
2 changes: 1 addition & 1 deletion src/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export async function resolveCSSPath (cssPath: ModuleOptions['cssPath'], nuxt =
* @returns object
*/
const resolveBoolObj = <T, U extends Record<string, any>>(config: T, fb: U): U => defu(typeof config === 'object' ? config : {}, fb)
export const resolveViewerConfig = (config: ModuleOptions['viewer']): ViewerConfig => resolveBoolObj(config, { endpoint: '_tailwind' })
export const resolveViewerConfig = (config: ModuleOptions['viewer']): ViewerConfig => resolveBoolObj(config, { endpoint: '/_tailwind', exportViewer: false })
export const resolveExposeConfig = (config: ModuleOptions['exposeConfig']): ExposeConfig => resolveBoolObj(config, { alias: '#tailwind-config', level: 2 })

/**
Expand Down
10 changes: 9 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ export type ViewerConfig = {
*
* @default '/_tailwind'
*/
endpoint: string
endpoint: `/${string}`
/**
* Export the viewer during build
*
* Works in Nuxt 3; for Nuxt 2, use `npx tailwind-config-viewer export`
*
* @default false
*/
exportViewer: boolean;
};

export type ExposeConfig = {
Expand Down
28 changes: 23 additions & 5 deletions src/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,43 @@ import { underline, yellow } from 'colorette'
import { eventHandler, sendRedirect } from 'h3'
import { addDevServerHandler, isNuxt2, isNuxt3, useLogger, useNuxt } from '@nuxt/kit'
import { withTrailingSlash, withoutTrailingSlash, joinURL } from 'ufo'
import { relative } from 'pathe'
import type { TWConfig, ViewerConfig } from './types'

export default async function (twConfig: Partial<TWConfig>, config: ViewerConfig, nuxt = useNuxt()) {
const logger = useLogger('nuxt:tailwindcss')

export const setupViewer = async (twConfig: Partial<TWConfig>, config: ViewerConfig, nuxt = useNuxt()) => {
const route = joinURL(nuxt.options.app?.baseURL, config.endpoint)
// @ts-ignore
const createServer = await import('tailwind-config-viewer/server/index.js').then(r => r.default || r) as any
const routerPrefix = isNuxt3() ? route : undefined
const _viewerDevMiddleware = createServer({ tailwindConfigProvider: () => twConfig, routerPrefix }).asMiddleware()
const viewerDevMiddleware = eventHandler((event) => {
if (event.req.url === withoutTrailingSlash(route)) {
return sendRedirect(event, withTrailingSlash(event.req.url), 301)
const withoutSlash = withoutTrailingSlash(route)
if (event.node?.req.url === withoutSlash || event.req.url === withoutSlash) {
return sendRedirect(event, route, 301)
}
_viewerDevMiddleware(event.req, event.res)
_viewerDevMiddleware(event.node?.req || event.req, event.node?.res || event.res)
})
if (isNuxt3()) { addDevServerHandler({ route, handler: viewerDevMiddleware }) }
// @ts-ignore
if (isNuxt2()) { nuxt.options.serverMiddleware.push({ route, handler: (req, res) => viewerDevMiddleware(new H3Event(req, res)) }) }
nuxt.hook('listen', (_, listener) => {
const viewerUrl = `${withoutTrailingSlash(listener.url)}${route}`.replace(/\/+/g, '/')
useLogger('nuxt:tailwindcss').info(`Tailwind Viewer: ${underline(yellow(withTrailingSlash(viewerUrl)))}`)
logger.info(`Tailwind Viewer: ${underline(yellow(withTrailingSlash(viewerUrl)))}`)
})
}

export const exportViewer = async (pathToConfig: string, config: ViewerConfig, nuxt = useNuxt()) => {
if (!config.exportViewer) { return }
// @ts-ignore
const cli = await import('tailwind-config-viewer/cli/export.js').then(r => r.default || r) as any

nuxt.hook('nitro:build:public-assets', (nitro) => {
// nitro.options.prerender.ignore.push(config.endpoint);

const dir = joinURL(nitro.options.output.publicDir, config.endpoint);
cli(dir, pathToConfig)
logger.success(`Exported viewer to ${yellow(relative(nuxt.options.srcDir, dir))}`)
})
}

0 comments on commit 1769e6a

Please sign in to comment.