refactor(assets): extract UnoCSS config into @hugo-fixit/unocss-preset package (#829)

Extract theme tokens, shortcuts, blocklist, safelist, and icon configuration
from uno.config.ts into a reusable workspace package at packages/unocss-preset/.

- Create @hugo-fixit/unocss-preset with presetFixIt and createFixItConfig()
- Simplify uno.config.ts to use createFixItConfig() with content/cli overrides
- Move unocss, @iconify/json from root devDependencies to preset package
This commit is contained in:
Cell
2026-08-14 12:33:18 +08:00
committed by GitHub
parent 65e9f2ff92
commit 3c449a9017
7 changed files with 234 additions and 109 deletions
+2 -4
View File
@@ -51,8 +51,7 @@
},
"devDependencies": {
"@antfu/eslint-config": "^9.2.0",
"@iconify/json": "^2.2.507",
"@iconify/utils": "^3.1.3",
"@hugo-fixit/unocss-preset": "workspace:*",
"@types/node": "^25.9.4",
"@unocss/cli": "^66.7.4",
"auto-changelog-plus": "^1.3.0",
@@ -64,8 +63,7 @@
"simple-git-hooks": "^2.13.1",
"tsx": "^4.22.4",
"typedoc": "^0.28.20",
"typescript": "^6.0.3",
"unocss": "^66.7.4"
"typescript": "^6.0.3"
},
"simple-git-hooks": {
"pre-commit": "pnpm -F versioning start dev && pnpm typecheck && pnpm lint-staged"
+60
View File
@@ -0,0 +1,60 @@
# @hugo-fixit/unocss-preset
UnoCSS preset for the [FixIt](https://fixit.lruihao.cn) Hugo theme. Provides theme tokens, shortcuts, blocklist, safelist, and icon configuration.
## Exports
- `presetFixIt` — the main UnoCSS preset (theme breakpoints/colors, z-index shortcuts, blocklist, safelist)
- `createFixItConfig(options?)` — creates a complete UnoCSS config combining `presetWind3`, `presetIcons` (lucide + octicon), and `presetFixIt`
## Usage
```ts
// uno.config.ts
import { createFixItConfig } from '@hugo-fixit/unocss-preset'
export default createFixItConfig({
overrides: {
content: {
filesystem: ['layouts/**/*.html'],
},
},
})
```
### Options
| Option | Type | Description |
| ----------- | ---------------------------- | --------------------------------------- |
| `presets` | `PresetOrFactoryAwaitable[]` | Additional UnoCSS presets to include |
| `overrides` | `Partial<UserConfig>` | Override or extend the generated config |
## Theme
### Breakpoints (min-width, mobile-first)
| Token | Value |
| ----- | -------- |
| `sm` | `680px` |
| `md` | `960px` |
| `lg` | `1200px` |
| `xl` | `1440px` |
Use `max-sm:` prefix for xs (< 680px).
### Colors (CSS custom properties)
`primary`, `secondary`, `success`, `info`, `warning`, `danger` — mapped to `var(--fi-*)`.
## Shortcuts
Semantic z-index utilities mirroring `core/mixins/_z-index.scss`:
| Shortcut | Utility |
| ----------- | -------- |
| `z-hide` | `z--1` |
| `z-auto` | `z-auto` |
| `z-base` | `z-1` |
| `z-loading` | `z-10` |
| `z-sticky` | `z-100` |
| `z-fixed` | `z-200` |
+13
View File
@@ -0,0 +1,13 @@
{
"name": "@hugo-fixit/unocss-preset",
"type": "module",
"version": "0.1.0",
"private": true,
"description": "UnoCSS preset for Hugo FixIt theme",
"author": "Lruihao",
"main": "src/index.ts",
"dependencies": {
"@iconify/json": "^2.2.507",
"unocss": "^66.7.4"
}
}
+112
View File
@@ -0,0 +1,112 @@
import type { UserConfig } from 'unocss'
import { definePreset, presetIcons, presetWind3 } from 'unocss'
/**
* FixIt UnoCSS preset — theme tokens, shortcuts, blocklist, and safelist.
*/
export const presetFixIt = definePreset<object>(() => ({
name: 'preset-fixit',
theme: {
// FixIt responsive breakpoints (min-width, mobile-first)
// xs (< 680px) use max-sm: prefix in UnoCSS
breakpoints: {
sm: '680px',
md: '960px',
lg: '1200px',
xl: '1440px',
},
colors: {
primary: 'var(--fi-primary)',
secondary: 'var(--fi-secondary)',
success: 'var(--fi-success)',
info: 'var(--fi-info)',
warning: 'var(--fi-warning)',
danger: 'var(--fi-danger)',
},
},
// No preflight/reset — FixIt has its own in core/_reboot.scss
preflights: [],
// Semantic z-index shortcuts (mirrors core/mixins/_z-index.scss)
shortcuts: {
'z-hide': 'z--1',
'z-auto': 'z-auto',
'z-base': 'z-1',
'z-loading': 'z-10',
'z-sticky': 'z-100',
'z-fixed': 'z-200',
},
// Block unused or false-positive utilities
blocklist: [
'container',
/^h[1-6]$/,
// Block legacy Font Awesome icons (FA uses CSS font, not SVG)
/^fa-/,
],
// Always generate these utilities (used dynamically in templates)
safelist: [
'text-success',
'text-error',
'text-warning',
'text-info',
'text-primary',
'bg-success',
'bg-error',
'bg-warning',
'bg-info',
'bg-primary',
// For footer lines order, optional values: ["first", 0-5, "last"]
'order-first',
'order-last',
'order-0',
'order-1',
'order-2',
'order-3',
'order-4',
'order-5',
// Responsive visibility
'sm:hidden',
'max-sm:hidden',
'print:hidden',
// Print page breaks
'break-before-page',
'break-after-page',
],
}))
export interface FixItConfigOptions {
/**
* Additional UnoCSS presets to include alongside FixIt defaults.
*/
presets?: UserConfig['presets']
/**
* Override or extend the FixIt config.
*/
overrides?: Partial<UserConfig>
}
/**
* Create a complete UnoCSS config for FixIt.
* Includes presetWind3, presetFixIt, and presetFixItIcons by default.
*/
export function createFixItConfig(options: FixItConfigOptions = {}): UserConfig {
const { presets = [], overrides = {} } = options
return {
presets: [
presetIcons({
prefix: '',
collections: {
lucide: () => import('@iconify/json/json/lucide.json').then(i => i.default),
octicon: () => import('@iconify/json/json/octicon.json').then(i => i.default),
},
extraProperties: {
'display': 'inline-block',
'vertical-align': 'text-bottom',
},
}),
presetWind3(),
presetFixIt(),
...presets,
],
...overrides,
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": ["ESNext"],
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
+12 -9
View File
@@ -11,12 +11,9 @@ importers:
'@antfu/eslint-config':
specifier: ^9.2.0
version: 9.2.0(@typescript-eslint/typescript-estree@8.65.0(typescript@6.0.3))(@typescript-eslint/utils@8.65.0(eslint@10.8.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.40)(eslint@10.8.0(jiti@2.7.0))(typescript@6.0.3)
'@iconify/json':
specifier: ^2.2.507
version: 2.2.507
'@iconify/utils':
specifier: ^3.1.3
version: 3.1.4
'@hugo-fixit/unocss-preset':
specifier: workspace:*
version: link:packages/unocss-preset
'@types/node':
specifier: ^25.9.4
version: 25.9.5
@@ -53,9 +50,6 @@ importers:
typescript:
specifier: ^6.0.3
version: 6.0.3
unocss:
specifier: ^66.7.4
version: 66.7.5(vite@8.1.5(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))
apps/demo: {}
@@ -112,6 +106,15 @@ importers:
specifier: ^3.4.2
version: 3.4.2
packages/unocss-preset:
dependencies:
'@iconify/json':
specifier: ^2.2.507
version: 2.2.507
unocss:
specifier: ^66.7.4
version: 66.7.5(vite@8.1.5(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))
packages/versioning:
devDependencies:
'@hugo-fixit/shared':
+19 -96
View File
@@ -1,102 +1,25 @@
import { defineConfig, presetIcons, presetWind3 } from 'unocss'
import { createFixItConfig } from '@hugo-fixit/unocss-preset'
export default defineConfig({
presets: [
presetIcons({
prefix: '',
collections: {
lucide: () => import('@iconify/json/json/lucide.json').then(i => i.default),
octicon: () => import('@iconify/json/json/octicon.json').then(i => i.default),
export default createFixItConfig({
overrides: {
// Scan Hugo templates for class usage
content: {
filesystem: [
'layouts/**/*.html',
'assets/js/**/*.ts',
],
pipeline: {
exclude: ['node_modules', 'dist'],
},
extraProperties: {
'display': 'inline-block',
'vertical-align': 'text-bottom',
},
}),
presetWind3(),
],
theme: {
// FixIt responsive breakpoints (min-width, mobile-first)
// xs (< 680px) use max-sm: prefix in UnoCSS
breakpoints: {
sm: '680px',
md: '960px',
lg: '1200px',
xl: '1440px',
},
colors: {
primary: 'var(--fi-primary)',
secondary: 'var(--fi-secondary)',
success: 'var(--fi-success)',
info: 'var(--fi-info)',
warning: 'var(--fi-warning)',
danger: 'var(--fi-danger)',
// CLI entry for unocss / unocss:watch
cli: {
entry: [
{
patterns: ['layouts/**/*.html', 'assets/js/**/*.ts'],
outFile: 'assets/css/unocss.css',
},
],
},
},
// No preflight/reset — FixIt has its own in core/_reboot.scss
preflights: [],
// Semantic z-index shortcuts (mirrors core/mixins/_z-index.scss)
shortcuts: {
'z-hide': 'z--1',
'z-auto': 'z-auto',
'z-base': 'z-1',
'z-loading': 'z-10',
'z-sticky': 'z-100',
'z-fixed': 'z-200',
},
// Block unused or false-positive utilities
blocklist: [
'container',
/^h[1-6]$/,
// Block legacy Font Awesome icons (FA uses CSS font, not SVG)
/^fa-/,
],
// Always generate order utilities (used dynamically in templates)
safelist: [
'text-success',
'text-error',
'text-warning',
'text-info',
'text-primary',
'bg-success',
'bg-error',
'bg-warning',
'bg-info',
'bg-primary',
// For footer lines order, optional values: ["first", 0-5, "last"]
'order-first',
'order-last',
'order-0',
'order-1',
'order-2',
'order-3',
'order-4',
'order-5',
// Responsive visibility
'sm:hidden',
'max-sm:hidden',
'print:hidden',
// Print page breaks
'break-before-page',
'break-after-page',
],
// Scan Hugo templates for class usage
content: {
filesystem: [
'layouts/**/*.html',
'assets/js/**/*.ts',
],
pipeline: {
exclude: ['node_modules', 'dist'],
},
},
// CLI entry for unocss / unocss:watch
cli: {
entry: [
{
patterns: ['layouts/**/*.html', 'assets/js/**/*.ts'],
outFile: 'assets/css/unocss.css',
},
],
},
})