@lumal/vite 0.0.4-beta → 0.0.6-beta

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
@@ -1,5 +1,21 @@
1
1
  # @lumal/vite
2
2
 
3
+ ## 0.0.6-beta (2026-10-25)
4
+
5
+ ### Minor Changes
6
+
7
+ - 新增默认关闭的 createViewportTransformPlugin / createViewportPostcssPlugin,显式限定 CSS 转换范围。
8
+ - Dev/Build 使用同一转换逻辑,默认排除依赖;支持显式依赖白名单、字体和自定义属性策略。
9
+ - 保护 Windows/pnpm 路径、SFC/SCSS/CSS 来源边界,不转换脚本普通数字、内联 style 或 URL。
10
+ - 工作区 alias 增加 @lumal/viewport;公共包版本同步为 0.0.6-beta。
11
+
12
+ ## 0.0.5-beta (2026-10-20)
13
+
14
+ ### Patch Changes
15
+
16
+ - 新增 Vben 兼容层 v5、v5/router、legacy 和 style.css 的源码/产物 alias,并验证最长子入口优先。
17
+ - 与 fixed-group 公共包同步为 0.0.5-beta,无新增运行时依赖。
18
+
3
19
  ## 0.0.4-beta (2026-10-20)
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @lumal/vite
2
2
 
3
+ ## 可选的局部 px → vw
4
+
5
+ 以下 API 属于 `0.0.6-beta`,实际版本可用性以 registry 为准;发布核验前使用候选 tarball:
6
+
7
+ ```ts
8
+ import { createViewportTransformPlugin } from '@lumal/vite'
9
+
10
+ const viewport = createViewportTransformPlugin({
11
+ enabled: true,
12
+ include: ['src/screen/**'],
13
+ exclude: ['**/map/**'],
14
+ viewportWidth: 1920,
15
+ fontSize: false,
16
+ customProperties: false,
17
+ })
18
+ // 将 viewport 加入已有 Vite plugins。
19
+ ```
20
+
21
+ 默认 `enabled=false`,开启必须指定 include。Dev/Build 共用 PostCSS 声明转换,
22
+ 保留已有 inline 或文件 PostCSS 配置;SCSS 在预处理后转换,SFC仅转换style。
23
+ 默认不转换 node_modules,仅 `dependencies: ['明确的包名']` 可白名单加入。
24
+ 默认保留 <=1px、font/font-size 和 CSS 自定义属性;已有vw、URL、var引用、
25
+ 引号字符串和普通数字不变,重复执行幂等。
26
+
27
+ 预处理器有原始 source map 时,按每条声明的真实来源判断范围,而非入口文件名。
28
+ 没有可靠 source map 时,跨文件 `@use` / `@forward` / Sass `@import`、
29
+ 无法解析的预处理语法或函数形式 `additionalData` 会使该 style 整体跳过并警告。
30
+ 这是对转换边界的保护:请把第三方/Shared 样式与需要转换的 Screen 声明分开;
31
+ 同一 SFC 的独立安全 style 块仍可转换。纯 SCSS 声明不受此限制。
32
+ 直接使用 `createViewportPostcssPlugin` 处理预编译的 SCSS/SFC 输出时,
33
+ 必须传入原始 source map,否则保守保留 px,不能根据入口路径猜测来源。
34
+
35
+ 不转换模板内联 style、TS/JS 字符串或坐标;动态数值布局使用响应式 viewport Composable。
36
+ 不提供旧插件的全依赖/全脚本扫描开关。不要将本插件与同一画布的 transform 双重缩放,
37
+ 也不要让转换范围覆盖 Admin、Element Plus 或地图引擎样式。
38
+ 解析依赖仅供 Node 构建工具使用,不进入应用运行时。
39
+
3
40
  Lumal 的轻量 Vite 配置助手,提供组件 resolver、工作区源码/产物 alias 和可选 Devtools 接线。
4
41
 
5
42
  ```ts
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("node:path");var t=[...[`auth`,`components`,`composables`,`dictionary`,`directives`,`layout`,`minimal`,`permission`,`request`,`router`,`theme`,`utils`].map(e=>({dist:`packages/core/dist/${e}.js`,packageName:`core`,source:e===`components`?`packages/core/src/exports/components.ts`:`packages/core/src/${e}/index.ts`,specifier:`@lumal/core/${e}`})),{dist:`packages/core/dist/core.css`,packageName:`core`,source:`packages/core/src/source-style.css`,specifier:`@lumal/core/style.css`},{dist:`packages/core/theme-chalk/index.scss`,packageName:`core`,source:`packages/core/theme-chalk/index.scss`,specifier:`@lumal/core/theme-chalk/index.scss`},{dist:`packages/icons/dist/vite.js`,packageName:`icons`,source:`packages/icons/src/vite/index.ts`,specifier:`@lumal/icons/vite`},{dist:`packages/icons/dist/morph.js`,packageName:`icons`,source:`packages/icons/src/morph/index.ts`,specifier:`@lumal/icons/morph`},{dist:`packages/icons-vue/dist/icons-vue.css`,packageName:`icons-vue`,source:`packages/icons-vue/src/source-style.css`,specifier:`@lumal/icons-vue/style.css`},{dist:`packages/charts/dist/charts.css`,packageName:`charts`,source:`packages/charts/src/source-style.css`,specifier:`@lumal/charts/style.css`},{dist:`packages/datav/dist/datav.css`,packageName:`datav`,source:`packages/datav/src/source-style.css`,specifier:`@lumal/datav/style.css`},{dist:`packages/cockpit/dist/designer.js`,packageName:`cockpit`,source:`packages/cockpit/src/designer/index.ts`,specifier:`@lumal/cockpit/designer`},{dist:`packages/cockpit/dist/registry.js`,packageName:`cockpit`,source:`packages/cockpit/src/registry/index.ts`,specifier:`@lumal/cockpit/registry`},{dist:`packages/cockpit/dist/runtime.js`,packageName:`cockpit`,source:`packages/cockpit/src/runtime/index.ts`,specifier:`@lumal/cockpit/runtime`},{dist:`packages/cockpit/dist/cockpit.css`,packageName:`cockpit`,source:`packages/cockpit/src/source-style.scss`,specifier:`@lumal/cockpit/style.css`},{dist:`packages/vben-compat/dist/index.js`,packageName:`vben-compat`,source:`packages/vben-compat/src/index.ts`,specifier:`@lumal/vben-compat`},{dist:`packages/charts/dist/index.js`,packageName:`charts`,source:`packages/charts/src/index.ts`,specifier:`@lumal/charts`},{dist:`packages/datav/dist/index.js`,packageName:`datav`,source:`packages/datav/src/index.ts`,specifier:`@lumal/datav`},{dist:`packages/icons/dist/index.js`,packageName:`icons`,source:`packages/icons/src/index.ts`,specifier:`@lumal/icons`},{dist:`packages/icons-vue/dist/index.js`,packageName:`icons-vue`,source:`packages/icons-vue/src/index.ts`,specifier:`@lumal/icons-vue`},{dist:`packages/core/dist/index.js`,packageName:`core`,source:`packages/core/src/index.ts`,specifier:`@lumal/core`},{dist:`packages/cockpit/dist/index.js`,packageName:`cockpit`,source:`packages/cockpit/src/index.ts`,specifier:`@lumal/cockpit`}];function n(n){let r=n.target??`source`,i=new Set(n.packages??[`charts`,`cockpit`,`core`,`datav`,`icons`,`icons-vue`,`vben-compat`]);return t.filter(e=>i.has(e.packageName)).map(t=>({find:t.specifier,replacement:(0,e.resolve)(n.workspaceRoot,t[r])})).sort((e,t)=>t.find.length-e.find.length)}var r=new Map([[`LumalAccessControl`,`@lumal/core/permission`],[`LumalBreadcrumb`,`@lumal/core/layout`],[`LumalChart`,`@lumal/charts`],[`LumalChartPanel`,`@lumal/charts`],[`LumalContent`,`@lumal/core/layout`],[`LumalCrudTable`,`@lumal/core/components`],[`LumalHeader`,`@lumal/core/layout`],[`LumalGlobalSearch`,`@lumal/core/layout`],[`LumalIcon`,`@lumal/icons-vue`],[`LumalIconPicker`,`@lumal/icons-vue`],[`LumalIconPickerDialog`,`@lumal/icons-vue`],[`LumalInfoTable`,`@lumal/core/components`],[`LumalLayout`,`@lumal/core/layout`],[`LumalPage`,`@lumal/core/components`],[`LumalPageLayout`,`@lumal/core/components`],[`LumalPagination`,`@lumal/core/components`],[`LumalRouterView`,`@lumal/core/layout`],[`LumalSchemaForm`,`@lumal/core/components`],[`LumalSchemaTable`,`@lumal/core/components`],[`LumalSidebar`,`@lumal/core/layout`],[`LumalTabs`,`@lumal/core/layout`],[`LumalThemeSettingsPanel`,`@lumal/core/theme`],[`LumalTopNav`,`@lumal/core/layout`]]);function i(e){if(e.startsWith(`@lumal/core`))return`@lumal/core/style.css`;if(e===`@lumal/icons-vue`||e===`@lumal/charts`)return`${e}/style.css`}function a(e={}){let t=new Map(r);for(let[n,r]of Object.entries(e.customComponents??{}))t.set(n,r);return{type:`component`,resolve(n){let r=t.get(n);if(r)return{from:r,name:n,sideEffects:e.importStyle?i(r):void 0}}}}function o(e={}){if(e.enabled!==!1)return e.factory?.()??e.plugin}exports.createLumalAliases=n,exports.createLumalComponentResolver=a,exports.resolveLumalDevtoolsPlugin=o;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require("node:path"),l=require("node:process");l=s(l,1);let u=require("picomatch");u=s(u,1);let d=require("postcss"),f=require("postcss-load-config");f=s(f,1);let p=require("postcss-value-parser");p=s(p,1);var m=[{dist:`packages/viewport/dist/index.js`,packageName:`viewport`,source:`packages/viewport/src/index.ts`,specifier:`@lumal/viewport`},...[`auth`,`components`,`composables`,`dictionary`,`directives`,`layout`,`minimal`,`permission`,`request`,`router`,`theme`,`utils`].map(e=>({dist:`packages/core/dist/${e}.js`,packageName:`core`,source:e===`components`?`packages/core/src/exports/components.ts`:`packages/core/src/${e}/index.ts`,specifier:`@lumal/core/${e}`})),{dist:`packages/core/dist/core.css`,packageName:`core`,source:`packages/core/src/source-style.css`,specifier:`@lumal/core/style.css`},{dist:`packages/core/theme-chalk/index.scss`,packageName:`core`,source:`packages/core/theme-chalk/index.scss`,specifier:`@lumal/core/theme-chalk/index.scss`},{dist:`packages/icons/dist/vite.js`,packageName:`icons`,source:`packages/icons/src/vite/index.ts`,specifier:`@lumal/icons/vite`},{dist:`packages/icons/dist/morph.js`,packageName:`icons`,source:`packages/icons/src/morph/index.ts`,specifier:`@lumal/icons/morph`},{dist:`packages/icons-vue/dist/icons-vue.css`,packageName:`icons-vue`,source:`packages/icons-vue/src/source-style.css`,specifier:`@lumal/icons-vue/style.css`},{dist:`packages/charts/dist/charts.css`,packageName:`charts`,source:`packages/charts/src/source-style.css`,specifier:`@lumal/charts/style.css`},{dist:`packages/datav/dist/datav.css`,packageName:`datav`,source:`packages/datav/src/source-style.css`,specifier:`@lumal/datav/style.css`},{dist:`packages/cockpit/dist/designer.js`,packageName:`cockpit`,source:`packages/cockpit/src/designer/index.ts`,specifier:`@lumal/cockpit/designer`},{dist:`packages/cockpit/dist/registry.js`,packageName:`cockpit`,source:`packages/cockpit/src/registry/index.ts`,specifier:`@lumal/cockpit/registry`},{dist:`packages/cockpit/dist/runtime.js`,packageName:`cockpit`,source:`packages/cockpit/src/runtime/index.ts`,specifier:`@lumal/cockpit/runtime`},{dist:`packages/cockpit/dist/cockpit.css`,packageName:`cockpit`,source:`packages/cockpit/src/source-style.scss`,specifier:`@lumal/cockpit/style.css`},{dist:`packages/vben-compat/dist/v5-router.js`,packageName:`vben-compat`,source:`packages/vben-compat/src/v5/router.ts`,specifier:`@lumal/vben-compat/v5/router`},{dist:`packages/vben-compat/dist/v5.js`,packageName:`vben-compat`,source:`packages/vben-compat/src/v5/index.ts`,specifier:`@lumal/vben-compat/v5`},{dist:`packages/vben-compat/dist/legacy.js`,packageName:`vben-compat`,source:`packages/vben-compat/src/legacy.ts`,specifier:`@lumal/vben-compat/legacy`},{dist:`packages/vben-compat/dist/vben-compat.css`,packageName:`vben-compat`,source:`packages/vben-compat/src/source-style.css`,specifier:`@lumal/vben-compat/style.css`},{dist:`packages/vben-compat/dist/index.js`,packageName:`vben-compat`,source:`packages/vben-compat/src/index.ts`,specifier:`@lumal/vben-compat`},{dist:`packages/charts/dist/index.js`,packageName:`charts`,source:`packages/charts/src/index.ts`,specifier:`@lumal/charts`},{dist:`packages/datav/dist/index.js`,packageName:`datav`,source:`packages/datav/src/index.ts`,specifier:`@lumal/datav`},{dist:`packages/icons/dist/index.js`,packageName:`icons`,source:`packages/icons/src/index.ts`,specifier:`@lumal/icons`},{dist:`packages/icons-vue/dist/index.js`,packageName:`icons-vue`,source:`packages/icons-vue/src/index.ts`,specifier:`@lumal/icons-vue`},{dist:`packages/core/dist/index.js`,packageName:`core`,source:`packages/core/src/index.ts`,specifier:`@lumal/core`},{dist:`packages/cockpit/dist/index.js`,packageName:`cockpit`,source:`packages/cockpit/src/index.ts`,specifier:`@lumal/cockpit`}];function h(e){let t=e.target??`source`,n=new Set(e.packages??[`charts`,`cockpit`,`core`,`datav`,`icons`,`icons-vue`,`vben-compat`,`viewport`]);return m.filter(e=>n.has(e.packageName)).map(n=>({find:n.specifier,replacement:(0,c.resolve)(e.workspaceRoot,n[t])})).sort((e,t)=>t.find.length-e.find.length)}var g=new Map([[`LumalAccessControl`,`@lumal/core/permission`],[`LumalBreadcrumb`,`@lumal/core/layout`],[`LumalChart`,`@lumal/charts`],[`LumalChartPanel`,`@lumal/charts`],[`LumalContent`,`@lumal/core/layout`],[`LumalCrudTable`,`@lumal/core/components`],[`LumalHeader`,`@lumal/core/layout`],[`LumalGlobalSearch`,`@lumal/core/layout`],[`LumalIcon`,`@lumal/icons-vue`],[`LumalIconPicker`,`@lumal/icons-vue`],[`LumalIconPickerDialog`,`@lumal/icons-vue`],[`LumalInfoTable`,`@lumal/core/components`],[`LumalLayout`,`@lumal/core/layout`],[`LumalPage`,`@lumal/core/components`],[`LumalPageLayout`,`@lumal/core/components`],[`LumalPagination`,`@lumal/core/components`],[`LumalRouterView`,`@lumal/core/layout`],[`LumalSchemaForm`,`@lumal/core/components`],[`LumalSchemaTable`,`@lumal/core/components`],[`LumalSidebar`,`@lumal/core/layout`],[`LumalTabs`,`@lumal/core/layout`],[`LumalThemeSettingsPanel`,`@lumal/core/theme`],[`LumalTopNav`,`@lumal/core/layout`]]);function _(e){if(e.startsWith(`@lumal/core`))return`@lumal/core/style.css`;if(e===`@lumal/icons-vue`||e===`@lumal/charts`)return`${e}/style.css`}function v(e={}){let t=new Map(g);for(let[n,r]of Object.entries(e.customComponents??{}))t.set(n,r);return{type:`component`,resolve(n){let r=t.get(n);if(r)return{from:r,name:n,sideEffects:e.importStyle?_(r):void 0}}}}function y(e={}){if(e.enabled!==!1)return e.factory?.()??e.plugin}function b(e){if(e.startsWith(`file:`)){let t=new URL(e);e=`${t.host?`//${t.host}`:``}${decodeURIComponent(t.pathname)}`}let t=e.replaceAll(`\\`,`/`).split(`?`)[0];return t.match(/(?:^|\/)([a-z]:\/.*)$/i)?.[1]??t}var x=[`scss`,`sass`,`less`,`styl`,`stylus`];function S(e){return e.match(/\.(scss|sass|less|styl|stylus)(?:$|[?&])/i)?.[1]?.toLowerCase()}function C(e,t){let n=b(/^[a-z]:[/\\]/i.test(t)?t:(0,c.resolve)(t)).replace(/\/$/,``),r=(0,u.default)(e.include??[],{dot:!0}),i=(0,u.default)(e.exclude??[],{dot:!0});return t=>{if(!t||!e.enabled)return!1;let a=b(t),o=a.toLowerCase().startsWith(`${n.toLowerCase()}/`)?a.slice(n.length+1):a;if(i(a)||i(o))return!1;let s=a.split(`/node_modules/`).at(-1);if(s!==a){let t=s.split(`/`),n=t[0].startsWith(`@`)?t.slice(0,2).join(`/`):t[0];return e.dependencies?.includes(n)??!1}return r(o)||r(a)}}function w(e,t,n){let r=e.viewportWidth??1920,i=e.precision??6;if(!(r>0)||!Number.isFinite(r))throw Error(`viewportWidth 必须为正数`);if(!Number.isInteger(i)||i<0||i>10)throw Error(`precision 必须为0到10的整数`);if(e.enabled&&!e.include?.length)throw Error(`视口转换必须显式指定 include 范围`);let a=C(e,t);function o(e){let t=e.source;if(!t)return;if(t.input.map){let e=t.start&&t.input.origin(t.start.line,t.start.column);return e?e.file??e.url:void 0}let r=t.input.file;if(!r)return;if(n)return n(r)?r:void 0;let i=/\.vue(?:$|\?)/i.test(r)&&!/[?&]lang\.css(?:&|$)/i.test(r);return S(r)||i?void 0:r}return{postcssPlugin:`lumal-scoped-viewport`,Declaration(t){if(!a(o(t))||!e.customProperties&&t.prop.startsWith(`--`)||!e.fontSize&&/^(?:font|font-size)$/i.test(t.prop))return;let n=(0,p.default)(t.value),s=!1;n.walk(t=>{if(t.type===`function`&&/^(?:url|var)$/i.test(t.value))return!1;if(t.type!==`word`||!/^-?(?:\d+(?:\.\d*)?|\.\d+)px$/i.test(t.value))return;let n=Number.parseFloat(t.value);Math.abs(n)<=(e.minPixelValue??1)||(t.value=`${Number((n/r*100).toFixed(i))}vw`,s=!0)}),s&&(t.value=n.toString())}}}function T(e,t=l.default.cwd()){return w(e,t)}function E(e){return new URLSearchParams(e.split(`?`)[1]).get(`index`)??``}function D(e,t){try{let n=!1;return(0,d.parse)(e,{from:t}).walkAtRules(/^(?:use|forward|import)$/i,e=>{let t=(0,p.default)(e.params).nodes,r=t.filter(e=>e.type===`string`);if(!r.length){let r=e.name.toLowerCase()===`import`&&t.some(e=>e.type===`function`&&e.value.toLowerCase()===`url`);n||=!r;return}for(let t of r){let r=t.value.startsWith(`sass:`),i=e.name.toLowerCase()===`import`&&/^(?:https?:)?\/\/|\.css(?:[?#]|$)/i.test(t.value);n||=!r&&!i}}),n}catch{return!0}}function O(e){let t=new Map,n=new Map,r=()=>!1;function i(e){let n=t.get(b(e));return n?.get(E(e))??[...n?.values()??[]].every(Boolean)}return{name:`lumal-scoped-viewport`,enforce:`pre`,transform(e,i){let a=S(i);if(!r(i)||!a)return;let o=n.get(a)!==!1&&!D(e,i),s=b(i),c=t.get(s)??new Map;c.set(E(i),o),t.set(s,c),o||this.warn(`跳过视口转换 ${s}:预处理样式含跨文件导入或无法可靠解析的语法;请将外部样式与 Screen 声明分离,避免无原始 source map 时越过转换边界。`)},configResolved(e){for(let t of x){let r=e.css.preprocessorOptions?.[t]?.additionalData;n.set(t,r===void 0||typeof r==`string`&&!D(r,`${e.root}/injected.${t}`))}},async config(t){if(!e.enabled)return;let n=(0,c.resolve)(t.root??l.default.cwd());r=C(e,n);let a=t.css?.postcss,o=typeof a==`object`?a:void 0;if(!o)try{let e=await(0,f.default)({},typeof a==`string`?(0,c.resolve)(n,a):n);o={...e.options,plugins:e.plugins}}catch(e){if(a||!(e instanceof Error)||!e.message.startsWith(`No PostCSS Config found`))throw e}t.css??={},t.css.postcss={...o,plugins:[...o?.plugins??[],w(e,n,i)]}}}}exports.createLumalAliases=h,exports.createLumalComponentResolver=v,exports.createViewportPostcssPlugin=T,exports.createViewportTransformPlugin=O,exports.resolveLumalDevtoolsPlugin=y;
package/dist/index.js CHANGED
@@ -1,6 +1,17 @@
1
1
  import { resolve as e } from "node:path";
2
+ import t from "node:process";
3
+ import n from "picomatch";
4
+ import { parse as r } from "postcss";
5
+ import i from "postcss-load-config";
6
+ import a from "postcss-value-parser";
2
7
  //#region src/aliases.ts
3
- var t = [
8
+ var o = [
9
+ {
10
+ dist: "packages/viewport/dist/index.js",
11
+ packageName: "viewport",
12
+ source: "packages/viewport/src/index.ts",
13
+ specifier: "@lumal/viewport"
14
+ },
4
15
  ...[
5
16
  "auth",
6
17
  "components",
@@ -86,6 +97,30 @@ var t = [
86
97
  source: "packages/cockpit/src/source-style.scss",
87
98
  specifier: "@lumal/cockpit/style.css"
88
99
  },
100
+ {
101
+ dist: "packages/vben-compat/dist/v5-router.js",
102
+ packageName: "vben-compat",
103
+ source: "packages/vben-compat/src/v5/router.ts",
104
+ specifier: "@lumal/vben-compat/v5/router"
105
+ },
106
+ {
107
+ dist: "packages/vben-compat/dist/v5.js",
108
+ packageName: "vben-compat",
109
+ source: "packages/vben-compat/src/v5/index.ts",
110
+ specifier: "@lumal/vben-compat/v5"
111
+ },
112
+ {
113
+ dist: "packages/vben-compat/dist/legacy.js",
114
+ packageName: "vben-compat",
115
+ source: "packages/vben-compat/src/legacy.ts",
116
+ specifier: "@lumal/vben-compat/legacy"
117
+ },
118
+ {
119
+ dist: "packages/vben-compat/dist/vben-compat.css",
120
+ packageName: "vben-compat",
121
+ source: "packages/vben-compat/src/source-style.css",
122
+ specifier: "@lumal/vben-compat/style.css"
123
+ },
89
124
  {
90
125
  dist: "packages/vben-compat/dist/index.js",
91
126
  packageName: "vben-compat",
@@ -129,24 +164,25 @@ var t = [
129
164
  specifier: "@lumal/cockpit"
130
165
  }
131
166
  ];
132
- function n(n) {
133
- let r = n.target ?? "source", i = new Set(n.packages ?? [
167
+ function s(t) {
168
+ let n = t.target ?? "source", r = new Set(t.packages ?? [
134
169
  "charts",
135
170
  "cockpit",
136
171
  "core",
137
172
  "datav",
138
173
  "icons",
139
174
  "icons-vue",
140
- "vben-compat"
175
+ "vben-compat",
176
+ "viewport"
141
177
  ]);
142
- return t.filter((e) => i.has(e.packageName)).map((t) => ({
143
- find: t.specifier,
144
- replacement: e(n.workspaceRoot, t[r])
178
+ return o.filter((e) => r.has(e.packageName)).map((r) => ({
179
+ find: r.specifier,
180
+ replacement: e(t.workspaceRoot, r[n])
145
181
  })).sort((e, t) => t.find.length - e.find.length);
146
182
  }
147
183
  //#endregion
148
184
  //#region src/component-resolver.ts
149
- var r = /* @__PURE__ */ new Map([
185
+ var c = /* @__PURE__ */ new Map([
150
186
  ["LumalAccessControl", "@lumal/core/permission"],
151
187
  ["LumalBreadcrumb", "@lumal/core/layout"],
152
188
  ["LumalChart", "@lumal/charts"],
@@ -171,12 +207,12 @@ var r = /* @__PURE__ */ new Map([
171
207
  ["LumalThemeSettingsPanel", "@lumal/core/theme"],
172
208
  ["LumalTopNav", "@lumal/core/layout"]
173
209
  ]);
174
- function i(e) {
210
+ function l(e) {
175
211
  if (e.startsWith("@lumal/core")) return "@lumal/core/style.css";
176
212
  if (e === "@lumal/icons-vue" || e === "@lumal/charts") return `${e}/style.css`;
177
213
  }
178
- function a(e = {}) {
179
- let t = new Map(r);
214
+ function u(e = {}) {
215
+ let t = new Map(c);
180
216
  for (let [n, r] of Object.entries(e.customComponents ?? {})) t.set(n, r);
181
217
  return {
182
218
  type: "component",
@@ -185,15 +221,149 @@ function a(e = {}) {
185
221
  if (r) return {
186
222
  from: r,
187
223
  name: n,
188
- sideEffects: e.importStyle ? i(r) : void 0
224
+ sideEffects: e.importStyle ? l(r) : void 0
189
225
  };
190
226
  }
191
227
  };
192
228
  }
193
229
  //#endregion
194
230
  //#region src/devtools.ts
195
- function o(e = {}) {
231
+ function d(e = {}) {
196
232
  if (e.enabled !== !1) return e.factory?.() ?? e.plugin;
197
233
  }
198
234
  //#endregion
199
- export { n as createLumalAliases, a as createLumalComponentResolver, o as resolveLumalDevtoolsPlugin };
235
+ //#region src/viewport-transform.ts
236
+ function f(e) {
237
+ if (e.startsWith("file:")) {
238
+ let t = new URL(e);
239
+ e = `${t.host ? `//${t.host}` : ""}${decodeURIComponent(t.pathname)}`;
240
+ }
241
+ let t = e.replaceAll("\\", "/").split("?")[0];
242
+ return t.match(/(?:^|\/)([a-z]:\/.*)$/i)?.[1] ?? t;
243
+ }
244
+ var p = [
245
+ "scss",
246
+ "sass",
247
+ "less",
248
+ "styl",
249
+ "stylus"
250
+ ];
251
+ function m(e) {
252
+ return e.match(/\.(scss|sass|less|styl|stylus)(?:$|[?&])/i)?.[1]?.toLowerCase();
253
+ }
254
+ function h(t, r) {
255
+ let i = f(/^[a-z]:[/\\]/i.test(r) ? r : e(r)).replace(/\/$/, ""), a = n(t.include ?? [], { dot: !0 }), o = n(t.exclude ?? [], { dot: !0 });
256
+ return (e) => {
257
+ if (!e || !t.enabled) return !1;
258
+ let n = f(e), r = n.toLowerCase().startsWith(`${i.toLowerCase()}/`) ? n.slice(i.length + 1) : n;
259
+ if (o(n) || o(r)) return !1;
260
+ let s = n.split("/node_modules/").at(-1);
261
+ if (s !== n) {
262
+ let e = s.split("/"), n = e[0].startsWith("@") ? e.slice(0, 2).join("/") : e[0];
263
+ return t.dependencies?.includes(n) ?? !1;
264
+ }
265
+ return a(r) || a(n);
266
+ };
267
+ }
268
+ function g(e, t, n) {
269
+ let r = e.viewportWidth ?? 1920, i = e.precision ?? 6;
270
+ if (!(r > 0) || !Number.isFinite(r)) throw Error("viewportWidth 必须为正数");
271
+ if (!Number.isInteger(i) || i < 0 || i > 10) throw Error("precision 必须为0到10的整数");
272
+ if (e.enabled && !e.include?.length) throw Error("视口转换必须显式指定 include 范围");
273
+ let o = h(e, t);
274
+ function s(e) {
275
+ let t = e.source;
276
+ if (!t) return;
277
+ if (t.input.map) {
278
+ let e = t.start && t.input.origin(t.start.line, t.start.column);
279
+ return e ? e.file ?? e.url : void 0;
280
+ }
281
+ let r = t.input.file;
282
+ if (!r) return;
283
+ if (n) return n(r) ? r : void 0;
284
+ let i = /\.vue(?:$|\?)/i.test(r) && !/[?&]lang\.css(?:&|$)/i.test(r);
285
+ return m(r) || i ? void 0 : r;
286
+ }
287
+ return {
288
+ postcssPlugin: "lumal-scoped-viewport",
289
+ Declaration(t) {
290
+ if (!o(s(t)) || !e.customProperties && t.prop.startsWith("--") || !e.fontSize && /^(?:font|font-size)$/i.test(t.prop)) return;
291
+ let n = a(t.value), c = !1;
292
+ n.walk((t) => {
293
+ if (t.type === "function" && /^(?:url|var)$/i.test(t.value)) return !1;
294
+ if (t.type !== "word" || !/^-?(?:\d+(?:\.\d*)?|\.\d+)px$/i.test(t.value)) return;
295
+ let n = Number.parseFloat(t.value);
296
+ Math.abs(n) <= (e.minPixelValue ?? 1) || (t.value = `${Number((n / r * 100).toFixed(i))}vw`, c = !0);
297
+ }), c && (t.value = n.toString());
298
+ }
299
+ };
300
+ }
301
+ function _(e, n = t.cwd()) {
302
+ return g(e, n);
303
+ }
304
+ function v(e) {
305
+ return new URLSearchParams(e.split("?")[1]).get("index") ?? "";
306
+ }
307
+ function y(e, t) {
308
+ try {
309
+ let n = !1;
310
+ return r(e, { from: t }).walkAtRules(/^(?:use|forward|import)$/i, (e) => {
311
+ let t = a(e.params).nodes, r = t.filter((e) => e.type === "string");
312
+ if (!r.length) {
313
+ let r = e.name.toLowerCase() === "import" && t.some((e) => e.type === "function" && e.value.toLowerCase() === "url");
314
+ n ||= !r;
315
+ return;
316
+ }
317
+ for (let t of r) {
318
+ let r = t.value.startsWith("sass:"), i = e.name.toLowerCase() === "import" && /^(?:https?:)?\/\/|\.css(?:[?#]|$)/i.test(t.value);
319
+ n ||= !r && !i;
320
+ }
321
+ }), n;
322
+ } catch {
323
+ return !0;
324
+ }
325
+ }
326
+ function b(n) {
327
+ let r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = () => !1;
328
+ function s(e) {
329
+ let t = r.get(f(e));
330
+ return t?.get(v(e)) ?? [...t?.values() ?? []].every(Boolean);
331
+ }
332
+ return {
333
+ name: "lumal-scoped-viewport",
334
+ enforce: "pre",
335
+ transform(e, t) {
336
+ let n = m(t);
337
+ if (!o(t) || !n) return;
338
+ let i = a.get(n) !== !1 && !y(e, t), s = f(t), c = r.get(s) ?? /* @__PURE__ */ new Map();
339
+ c.set(v(t), i), r.set(s, c), i || this.warn(`跳过视口转换 ${s}:预处理样式含跨文件导入或无法可靠解析的语法;请将外部样式与 Screen 声明分离,避免无原始 source map 时越过转换边界。`);
340
+ },
341
+ configResolved(e) {
342
+ for (let t of p) {
343
+ let n = e.css.preprocessorOptions?.[t]?.additionalData;
344
+ a.set(t, n === void 0 || typeof n == "string" && !y(n, `${e.root}/injected.${t}`));
345
+ }
346
+ },
347
+ async config(r) {
348
+ if (!n.enabled) return;
349
+ let a = e(r.root ?? t.cwd());
350
+ o = h(n, a);
351
+ let c = r.css?.postcss, l = typeof c == "object" ? c : void 0;
352
+ if (!l) try {
353
+ let t = await i({}, typeof c == "string" ? e(a, c) : a);
354
+ l = {
355
+ ...t.options,
356
+ plugins: t.plugins
357
+ };
358
+ } catch (e) {
359
+ if (c || !(e instanceof Error) || !e.message.startsWith("No PostCSS Config found")) throw e;
360
+ }
361
+ r.css ??= {}, r.css.postcss = {
362
+ ...l,
363
+ plugins: [...l?.plugins ?? [], g(n, a, s)]
364
+ };
365
+ }
366
+ };
367
+ }
368
+ //#endregion
369
+ export { s as createLumalAliases, u as createLumalComponentResolver, _ as createViewportPostcssPlugin, b as createViewportTransformPlugin, d as resolveLumalDevtoolsPlugin };
@@ -1,5 +1,5 @@
1
1
  export type LumalAliasTarget = 'dist' | 'source';
2
- export type LumalAliasPackage = 'charts' | 'cockpit' | 'core' | 'datav' | 'icons' | 'icons-vue' | 'vben-compat';
2
+ export type LumalAliasPackage = 'charts' | 'cockpit' | 'core' | 'datav' | 'icons' | 'icons-vue' | 'vben-compat' | 'viewport';
3
3
  export interface LumalAliasEntry {
4
4
  find: string;
5
5
  replacement: string;
@@ -1 +1 @@
1
- {"version":3,"file":"aliases.d.ts","sourceRoot":"","sources":["../../src/aliases.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAA;AAChD,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG,aAAa,CAAA;AAE/G,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC9B,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;CACtB;AA+HD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,eAAe,EAAE,CAWxF"}
1
+ {"version":3,"file":"aliases.d.ts","sourceRoot":"","sources":["../../src/aliases.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAA;AAChD,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG,aAAa,GAAG,UAAU,CAAA;AAE5H,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC9B,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;CACtB;AA6JD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,eAAe,EAAE,CAWxF"}
@@ -4,4 +4,6 @@ export { createLumalComponentResolver, } from './component-resolver';
4
4
  export type { CreateLumalComponentResolverOptions, LumalComponentResolver, LumalComponentResolverResult, } from './component-resolver';
5
5
  export { resolveLumalDevtoolsPlugin, } from './devtools';
6
6
  export type { ResolveLumalDevtoolsPluginOptions, } from './devtools';
7
+ export { createViewportPostcssPlugin, createViewportTransformPlugin } from './viewport-transform';
8
+ export type { ViewportTransformOptions } from './viewport-transform';
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,yBAAyB,EACzB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,4BAA4B,GAC7B,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,mCAAmC,EACnC,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,0BAA0B,GAC3B,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,iCAAiC,GAClC,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,yBAAyB,EACzB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,4BAA4B,GAC7B,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,mCAAmC,EACnC,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,0BAA0B,GAC3B,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,iCAAiC,GAClC,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAA;AACjG,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,22 @@
1
+ import type { Plugin as PostcssPlugin } from 'postcss';
2
+ import type { Plugin as VitePlugin } from 'vite';
3
+ export interface ViewportTransformOptions {
4
+ /** 必须显式开启;不设置时不修改配置。 */
5
+ enabled?: boolean;
6
+ /** 相对 Vite root 的 glob,例如 src/screen/**,不允许隐式全项目转换。 */
7
+ include: string[];
8
+ exclude?: string[];
9
+ viewportWidth?: number;
10
+ precision?: number;
11
+ /** 默认保留 <=1px,避免细边框消失。 */
12
+ minPixelValue?: number;
13
+ fontSize?: boolean;
14
+ customProperties?: boolean;
15
+ /** 默认排除全部依赖;仅此处显式列出的包可以转换。 */
16
+ dependencies?: string[];
17
+ }
18
+ /** 在预处理后的 CSS AST 上操作,不扫描脚本、模板数字或任意文本。 */
19
+ export declare function createViewportPostcssPlugin(options: ViewportTransformOptions, root?: string): PostcssPlugin;
20
+ /** 保留已有 inline/file PostCSS 配置,开发和构建都在同一 CSS 管线上执行。 */
21
+ export declare function createViewportTransformPlugin(options: ViewportTransformOptions): VitePlugin;
22
+ //# sourceMappingURL=viewport-transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport-transform.d.ts","sourceRoot":"","sources":["../../src/viewport-transform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,MAAM,IAAI,aAAa,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAA;AAQhD,MAAM,WAAW,wBAAwB;IACvC,wBAAwB;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,uDAAuD;IACvD,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB;AA8FD,0CAA0C;AAC1C,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,wBAAwB,EAAE,IAAI,SAAgB,GAAG,aAAa,CAElH;AA+BD,uDAAuD;AACvD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,wBAAwB,GAAG,UAAU,CAwD3F"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@lumal/vite",
3
3
  "type": "module",
4
- "version": "0.0.4-beta",
5
- "description": "Lumal Vite component resolver, workspace aliases and optional devtools helpers.",
4
+ "version": "0.0.6-beta",
5
+ "description": "Lumal Vite resolvers, workspace aliases, devtools helpers and scoped optional CSS viewport transforms.",
6
6
  "license": "MIT",
7
7
  "keywords": [
8
8
  "lumal",
@@ -29,6 +29,15 @@
29
29
  "README.md",
30
30
  "dist"
31
31
  ],
32
+ "dependencies": {
33
+ "picomatch": "^4.0.5",
34
+ "postcss": "^8.5.16",
35
+ "postcss-load-config": "^6.0.1",
36
+ "postcss-value-parser": "^4.2.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/picomatch": "^4.0.3"
40
+ },
32
41
  "scripts": {
33
42
  "build": "vite build --config vite.config.ts && tsc -p tsconfig.json --emitDeclarationOnly && node ../../scripts/clean-package-dist.mjs dist",
34
43
  "typecheck": "tsc --noEmit -p tsconfig.json",