@sylphx/silk-vite-plugin 2.0.2 → 2.1.0

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/dist/index.d.ts CHANGED
@@ -26,6 +26,33 @@ export interface CompressionOptions {
26
26
  */
27
27
  gzipLevel?: number;
28
28
  }
29
+ export interface PostCssOptions {
30
+ /**
31
+ * Enable PostCSS processing
32
+ * @default false
33
+ */
34
+ enable?: boolean;
35
+ /**
36
+ * PostCSS plugins (e.g., autoprefixer, cssnano)
37
+ * @example
38
+ * ```typescript
39
+ * import autoprefixer from 'autoprefixer'
40
+ *
41
+ * postCss: {
42
+ * enable: true,
43
+ * plugins: [
44
+ * autoprefixer({ overrideBrowserslist: ['> 1%', 'last 2 versions'] })
45
+ * ]
46
+ * }
47
+ * ```
48
+ */
49
+ plugins?: any[];
50
+ /**
51
+ * Generate source maps
52
+ * @default false
53
+ */
54
+ sourceMaps?: boolean;
55
+ }
29
56
  export interface SilkPluginOptions {
30
57
  /**
31
58
  * Output CSS file path
@@ -41,6 +68,24 @@ export interface SilkPluginOptions {
41
68
  * Pre-compression options
42
69
  */
43
70
  compression?: CompressionOptions;
71
+ /**
72
+ * PostCSS processing (optional)
73
+ * Add autoprefixer for legacy browser support or custom PostCSS plugins
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * import autoprefixer from 'autoprefixer'
78
+ *
79
+ * {
80
+ * postCss: {
81
+ * enable: true,
82
+ * plugins: [autoprefixer()],
83
+ * sourceMaps: true
84
+ * }
85
+ * }
86
+ * ```
87
+ */
88
+ postCss?: PostCssOptions;
44
89
  /**
45
90
  * Babel plugin options
46
91
  */
@@ -57,7 +102,7 @@ export interface SilkPluginOptions {
57
102
  */
58
103
  export declare const unpluginSilk: import("unplugin").UnpluginInstance<SilkPluginOptions, boolean>;
59
104
  export declare const vite: (options: SilkPluginOptions) => import("vite").Plugin<any> | import("vite").Plugin<any>[];
60
- export declare const webpack: (options: SilkPluginOptions) => WebpackPluginInstance;
105
+ export declare const webpack: (options: SilkPluginOptions) => import("unplugin").WebpackPluginInstance;
61
106
  export declare const rollup: (options: SilkPluginOptions) => import("rollup").Plugin<any> | import("rollup").Plugin<any>[];
62
107
  export declare const esbuild: (options: SilkPluginOptions) => import("unplugin").EsbuildPlugin;
63
108
  export default vite;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;OAEG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAEhC;;OAEG;IACH,YAAY,CAAC,EAAE;QACb,UAAU,CAAC,EAAE,OAAO,CAAA;QACpB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC5B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACrC,CAAA;CACF;AAyBD;;GAEG;AACH,eAAO,MAAM,YAAY,iEA0LvB,CAAA;AAGF,eAAO,MAAM,IAAI,2FAAoB,CAAA;AACrC,eAAO,MAAM,OAAO,uDAAuB,CAAA;AAC3C,eAAO,MAAM,MAAM,+FAAsB,CAAA;AACzC,eAAO,MAAM,OAAO,kEAAuB,CAAA;AAG3C,eAAe,IAAI,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,EAAE,GAAG,EAAE,CAAA;IAEf;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;OAEG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAEhC;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE;QACb,UAAU,CAAC,EAAE,OAAO,CAAA;QACpB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC5B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACrC,CAAA;CACF;AA0DD;;GAEG;AACH,eAAO,MAAM,YAAY,iEAkPvB,CAAA;AAGF,eAAO,MAAM,IAAI,2FAAoB,CAAA;AACrC,eAAO,MAAM,OAAO,0EAAuB,CAAA;AAC3C,eAAO,MAAM,MAAM,+FAAsB,CAAA;AACzC,eAAO,MAAM,OAAO,kEAAuB,CAAA;AAG3C,eAAe,IAAI,CAAA"}
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@
7
7
  import { createUnplugin } from 'unplugin';
8
8
  import * as path from 'node:path';
9
9
  import { gzipSync, brotliCompressSync, constants } from 'node:zlib';
10
+ import { createHash } from 'node:crypto';
10
11
  // @ts-ignore - Babel preset types not needed
11
12
  import presetReact from '@babel/preset-react';
12
13
  // @ts-ignore - Babel preset types not needed
@@ -33,11 +34,38 @@ function formatBytes(bytes) {
33
34
  return `${(bytes / 1024).toFixed(1)}KB`;
34
35
  return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
35
36
  }
37
+ /**
38
+ * Process CSS with PostCSS (optional)
39
+ */
40
+ async function processWithPostCss(css, postCssOptions) {
41
+ if (!postCssOptions?.enable || !postCssOptions?.plugins?.length) {
42
+ return { css };
43
+ }
44
+ try {
45
+ // Dynamic import to avoid forcing PostCSS as a dependency
46
+ const postcss = await import('postcss').then(m => m.default || m);
47
+ const result = await postcss(postCssOptions.plugins).process(css, {
48
+ from: undefined,
49
+ map: postCssOptions.sourceMaps ? { inline: false } : false
50
+ });
51
+ return {
52
+ css: result.css,
53
+ map: result.map?.toString()
54
+ };
55
+ }
56
+ catch (error) {
57
+ if (error?.code === 'ERR_MODULE_NOT_FOUND') {
58
+ console.warn('[Silk] PostCSS enabled but not installed. Run: npm install postcss');
59
+ return { css };
60
+ }
61
+ throw error;
62
+ }
63
+ }
36
64
  /**
37
65
  * Silk unplugin instance
38
66
  */
39
67
  export const unpluginSilk = createUnplugin((options = {}) => {
40
- const { outputFile = 'silk.css', minify: shouldMinify, compression = {}, babelOptions = {}, } = options;
68
+ const { outputFile = 'silk.css', minify: shouldMinify, compression = {}, babelOptions = {}, postCss, } = options;
41
69
  const compressionConfig = {
42
70
  brotli: compression.brotli ?? true,
43
71
  brotliQuality: compression.brotliQuality ?? 11,
@@ -182,13 +210,62 @@ export const unpluginSilk = createUnplugin((options = {}) => {
182
210
  if (cssRules.size === 0)
183
211
  return;
184
212
  let css = Array.from(cssRules.values()).join('\n');
213
+ let sourceMap;
214
+ // Minify CSS
185
215
  if (shouldMinify ?? true) {
186
216
  css = minifyCSS(css);
187
217
  }
218
+ // PostCSS processing (optional)
219
+ if (postCss?.enable) {
220
+ const result = await processWithPostCss(css, postCss);
221
+ css = result.css;
222
+ sourceMap = result.map;
223
+ }
224
+ // Generate content hash for cache busting
225
+ const hash = createHash('md5').update(css).digest('hex').slice(0, 8);
226
+ const baseName = outputFile.replace('.css', '');
227
+ const hashedFileName = `${baseName}.${hash}.css`;
228
+ // Emit to both locations for Next.js compatibility
188
229
  compilation.assets[outputFile] = {
189
230
  source: () => css,
190
231
  size: () => css.length,
191
232
  };
233
+ // Emit with content hash to static/css directory (production)
234
+ const staticCssPath = `static/css/${hashedFileName}`;
235
+ compilation.assets[staticCssPath] = {
236
+ source: () => css,
237
+ size: () => css.length,
238
+ };
239
+ // Also emit non-hashed version for backwards compatibility
240
+ const staticCssPathLegacy = `static/css/${outputFile}`;
241
+ compilation.assets[staticCssPathLegacy] = {
242
+ source: () => css,
243
+ size: () => css.length,
244
+ };
245
+ // Emit source map if PostCSS generated one
246
+ if (sourceMap) {
247
+ compilation.assets[`${staticCssPath}.map`] = {
248
+ source: () => sourceMap,
249
+ size: () => sourceMap.length,
250
+ };
251
+ compilation.assets[`${outputFile}.map`] = {
252
+ source: () => sourceMap,
253
+ size: () => sourceMap.length,
254
+ };
255
+ }
256
+ console.log(`[Silk] Emitted CSS:`);
257
+ console.log(` • ${outputFile} (${css.length} bytes)`);
258
+ console.log(` • ${staticCssPath} (content-hashed, cacheable)`);
259
+ console.log(` • ${staticCssPathLegacy} (legacy, no hash)`);
260
+ if (postCss?.enable) {
261
+ console.log(` • PostCSS: ${postCss.plugins?.length || 0} plugins applied`);
262
+ }
263
+ if (sourceMap) {
264
+ console.log(` • Source map generated`);
265
+ }
266
+ // Store the hashed filename for potential use in HTML injection
267
+ ;
268
+ compilation.__silkCssFileName = hashedFileName;
192
269
  });
193
270
  },
194
271
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylphx/silk-vite-plugin",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Vite plugin for Silk - Build-time CSS extraction with production optimizations",
5
5
  "keywords": [
6
6
  "silk",
@@ -43,17 +43,29 @@
43
43
  "@babel/core": "^7.23.0",
44
44
  "@babel/preset-react": "^7.23.0",
45
45
  "@babel/preset-typescript": "^7.23.0",
46
- "@sylphx/babel-plugin-silk": "^2.0.0",
46
+ "@sylphx/babel-plugin-silk": "^2.0.1",
47
47
  "@sylphx/silk": "^2.0.0",
48
48
  "unplugin": "^2.3.10"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/babel__core": "^7.20.5",
52
+ "autoprefixer": "^10.4.21",
53
+ "postcss": "^8.5.6",
52
54
  "typescript": "^5.3.0",
53
55
  "vite": "^5.0.0"
54
56
  },
55
57
  "peerDependencies": {
56
- "vite": "^4.0.0 || ^5.0.0"
58
+ "vite": "^4.0.0 || ^5.0.0",
59
+ "postcss": "^8.0.0",
60
+ "autoprefixer": "^10.0.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "postcss": {
64
+ "optional": true
65
+ },
66
+ "autoprefixer": {
67
+ "optional": true
68
+ }
57
69
  },
58
70
  "publishConfig": {
59
71
  "access": "public"