@cwcss/crosswind 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/PLUGIN.md +235 -0
  2. package/benchmark/framework-comparison.bench.ts +850 -0
  3. package/bin/cli.ts +365 -0
  4. package/bin/crosswind +0 -0
  5. package/bin/headwind +0 -0
  6. package/build.ts +8 -0
  7. package/crosswind.config.ts +9 -0
  8. package/example/comprehensive.html +70 -0
  9. package/example/index.html +21 -0
  10. package/example/output.css +236 -0
  11. package/examples/plugin/README.md +112 -0
  12. package/examples/plugin/build.ts +32 -0
  13. package/examples/plugin/src/index.html +34 -0
  14. package/examples/plugin/src/index.ts +7 -0
  15. package/headwind +2 -0
  16. package/package.json +92 -0
  17. package/src/build.ts +101 -0
  18. package/src/config.ts +529 -0
  19. package/src/generator.ts +2173 -0
  20. package/src/index.ts +10 -0
  21. package/src/parser.ts +1471 -0
  22. package/src/plugin.ts +118 -0
  23. package/src/preflight-forms.ts +229 -0
  24. package/src/preflight.ts +388 -0
  25. package/src/rules-advanced.ts +477 -0
  26. package/src/rules-effects.ts +457 -0
  27. package/src/rules-forms.ts +103 -0
  28. package/src/rules-grid.ts +241 -0
  29. package/src/rules-interactivity.ts +525 -0
  30. package/src/rules-layout.ts +385 -0
  31. package/src/rules-transforms.ts +412 -0
  32. package/src/rules-typography.ts +486 -0
  33. package/src/rules.ts +805 -0
  34. package/src/scanner.ts +84 -0
  35. package/src/transformer-compile-class.ts +275 -0
  36. package/src/types.ts +197 -0
  37. package/test/advanced-features.test.ts +911 -0
  38. package/test/arbitrary.test.ts +396 -0
  39. package/test/attributify.test.ts +592 -0
  40. package/test/bracket-syntax.test.ts +1133 -0
  41. package/test/build.test.ts +99 -0
  42. package/test/colors.test.ts +934 -0
  43. package/test/flexbox.test.ts +669 -0
  44. package/test/generator.test.ts +597 -0
  45. package/test/grid.test.ts +584 -0
  46. package/test/layout.test.ts +404 -0
  47. package/test/modifiers.test.ts +417 -0
  48. package/test/parser.test.ts +564 -0
  49. package/test/performance-regression.test.ts +376 -0
  50. package/test/performance.test.ts +568 -0
  51. package/test/plugin.test.ts +160 -0
  52. package/test/scanner.test.ts +94 -0
  53. package/test/sizing.test.ts +481 -0
  54. package/test/spacing.test.ts +394 -0
  55. package/test/transformer-compile-class.test.ts +287 -0
  56. package/test/transforms.test.ts +448 -0
  57. package/test/typography.test.ts +632 -0
  58. package/test/variants-form-states.test.ts +225 -0
  59. package/test/variants-group-peer.test.ts +66 -0
  60. package/test/variants-media.test.ts +213 -0
  61. package/test/variants-positional.test.ts +58 -0
  62. package/test/variants-pseudo-elements.test.ts +47 -0
  63. package/test/variants-state.test.ts +62 -0
  64. package/tsconfig.json +18 -0
@@ -0,0 +1,112 @@
1
+ # Crosswind Bun Plugin Example
2
+
3
+ This example demonstrates how to use the Crosswind Bun plugin to automatically generate and inject CSS into your HTML files during the build process.
4
+
5
+ ## Project Structure
6
+
7
+ ```
8
+ examples/plugin/
9
+ ├── src/
10
+ │ ├── index.ts # TypeScript entrypoint that imports HTML
11
+ │ └── index.html # HTML file with utility classes
12
+ ├── build.ts # Build script
13
+ └── README.md
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ The plugin works by intercepting HTML imports in your TypeScript/JavaScript code. When you import an HTML file, the plugin:
19
+
20
+ 1. Scans the HTML for Crosswind utility classes
21
+ 2. Generates the corresponding CSS
22
+ 3. Injects the CSS into the `<head>` section
23
+ 4. Returns the processed HTML
24
+
25
+ ### Basic Setup
26
+
27
+ ```typescript
28
+ import { plugin } from '@cwcss/crosswind'
29
+
30
+ await Bun.build({
31
+ entrypoints: ['./src/index.ts'],
32
+ outdir: './dist',
33
+ plugins: [plugin()],
34
+ })
35
+ ```
36
+
37
+ **Your TypeScript file** (`src/index.ts`):
38
+
39
+ ```typescript
40
+ import html from './index.html'
41
+
42
+ // Use the HTML content (it will have CSS injected)
43
+ document.body.innerHTML = html
44
+ ```
45
+
46
+ ### With Custom Configuration
47
+
48
+ ```typescript
49
+ import { plugin } from '@cwcss/crosswind'
50
+
51
+ await Bun.build({
52
+ entrypoints: ['./src/index.ts'],
53
+ outdir: './dist',
54
+ plugins: [
55
+ plugin({
56
+ config: {
57
+ minify: true,
58
+ theme: {
59
+ colors: {
60
+ primary: '#3b82f6',
61
+ secondary: '#10b981',
62
+ },
63
+ },
64
+ },
65
+ includePreflight: true,
66
+ }),
67
+ ],
68
+ })
69
+ ```
70
+
71
+ ## Running This Example
72
+
73
+ ```bash
74
+ # Build the example
75
+ bun run build.ts
76
+
77
+ # The output will be in ./dist/
78
+ ```
79
+
80
+ ## How It Works
81
+
82
+ 1. The plugin hooks into Bun's module loading system via `onLoad`
83
+ 2. When a `.html` file is imported, the plugin intercepts the load
84
+ 3. It extracts utility classes from the HTML using Crosswind's parser
85
+ 4. It generates CSS for those classes using Crosswind's generator
86
+ 5. The generated CSS is injected into the `<head>` section
87
+ 6. The processed HTML is returned as a string in the bundled output
88
+
89
+ ## Options
90
+
91
+ ### `config`
92
+
93
+ Custom Crosswind configuration to override defaults. This can include:
94
+
95
+ - `minify`: Minify the generated CSS
96
+ - `theme`: Custom theme colors, spacing, fonts, etc.
97
+ - `shortcuts`: Define utility class shortcuts
98
+ - `safelist`: Classes to always include
99
+ - And more...
100
+
101
+ ### `includePreflight`
102
+
103
+ Whether to include preflight (reset) CSS. Default: `true`
104
+
105
+ ## Use Cases
106
+
107
+ This plugin is ideal for:
108
+
109
+ - Single Page Applications (SPAs) that import HTML templates
110
+ - Component-based architectures where HTML is imported as strings
111
+ - Build processes that need automatic CSS generation from HTML
112
+ - Projects using Bun's native bundler with HTML assets
@@ -0,0 +1,32 @@
1
+ import { plugin } from '@cwcss/crosswind'
2
+
3
+ // Build with crosswind plugin
4
+ // The plugin will automatically process HTML files that are imported in your TypeScript/JavaScript code
5
+ const result = await Bun.build({
6
+ entrypoints: ['./src/index.ts'], // Your TS entrypoint that imports HTML files
7
+ outdir: './dist',
8
+ plugins: [
9
+ plugin({
10
+ // Optional: provide custom config
11
+ config: {
12
+ minify: true,
13
+ theme: {
14
+ colors: {
15
+ primary: '#3b82f6',
16
+ secondary: '#10b981',
17
+ },
18
+ },
19
+ },
20
+ // Optional: include preflight CSS
21
+ includePreflight: true,
22
+ }),
23
+ ],
24
+ })
25
+
26
+ if (result.success) {
27
+ console.log('Build complete!')
28
+ console.log(`Generated ${result.outputs.length} output(s)`)
29
+ }
30
+ else {
31
+ console.error('Build failed:', result.logs)
32
+ }
@@ -0,0 +1,34 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Crosswind Bun Plugin Example</title>
7
+ </head>
8
+ <body>
9
+ <div class="flex items-center justify-between p-4 bg-blue-500 text-white rounded-lg shadow-md hover:bg-blue-600">
10
+ <h1 class="text-2xl font-bold">Hello Crosswind!</h1>
11
+ <button class="px-4 py-2 bg-white text-blue-500 rounded hover:bg-gray-100">
12
+ Click me
13
+ </button>
14
+ </div>
15
+
16
+ <div class="container mx-auto mt-8 p-6">
17
+ <h2 class="text-xl font-semibold mb-4">Features</h2>
18
+ <ul class="space-y-2">
19
+ <li class="flex items-center gap-2">
20
+ <span class="w-2 h-2 bg-green-500 rounded-full"></span>
21
+ <span class="text-gray-700">Automatic CSS generation</span>
22
+ </li>
23
+ <li class="flex items-center gap-2">
24
+ <span class="w-2 h-2 bg-green-500 rounded-full"></span>
25
+ <span class="text-gray-700">On-demand utilities</span>
26
+ </li>
27
+ <li class="flex items-center gap-2">
28
+ <span class="w-2 h-2 bg-green-500 rounded-full"></span>
29
+ <span class="text-gray-700">Tailwind-compatible</span>
30
+ </li>
31
+ </ul>
32
+ </div>
33
+ </body>
34
+ </html>
@@ -0,0 +1,7 @@
1
+ // Import HTML file - the plugin will process it and inject Crosswind CSS
2
+ import html from './index.html'
3
+
4
+ // You can use the HTML content
5
+ document.body.innerHTML = html
6
+
7
+ export default html
package/headwind ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ import('./bin/cli')
package/package.json ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "@cwcss/crosswind",
3
+ "type": "module",
4
+ "version": "0.1.4",
5
+ "description": "A performant Utility-First CSS framework. Similar to Tailwind or UnoCSS.",
6
+ "author": "Chris Breuer <chris@stacksjs.org>",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/cwcss/crosswind#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/cwcss/crosswind.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/cwcss/crosswind/issues"
15
+ },
16
+ "keywords": [
17
+ "css",
18
+ "utility-first",
19
+ "tailwind",
20
+ "css-framework",
21
+ "bun",
22
+ "performance",
23
+ "crosswind",
24
+ "atomic-css",
25
+ "typescript",
26
+ "on-demand"
27
+ ],
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./*": {
34
+ "import": "./dist/*"
35
+ }
36
+ },
37
+ "module": "./dist/index.js",
38
+ "types": "./dist/index.d.ts",
39
+ "bin": {
40
+ "crosswind": "./dist/bin/cli.js"
41
+ },
42
+ "files": [
43
+ "README.md",
44
+ "dist"
45
+ ],
46
+ "scripts": {
47
+ "build": "bun --bun build.ts && bun run compile",
48
+ "compile": "bun build ./bin/cli.ts --compile --minify --outfile bin/crosswind",
49
+ "compile:all": "bun run compile:linux-x64 && bun run compile:linux-arm64 && bun run compile:windows-x64 && bun run compile:darwin-x64 && bun run compile:darwin-arm64",
50
+ "compile:linux-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-x64 --outfile bin/crosswind-linux-x64",
51
+ "compile:linux-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-arm64 --outfile bin/crosswind-linux-arm64",
52
+ "compile:windows-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-windows-x64 --outfile bin/crosswind-windows-x64.exe",
53
+ "compile:darwin-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-x64 --outfile bin/crosswind-darwin-x64",
54
+ "compile:darwin-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-arm64 --outfile bin/crosswind-darwin-arm64",
55
+ "zip": "bun run zip:all",
56
+ "zip:all": "bun run zip:linux-x64 && bun run zip:linux-arm64 && bun run zip:windows-x64 && bun run zip:darwin-x64 && bun run zip:darwin-arm64",
57
+ "zip:linux-x64": "zip -j bin/crosswind-linux-x64.zip bin/crosswind-linux-x64",
58
+ "zip:linux-arm64": "zip -j bin/crosswind-linux-arm64.zip bin/crosswind-linux-arm64",
59
+ "zip:windows-x64": "zip -j bin/crosswind-windows-x64.zip bin/crosswind-windows-x64.exe",
60
+ "zip:darwin-x64": "zip -j bin/crosswind-darwin-x64.zip bin/crosswind-darwin-x64",
61
+ "zip:darwin-arm64": "zip -j bin/crosswind-darwin-arm64.zip bin/crosswind-darwin-arm64",
62
+ "benchmark": "bun run benchmark/framework-comparison.bench.ts",
63
+ "lint": "bunx --bun pickier run --mode lint",
64
+ "lint:fix": "bunx --bun pickier run --mode lint --fix",
65
+ "fresh": "bunx rimraf node_modules/ bun.lock && bun i",
66
+ "changelog": "bunx changelogen --output CHANGELOG.md",
67
+ "prepublishOnly": "bun --bun run build && bun run compile:all && bun run zip",
68
+ "release": "bun run changelog && bunx bumpp package.json --all",
69
+ "test": "bun test"
70
+ },
71
+ "dependencies": {
72
+ "@stacksjs/clapp": "^0.2.0",
73
+ "bunfig": "^0.15.0"
74
+ },
75
+ "overrides": {
76
+ "unconfig": "0.3.10"
77
+ },
78
+ "lint-staged": {
79
+ "*.{js,ts}": "bunx --bun pickier run --mode lint --fix"
80
+ },
81
+ "devDependencies": {
82
+ "@tailwindcss/node": "^4.1.14",
83
+ "@tailwindcss/postcss": "^4.1",
84
+ "@tailwindcss/vite": "^4.1",
85
+ "@unocss/core": "^66.5.4",
86
+ "@unocss/preset-wind": "^66.5.4",
87
+ "mitata": "^1.0.34",
88
+ "postcss": "^8.5.6",
89
+ "tailwindcss": "^3",
90
+ "tailwindcss-v4": "npm:tailwindcss@^4"
91
+ }
92
+ }
package/src/build.ts ADDED
@@ -0,0 +1,101 @@
1
+ import type { CrosswindConfig } from './types'
2
+ import { CSSGenerator } from './generator'
3
+ import { Scanner } from './scanner'
4
+ import { CompileClassTransformer } from './transformer-compile-class'
5
+
6
+ export interface BuildResult {
7
+ css: string
8
+ classes: Set<string>
9
+ duration: number
10
+ compiledClasses?: Map<string, { className: string, utilities: string[] }>
11
+ transformedFiles?: Map<string, string>
12
+ }
13
+
14
+ /**
15
+ * Build CSS from content patterns
16
+ */
17
+ export async function build(config: CrosswindConfig): Promise<BuildResult> {
18
+ const startTime = performance.now()
19
+
20
+ // Initialize compile class transformer if enabled
21
+ const transformer = config.compileClass?.enabled
22
+ ? new CompileClassTransformer({
23
+ trigger: config.compileClass.trigger,
24
+ classPrefix: config.compileClass.classPrefix,
25
+ layer: config.compileClass.layer,
26
+ })
27
+ : null
28
+
29
+ // Scan files for utility classes
30
+ const scanner = new Scanner(config.content, transformer, {
31
+ attributify: config.attributify,
32
+ bracketSyntax: config.bracketSyntax,
33
+ })
34
+ const { classes, transformedFiles } = await scanner.scan()
35
+
36
+ // Add safelist classes
37
+ for (const cls of config.safelist) {
38
+ classes.add(cls)
39
+ }
40
+
41
+ // If using compile class transformer, also add compiled utilities
42
+ if (transformer) {
43
+ const compiledClasses = transformer.getCompiledClasses()
44
+ for (const [, { utilities }] of compiledClasses) {
45
+ for (const utility of utilities) {
46
+ classes.add(utility)
47
+ }
48
+ }
49
+ }
50
+
51
+ // Generate CSS
52
+ const generator = new CSSGenerator(config)
53
+
54
+ for (const className of classes) {
55
+ generator.generate(className)
56
+ }
57
+
58
+ // Preflight CSS is now added by generator.toCSS()
59
+ const css = generator.toCSS(true, config.minify)
60
+ const duration = performance.now() - startTime
61
+
62
+ return {
63
+ css,
64
+ classes,
65
+ duration,
66
+ compiledClasses: transformer?.getCompiledClasses(),
67
+ transformedFiles,
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Write CSS to output file
73
+ */
74
+ export async function writeCSS(css: string, outputPath: string): Promise<void> {
75
+ await Bun.write(outputPath, css)
76
+ }
77
+
78
+ /**
79
+ * Write transformed files to disk
80
+ */
81
+ export async function writeTransformedFiles(transformedFiles: Map<string, string>): Promise<void> {
82
+ const writes = Array.from(transformedFiles.entries()).map(([path, content]) =>
83
+ Bun.write(path, content),
84
+ )
85
+ await Promise.all(writes)
86
+ }
87
+
88
+ /**
89
+ * Build and write CSS to output file
90
+ */
91
+ export async function buildAndWrite(config: CrosswindConfig): Promise<BuildResult> {
92
+ const result = await build(config)
93
+ await writeCSS(result.css, config.output)
94
+
95
+ // Write transformed files if compile class is enabled
96
+ if (result.transformedFiles && result.transformedFiles.size > 0) {
97
+ await writeTransformedFiles(result.transformedFiles)
98
+ }
99
+
100
+ return result
101
+ }