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

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,26 @@
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
+ ### Bug Fixes
10
+
11
+ - Rebuilt tracked stylesheets from fresh PostCSS plugin instances on non-CSS source changes so Tailwind utility generation updates without stale caches or forced reloads.
12
+
13
+ ### Features
14
+
15
+ - **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`).
16
+ - **`PostcssProcessor` class** — New `postcss-processor.ts` exposes a programmatic API for the processor separate from the plugin DSL.
17
+
18
+ ### Refactoring
19
+
20
+ - `plugin.ts` significantly overhauled to integrate with the new build adapter and support build dependency graph registration (`e7653c9b`).
21
+ - Test suite updated for esbuild adapter and Node runtime compatibility (`31a44458`).
22
+ - Removed unused `@types/postcss` dev dependency.
23
+
24
+ ### Tests
25
+
26
+ - Updated `plugin.test.ts`, `postcss-processor.test.ts`, and `presets.test.ts` for new plugin contract.
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.3",
4
4
  "description": "Postcss processor, transform string or postcss file to css",
5
5
  "keywords": [
6
6
  "postcss",
@@ -8,24 +8,17 @@
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/core": "0.2.0-alpha.3",
21
+ "@ecopages/file-system": "0.2.0-alpha.3",
29
22
  "@ecopages/logger": "latest",
30
23
  "autoprefixer": "^10.4.0",
31
24
  "browserslist": "^4.28.1",
@@ -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.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './plugin';
2
+ export * from './postcss-processor';
package/src/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./plugin";
2
+ export * from "./postcss-processor";
@@ -0,0 +1,112 @@
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 postcssPlugins;
65
+ private pluginFactories?;
66
+ private readonly runtimeCssCache;
67
+ private readonly trackedCssFiles;
68
+ private watchQueue;
69
+ private getCssFilter;
70
+ private resolveProcessedCssPath;
71
+ private readProcessedCssFromDist;
72
+ private persistProcessedCss;
73
+ private prewarmRuntimeCssCache;
74
+ private transformCssSync;
75
+ private transformCssAsync;
76
+ matchesFileFilter(filepath: string): boolean;
77
+ private materializePluginFactories;
78
+ private refreshConfiguredPlugins;
79
+ private enqueueWatchTask;
80
+ private getTrackedCssFiles;
81
+ private handleDependencyChange;
82
+ constructor(config?: Omit<ProcessorConfig<PostCssProcessorPluginConfig>, 'name' | 'description'>);
83
+ /**
84
+ * Handles CSS file changes during development.
85
+ * Processes the file and broadcasts a css-update event for hot reloading.
86
+ */
87
+ private handleCssChange;
88
+ get buildPlugins(): EcoBuildPlugin[];
89
+ get plugins(): EcoBuildPlugin[];
90
+ /**
91
+ * Setup the PostCSS processor.
92
+ */
93
+ setup(): Promise<void>;
94
+ /**
95
+ * Get the PostCSS plugins from the options or a config file.
96
+ * Searches for postcss.config.{js,cjs,mjs,ts} in the root directory.
97
+ */
98
+ private collectPostcssPlugins;
99
+ /**
100
+ * Process CSS content
101
+ * @param fileAsString CSS content as string
102
+ * @param filePath Optional file path for resolving relative imports
103
+ * @returns Processed CSS
104
+ */
105
+ process(fileAsString: string, filePath?: string): Promise<string>;
106
+ processSync(fileAsString: string, filePath?: string): string;
107
+ /**
108
+ * Teardown the PostCSS processor.
109
+ */
110
+ teardown(): Promise<void>;
111
+ }
112
+ export declare const postcssProcessorPlugin: (config?: PostCssProcessorPluginConfig) => PostCssProcessorPlugin;
package/src/plugin.js ADDED
@@ -0,0 +1,354 @@
1
+ import path from "node:path";
2
+ import { fileSystem } from "@ecopages/file-system";
3
+ import { Processor } from "@ecopages/core/plugins/processor";
4
+ import { Logger } from "@ecopages/logger";
5
+ import { PostCssProcessor } from "./postcss-processor";
6
+ import { createCssLoaderPlugin } from "./runtime/css-loader-plugin";
7
+ const logger = new Logger("[@ecopages/postcss-processor]", {
8
+ debug: process.env.ECOPAGES_LOGGER_DEBUG === "true"
9
+ });
10
+ class PostCssProcessorPlugin extends Processor {
11
+ static DEFAULT_OPTIONS = {
12
+ filter: /\.css$/
13
+ };
14
+ postcssPlugins = [];
15
+ pluginFactories;
16
+ runtimeCssCache = /* @__PURE__ */ new Map();
17
+ trackedCssFiles = /* @__PURE__ */ new Set();
18
+ watchQueue = Promise.resolve();
19
+ getCssFilter() {
20
+ return this.options?.filter ?? PostCssProcessorPlugin.DEFAULT_OPTIONS.filter;
21
+ }
22
+ resolveProcessedCssPath(filePath) {
23
+ if (!this.context) {
24
+ return null;
25
+ }
26
+ const relativePath = path.relative(this.context.srcDir, filePath);
27
+ if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
28
+ return null;
29
+ }
30
+ return path.join(this.context.distDir, "assets", relativePath);
31
+ }
32
+ readProcessedCssFromDist(filePath) {
33
+ const outputPath = this.resolveProcessedCssPath(filePath);
34
+ if (!outputPath || !fileSystem.exists(outputPath)) {
35
+ return null;
36
+ }
37
+ return fileSystem.readFileAsBuffer(outputPath).toString("utf-8");
38
+ }
39
+ async persistProcessedCss(filePath, css) {
40
+ const outputPath = this.resolveProcessedCssPath(filePath);
41
+ if (!outputPath) {
42
+ return;
43
+ }
44
+ fileSystem.ensureDir(path.dirname(outputPath));
45
+ fileSystem.write(outputPath, css);
46
+ }
47
+ async prewarmRuntimeCssCache() {
48
+ if (!this.context) {
49
+ return;
50
+ }
51
+ const sourceFiles = await fileSystem.glob(["**/*.{css,scss,sass,less}"], {
52
+ cwd: this.context.srcDir
53
+ });
54
+ for (const relativePath of sourceFiles) {
55
+ const filePath = path.join(this.context.srcDir, relativePath);
56
+ if (!this.matchesFileFilter(filePath)) {
57
+ continue;
58
+ }
59
+ this.trackedCssFiles.add(filePath);
60
+ const rawContents = await fileSystem.readFile(filePath);
61
+ let transformedInput = rawContents;
62
+ if (this.options?.transformInput) {
63
+ transformedInput = await this.options.transformInput(rawContents, filePath);
64
+ }
65
+ const processed = await this.process(transformedInput, filePath);
66
+ this.runtimeCssCache.set(filePath, processed);
67
+ await this.persistProcessedCss(filePath, processed);
68
+ }
69
+ }
70
+ transformCssSync(input) {
71
+ const cached = this.runtimeCssCache.get(input.filePath);
72
+ if (cached) {
73
+ return cached;
74
+ }
75
+ const persisted = this.readProcessedCssFromDist(input.filePath);
76
+ if (persisted) {
77
+ this.runtimeCssCache.set(input.filePath, persisted);
78
+ return persisted;
79
+ }
80
+ const { contents } = input;
81
+ return typeof contents === "string" ? contents : contents.toString("utf-8");
82
+ }
83
+ async transformCssAsync(input) {
84
+ const { contents, filePath } = input;
85
+ let transformed = typeof contents === "string" ? contents : contents.toString("utf-8");
86
+ if (this.options?.transformInput) {
87
+ const result = this.options.transformInput(contents, filePath);
88
+ transformed = typeof result.then === "function" ? await result : result;
89
+ }
90
+ const processed = await this.process(transformed, filePath);
91
+ this.runtimeCssCache.set(filePath, processed);
92
+ await this.persistProcessedCss(filePath, processed);
93
+ return processed;
94
+ }
95
+ matchesFileFilter(filepath) {
96
+ const filter = this.options?.filter ?? PostCssProcessorPlugin.DEFAULT_OPTIONS.filter;
97
+ return filter.test(filepath);
98
+ }
99
+ materializePluginFactories(pluginFactories) {
100
+ return Object.values(pluginFactories).map((factory) => factory());
101
+ }
102
+ refreshConfiguredPlugins() {
103
+ if (!this.pluginFactories) {
104
+ return;
105
+ }
106
+ this.postcssPlugins = this.materializePluginFactories(this.pluginFactories);
107
+ }
108
+ enqueueWatchTask(task) {
109
+ const queuedTask = this.watchQueue.then(task, task);
110
+ this.watchQueue = queuedTask.catch(() => void 0);
111
+ return queuedTask;
112
+ }
113
+ getTrackedCssFiles() {
114
+ return Array.from(this.trackedCssFiles).filter(
115
+ (filePath) => this.matchesFileFilter(filePath) && fileSystem.exists(filePath)
116
+ );
117
+ }
118
+ async handleDependencyChange(bridge) {
119
+ if (!this.context) {
120
+ return;
121
+ }
122
+ const cssFiles = this.getTrackedCssFiles();
123
+ if (cssFiles.length === 0) {
124
+ return;
125
+ }
126
+ this.refreshConfiguredPlugins();
127
+ for (const cssFilePath of cssFiles) {
128
+ await this.handleCssChange(cssFilePath, bridge, false);
129
+ }
130
+ }
131
+ constructor(config = {
132
+ options: PostCssProcessorPlugin.DEFAULT_OPTIONS
133
+ }) {
134
+ super({
135
+ name: "ecopages-postcss-processor",
136
+ description: "A Processor for transforming CSS files using PostCSS.",
137
+ capabilities: [
138
+ {
139
+ kind: "stylesheet",
140
+ extensions: ["*.{css,scss,sass,less}"]
141
+ }
142
+ ],
143
+ watch: {
144
+ paths: [],
145
+ extensions: [
146
+ ".css",
147
+ ".scss",
148
+ ".sass",
149
+ ".less",
150
+ ".tsx",
151
+ ".ts",
152
+ ".jsx",
153
+ ".js",
154
+ ".mdx",
155
+ ".html",
156
+ ".svelte",
157
+ ".vue"
158
+ ],
159
+ onChange: async ({ path: path2, bridge }) => {
160
+ await this.enqueueWatchTask(async () => {
161
+ if (this.matchesFileFilter(path2)) {
162
+ await this.handleCssChange(path2, bridge);
163
+ return;
164
+ }
165
+ await this.handleDependencyChange(bridge);
166
+ });
167
+ },
168
+ onCreate: async ({ path: path2, bridge }) => {
169
+ await this.enqueueWatchTask(async () => {
170
+ if (this.matchesFileFilter(path2)) {
171
+ await this.handleCssChange(path2, bridge);
172
+ return;
173
+ }
174
+ await this.handleDependencyChange(bridge);
175
+ });
176
+ },
177
+ onDelete: async ({ path: path2, bridge }) => {
178
+ await this.enqueueWatchTask(async () => {
179
+ if (this.matchesFileFilter(path2)) {
180
+ this.runtimeCssCache.delete(path2);
181
+ this.trackedCssFiles.delete(path2);
182
+ return;
183
+ }
184
+ await this.handleDependencyChange(bridge);
185
+ });
186
+ }
187
+ },
188
+ ...config
189
+ });
190
+ }
191
+ /**
192
+ * Handles CSS file changes during development.
193
+ * Processes the file and broadcasts a css-update event for hot reloading.
194
+ */
195
+ async handleCssChange(filePath, bridge, refreshPlugins = true) {
196
+ if (!this.context) return;
197
+ if (!fileSystem.exists(filePath)) return;
198
+ try {
199
+ this.trackedCssFiles.add(filePath);
200
+ if (refreshPlugins) {
201
+ this.refreshConfiguredPlugins();
202
+ }
203
+ let content = await fileSystem.readFile(filePath);
204
+ if (this.options?.transformInput) {
205
+ content = await this.options.transformInput(content, filePath);
206
+ }
207
+ const processed = await this.process(content, filePath);
208
+ const cached = this.runtimeCssCache.get(filePath);
209
+ if (cached === processed) {
210
+ return;
211
+ }
212
+ this.runtimeCssCache.set(filePath, processed);
213
+ await this.persistProcessedCss(filePath, processed);
214
+ bridge.cssUpdate(filePath);
215
+ logger.debug(`Processed CSS: ${filePath}`);
216
+ } catch (error) {
217
+ const errorMessage = error instanceof Error ? error.message : String(error);
218
+ logger.error(`Failed to process CSS: ${filePath}`, errorMessage);
219
+ bridge.error(errorMessage);
220
+ }
221
+ }
222
+ get buildPlugins() {
223
+ return [
224
+ createCssLoaderPlugin({
225
+ name: "postcss-processor-build-loader",
226
+ filter: this.getCssFilter(),
227
+ transform: this.transformCssAsync.bind(this)
228
+ })
229
+ ];
230
+ }
231
+ get plugins() {
232
+ return [
233
+ createCssLoaderPlugin({
234
+ name: "postcss-processor-runtime-loader",
235
+ filter: this.getCssFilter(),
236
+ transform: this.transformCssSync.bind(this)
237
+ })
238
+ ];
239
+ }
240
+ /**
241
+ * Setup the PostCSS processor.
242
+ */
243
+ async setup() {
244
+ await this.collectPostcssPlugins();
245
+ await this.prewarmRuntimeCssCache();
246
+ }
247
+ /**
248
+ * Get the PostCSS plugins from the options or a config file.
249
+ * Searches for postcss.config.{js,cjs,mjs,ts} in the root directory.
250
+ */
251
+ async collectPostcssPlugins() {
252
+ if (!this.context) {
253
+ throw new Error("Context must be set");
254
+ }
255
+ const configExtensions = ["js", "cjs", "mjs", "ts"];
256
+ let foundConfigPath;
257
+ let loadedPlugins;
258
+ let loadedPluginFactories;
259
+ for (const ext of configExtensions) {
260
+ const configPath = path.join(this.context.rootDir, `postcss.config.${ext}`);
261
+ if (fileSystem.exists(configPath)) {
262
+ foundConfigPath = configPath;
263
+ break;
264
+ }
265
+ }
266
+ if (foundConfigPath) {
267
+ try {
268
+ logger.debug(`Loading PostCSS config from: ${foundConfigPath}`);
269
+ const postcssConfigModule = await import(foundConfigPath);
270
+ const postcssConfig = postcssConfigModule.default || postcssConfigModule;
271
+ if (postcssConfig && typeof postcssConfig.pluginFactories === "object" && postcssConfig.pluginFactories !== null) {
272
+ loadedPluginFactories = postcssConfig.pluginFactories;
273
+ }
274
+ if (postcssConfig && typeof postcssConfig.plugins === "object" && postcssConfig.plugins !== null) {
275
+ if (Array.isArray(postcssConfig.plugins)) {
276
+ loadedPlugins = postcssConfig.plugins;
277
+ } else {
278
+ loadedPlugins = Object.values(postcssConfig.plugins);
279
+ }
280
+ logger.debug(`Successfully loaded ${loadedPlugins?.length ?? 0} plugins from config file.`);
281
+ } else {
282
+ logger.warn(
283
+ `PostCSS config file found (${foundConfigPath}), but no valid 'plugins' export detected.`
284
+ );
285
+ }
286
+ } catch (error) {
287
+ logger.error(`Error loading PostCSS config from ${foundConfigPath}: ${error.message}`, error);
288
+ loadedPlugins = void 0;
289
+ }
290
+ } else {
291
+ logger.debug("No PostCSS config file found in root directory.");
292
+ }
293
+ if (loadedPluginFactories) {
294
+ this.pluginFactories = loadedPluginFactories;
295
+ this.postcssPlugins = this.materializePluginFactories(loadedPluginFactories);
296
+ } else if (loadedPlugins) {
297
+ this.pluginFactories = void 0;
298
+ this.postcssPlugins = loadedPlugins;
299
+ } else if (this.options?.pluginFactories) {
300
+ logger.debug("Using PostCSS plugin factories provided in processor options.");
301
+ this.pluginFactories = this.options.pluginFactories;
302
+ this.postcssPlugins = this.materializePluginFactories(this.options.pluginFactories);
303
+ } else if (this.options?.plugins) {
304
+ logger.debug("Using PostCSS plugins provided in processor options.");
305
+ this.pluginFactories = void 0;
306
+ this.postcssPlugins = Object.values(this.options.plugins);
307
+ } else {
308
+ logger.warn(
309
+ "No PostCSS plugins configured. Use a preset like tailwindV3Preset() or tailwindV4Preset(), provide plugins via options, or create a postcss.config file."
310
+ );
311
+ this.pluginFactories = void 0;
312
+ this.postcssPlugins = [];
313
+ }
314
+ if (!this.postcssPlugins || this.postcssPlugins.length === 0) {
315
+ logger.warn("No PostCSS plugins configured or loaded. CSS processing might be minimal.");
316
+ this.postcssPlugins = [];
317
+ }
318
+ }
319
+ /**
320
+ * Process CSS content
321
+ * @param fileAsString CSS content as string
322
+ * @param filePath Optional file path for resolving relative imports
323
+ * @returns Processed CSS
324
+ */
325
+ async process(fileAsString, filePath) {
326
+ return await PostCssProcessor.processStringOrBuffer(fileAsString, {
327
+ filePath,
328
+ plugins: this.postcssPlugins,
329
+ transformOutput: this.options?.transformOutput
330
+ });
331
+ }
332
+ processSync(fileAsString, filePath) {
333
+ return PostCssProcessor.processStringOrBufferSync(fileAsString, {
334
+ filePath,
335
+ plugins: this.postcssPlugins,
336
+ transformOutput: this.options?.transformOutput
337
+ });
338
+ }
339
+ /**
340
+ * Teardown the PostCSS processor.
341
+ */
342
+ async teardown() {
343
+ logger.debug("Tearing down PostCSS processor");
344
+ }
345
+ }
346
+ const postcssProcessorPlugin = (config) => {
347
+ return new PostCssProcessorPlugin({
348
+ options: config
349
+ });
350
+ };
351
+ export {
352
+ PostCssProcessorPlugin,
353
+ postcssProcessorPlugin
354
+ };