@ecopages/postcss-processor 0.2.0-alpha.2 → 0.2.0-alpha.21

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 CHANGED
@@ -8,15 +8,14 @@ All notable changes to `@ecopages/postcss-processor` are documented here.
8
8
 
9
9
  ### Features
10
10
 
11
- - **Runtime CSS loaders** — Added `css-loader-plugin.ts`, `css-loader.bun.ts`, and `css-runtime-contract.ts` to support runtime CSS loading. CSS is now cached at runtime to avoid redundant processing during HMR (`cbaafea4`, `e7653c9b`).
12
- - **`PostcssProcessor` class** — New `postcss-processor.ts` exposes a programmatic API for the processor separate from the plugin DSL.
11
+ - Added reusable runtime CSS loading, a public `PostcssProcessor` class, and build-adapter registration for the plugin.
13
12
 
14
- ### Refactoring
13
+ ### Bug Fixes
15
14
 
16
- - `plugin.ts` significantly overhauled to integrate with the new build adapter and support build dependency graph registration (`e7653c9b`).
17
- - Test suite updated for esbuild adapter and Node runtime compatibility (`31a44458`).
18
- - Removed unused `@types/postcss` dev dependency.
15
+ - Fixed runtime PostCSS config loading and stylesheet rebuilds for Tailwind-driven template changes.
16
+
17
+ - Fixed direct stylesheet processing and preset output so Tailwind v4 preserves injected references and nested BEM selectors.
19
18
 
20
19
  ### Tests
21
20
 
22
- - Updated `plugin.test.ts`, `postcss-processor.test.ts`, and `presets.test.ts` for new plugin contract.
21
+ - 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
- bunx jsr add @ecopages/postcss-processor
15
+ bun 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.2",
3
+ "version": "0.2.0-alpha.21",
4
4
  "description": "Postcss processor, transform string or postcss file to css",
5
5
  "keywords": [
6
6
  "postcss",
@@ -17,17 +17,17 @@
17
17
  "directory": "packages/processors/postcss-processor"
18
18
  },
19
19
  "dependencies": {
20
- "@ecopages/core": "0.2.0-alpha.2",
21
- "@ecopages/file-system": "0.2.0-alpha.2",
22
- "@ecopages/logger": "latest",
20
+ "@ecopages/file-system": "0.2.0-alpha.21",
21
+ "@ecopages/logger": "^0.2.3",
23
22
  "autoprefixer": "^10.4.0",
24
23
  "browserslist": "^4.28.1",
25
- "cssnano": "^6.0.0",
24
+ "cssnano": "^7.1.4",
26
25
  "postcss": "^8.4.32",
27
- "postcss-import": "^15.0.0",
26
+ "postcss-import": "^16.1.1",
28
27
  "postcss-nested": "^7.0.2"
29
28
  },
30
29
  "peerDependencies": {
30
+ "@ecopages/core": "0.2.0-alpha.21",
31
31
  "@tailwindcss/postcss": ">=4",
32
32
  "tailwindcss": ">=3"
33
33
  },
package/src/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from './plugin';
2
- export * from './postcss-processor';
1
+ export * from './plugin.js';
2
+ export * from './postcss-processor.js';
package/src/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export * from "./plugin";
2
- export * from "./postcss-processor";
1
+ export * from "./plugin.js";
2
+ export * from "./postcss-processor.js";
package/src/plugin.d.ts CHANGED
@@ -9,6 +9,15 @@ import type postcss from 'postcss';
9
9
  * Record of PostCSS plugins keyed by name
10
10
  */
11
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>;
12
21
  /**
13
22
  * Configuration for the PostCSS processor
14
23
  */
@@ -17,6 +26,13 @@ export interface PostCssProcessorPluginConfig {
17
26
  * Regex filter to match files to process
18
27
  */
19
28
  filter?: RegExp;
29
+ /**
30
+ * CSS entry files to rebuild when a non-CSS dependency changes.
31
+ *
32
+ * Use this when the processor watches template or script files that affect a
33
+ * known stylesheet entry, such as a Tailwind reference file.
34
+ */
35
+ dependencyEntryPaths?: string[];
20
36
  /**
21
37
  * Function to transform the contents of the file.
22
38
  * It can be handy to add a custom header or footer to the file.
@@ -38,6 +54,13 @@ export interface PostCssProcessorPluginConfig {
38
54
  * @default undefined (uses default plugins)
39
55
  */
40
56
  plugins?: PluginsRecord;
57
+ /**
58
+ * Factory functions for recreating stateful PostCSS plugins.
59
+ *
60
+ * When provided, Ecopages uses these factories to build a fresh plugin list
61
+ * for dependency-driven stylesheet rebuilds during development.
62
+ */
63
+ pluginFactories?: PluginFactoryRecord;
41
64
  }
42
65
  /**
43
66
  * PostCssProcessorPlugin
@@ -45,26 +68,78 @@ export interface PostCssProcessorPluginConfig {
45
68
  */
46
69
  export declare class PostCssProcessorPlugin extends Processor<PostCssProcessorPluginConfig> {
47
70
  static DEFAULT_OPTIONS: Required<Pick<PostCssProcessorPluginConfig, 'filter'>>;
71
+ private buildContributionsPrepared;
48
72
  private postcssPlugins;
73
+ private pluginFactories?;
49
74
  private readonly runtimeCssCache;
75
+ private readonly trackedCssFiles;
76
+ private watchQueue;
77
+ /**
78
+ * Maps an imported CSS file path → set of tracked CSS entry files that import it.
79
+ * Used to resolve which parent entry files need re-processing when a dependency changes.
80
+ */
81
+ private readonly cssDependencyMap;
50
82
  private getCssFilter;
51
83
  private resolveProcessedCssPath;
52
84
  private readProcessedCssFromDist;
53
85
  private persistProcessedCss;
54
86
  private prewarmRuntimeCssCache;
87
+ /**
88
+ * Regex to match CSS @import statements and extract the path.
89
+ * Handles: @import './foo.css'; @import "./foo.css"; @import url('./foo.css');
90
+ */
91
+ private static readonly CSS_IMPORT_REGEX;
92
+ /**
93
+ * Builds the CSS dependency map by scanning tracked CSS files for @import directives.
94
+ * Maps each imported file to the set of tracked entry files that import it (directly or transitively).
95
+ */
96
+ private buildCssDependencyMap;
97
+ /**
98
+ * Extracts resolved absolute paths of CSS files imported via @import in the given CSS content.
99
+ * Recursively follows imports to capture transitive dependencies.
100
+ * It skips bare module imports like @import 'tailwindcss'.
101
+ * It recursively follows imports to capture transitive dependencies.
102
+ */
103
+ private extractCssImports;
104
+ /**
105
+ * Resolves a changed CSS file to its parent entry file(s) if it is an @import dependency.
106
+ * Returns an empty array if the file is not an import dependency (i.e., it's an entry file itself).
107
+ */
108
+ private resolveEntryFiles;
55
109
  private transformCssSync;
56
110
  private transformCssAsync;
57
111
  matchesFileFilter(filepath: string): boolean;
112
+ private materializePluginFactories;
113
+ private refreshConfiguredPlugins;
114
+ private enqueueWatchTask;
115
+ private getTrackedCssFiles;
116
+ private getTrackedCssEntryFiles;
117
+ private getDependencyEntryFiles;
118
+ private handleDependencyChange;
58
119
  constructor(config?: Omit<ProcessorConfig<PostCssProcessorPluginConfig>, 'name' | 'description'>);
59
120
  /**
60
121
  * Handles CSS file changes during development.
61
- * Processes the file and broadcasts a css-update event for hot reloading.
122
+ * If the file is an @import dependency, re-processes the parent entry file(s) instead.
123
+ * Broadcasts a css-update event for hot reloading.
62
124
  */
63
125
  private handleCssChange;
126
+ /**
127
+ * Processes a CSS file and broadcasts a css-update event.
128
+ * Skips broadcast if the processed output hasn't changed.
129
+ */
130
+ private processAndBroadcast;
64
131
  get buildPlugins(): EcoBuildPlugin[];
65
132
  get plugins(): EcoBuildPlugin[];
66
133
  /**
67
- * Setup the PostCSS processor.
134
+ * Resolves the configured PostCSS plugin list before config build seals the
135
+ * app manifest.
136
+ *
137
+ * @remarks
138
+ * Runtime setup reuses this prepared list and only performs cache prewarming.
139
+ */
140
+ prepareBuildContributions(): Promise<void>;
141
+ /**
142
+ * Prepares build contributions if not already done and prewarms the runtime CSS cache.
68
143
  */
69
144
  setup(): Promise<void>;
70
145
  /**