{"_id":"@10coding/postcss-jsx-scoped","_rev":"2-ebc8c3d1c949fd54d21fdd53e7a4a4a0","name":"@10coding/postcss-jsx-scoped","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@10coding/postcss-jsx-scoped","version":"0.1.0","license":"MIT","_id":"@10coding/postcss-jsx-scoped@0.1.0","maintainers":[{"name":"scliuyilin","email":"scliuyilin@163.com"}],"dist":{"shasum":"11da69cb42e5c155280213e59b6855cd25a1c338","tarball":"https://registry.npmjs.org/@10coding/postcss-jsx-scoped/-/postcss-jsx-scoped-0.1.0.tgz","fileCount":8,"integrity":"sha512-0xZwagNsr91it9zG3sS9+8bHI9EPmhxTMHgDOshPVRz9JoLQhQgmyg8KY7l848mvhfPopSA7RIjQb9D6lPU3Jg==","signatures":[{"sig":"MEUCICja3rhee7x1CjxIkAMwaidQxLTzsx7G2HuqKOXuFqNVAiEAsTwHT0H9YXnP8ffsQmKi2HdiItbpRz9hre1pZtF96Mg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38004},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"test":"pnpm build && node scripts/verify.mjs","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"scliuyilin","email":"scliuyilin@163.com"},"description":"PostCSS plugin for Vue-like scoped styles in JSX/TSX: appends [data-v-{hash}] attribute selectors to CSS selectors","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","dependencies":{"postcss":"^8.5.1","postcss-selector-parser":"^7.1.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/postcss-jsx-scoped_0.1.0_1788520485143_0.5275119384223754","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@10coding/postcss-jsx-scoped","version":"0.2.0","description":"PostCSS plugin for Vue-like scoped styles in JSX/TSX: appends [data-v-{hash}] attribute selectors to CSS selectors","license":"MIT","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":false,"engines":{"node":">=18"},"publishConfig":{"access":"public"},"dependencies":{"postcss":"^8.5.1","postcss-selector-parser":"^7.1.6"},"devDependencies":{"@types/node":"^22.10.0","tsup":"^8.3.5","typescript":"^5.7.2"},"scripts":{"build":"tsup","typecheck":"tsc --noEmit","test":"pnpm build && node scripts/verify.mjs"},"_nodeVersion":"24.14.1","_id":"@10coding/postcss-jsx-scoped@0.2.0","dist":{"integrity":"sha512-IrJzNj0ELOYwW7WBfn/K4iBdZ+hsbDq03t6CJ9XPreI5q0xjW19JGRMbUyYMFNLrDe1SB9DhWmdXaJMWTKCzgQ==","shasum":"e822c978f1910a4c87d96aa56384a253065729fe","tarball":"https://registry.npmjs.org/@10coding/postcss-jsx-scoped/-/postcss-jsx-scoped-0.2.0.tgz","fileCount":8,"unpackedSize":81399,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCGxmt7Nf04ucLs+Igyrx8oOS4nDvnFN9fffSbRuXgqCAIgc5qD0mtAYVXZhONSCW9LIcN8ZVnKhlNXZJQZIzV9kNs="}]},"_npmUser":{"name":"scliuyilin","email":"scliuyilin@163.com"},"directories":{},"maintainers":[{"name":"scliuyilin","email":"scliuyilin@163.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/postcss-jsx-scoped_0.2.0_1789017226845_0.8202750016717559"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-04T11:14:44.998Z","modified":"2026-09-10T05:13:47.191Z","0.1.0":"2026-09-04T11:14:45.273Z","0.2.0":"2026-09-10T05:13:47.007Z"},"license":"MIT","description":"PostCSS plugin for Vue-like scoped styles in JSX/TSX: appends [data-v-{hash}] attribute selectors to CSS selectors","maintainers":[{"name":"scliuyilin","email":"scliuyilin@163.com"}],"readme":"# @10coding/postcss-jsx-scoped\n\nPostCSS 插件：为 CSS 选择器追加 scope 属性选择器，实现 Vue-like scoped 样式的\n「选择器收尾」环节。\n\n```\n.demo .title        →  .demo .title[data-v-3f2a9c1d]\nh1, h2              →  h1[data-v-3f2a9c1d], h2[data-v-3f2a9c1d]\n.btn::before        →  .btn[data-v-3f2a9c1d]::before   （伪元素保持在属性之后）\n@media (...) { .a } →  @media (...) { .a[data-v-3f2a9c1d] }\n@keyframes { from{} }→  from{} 帧选择器不追加\n```\n\n> 组件 JSX 侧注入 `data-v-{hash}` 由 `@10coding/plugin-jsx-scoped`（babel）完成，\n> 编排与预处理器编译由 `@10coding/vite-plugin-jsx-scoped`（vite）完成；\n> 本包只负责把「已编译成普通 CSS 的选择器」追加 scope 属性。\n\n## 安装\n\n```bash\npnpm add -D @10coding/postcss-jsx-scoped\n```\n\n## 用法\n\n### 方式一：编程式（vite 插件内部即用这个入口）\n\n```ts\nimport { transformScopedCss } from '@10coding/postcss-jsx-scoped'\n\n// 注意：输入必须是普通 CSS（scss/less 需先预处理，见下方「内联样式隔离」示例）\nconst css = await transformScopedCss(plainCss, 'data-v-3f2a9c1d', {\n  from: '/abs/path/to/file.css',\n})\n```\n\n### 方式二：作为 PostCSS 插件\n\n```js\nimport postcssJsxScoped from '@10coding/postcss-jsx-scoped'\n\npostcss([postcssJsxScoped({ scopeAttr: 'data-v-3f2a9c1d' })]).process(css)\n```\n\n### 方式三：多文件共用实例（resolveScope 模式）\n\n常用于把插件挂到 Vite 的 `css.postcss` 或全局 PostCSS 配置里，\n按 css 文件路径解析各自的 scope：\n\n```js\npostcssJsxScoped({\n  resolveScope: (from) =>\n    from?.endsWith('.scoped.css') ? scopeRegistry.get(from) : undefined,\n})\n```\n\n## 内联 `<style scoped>` 样式隔离（用法与示例）\n\n内联样式的隔离遵循与外部 `*.scoped.*` 完全相同的原则：\n**预处理器必须先编译成普通 CSS，再由本插件追加 `[data-v-{hash}]`，\n禁止直接改 scss/less 源码**。\n\n```tsx\n// 组件里（由 vite 插件提取）\nexport default function Demo() {\n  return (\n    <section className=\"demo\">\n      {/* lang 缺省 = css */}\n      <style scoped>{`.demo__tip { color: teal; }`}</style>\n\n      {/* 想要 scss 嵌套 / 变量，必须写 lang=\"scss\" */}\n      <style scoped lang=\"scss\">{`\n        .panel {\n          .panel__title { color: #4f46e5; font-weight: 700; }\n        }\n      `}</style>\n    </section>\n  )\n}\n```\n\n等价的手动流水线（不依赖 vite 插件，演示本包职责）：\n\n```ts\nimport { transformScopedCss } from '@10coding/postcss-jsx-scoped'\nimport { compileStringAsync } from 'sass'\n\n// 1) 提取到的内联 scss 文本（生产环境由 babel/vite 插件自动完成）\nconst rawScss = `.panel { .panel__title { color: #4f46e5; } }`\n// 2) 先编译成普通 CSS（原则：不直接改 scss 源码）\nconst { css } = await compileStringAsync(rawScss, { style: 'expanded' })\n// 3) 再追加 [data-v-{hash}]\nconst scopedCss = await transformScopedCss(css, 'data-v-3f2a9c1d')\n```\n\n结果：\n\n```css\n.panel[data-v-3f2a9c1d] { }\n.panel .panel__title[data-v-3f2a9c1d] { color: #4f46e5; }\n```\n\n### 内联样式隔离的完整链路（Vite 项目）\n\n1. vite 插件在组件 transform 阶段扫描 `<style scoped>`（属性名存在即开启；\n   `lang` 缺省按 css，`lang=\"scss\" | \"sass\" | \"less\"` 指定预处理器），\n   并把标签从 JSX 中移除，改写成虚拟 css 模块导入；\n2. 虚拟 css 模块 load 时：读取该内联块文本 → sass/less/css 编译为普通 CSS；\n3. 调用本包 `transformScopedCss(css, scopeAttr)` 追加 `[data-v-{hash}]`；\n4. 以普通 `.css` 模块交还 Vite css 管线（dev 注入 + HMR、build 抽取 css 产物）。\n\n> 同一组件可混用外部 `*.scoped.*` 与多个内联 `<style scoped>`，全部复用同一个\n> 由组件文件路径生成的 hash。重复调用本插件是安全的（幂等：已含同属性则跳过）。\n\n## 选择器宏（Vue 风格）\n\n在 scoped 样式里可以用两个函数式宏精确控制“哪一段不加 scope 属性”：\n\n```css\n/* :deep(...) —— 进入子组件作用域：本文件属性挂在左侧最后一个复合选择器上，\n   宏及其右侧不再追加（父组件样式借此命中子组件内部 DOM） */\n.parent :deep(.child) { color: red; }\n/* → .parent[data-v-x] .child */\n\n/* :global(...) —— 括号内跳出作用域，其余照常 */\n.card :global(.ant-btn) { color: red; }\n/* → .card[data-v-x] .ant-btn */\n```\n\n- `:deep(.b)` 无前缀写法 = `[data-v-x] .b`（收窄到本组件根）；\n- `:deep(.a, .b)` 多段参数会展开为多条选择器；\n- `:global(.b)` 无前缀且无后续选择器 = `.b`（纯全局规则）；\n- 只支持**函数式**写法；`>>>`、`/deep/`、`::v-deep`、无括号 `:deep .b` 等旧写法/别名\n  不再特殊处理（会按普通伪类/伪元素走常规追加逻辑）；\n- 含宏的规则处理后会插入一条 `/* jsx-scoped:{attr}:macro */` 注释用于幂等，压缩时会被移除。\n\n> 与组件 scoped（`scopedId`）的关系：`:deep(...)` 解决“父组件样式命中子组件内部\n> 任意后代”；`scopedId` 解决“子组件主动继承父作用域（含逐层绑定）”。两者互补。\n\n## scoped 动画名（@keyframes）\n\nscoped 作用域内的 `@keyframes` 名会追加 `-{scopeAttr}` 后缀（与 Vue scoped 一致），\n避免不同组件的同名动画互相覆盖，同时自动改写 `animation` / `animation-name` 引用：\n\n```css\n@keyframes spin { from { opacity: 0 } to { opacity: 1 } }\n.card { animation: spin 2.4s infinite; }\n/* → @keyframes spin-data-v-x { … }  /  .card[data-v-x] { animation: spin-data-v-x 2.4s infinite } */\n```\n\n不需要该行为时传 `scopeKeyframes: false` 关闭。注意：若动画名被 JS 内联样式引用，\n改名后需同步（与 Vue scoped 的限制一致）。\n\n## 规则\n\n- 只处理**普通规则**的选择器；选择器列表（逗号）逐段追加；\n- `@media / @supports / @layer / @container` 内部规则正常追加；\n- `@keyframes` 帧选择器（`from` / `to` / 百分比）、`@page` 不追加；`@keyframes` 名本身\n  会按上一节改写（可关闭）；\n- 选择器宏 `:deep(...)` / `:global(...)` 按上一节语义处理（仅函数式写法）；\n- 已含同 scope 属性时跳过（幂等，可重复执行）；\n- 伪元素（`::before` 等，含单冒号旧写法）保持在 `[data-v-*]` 之后；\n- 输入必须是普通 CSS：scss/less 请先预处理（见上方示例），\n  嵌套/变量等语法由预处理器负责展开，本插件不参与。\n\n## 开发\n\n```bash\npnpm --filter @10coding/postcss-jsx-scoped build   # tsup esm/cjs/dts\npnpm --filter @10coding/postcss-jsx-scoped test    # 冒烟验证\n```\n\nLicense: MIT\n","readmeFilename":""}