Skip to content

Commit a6819c1

Browse files
Add support for Tailwind CSS (#9)
1 parent ffe58e1 commit a6819c1

File tree

16 files changed

+132
-13
lines changed

16 files changed

+132
-13
lines changed

packages/create-vue-lib/src/index.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ type Config = {
8686
includeGithubCi: boolean
8787
includeAtAliases: boolean
8888
includeTestVariable: boolean
89+
includeTailwind: boolean
90+
includeVpRaw: boolean
8991
}
9092

9193
type Args = {
@@ -263,10 +265,12 @@ async function init() {
263265
process.exit(1)
264266
}
265267

268+
const includeTailwind = await togglePrompt('Include Tailwind CSS?')
266269
const includeEsLint = await togglePrompt('Include ESLint?', true)
267270
const includeEsLintStylistic = await togglePromptIf(includeEsLint, 'Include ESLint Stylistic for formatting?', includeEsLint)
268271
const includeVitest = await togglePromptIf(extended, 'Include Vitest for testing?', true)
269272
const includeDocs = await togglePrompt('Include VitePress for documentation?', true)
273+
const includeVpRaw = includeDocs && await togglePromptIf(extended, 'Include support for vp-raw in VitePress?', includeTailwind)
270274
const includeGithubPages = includeDocs && await togglePrompt('Include GitHub Pages config for documentation?')
271275
const includePlayground = await togglePrompt('Include playground application for development?', true)
272276
const includeGithubCi = await togglePrompt('Include GitHub CI configuration?', !!githubPath)
@@ -338,7 +342,9 @@ async function init() {
338342
includeVitest,
339343
includeGithubCi,
340344
includeAtAliases,
341-
includeTestVariable
345+
includeTestVariable,
346+
includeTailwind,
347+
includeVpRaw
342348
}
343349

344350
copyTemplate('base', config)
@@ -367,6 +373,14 @@ async function init() {
367373
copyTemplate('ci', config)
368374
}
369375

376+
if (config.includeTailwind) {
377+
copyTemplate('tailwind', config)
378+
}
379+
380+
if (config.includeVpRaw) {
381+
copyTemplate('vp-raw', config)
382+
}
383+
370384
console.log()
371385
console.log(`${bgGreen(bold(black('DONE')))} Project created`)
372386
console.log()
@@ -441,7 +455,10 @@ function copyFiles(templateFile: string, config: Config) {
441455
const target = targetPath.replace(/\.ejs$/, '')
442456
let content = ejs.render(template, { config })
443457

444-
if (/\.(json|m?[jt]s)$/.test(target)) {
458+
if (/\.(json|m?[jt]s|vue)$/.test(target)) {
459+
// Ensure there are no blank lines at the start and a single blank line at the end
460+
content = content.trim() + '\n'
461+
445462
// Trim spaces from the ends of lines
446463
content = content.replace(/ +\n/g, '\n')
447464

@@ -450,6 +467,9 @@ function copyFiles(templateFile: string, config: Config) {
450467

451468
// Remove trailing commas and any blank newlines that follow them
452469
content = content.replace(/, *(?:\n+(\n\s*)|(\s*))([}\])])/g, '$1$2$3')
470+
471+
// Trim blank lines after {, [ or (
472+
content = content.replace(/([{[(]\n)\n+/g, '$1')
453473
}
454474

455475
fs.writeFileSync(target, content)

packages/create-vue-lib/src/template/base/config/packages/@projectName@/package.json.ejs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
},
4040
"devDependencies": {
4141
"@rollup/plugin-replace": "^6.0.2",
42+
<%_ if (config.includeTailwind) { _%>
43+
"@tailwindcss/vite": "^4.1.5",
44+
<%_ } _%>
4245
"@tsconfig/node22": "^22.0.1",
4346
"@types/jsdom": "^21.1.7",
4447
"@types/node": "^22.13.14",
@@ -53,6 +56,9 @@
5356
"npm-run-all2": "^7.0.2",
5457
"publint": "^0.3.9",
5558
"rimraf": "^5.0.1",
59+
<%_ if (config.includeTailwind) { _%>
60+
"tailwindcss": "^4.1.5",
61+
<%_ } _%>
5662
"typescript": "~5.8.0",
5763
"vite": "^6.2.4",
5864
"vite-plugin-dts": "^4.5.3",

packages/create-vue-lib/src/template/base/config/packages/@projectName@/vite.config.mts.ejs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { defineConfig, type UserConfig } from 'vite'
44
import replace from '@rollup/plugin-replace'
55
import vue from '@vitejs/plugin-vue'
66
import dts from 'vite-plugin-dts'
7+
<%_ if (config.includeTailwind) { _%>
8+
import tailwindcss from '@tailwindcss/vite'
9+
<%_ } _%>
710

811
export default defineConfig(({ mode }): UserConfig => {
912
if (mode !== 'production' && mode !== 'development' && mode !== 'neutral' && mode !== 'test') {
@@ -38,6 +41,9 @@ export default defineConfig(({ mode }): UserConfig => {
3841
prodDevtools: mode === 'development'
3942
}
4043
}),
44+
<%_ if (config.includeTailwind) { _%>
45+
tailwindcss(),
46+
<%_ } _%>
4147
dtsPlugin
4248
],
4349

packages/create-vue-lib/src/template/base/examples/packages/@projectName@/src/components/ExampleComponent.vue.ejs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ const msg = ref('Hello world!')
99
</script>
1010

1111
<template>
12-
<div class="outer">
13-
<input v-model="msg">
12+
<div class="outer<%- config.includeTailwind ? ' border-1 border-solid border-green-700 p-5' : '' %>">
13+
<input v-model="msg"<%- config.includeTailwind ? ' class="border-1 border-solid border-neutral-500 px-1 py-0.5"' : '' %>>
1414
<p>{{ msg }}</p>
1515
</div>
1616
</template>
1717

18+
<%_ if (!config.includeTailwind) { _%>
1819
<style scoped>
1920
.outer {
2021
border: 1px solid green;
@@ -26,3 +27,4 @@ const msg = ref('Hello world!')
2627
padding: 2px 4px;
2728
}
2829
</style>
30+
<%_ } _%>

packages/create-vue-lib/src/template/base/examples/packages/@projectName@/src/components/MyPanel.vue renamed to packages/create-vue-lib/src/template/base/examples/packages/@projectName@/src/components/MyPanel.vue.ejs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,22 @@ if (__DEV__) {
1313
</script>
1414

1515
<template>
16-
<div class="panel">
16+
<div class="panel<%- config.includeTailwind ? ' border-1 border-solid border-[#34495e] rounded-[5px] flex flex-col font-sans overflow-hidden [&>*+*]:border-t-1 [&>*+*]:border-t-solid [&>*+*]:border-t-[#34495e] [&>.panel-section:first-child]:rounded-t-[5px] [&>.panel-section:last-child]:rounded-b-[5px]' : '' %>">
1717
<slot name="header">
18-
<MyPanelSection v-if="title" class="panel-header">{{ title }}</MyPanelSection>
18+
<MyPanelSection v-if="title" class="panel-header<%- config.includeTailwind ? ' bg-[#34495e] inset-ring inset-ring-white text-white tracking-wide text-shadow-sm' : '' %>">{{ title }}</MyPanelSection>
1919
</slot>
2020
<slot name="body">
21-
<MyPanelSection class="panel-body">
21+
<MyPanelSection class="panel-body<%- config.includeTailwind ? ' flex-auto overflow-auto' : '' %>">
2222
<slot />
2323
</MyPanelSection>
2424
</slot>
2525
<slot name="footer">
26-
<MyPanelSection v-if="footer" class="panel-footer">{{ footer }}</MyPanelSection>
26+
<MyPanelSection v-if="footer" class="panel-footer<%- config.includeTailwind ? ' bg-[#34495e] inset-ring inset-ring-white text-white tracking-wide text-shadow-sm' : '' %>">{{ footer }}</MyPanelSection>
2727
</slot>
2828
</div>
2929
</template>
3030

31+
<%_ if (!config.includeTailwind) { _%>
3132
<style scoped>
3233
.panel {
3334
border: 1px solid #34495e;
@@ -65,3 +66,4 @@ if (__DEV__) {
6566
overflow: auto;
6667
}
6768
</style>
69+
<%_ } _%>

packages/create-vue-lib/src/template/base/examples/packages/@projectName@/src/components/MyPanelSection.vue.ejs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ if (__DEV__) {
1313
</script>
1414

1515
<template>
16-
<div class="panel-section">
16+
<div class="panel-section<%- config.includeTailwind ? ' p-2' : '' %>">
1717
<slot />
1818
</div>
1919
</template>
2020

21+
<%_ if (!config.includeTailwind) { _%>
2122
<style scoped>
2223
.panel-section {
2324
padding: 10px;
2425
}
2526
</style>
27+
<%_ } _%>

packages/create-vue-lib/src/template/base/examples/packages/@projectName@/src/index.ts.ejs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
<%_ if (config.includeTailwind) { _%>
2+
import './index.css'
3+
4+
<%_ } _%>
15
export { default as ExampleComponent } from './components/ExampleComponent.vue'
26
export { default as MyPanel } from './components/MyPanel.vue'
37
export { default as MyPanelSection } from './components/MyPanelSection.vue'

packages/create-vue-lib/src/template/playground/config/packages/playground/package.json renamed to packages/create-vue-lib/src/template/playground/config/packages/playground/package.json.ejs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55
"vue": "^3.5.13"
66
},
77
"devDependencies": {
8+
<%_ if (config.includeTailwind) { _%>
9+
"@tailwindcss/vite": "^4.1.5",
10+
<%_ } _%>
811
"@tsconfig/node22": "^22.0.1",
912
"@types/node": "^22.13.14",
1013
"@vitejs/plugin-vue": "^5.2.3",
1114
"@vue/tsconfig": "^0.7.0",
1215
"npm-run-all2": "^7.0.2",
1316
"rimraf": "^5.0.1",
17+
<%_ if (config.includeTailwind) { _%>
18+
"tailwindcss": "^4.1.5",
19+
<%_ } _%>
1420
"typescript": "~5.8.0",
1521
"vite": "^6.2.4",
1622
"vite-plugin-vue-devtools": "^7.7.2",

packages/create-vue-lib/src/template/playground/config/packages/playground/vite.config.mts.ejs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { fileURLToPath, URL } from 'node:url'
33
import { defineConfig, type UserConfig } from 'vite'
44
import vue from '@vitejs/plugin-vue'
55
import vueDevTools from 'vite-plugin-vue-devtools'
6+
<%_ if (config.includeTailwind) { _%>
7+
import tailwindcss from '@tailwindcss/vite'
8+
<%_ } _%>
69

710
<%_ if (config.includeAtAliases) { _%>
811
const librarySrc = fileURLToPath(new URL('../<%- config.mainPackageDirName %>/src/', import.meta.url))
@@ -12,6 +15,9 @@ const playgroundSrc = fileURLToPath(new URL('./src/', import.meta.url))
1215
export default defineConfig(({ mode }): UserConfig => ({
1316
plugins: [
1417
vue(),
18+
<%_ if (config.includeTailwind) { _%>
19+
tailwindcss(),
20+
<%_ } _%>
1521
vueDevTools()
1622
],
1723

packages/create-vue-lib/src/template/playground/examples/packages/playground/src/App.vue renamed to packages/create-vue-lib/src/template/playground/examples/packages/playground/src/App.vue.ejs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<script setup lang="ts">
2-
import { ExampleComponent, MyPanel } from '@scopedPackageName@'
2+
import { ExampleComponent, MyPanel } from '<%- config.scopedPackageName %>'
33
</script>
44

55
<template>
6-
<div class="main">
6+
<div class="main<%- config.includeTailwind ? ' flex flex-col max-w-75 gap-2.5 m-2.5' : '' %>">
77
<ExampleComponent />
88
<MyPanel title="Panel title" footer="Panel footer">
99
Header and footer
@@ -20,6 +20,7 @@ import { ExampleComponent, MyPanel } from '@scopedPackageName@'
2020
</div>
2121
</template>
2222

23+
<%_ if (!config.includeTailwind) { _%>
2324
<style scoped>
2425
.main {
2526
max-width: 300px;
@@ -29,3 +30,4 @@ import { ExampleComponent, MyPanel } from '@scopedPackageName@'
2930
margin-top: 10px;
3031
}
3132
</style>
33+
<%_ } _%>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@import "tailwindcss";
2+
3+
@source ".";

packages/create-vue-lib/src/template/vitepress/config/packages/docs/.vitepress/config.mts.ejs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { fileURLToPath, URL } from 'node:url'
22

33
import { defineConfigWithTheme } from 'vitepress'
4+
<%_ if (config.includeTailwind) { _%>
5+
import tailwindcss from '@tailwindcss/vite'
6+
<%_ } _%>
47

58
<%_ if (config.includeAtAliases) { _%>
69
const librarySrc = fileURLToPath(new URL('../../<%- config.mainPackageDirName %>/src/', import.meta.url))
@@ -34,6 +37,12 @@ export default ({ mode }: { mode: string }) => defineConfigWithTheme({
3437
<%_ } _%>
3538
3639
vite: {
40+
<%_ if (config.includeTailwind) { _%>
41+
plugins: [
42+
tailwindcss()
43+
],
44+
<%_ } _%>
45+
3746
resolve: {
3847
<%_ if (config.includeAtAliases) { _%>
3948
alias: [

packages/create-vue-lib/src/template/vitepress/config/packages/docs/package.json renamed to packages/create-vue-lib/src/template/vitepress/config/packages/docs/package.json.ejs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@
55
"vue": "^3.5.13"
66
},
77
"devDependencies": {
8+
<%_ if (config.includeTailwind) { _%>
9+
"@tailwindcss/vite": "^4.1.5",
10+
<%_ } _%>
811
"@tsconfig/node22": "^22.0.1",
912
"@types/node": "^22.13.14",
1013
"@vue/tsconfig": "^0.7.0",
1114
"npm-run-all2": "^7.0.2",
15+
<%_ if (config.includeVpRaw) { _%>
16+
"postcss": "^8.5.3",
17+
<%_ } _%>
1218
"rimraf": "^5.0.1",
19+
<%_ if (config.includeTailwind) { _%>
20+
"tailwindcss": "^4.1.5",
21+
<%_ } _%>
1322
"typescript": "~5.8.0",
1423
"vitepress": "^1.6.3",
1524
"vue-tsc": "^2.2.8"

packages/create-vue-lib/src/template/vitepress/examples/packages/docs/src/introduction.md renamed to packages/create-vue-lib/src/template/vitepress/examples/packages/docs/src/introduction.md.ejs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { ExampleComponent, MyPanel } from '@scopedPackageName@'
2+
import { ExampleComponent, MyPanel } from '<%- config.scopedPackageName %>'
33
</script>
44

55
<style scoped>
@@ -10,6 +10,9 @@ import { ExampleComponent, MyPanel } from '@scopedPackageName@'
1010

1111
# Introduction
1212

13+
<%_ if (config.includeVpRaw) { _%>
14+
::: raw
15+
<%_ } _%>
1316
<ExampleComponent />
1417

1518
<MyPanel title="Panel title" footer="Panel footer">
@@ -27,3 +30,6 @@ import { ExampleComponent, MyPanel } from '@scopedPackageName@'
2730
<MyPanel>
2831
No header or footer
2932
</MyPanel>
33+
<%_ if (config.includeVpRaw) { _%>
34+
:::
35+
<%_ } _%>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { postcssIsolateStyles } from 'vitepress'
2+
3+
export default {
4+
plugins: [
5+
// See https://vitepress.dev/guide/markdown#raw
6+
postcssIsolateStyles({
7+
includeFiles: [/base\.css/, /vp-doc\.css/]
8+
})
9+
]
10+
}

packages/docs/src/questions.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@
4444
<span class="check">✔</span> <a href="#main-package-directory">Main package directory … test-project</a>
4545
<span class="check">✔</span> <a href="#global-variable-name">Global variable name … TestProject</a>
4646
<span class="check">✔</span> <a href="#github-path">GitHub path (optional) … skirtles-code/test-project</a>
47+
<span class="check">✔</span> <a href="#include-tailwind-css">Include Tailwind CSS? … No / Yes</a>
4748
<span class="check">✔</span> <a href="#include-eslint">Include ESLint? … No / Yes</a>
4849
<span class="check">✔</span> <a href="#include-eslint-stylistic">Include ESLint Stylistic for formatting? … No / Yes</a>
4950
<span class="check">✔</span> <a href="#include-vitest">Include Vitest for testing? … No / Yes</a>
5051
<span class="check">✔</span> <a href="#include-vitepress">Include VitePress for documentation? … No / Yes</a>
52+
<span class="check">✔</span> <a href="#include-vp-raw">Include support for vp-raw in VitePress? … No / Yes</a>
5153
<span class="check">✔</span> <a href="#include-github-pages">Include GitHub Pages config for documentation? … No / Yes</a>
5254
<span class="check">✔</span> <a href="#include-playground">Include playground application for development? … No / Yes</a>
5355
<span class="check">✔</span> <a href="#include-github-ci">Include GitHub CI configuration? … No / Yes</a>
@@ -140,6 +142,12 @@ For example, this project has its repository at `https://github.com/skirtles-cod
140142

141143
While answering this question is optional, it can be especially useful if you intend to use GitHub Pages to host your documentation, as the generated configuration files will be much closer to their final form.
142144

145+
## Include Tailwind CSS?{#include-tailwind-css}
146+
147+
[Tailwind CSS](https://tailwindcss.com/) is a popular CSS framework.
148+
149+
Selecting this option will add version 4 of Tailwind CSS to the project. This will include Vite configuration for all packages, as well as using Tailwind in the example code.
150+
143151
## Include ESLint?
144152

145153
Include configuration for ESLint. This will be very similar to the default configuration generated by the official [`create-vue`](https://github.com/vuejs/create-vue) tool.
@@ -172,9 +180,27 @@ Very small libraries might prefer to just use a GitHub `README.md` instead. Larg
172180

173181
VitePress will be configured with an `alias` to allow you to access your library within the documentation. This will use the library source code directly, without needing a build or release of the library.
174182

183+
## Include support for vp-raw in VitePress?{#include-vp-raw}
184+
185+
:::info NOTE
186+
You'll only see this question if you chose to include VitePress *and* you're using the `--extended` flag.
187+
:::
188+
189+
The default theme for VitePress can potentially clash with the CSS for components in your library. This is especially problematic when using Tailwind.
190+
191+
To mitigate this, VitePress supports the use of a `vp-raw` CSS class (or a `raw` custom container) to isolate component examples from the default VitePress styling:
192+
193+
- <https://vitepress.dev/guide/markdown#raw>
194+
195+
Isolating the styles will increase the size and complexity of the documentation CSS, so VitePress doesn't enable it by default. Instead, it must be enabled via a PostCSS plugin.
196+
197+
If you choose to include support for `vp-raw` then PostCSS will be added to the documentation package, along with the relevant configuration to enable style isolation.
198+
199+
This option will default to **Yes** if the project is using Tailwind.
200+
175201
## Include GitHub Pages config for documentation?{#include-github-pages}
176202

177-
You'll only see this question if you chose to include VitePress in the previous question.
203+
You'll only see this question if you chose to include VitePress.
178204

179205
Selecting this option will generate configuration files for deploying your documentation to GitHub Pages via a GitHub Action. The workflow is configured to deploy from the `main` branch.
180206

0 commit comments

Comments
 (0)