@ecopages/postcss-processor 0.2.0-alpha.1 → 0.2.0-alpha.10

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@ecopages/postcss-processor` are documented here.
4
+
5
+ > **Note:** Changelog tracking begins at version `0.2.0`. Changes prior to this release are not recorded here but are available in the git history.
6
+
7
+ ## [UNRELEASED] — TBD
8
+
9
+ ### Features
10
+
11
+ - Added runtime CSS loader support and a `PostcssProcessor` class so PostCSS processing can be reused outside the plugin DSL.
12
+ - Added esbuild build adapter registration and dependency graph integration to the PostCSS processor plugin.
13
+
14
+ ### Bug Fixes
15
+
16
+ - Rebuilt tracked stylesheets from fresh PostCSS plugin instances on non-CSS source changes so Tailwind-style utility generation picks up template edits without stale caches.
17
+ - Applied `transformInput` during direct stylesheet asset processing so Tailwind v4 page CSS keeps injected `@reference` directives and preserves nested BEM selectors in preview/build output.
18
+ - Disabled Tailwind v4 PostCSS optimization in the official plugin preset so preview/build no longer rewrites nested BEM selectors into invalid output.
19
+
20
+ ### Tests
21
+
22
+ - Added processor and preset coverage for the runtime CSS loader and build adapter flow.
package/README.md CHANGED
@@ -1,56 +1,32 @@
1
- # PostCSS Processor
1
+ # @ecopages/postcss-processor
2
2
 
3
- This module provides a PostCSS processor plugin for Ecopages and utility functions for processing CSS files and strings using PostCSS. It includes built-in presets for Tailwind CSS (v3 and v4).
3
+ PostCSS processing pipeline for Ecopages. It provides a processor plugin that seamlessly integrates PostCSS into the Ecopages build system, and includes built-in presets for Tailwind CSS (v3 and v4).
4
4
 
5
5
  ## Features
6
6
 
7
- - **Ecopages Processor Plugin**: Seamless integration with Ecopages build system.
8
- - **Tailwind Presets**: Ready-to-use configurations for Tailwind CSS v3 and v4.
9
- - **Automatic Configuration**: Detects `postcss.config.{js,ts,etc}` automatically.
10
- - **Standalone Usage**: Process CSS files or strings directly.
11
- - **Bun Loader**: Automatically registers a Bun loader for importing CSS in TS/JS files.
7
+ - **Ecopages Processor Plugin**: Hook right into the build pipeline.
8
+ - **Tailwind Presets**: Pre-configured pipelines for Tailwind CSS v3 and v4.
9
+ - **Automatic Configuration**: Detects existing `postcss.config.{js,ts,etc}`.
10
+ - **Bun Loader**: Registers a Bun loader for importing CSS in TS/JS files.
12
11
 
13
- ## Install
12
+ ## Installation
14
13
 
15
14
  ```bash
16
15
  bunx jsr add @ecopages/postcss-processor
17
16
  ```
18
17
 
19
- ## Usage with Ecopages
18
+ ## Usage
20
19
 
21
- Integrate the processor into your `eco.config.ts` using one of the available presets.
22
-
23
- ### Tailwind v3 Preset
24
-
25
- Includes `tailwindcss`, `autoprefixer`, `postcss-import`, `cssnano`.
26
-
27
- ```bash
28
- bun add -D tailwindcss@3.4.19
29
- ```
30
-
31
- ```typescript
32
- // eco.config.ts
33
- import { ConfigBuilder } from '@ecopages/core';
34
- import { postcssProcessorPlugin } from '@ecopages/postcss-processor';
35
- import { tailwindV3Preset } from '@ecopages/postcss-processor/presets/tailwind-v3';
36
-
37
- const config = await new ConfigBuilder().setProcessors([postcssProcessorPlugin(tailwindV3Preset())]).build();
38
-
39
- export default config;
40
- ```
20
+ Integrate the processor into your `eco.config.ts` using a preset.
41
21
 
42
22
  ### Tailwind v4 Preset (Recommended)
43
23
 
44
- Includes `@tailwindcss/postcss`, `autoprefixer`, `postcss-nested`, `cssnano`, and handles `@reference` injection for `@apply`.
45
-
46
- ```bash
47
- bun add -D @tailwindcss/postcss tailwindcss
48
- ```
24
+ Requires `@tailwindcss/postcss` and `tailwindcss` to be installed.
49
25
 
50
26
  ```typescript
51
27
  // eco.config.ts
52
28
  import path from 'node:path';
53
- import { ConfigBuilder } from '@ecopages/core';
29
+ import { ConfigBuilder } from '@ecopages/core/config-builder';
54
30
  import { postcssProcessorPlugin } from '@ecopages/postcss-processor';
55
31
  import { tailwindV4Preset } from '@ecopages/postcss-processor/presets/tailwind-v4';
56
32
 
@@ -58,7 +34,7 @@ const config = await new ConfigBuilder()
58
34
  .setProcessors([
59
35
  postcssProcessorPlugin(
60
36
  tailwindV4Preset({
61
- referencePath: path.resolve(import.meta.dir, 'src/styles/app.css'),
37
+ referencePath: path.resolve(import.meta.dirname, 'src/styles/app.css'),
62
38
  }),
63
39
  ),
64
40
  ])
@@ -67,53 +43,41 @@ const config = await new ConfigBuilder()
67
43
  export default config;
68
44
  ```
69
45
 
70
- ### Browser Support
71
-
72
- By default, the presets target a broad range of modern browsers (`>0.3%, not ie 11, not dead, not op_mini all`).
73
-
74
- To override this, add a `browserslist` configuration to your `package.json` or create a `.browserslistrc` file in your project root. The processor will automatically detect and use your custom configuration.
75
-
76
- ### Custom Configuration
77
-
78
- You can also use a standard `postcss.config.js` file or pass plugins manually.
79
-
80
- **Using `postcss.config.js`:**
81
- Create the file in your root, and simply add `postcssProcessorPlugin()` to your config without arguments.
46
+ ### Tailwind v3 Preset
82
47
 
83
- **Manual Configuration:**
48
+ Requires `tailwindcss@3`, `autoprefixer`, `postcss-import`, and `cssnano` to be installed.
84
49
 
85
50
  ```typescript
51
+ // eco.config.ts
52
+ import { ConfigBuilder } from '@ecopages/core/config-builder';
86
53
  import { postcssProcessorPlugin } from '@ecopages/postcss-processor';
87
- import myPlugin from 'postcss-my-plugin';
54
+ import { tailwindV3Preset } from '@ecopages/postcss-processor/presets/tailwind-v3';
55
+
56
+ const config = await new ConfigBuilder().setProcessors([postcssProcessorPlugin(tailwindV3Preset())]).build();
88
57
 
89
- postcssProcessorPlugin({
90
- plugins: {
91
- 'my-plugin': myPlugin(),
92
- },
93
- });
58
+ export default config;
94
59
  ```
95
60
 
96
- **Advanced Configuration:**
61
+ ## Custom Configuration
97
62
 
98
- For advanced use cases, use transformation hooks to modify CSS before or after processing:
63
+ To use your own `postcss.config.js`, simply call `postcssProcessorPlugin()` without arguments.
64
+
65
+ You can also pass raw plugins or transformation hooks manually:
99
66
 
100
67
  ```typescript
101
- import { ConfigBuilder } from '@ecopages/core';
68
+ import { ConfigBuilder } from '@ecopages/core/config-builder';
102
69
  import { postcssProcessorPlugin } from '@ecopages/postcss-processor';
70
+ import myPlugin from 'postcss-my-plugin';
103
71
 
104
72
  const config = await new ConfigBuilder()
105
73
  .setProcessors([
106
74
  postcssProcessorPlugin({
107
- // Define a filter for files to process (defaults to /\.css$/)
108
75
  filter: /\.css$/,
109
- // Provide a function to transform input before processing
110
- transformInput: async (css) => `/* My Custom Header */\n${css}`,
111
- // Provide a function to transform output after processing
112
- transformOutput: async (css) => css.replace('blue', 'red'),
113
- // Explicitly provide plugins (overrides defaults)
114
76
  plugins: {
115
- /* custom plugins */
77
+ 'my-plugin': myPlugin(),
116
78
  },
79
+ transformInput: async (css) => `/* Header */\n${css}`,
80
+ transformOutput: async (css) => css.replace('blue', 'red'),
117
81
  }),
118
82
  ])
119
83
  .build();
@@ -121,9 +85,9 @@ const config = await new ConfigBuilder()
121
85
  export default config;
122
86
  ```
123
87
 
124
- ## Standalone Usage
88
+ ## Standalone Processing
125
89
 
126
- You can use the underlying processor functions directly:
90
+ You can bypass Ecopages entirely and use the processor utilities directly:
127
91
 
128
92
  ```typescript
129
93
  import { PostCssProcessor } from '@ecopages/postcss-processor';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecopages/postcss-processor",
3
- "version": "0.2.0-alpha.1",
3
+ "version": "0.2.0-alpha.10",
4
4
  "description": "Postcss processor, transform string or postcss file to css",
5
5
  "keywords": [
6
6
  "postcss",
@@ -8,24 +8,16 @@
8
8
  "css"
9
9
  ],
10
10
  "license": "MIT",
11
- "main": "./src/postcss-processor.ts",
11
+ "main": "./src/postcss-processor.js",
12
12
  "type": "module",
13
- "types": "./src/postcss-processor.ts",
14
- "files": [
15
- "src"
16
- ],
13
+ "types": "./src/postcss-processor.d.ts",
17
14
  "repository": {
18
15
  "type": "git",
19
16
  "url": "https://github.com/ecopages/ecopages.git",
20
17
  "directory": "packages/processors/postcss-processor"
21
18
  },
22
- "scripts": {
23
- "typecheck": "tsc --noEmit",
24
- "release:jsr": "bunx jsr publish"
25
- },
26
19
  "dependencies": {
27
- "@ecopages/core": "workspace:*",
28
- "@ecopages/file-system": "workspace:*",
20
+ "@ecopages/file-system": "0.2.0-alpha.10",
29
21
  "@ecopages/logger": "latest",
30
22
  "autoprefixer": "^10.4.0",
31
23
  "browserslist": "^4.28.1",
@@ -35,6 +27,7 @@
35
27
  "postcss-nested": "^7.0.2"
36
28
  },
37
29
  "peerDependencies": {
30
+ "@ecopages/core": "0.2.0-alpha.10",
38
31
  "@tailwindcss/postcss": ">=4",
39
32
  "tailwindcss": ">=3"
40
33
  },
@@ -46,37 +39,50 @@
46
39
  "optional": true
47
40
  }
48
41
  },
49
- "devDependencies": {
50
- "@tailwindcss/postcss": "^4.1.18",
51
- "@types/bun": "latest",
52
- "@types/postcss-import": "^14",
53
- "postcss-simple-vars": "^7.0.1",
54
- "tailwindcss": "^3.4.19"
55
- },
56
42
  "exports": {
57
43
  ".": {
58
- "default": "./src/index.ts",
59
- "types": "./src/index.ts"
44
+ "default": "./src/index.js",
45
+ "types": "./src/index.d.ts"
60
46
  },
61
47
  "./postcss-processor": {
62
- "default": "./src/postcss-processor.ts",
63
- "types": "./src/postcss-processor.ts"
48
+ "default": "./src/postcss-processor.js",
49
+ "types": "./src/postcss-processor.d.ts"
64
50
  },
65
51
  "./plugin": {
66
- "default": "./src/plugin.ts",
67
- "types": "./src/plugin.ts"
52
+ "default": "./src/plugin.js",
53
+ "types": "./src/plugin.d.ts"
68
54
  },
69
55
  "./presets": {
70
- "default": "./src/presets/index.ts",
71
- "types": "./src/presets/index.ts"
56
+ "default": "./src/presets/index.js",
57
+ "types": "./src/presets/index.d.ts"
72
58
  },
73
59
  "./presets/tailwind-v3": {
74
- "default": "./src/presets/tailwind-v3.ts",
75
- "types": "./src/presets/tailwind-v3.ts"
60
+ "default": "./src/presets/tailwind-v3.js",
61
+ "types": "./src/presets/tailwind-v3.d.ts"
76
62
  },
77
63
  "./presets/tailwind-v4": {
78
- "default": "./src/presets/tailwind-v4.ts",
79
- "types": "./src/presets/tailwind-v4.ts"
64
+ "default": "./src/presets/tailwind-v4.js",
65
+ "types": "./src/presets/tailwind-v4.d.ts"
66
+ },
67
+ "./postcss-processor.ts": {
68
+ "default": "./src/postcss-processor.js",
69
+ "types": "./src/postcss-processor.d.ts"
70
+ },
71
+ "./plugin.ts": {
72
+ "default": "./src/plugin.js",
73
+ "types": "./src/plugin.d.ts"
74
+ },
75
+ "./presets.ts": {
76
+ "default": "./src/presets/index.js",
77
+ "types": "./src/presets/index.d.ts"
78
+ },
79
+ "./presets/tailwind-v3.ts": {
80
+ "default": "./src/presets/tailwind-v3.js",
81
+ "types": "./src/presets/tailwind-v3.d.ts"
82
+ },
83
+ "./presets/tailwind-v4.ts": {
84
+ "default": "./src/presets/tailwind-v4.js",
85
+ "types": "./src/presets/tailwind-v4.d.ts"
80
86
  }
81
87
  }
82
- }
88
+ }
package/src/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./plugin";
2
+ export * from "./postcss-processor";
@@ -0,0 +1,121 @@
1
+ /**
2
+ * PostCssProcessorPlugin
3
+ * @module @ecopages/postcss-processor
4
+ */
5
+ import { Processor, type ProcessorConfig } from '@ecopages/core/plugins/processor';
6
+ import type { EcoBuildPlugin } from '@ecopages/core/build/build-types';
7
+ import type postcss from 'postcss';
8
+ /**
9
+ * Record of PostCSS plugins keyed by name
10
+ */
11
+ export type PluginsRecord = Record<string, postcss.AcceptedPlugin>;
12
+ /**
13
+ * Lazily creates PostCSS plugins.
14
+ *
15
+ * This is primarily used in development when a non-CSS file change forces the
16
+ * processor to rebuild tracked stylesheets. Some plugins, including Tailwind,
17
+ * keep internal caches in long-lived plugin instances, so recreating them is
18
+ * required to pick up newly discovered classes.
19
+ */
20
+ export type PluginFactoryRecord = Record<string, () => postcss.AcceptedPlugin>;
21
+ /**
22
+ * Configuration for the PostCSS processor
23
+ */
24
+ export interface PostCssProcessorPluginConfig {
25
+ /**
26
+ * Regex filter to match files to process
27
+ */
28
+ filter?: RegExp;
29
+ /**
30
+ * Function to transform the contents of the file.
31
+ * It can be handy to add a custom header or footer to the file.
32
+ * Useful for injecting Tailwind v4 `@reference` directives.
33
+ * @param contents The contents of the file
34
+ * @param filePath The absolute path to the CSS file being processed
35
+ * @returns The transformed contents
36
+ */
37
+ transformInput?: (contents: string | Buffer, filePath: string) => string | Promise<string>;
38
+ /**
39
+ * Function to transform the output CSS after PostCSS processing.
40
+ * It can be handy to add a custom header or footer to the processed CSS.
41
+ * @param css The processed CSS
42
+ * @returns The transformed CSS
43
+ */
44
+ transformOutput?: (css: string) => Promise<string> | string;
45
+ /**
46
+ * Custom PostCSS plugins to use instead of the default ones
47
+ * @default undefined (uses default plugins)
48
+ */
49
+ plugins?: PluginsRecord;
50
+ /**
51
+ * Factory functions for recreating stateful PostCSS plugins.
52
+ *
53
+ * When provided, Ecopages uses these factories to build a fresh plugin list
54
+ * for dependency-driven stylesheet rebuilds during development.
55
+ */
56
+ pluginFactories?: PluginFactoryRecord;
57
+ }
58
+ /**
59
+ * PostCssProcessorPlugin
60
+ * A Processor for transforming CSS files.
61
+ */
62
+ export declare class PostCssProcessorPlugin extends Processor<PostCssProcessorPluginConfig> {
63
+ static DEFAULT_OPTIONS: Required<Pick<PostCssProcessorPluginConfig, 'filter'>>;
64
+ private buildContributionsPrepared;
65
+ private postcssPlugins;
66
+ private pluginFactories?;
67
+ private readonly runtimeCssCache;
68
+ private readonly trackedCssFiles;
69
+ private watchQueue;
70
+ private getCssFilter;
71
+ private resolveProcessedCssPath;
72
+ private readProcessedCssFromDist;
73
+ private persistProcessedCss;
74
+ private prewarmRuntimeCssCache;
75
+ private transformCssSync;
76
+ private transformCssAsync;
77
+ matchesFileFilter(filepath: string): boolean;
78
+ private materializePluginFactories;
79
+ private refreshConfiguredPlugins;
80
+ private enqueueWatchTask;
81
+ private getTrackedCssFiles;
82
+ private handleDependencyChange;
83
+ constructor(config?: Omit<ProcessorConfig<PostCssProcessorPluginConfig>, 'name' | 'description'>);
84
+ /**
85
+ * Handles CSS file changes during development.
86
+ * Processes the file and broadcasts a css-update event for hot reloading.
87
+ */
88
+ private handleCssChange;
89
+ get buildPlugins(): EcoBuildPlugin[];
90
+ get plugins(): EcoBuildPlugin[];
91
+ /**
92
+ * Resolves the configured PostCSS plugin list before config build seals the
93
+ * app manifest.
94
+ *
95
+ * @remarks
96
+ * Runtime setup reuses this prepared list and only performs cache prewarming.
97
+ */
98
+ prepareBuildContributions(): Promise<void>;
99
+ /**
100
+ * Prepares build contributions if not already done and prewarms the runtime CSS cache.
101
+ */
102
+ setup(): Promise<void>;
103
+ /**
104
+ * Get the PostCSS plugins from the options or a config file.
105
+ * Searches for postcss.config.{js,cjs,mjs,ts} in the root directory.
106
+ */
107
+ private collectPostcssPlugins;
108
+ /**
109
+ * Process CSS content
110
+ * @param fileAsString CSS content as string
111
+ * @param filePath Optional file path for resolving relative imports
112
+ * @returns Processed CSS
113
+ */
114
+ process(fileAsString: string, filePath?: string): Promise<string>;
115
+ processSync(fileAsString: string, filePath?: string): string;
116
+ /**
117
+ * Teardown the PostCSS processor.
118
+ */
119
+ teardown(): Promise<void>;
120
+ }
121
+ export declare const postcssProcessorPlugin: (config?: PostCssProcessorPluginConfig) => PostCssProcessorPlugin;