Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: implement fixes on viewer and allow exporting #754

Merged
merged 5 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -28,7 +28,7 @@
const extensionFormat = (s: string[]) => s.length > 1 ? `.{${s.join(',')}}` : `.${s.join('') || 'vue'}`

const defaultExtensions = extensionFormat(['js', 'ts', 'mjs'])
const extensions = Array.from(new Set(['vue', ...nuxt.options.extensions]))

Check warning on line 31 in src/resolvers.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

'extensions' is assigned a value but never used
const sfcExtensions = extensionFormat(Array.from(new Set(['vue', ...nuxt.options.extensions])).map(e => e.replace(/^\.*/, '')))

const importDirs = [...(nuxt.options.imports?.dirs || [])].map(r)
Expand Down Expand Up @@ -122,7 +122,7 @@
* @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;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was using property as export before, but it might conflict with JS keyword

};

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))}`)
})
}
Loading