diff --git a/.cfignore b/.cfignore index 26890eb..4b707d8 100644 --- a/.cfignore +++ b/.cfignore @@ -1,5 +1,6 @@ # Cloudflare Pages - Skip build dependencies # The project is built via GitHub Actions and artifacts are deployed + node_modules/ src/ public/ diff --git a/.editorconfig b/.editorconfig index e9712bf..96ed027 100644 --- a/.editorconfig +++ b/.editorconfig @@ -18,6 +18,3 @@ indent_size = 2 [*.{md,mdx}] indent_size = 2 trim_trailing_whitespace = false - -[Makefile] -indent_style = tab diff --git a/.gitattributes b/.gitattributes index 33eed04..c7a579d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,7 +4,6 @@ *.png binary *.gif binary *.webp binary -*.svg binary *.ico binary *.mp4 binary *.mov binary diff --git a/.gitignore b/.gitignore index 3c756b1..836d1a8 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ Thumbs.db node_modules/ .pnpm-store/ -# Build outputs +# Build output dist/ build/ @@ -41,6 +41,9 @@ test-results/ !.vscode/settings.json !.vscode/extensions.json .idea/ +*.iml +.zed/ +.cursor/ *.swp *.swo *~ @@ -62,3 +65,7 @@ temp/ # Husky runtime .husky/_/ + +# Minified files +*.min.js +*.min.css diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..e2a5758 --- /dev/null +++ b/.npmignore @@ -0,0 +1,10 @@ +# npm ignore file +# Even for private repos, good practice to define what would be published + +# Ignore everything +* + +# Except these +!dist/** +!README.md +!LICENSE diff --git a/.prettierignore b/.prettierignore index 4ea76b6..f04a094 100644 --- a/.prettierignore +++ b/.prettierignore @@ -25,3 +25,11 @@ build/ **/*.min.js **/*.min.css vite.config.*.timestamp-* + +# JSON is handled by Biome +*.json + +# Generated files +CLAUDE.md +.rules +CHANGELOG.md diff --git a/biome.json b/biome.json index 9cbc92f..627d99e 100644 --- a/biome.json +++ b/biome.json @@ -15,17 +15,19 @@ "indentWidth": 4, "lineWidth": 120, "lineEnding": "lf", - "formatWithErrors": true - }, - "assist": { - "enabled": false + "formatWithErrors": true, + "attributePosition": "auto" }, + "assist": { "actions": { "source": { "organizeImports": "off" } } }, "javascript": { "formatter": { "quoteStyle": "single", "trailingCommas": "all", "semicolons": "always", - "arrowParentheses": "always" + "arrowParentheses": "always", + "bracketSpacing": true, + "bracketSameLine": false, + "quoteProperties": "asNeeded" } }, "json": { @@ -36,14 +38,14 @@ }, "css": { "parser": { - "cssModules": false, + "cssModules": true, "allowWrongLineComments": false, "tailwindDirectives": true }, "formatter": { "indentWidth": 4, "lineWidth": 100, - "quoteStyle": "double" + "quoteStyle": "single" }, "linter": { "enabled": true @@ -53,23 +55,31 @@ "enabled": true, "rules": { "recommended": true, + "style": { + "noNonNullAssertion": "warn", + "useConst": "error", + "useBlockStatements": "off", + "noParameterAssign": "warn", + "useImportType": "error" + }, "suspicious": { "noExplicitAny": "warn", + "noDebugger": "error", "noConsole": "off", "noImplicitAnyLet": "off" }, - "style": { - "noNonNullAssertion": "warn", - "useImportType": "error" - }, "correctness": { "noUnusedVariables": "error", "noUnusedImports": "error", "noVoidTypeReturn": "off" }, "complexity": { + "noForEach": "off", "noStaticOnlyClass": "off", "noThisInStatic": "off" + }, + "security": { + "noDangerouslySetInnerHtml": "error" } } }, diff --git a/cspell.json b/cspell.json index 60f17dd..e341bbb 100644 --- a/cspell.json +++ b/cspell.json @@ -1,10 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", - "version": "0.2", "language": "en", + "allowCompoundWords": true, + "dictionaries": ["typescript", "node", "html", "css", "fonts", "npm", "softwareTerms"], "words": [ - "ambilab", - "atlases", + "Ambilab", "bindgroup", "bindgroups", "biomejs", @@ -13,40 +13,32 @@ "BTAPI", "btfont", "cfignore", - "Cietwierkowski", - "codecov", "commitlint", "cooldown", "cooldowns", - "dbaeumer", "esbuild", "Fabrizio", "gamepad", "invinc", "nsis", - "onuncapturederror", "pnpm", "rects", "retroblit", "RGBA", - "rgba8unorm", "Rollup", "Schiavi", "spritesheet", "subsystem", "subsystems", - "texcoord", "tilemap", "timestep", - "unorm", - "Václav", "Vančura", "Vite", "Vitest", + "Václav", "WASD", "WebGPU", "webstorm", - "WGSL", "yoffset" ], "flagWords": ["cant", "dont", "hte", "teh", "wont"], @@ -56,12 +48,13 @@ ".git", ".pnpm-store", "CHANGELOG.md", + "CLAUDE.md", "coverage", "dist", "node_modules", "pnpm-lock.yaml" ], - "ignoreRegExpList": ["/#[0-9A-Fa-f]{6,8}/", "/0x[0-9A-Fa-f]+/", "/@[a-zA-Z0-9_-]+\\/[a-zA-Z0-9_-]+/"], + "ignoreRegExpList": ["/#[0-9A-Fa-f]{3,8}/", "/0x[0-9A-Fa-f]+/", "/@[a-zA-Z0-9_-]+\\/[a-zA-Z0-9_-]+/"], "overrides": [ { "filename": "**/*.ts", diff --git a/demos/styles.css b/demos/styles.css index 3b95a83..781d32b 100644 --- a/demos/styles.css +++ b/demos/styles.css @@ -1,4 +1,4 @@ -@import "tailwindcss"; +@import 'tailwindcss'; @theme { /* Accent color - unified blue theme */ @@ -17,7 +17,7 @@ --color-success: #2ecc71; /* Font family */ - --font-mono: "Courier New", monospace; + --font-mono: 'Courier New', monospace; } /* Canvas pixel-perfect rendering - using both values for cross-browser support */ @@ -35,14 +35,14 @@ canvas { /* List marker styling */ .info-list li::before { - content: "\25B8"; + content: '\25B8'; position: absolute; left: 0; color: var(--color-accent); } .check-list li::before { - content: "\2713"; + content: '\2713'; position: absolute; left: 0; color: var(--color-success); diff --git a/eslint.config.js b/eslint.config.js index 394aec3..4c17fa9 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -26,6 +26,8 @@ export default [ '.pnpm-store/**', '**/.pnpm-store/**', 'vite.config.ts.timestamp-*', + 'CLAUDE.md', + '.rules', ], }, @@ -99,6 +101,9 @@ export default [ ...promisePlugin.configs.recommended.rules, 'promise/always-return': 'warn', 'promise/catch-or-return': 'warn', + 'promise/no-return-wrap': 'error', + 'promise/param-names': 'error', + 'promise/no-nesting': 'warn', // Security rules ...securityPlugin.configs.recommended.rules, diff --git a/package.json b/package.json index 50f2781..77b3509 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,9 @@ "preflight": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm spellcheck", "clean": "rm -rf dist node_modules/.vite", "sync-rules": "node scripts/sync-rules.mjs", - "prepare": "husky" + "prepare": "husky", + "security:audit": "pnpm audit --audit-level=moderate", + "security:audit:fix": "pnpm audit --fix" }, "packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a", "dependencies": { diff --git a/prettier.config.js b/prettier.config.js index 3b5e8b5..b91271f 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -11,11 +11,13 @@ export default { // Base settings (applied to Markdown/YAML) semi: true, singleQuote: true, - tabWidth: 2, + tabWidth: 4, useTabs: false, trailingComma: 'all', printWidth: 120, endOfLine: 'lf', + proseWrap: 'always', + htmlWhitespaceSensitivity: 'css', overrides: [ { diff --git a/scripts/sync-rules.mjs b/scripts/sync-rules.mjs index 54a7d4c..ee99034 100644 --- a/scripts/sync-rules.mjs +++ b/scripts/sync-rules.mjs @@ -1,7 +1,3 @@ -#!/usr/bin/env node - -/* eslint-disable security/detect-object-injection */ - /** * Sync AI assistant rules across different tools. *