Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions .github/workflows/autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ jobs:
- name: 📦 Install dependencies
run: pnpm install

- name: 🎨 Check for non-RTL CSS classes
run: pnpm rtl:check
- name: 🎨 Check for non-RTL/non-a11y CSS classes
run: pnpm lint:css

- name: 🌐 Compare translations
run: pnpm i18n:check
Expand Down
2 changes: 1 addition & 1 deletion app/components/LicenseDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const hasAnyValidLicense = computed(() => tokens.value.some(t => t.type === 'lic
{{ token.value }}
</a>
<span v-else-if="token.type === 'license'">{{ token.value }}</span>
<span v-else-if="token.type === 'operator'" class="text-[0.65em]">{{ token.value }}</span>
<span v-else-if="token.type === 'operator'" class="text-4xs">{{ token.value }}</span>
</template>
<span
v-if="hasAnyValidLicense"
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
"i18n:check:fix": "node scripts/compare-translations.ts --fix",
"i18n:report": "node scripts/find-invalid-translations.ts",
"i18n:report:fix": "node scripts/remove-unused-translations.ts",
"rtl:check": "node scripts/rtl-checker.ts",
"knip": "knip",
"knip:fix": "knip --fix",
"lint": "oxlint && oxfmt --check",
"lint:fix": "oxlint --fix && oxfmt",
"lint:css": "node scripts/unocss-checker.ts",
"generate": "nuxt generate",
"npmx-connector": "pnpm --filter npmx-connector dev",
"generate-pwa-icons": "pwa-assets-generator",
Expand Down Expand Up @@ -151,6 +151,9 @@
"*.{js,ts,mjs,cjs,vue}": [
"pnpm oxlint --fix"
],
"*.vue": [
"pnpm lint:css"
],
Comment thread
alexdln marked this conversation as resolved.
"*.{js,ts,mjs,cjs,vue,json,yml,md,html,css}": [
"pnpm oxfmt"
]
Expand Down
20 changes: 18 additions & 2 deletions scripts/rtl-checker.ts → scripts/unocss-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { fileURLToPath } from 'node:url'
import { resolve } from 'node:path'
import { createGenerator } from 'unocss'
import { presetRtl } from '../uno-preset-rtl.ts'
import { presetA11y } from '../uno-preset-a11y.ts'
import { COLORS } from './utils.ts'
import { presetWind4 } from 'unocss'

const argvFiles = process.argv.slice(2)
const APP_DIRECTORY = fileURLToPath(new URL('../app', import.meta.url))

async function checkFile(path: Dirent): Promise<string | undefined> {
Expand All @@ -33,6 +35,17 @@ async function checkFile(path: Dirent): Promise<string | undefined> {
`${COLORS.red} ❌ [RTL] ${filename}:${idx}${ruleIdx > -1 ? `:${ruleIdx + 1}` : ''} - ${warning}${COLORS.reset}`,
)
}),
presetA11y((warning, rule) => {
let entry = warnings.get(idx)
if (!entry) {
entry = []
warnings.set(idx, entry)
}
const ruleIdx = line.indexOf(rule)
entry.push(
`${COLORS.red} ❌ [A11y] ${filename}:${idx}${ruleIdx > -1 ? `:${ruleIdx + 1}` : ''} - ${warning}${COLORS.reset}`,
)
}),
],
})
const lines = file.split('\n')
Expand All @@ -46,7 +59,10 @@ async function checkFile(path: Dirent): Promise<string | undefined> {
}

async function check(): Promise<void> {
const dir = glob('**/*.vue', { withFileTypes: true, cwd: APP_DIRECTORY })
const dir = glob(argvFiles.length > 0 ? argvFiles : '**/*.vue', {
withFileTypes: true,
cwd: APP_DIRECTORY,
})
Comment thread
alexdln marked this conversation as resolved.
let hasErrors = false
for await (const file of dir) {
const result = await checkFile(file)
Expand All @@ -61,7 +77,7 @@ async function check(): Promise<void> {
process.exit(1)
} else {
// oxlint-disable-next-line no-console -- success logging
console.log(`${COLORS.green}✅ CSS RTL check passed!${COLORS.reset}`)
console.log(`${COLORS.green}✅ CSS check passed!${COLORS.reset}`)
}
}

Expand Down
77 changes: 77 additions & 0 deletions uno-preset-a11y.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import type { Preset } from 'unocss'

export type CollectorChecker = (warning: string, rule: string) => void

// Track warnings to avoid duplicates
const warnedClasses = new Set<string>()

function warnOnce(message: string, key: string) {
if (!warnedClasses.has(key)) {
warnedClasses.add(key)
// oxlint-disable-next-line no-console -- warn logging
console.warn(message)
}
}

/** Reset warning state (for testing) */
export function resetA11yWarnings() {
warnedClasses.clear()
}

const textPxToClass: Record<number, string> = {
11: 'text-2xs',
10: 'text-3xs',
9: 'text-4xs',
8: 'text-5xs',
}

function reportTextSizeWarning(match: string, suggestion: string, checker?: CollectorChecker) {
const message = `[A11y] Avoid using '${match}', ${suggestion}.`
if (checker) {
checker(message, match)
} else {
warnOnce(message, match)
}
}

export function presetA11y(checker?: CollectorChecker): Preset {
return {
name: 'a11y-preset',
// text-[N] (arbitrary where N is a size in px or em): recommend text-2xs/text-3xs/text-4xs/text-5xs or "use classes"
rules: [
[
/^text-\[(\d+(\.\d+)?)(px)?\]$/,
([match, numStr], context) => {
const num = Number(numStr)
const fullClass = context.rawSelector || match
const suggestedClass = textPxToClass[num]
if (suggestedClass) {
reportTextSizeWarning(fullClass, `use '${suggestedClass}' instead`, checker)
} else {
reportTextSizeWarning(
fullClass,
'use text-<size> classes or rem values instead of custom values',
checker,
)
}
return [['font-size', `${num}px`]]
},
{ autocomplete: 'text-[<num>]' },
],
[
/^text-\[(\d+(\.\d+)?)em\]$/,
([match, numStr], context) => {
const num = Number(numStr)
const fullClass = context.rawSelector || match
reportTextSizeWarning(
fullClass,
'use text-<size> classes or rem values instead of custom values',
checker,
)
return [['font-size', `${num}em`]]
},
{ autocomplete: 'text-[<num>]em' },
],
],
}
}
3 changes: 2 additions & 1 deletion uno.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from 'unocss'
import type { Theme } from '@unocss/preset-wind4/theme'
import { presetRtl } from './uno-preset-rtl'
import { presetA11y } from './uno-preset-a11y'

const customIcons = {
'agent-skills':
Expand All @@ -32,7 +33,7 @@ export default defineConfig({
},
}),
// keep this preset last
...(process.env.CI ? [] : [presetRtl()]),
...(process.env.CI ? [] : [presetRtl(), presetA11y()]),
].filter(Boolean),
transformers: [transformerDirectives(), transformerVariantGroup()],
theme: {
Expand Down
Loading