proteum 2.1.9-5 → 2.1.9-6

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.
@@ -83,6 +83,26 @@ const isCoreSourceModule = (module: Module) => {
83
83
 
84
84
  return modulePath.startsWith(frameworkSourceRoot + '/') || modulePath.includes('/node_modules/proteum/');
85
85
  };
86
+ const resolveLightningCssTargets = (app: App) => {
87
+ const browserslistConfig = app.packageJson.browserslist;
88
+
89
+ if (typeof browserslistConfig === 'string') return browserslistConfig;
90
+
91
+ if (Array.isArray(browserslistConfig) && browserslistConfig.every((target) => typeof target === 'string'))
92
+ return browserslistConfig;
93
+
94
+ if (!browserslistConfig || typeof browserslistConfig !== 'object') return undefined;
95
+
96
+ for (const env of ['production', 'defaults']) {
97
+ const targets = browserslistConfig[env];
98
+
99
+ if (typeof targets === 'string') return targets;
100
+
101
+ if (Array.isArray(targets) && targets.every((target) => typeof target === 'string')) return targets;
102
+ }
103
+
104
+ return undefined;
105
+ };
86
106
 
87
107
  /*----------------------------------
88
108
  - CONFIG
@@ -100,6 +120,7 @@ export default function createCompiler(
100
120
  (rootPath, index, list) => list.indexOf(rootPath) === index,
101
121
  );
102
122
  const transpileModuleDirectories = app.transpileModuleDirectories;
123
+ const lightningCssTargets = resolveLightningCssTargets(app);
103
124
  const hmrClientEntry = path.join(frameworkSourceRoot, 'client', 'dev', 'hmr.ts');
104
125
 
105
126
  const commonConfig = createCommonConfig(app, 'client', mode, outputTarget);
@@ -320,7 +341,9 @@ export default function createCompiler(
320
341
  removeAvailableModules: true,
321
342
  minimizer: [
322
343
  new rspack.SwcJsMinimizerRspackPlugin({}),
323
- new rspack.LightningCssMinimizerRspackPlugin({}),
344
+ new rspack.LightningCssMinimizerRspackPlugin({
345
+ ...(lightningCssTargets ? { minimizerOptions: { targets: lightningCssTargets } } : {}),
346
+ }),
324
347
  ],
325
348
  nodeEnv: 'production',
326
349
  sideEffects: true,
@@ -2,7 +2,7 @@ import path from 'path';
2
2
 
3
3
  // Plugons
4
4
  import { rspack } from '@rspack/core';
5
- import type { Root } from 'postcss';
5
+ import type { Declaration, Root } from 'postcss';
6
6
 
7
7
  import type { App } from '../../../app';
8
8
 
@@ -11,6 +11,17 @@ const normalizePath = (value: string) => path.resolve(value).replace(/\\/g, '/')
11
11
  const isPathInsideDirectory = (filepath: string, directory: string) =>
12
12
  filepath === directory || filepath.startsWith(directory + '/');
13
13
 
14
+ const VENDOR_PROPERTY_PREFIXES = ['-webkit-', '-moz-', '-ms-', '-o-'] as const;
15
+ const getVendorlessProperty = (property: string) => {
16
+ for (const prefix of VENDOR_PROPERTY_PREFIXES) {
17
+ if (property.startsWith(prefix)) return property.slice(prefix.length);
18
+ }
19
+
20
+ return property;
21
+ };
22
+ const isVendorPrefixedProperty = (property: string) =>
23
+ VENDOR_PROPERTY_PREFIXES.some((prefix) => property.startsWith(prefix));
24
+
14
25
  const createTailwindTranspileSourcesPlugin = (app: App) => {
15
26
  const appRoot = normalizePath(app.paths.root);
16
27
  const transpileSourceDirectories = Array.from(
@@ -50,9 +61,42 @@ const createTailwindTranspileSourcesPlugin = (app: App) => {
50
61
  };
51
62
  };
52
63
 
64
+ const createVendorPropertyOrderPlugin = () => {
65
+ return {
66
+ postcssPlugin: 'proteum-normalize-vendor-property-order',
67
+ Once(root: Root) {
68
+ root.walkRules((rule) => {
69
+ const declarations = (rule.nodes || []).filter((node): node is Declaration => node.type === 'decl');
70
+
71
+ for (const declaration of declarations) {
72
+ if (isVendorPrefixedProperty(declaration.prop)) continue;
73
+
74
+ const property = declaration.prop;
75
+ let nextNode = declaration.next();
76
+
77
+ // LightningCSS canonicalizes property aliases based on source order.
78
+ // Keep prefixed declarations before the standard property so target-aware
79
+ // minification preserves the right output for both old and modern browsers.
80
+ while (nextNode && nextNode.type === 'decl' && getVendorlessProperty(nextNode.prop) === property) {
81
+ const currentNextNode = nextNode;
82
+ nextNode = currentNextNode.next();
83
+
84
+ if (!isVendorPrefixedProperty(currentNextNode.prop)) continue;
85
+
86
+ const reorderedDeclaration = currentNextNode.clone();
87
+ currentNextNode.remove();
88
+ rule.insertBefore(declaration, reorderedDeclaration);
89
+ }
90
+ }
91
+ });
92
+ },
93
+ };
94
+ };
95
+
53
96
  module.exports = (app: App, dev: boolean, _client: boolean) => {
54
97
  const enableSourceMaps = dev;
55
98
  const tailwindTranspileSourcesPlugin = createTailwindTranspileSourcesPlugin(app);
99
+ const vendorPropertyOrderPlugin = createVendorPropertyOrderPlugin();
56
100
 
57
101
  return [
58
102
  // Keep CSS delivery identical in dev and prod: extract files so SSR links stylesheets in both modes.
@@ -86,9 +130,10 @@ module.exports = (app: App, dev: boolean, _client: boolean) => {
86
130
  // process is launched from another working directory (e.g. Docker).
87
131
  base: app.paths.root,
88
132
 
89
- // Avoid double-minifying: Webpack already runs CssMinimizerPlugin in prod.
133
+ // Avoid double-minifying: Rspack already runs LightningCssMinimizerRspackPlugin in prod.
90
134
  optimize: false,
91
135
  }),
136
+ vendorPropertyOrderPlugin,
92
137
  ///* Tailwind V3 */require('tailwindcss'),
93
138
  require('autoprefixer'),
94
139
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "proteum",
3
3
  "description": "LLM-first Opinionated Typescript Framework for web applications.",
4
- "version": "2.1.9-5",
4
+ "version": "2.1.9-6",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/proteum.git",
7
7
  "license": "MIT",