{"_id":"@data-mask/text-mask","_rev":"3-926d132fde68a15e95b07ff47d9f2ca0","name":"@data-mask/text-mask","dist-tags":{"latest":"1.3.2"},"versions":{"1.3.0":{"name":"@data-mask/text-mask","version":"1.3.0","keywords":[],"author":{"name":"mmj"},"license":"MIT","_id":"@data-mask/text-mask@1.3.0","maintainers":[{"name":"meji","email":"840719708@qq.com"}],"dist":{"shasum":"65bdd1b6d59ae9b77ada7f4510f3ed1249af21e7","tarball":"https://registry.npmjs.org/@data-mask/text-mask/-/text-mask-1.3.0.tgz","fileCount":51,"integrity":"sha512-uu4Rz9EgWDKcPeUzG7bjCRRzAhdMhaU7iiGhXiW2u8rYSUryXgtaXV6hbRdqphF1nYGh4IWKMAhOiyVtDuWGgw==","signatures":[{"sig":"MEUCIQCJsEGzAU6LVO3L2CAoaDKb7zbbFOlNZGIUfK35PwaxYgIgUvdp61TBetL3b0mIGEkXJQihLLzqGmgEKb/cQARWMw8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43796},"main":"./dist/cjs/index.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/es/index.js","scripts":{"dev":"vite","build":"vite build","ts:check":"vue-tsc -b --noEmit","publish:major":"pnpm build && npm version major && npm publish","publish:minor":"pnpm build && npm version minor && npm publish","publish:patch":"pnpm build && npm version patch && npm publish","publish:prerelease":"pnpm build && npm version prerelease --preid beta && npm publish --tag beta"},"_npmUser":{"name":"meji","email":"840719708@qq.com"},"_npmVersion":"10.9.2","description":"文本掩码库","directories":{},"_nodeVersion":"22.13.1","dependencies":{"@arco-design/web-vue":"~2.56.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.40","less":"^4.8.1","vite":"^6.4.3","terser":"^5.49.0","vue-tsc":"^3.3.9","crypto-js":"^4.2.0","@types/node":"^26.1.2","vite-plugin-dts":"^5.0.3","@types/crypto-js":"^4.2.2","@vitejs/plugin-vue":"^6.0.8","@vue/language-core":"^3.3.9","@typescript/typescript6":"^6.0.2","vite-plugin-lib-inject-css":"^2.2.2"},"_npmOperationalInternal":{"tmp":"tmp/text-mask_1.3.0_1785900531468_0.49709263387363856","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@data-mask/text-mask","version":"1.3.1","keywords":["@data-mask/text-mask","text-mask","脱敏"],"author":{"name":"mmj"},"license":"MIT","_id":"@data-mask/text-mask@1.3.1","maintainers":[{"name":"meji","email":"840719708@qq.com"}],"dist":{"shasum":"3272c3fa92378417382b55499de360a6648e80a9","tarball":"https://registry.npmjs.org/@data-mask/text-mask/-/text-mask-1.3.1.tgz","fileCount":51,"integrity":"sha512-PG8BMdyyqcy2TwMnSjdBOnMeRICFrbuvabkDUIVLcW2KzFXfOBVKE2T3gYsNL9aZ1YLJBuVNujLAjX87UC9vwQ==","signatures":[{"sig":"MEYCIQCi/AIRqqNpxLnKSaDzbmJQVOm5M6eIjPLsBqsNLNowhQIhANoxT5JqkelRMkCU4bSo5h2GlI0OqfU83GS16iN8giMJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43857},"main":"./dist/cjs/index.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/es/index.js","scripts":{"dev":"vite","build":"vite build","ts:check":"vue-tsc -b --noEmit","publish:major":"pnpm build && npm version major && npm publish","publish:minor":"pnpm build && npm version minor && npm publish","publish:patch":"pnpm build && npm version patch && npm publish","publish:prerelease":"pnpm build && npm version prerelease --preid beta && npm publish --tag beta"},"_npmUser":{"name":"meji","email":"840719708@qq.com"},"_npmVersion":"10.9.2","description":"文本掩码库","directories":{},"_nodeVersion":"22.13.1","dependencies":{"@arco-design/web-vue":"~2.56.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.40","less":"^4.8.1","vite":"^6.4.3","terser":"^5.49.0","vue-tsc":"^3.3.9","crypto-js":"^4.2.0","@types/node":"^26.1.2","vite-plugin-dts":"^5.0.3","@types/crypto-js":"^4.2.2","@vitejs/plugin-vue":"^6.0.8","@vue/language-core":"^3.3.9","@typescript/typescript6":"^6.0.2","vite-plugin-lib-inject-css":"^2.2.2"},"_npmOperationalInternal":{"tmp":"tmp/text-mask_1.3.1_1786417381684_0.3421398282720278","host":"s3://npm-registry-packages-npm-production"}},"1.3.2":{"name":"@data-mask/text-mask","version":"1.3.2","description":"文本掩码库","type":"module","main":"./dist/cjs/index.js","module":"./dist/es/index.js","types":"./dist/types/index.d.ts","scripts":{"build":"vite build","dev":"vite","ts:check":"vue-tsc -b --noEmit","publish:patch":"pnpm build && npm version patch && npm publish","publish:minor":"pnpm build && npm version minor && npm publish","publish:major":"pnpm build && npm version major && npm publish","publish:prerelease":"pnpm build && npm version prerelease --preid beta && npm publish --tag beta"},"keywords":["@data-mask/text-mask","text-mask","脱敏"],"author":{"name":"mmj"},"license":"MIT","devDependencies":{"@types/crypto-js":"^4.2.2","@types/node":"^26.1.2","@typescript/typescript6":"^6.0.2","@vitejs/plugin-vue":"^6.0.8","@vue/language-core":"^3.3.9","crypto-js":"^4.2.0","less":"^4.8.1","terser":"^5.49.0","vite":"^6.4.3","vite-plugin-dts":"^5.0.3","vite-plugin-lib-inject-css":"^2.2.2","vue":"^3.5.40","vue-tsc":"^3.3.9"},"dependencies":{"@arco-design/web-vue":"~2.56.2"},"publishConfig":{"access":"public"},"_id":"@data-mask/text-mask@1.3.2","_nodeVersion":"22.13.1","_npmVersion":"10.9.2","dist":{"integrity":"sha512-qBdWlreKn0sAVViS1+4QX7bpY9SjMa5ijGXSHM8i+Dp4OP43OWKv4lJJTJDaIcniqSgzEsJwkWOIy24RWJcSlA==","shasum":"bbc084615cd98afec94ce95914d21832d6b3d6e8","tarball":"https://registry.npmjs.org/@data-mask/text-mask/-/text-mask-1.3.2.tgz","fileCount":51,"unpackedSize":45350,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAxsCvDuZ5zqhpJi2fFOUGeCWlX+p2yHlRn6YSuhSwcGAiEAk77a01JgHZTKSf3tR2/yY37aT9+yeOygJQ8MqvKTx5E="}]},"_npmUser":{"name":"meji","email":"840719708@qq.com"},"directories":{},"maintainers":[{"name":"meji","email":"840719708@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/text-mask_1.3.2_1786690811451_0.9674850913313078"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-05T03:28:51.336Z","modified":"2026-08-14T07:00:11.778Z","1.3.0":"2026-08-05T03:28:51.597Z","1.3.1":"2026-08-11T03:03:01.845Z","1.3.2":"2026-08-14T07:00:11.582Z"},"author":{"name":"mmj"},"license":"MIT","keywords":["@data-mask/text-mask","text-mask","脱敏"],"description":"文本掩码库","maintainers":[{"name":"meji","email":"840719708@qq.com"}],"readme":"# @data-mask/text-mask\n\n文本掩码组件。默认展示脱敏文本，点击眼睛图标后展示原始文本；当启用内置 AES 插件时，展示原文前会先对 `value` 做 AES-CBC 解密。\n\n## 安装\n\n```bash\npnpm add @data-mask/text-mask\n```\n\n组件依赖 `vue`、`@arco-design/web-vue` 和 `crypto-js`(懒加载)，请确保业务项目中已经正确安装并配置。\n\n## 基础用法\n\n```vue\n<template>\n  <TextMask\n    value=\"13812345678\"\n    masked-value=\"138****5678\"\n    :default-plugin-names=\"[]\"\n  />\n</template>\n\n<script setup lang=\"ts\">\nimport { TextMask } from \"@data-mask/text-mask\";\n</script>\n```\n\n`value` 是展示原文时使用的值，`masked-value` 是隐藏状态下展示的值。`default-plugin-names` 为空时，组件只在 `value` 和 `maskedValue` 之间切换，不做额外处理。\n\n## AES 解密\n\n组件默认启用内置 `default-aes-filter`，点击展示原文时会把 `value` 当成 AES-CBC 密文解密。\n\n```vue\n<template>\n  <TextMask\n    value=\"AES_CBC_ENCRYPTED_TEXT\"\n    masked-value=\"138****5678\"\n    aes-key=\"xxx\"\n    aes-iv=\"xxx\"\n  />\n</template>\n\n<script setup lang=\"ts\">\nimport { TextMask, setAesKey, setAesIv } from \"@data-mask/text-mask\";\nconst AES_KEY = \"xxx\";\n// 和props 二选一，这里只需要全局设置一次\nsetAesKey(AES_KEY);\nsetAesIv(AES_KEY);\n</script>\n```\n\n如果不传 `aes-key` 和 `aes-iv`，组件会使用内置默认值。解密失败或解密结果为空时，会回退到当前值；因此明文值也可以在默认配置下使用，但如果确定不需要 AES 处理，建议显式设置 `:default-plugin-names=\"[]\"`。\n\n## 缓存解密结果\n\n`is-cache` 默认为 `false`。开启后，内置 AES 插件会以当前 `value` 为 key 缓存解密结果，后续展示同一密文时直接读取缓存。\n\n```vue\n<template>\n  <TextMask\n    value=\"AES_CBC_ENCRYPTED_TEXT\"\n    masked-value=\"138****5678\"\n    is-cache\n  />\n</template>\n```\n\n## 默认展示原文\n\n```vue\n<template>\n  <TextMask\n    value=\"13812345678\"\n    masked-value=\"138****5678\"\n    default-visible\n    :default-plugin-names=\"[]\"\n  />\n</template>\n```\n\n## 自定义图标\n\n`toggle` 插槽可以替换默认眼睛图标，插槽参数包含 `visible` 和 `loading`。\n\n```vue\n<template>\n  <TextMask value=\"13812345678\" masked-value=\"138****5678\">\n    <template #toggle=\"{ visible, loading }\">\n      <span>{{ loading ? \"...\" : visible ? \"隐藏\" : \"查看\" }}</span>\n    </template>\n  </TextMask>\n</template>\n```\n\n## 组件级 filter\n\n`filter` 用于追加当前组件的内容处理插件。组件会先执行 `default-plugin-names` 指定的内置插件，再按数组顺序执行 `filter`；前一个 filter 的返回值会作为后一个 filter 的入参。filter 支持同步或异步返回。\n\n```vue\n<template>\n  <TextMask\n    value=\"13812345678\"\n    masked-value=\"138****5678\"\n    :default-plugin-names=\"[]\"\n    :filter=\"[formatText]\"\n  />\n</template>\n\n<script setup lang=\"ts\">\nimport { TextMask, type TextMaskFilter } from \"@data-mask/text-mask\";\n\nconst formatText: TextMaskFilter = (value, visible) => {\n  if (!visible) {\n    return value;\n  }\n\n  return `手机号：${value}`;\n};\n</script>\n```\n\nfilter 也可以写成 plugin 对象：\n\n```ts\nimport type { TextMaskFilterPlugin } from \"@data-mask/text-mask\";\n\nconst permissionPlugin: TextMaskFilterPlugin = {\n  name: \"permission-filter\",\n  async filter(value, visible, props) {\n    if (!visible) {\n      return value;\n    }\n\n    const canView = await Promise.resolve(true);\n    return canView ? value : props.maskedValue;\n  },\n};\n```\n\n## 内置插件\n\n`DEFAULT_GLOBAL_FILTER_PLUGINS` 是内置插件对象，可以通过 `default-plugin-names` 选择组件启用哪些内置插件。\n\n```vue\n<template>\n  <TextMask\n    value=\"AES_CBC_ENCRYPTED_TEXT\"\n    masked-value=\"138****5678\"\n    :default-plugin-names=\"['default-aes-filter']\"\n  />\n</template>\n```\n\n当前内置插件：\n\n| 名称 | 说明 |\n| --- | --- |\n| `default-aes-filter` | 展示原文时使用 `aesKey` 和 `aesIv` 对当前值做 AES-CBC 解密；隐藏状态直接返回当前值 |\n| `default-mask` | 隐藏状态下对当前值做脱敏，展示原文时直接返回当前值 |\n\n`defaultMaskPlugin` 的脱敏规则：\n\n| 输入 | 输出 |\n| --- | --- |\n| `lucy` | `l**y` |\n| `13112342187` | `131****2187` |\n| `hello` | `h***o` |\n\n## 全局 filter API\n\n包内仍保留全局 filter API，适合在业务侧统一维护一组插件，并通过 `getGlobalFilter()` 或 `runFilterPlugins()` 手动复用。注意：当前 `TextMask` 组件不会自动读取 `setGlobalFilterPlugins()` 设置的全局插件；组件内置插件请使用 `default-plugin-names` 控制，组件级插件请使用 `filter` 传入。\n\n```ts\nimport {\n  addGlobalFilterPlugin,\n  getGlobalFilter,\n  resetGlobalFilterPlugins,\n  setGlobalFilterPlugins,\n} from \"@data-mask/text-mask\";\n\nsetGlobalFilterPlugins([\n  {\n    name: \"permission-filter\",\n    async filter(value, visible, props) {\n      if (!visible) {\n        return value;\n      }\n\n      const canView = await Promise.resolve(true);\n      return canView ? value : props.maskedValue;\n    },\n  },\n]);\n\naddGlobalFilterPlugin((value) => value);\n\nconst filter = getGlobalFilter();\nconst result = await filter(\"13812345678\", true, {});\n\nresetGlobalFilterPlugins();\n```\n\n旧的 `setGlobalFilter(filter)` 仍可使用，等价于 `setGlobalFilterPlugins([filter])`。\n\n## 全局注册\n\n```ts\nimport { createApp } from \"vue\";\nimport * as TextMaskPlugin from \"@data-mask/text-mask\";\nimport App from \"./App.vue\";\n\nconst app = createApp(App);\n\napp.use(TextMaskPlugin);\napp.mount(\"#app\");\n```\n\n注册后可直接在模板中使用：\n\n```vue\n<template>\n  <TextMask\n    value=\"6222020202020202020\"\n    masked-value=\"6222 **** **** 2020\"\n    :default-plugin-names=\"[]\"\n  />\n</template>\n```\n\n## 缓存方法\n\n```ts\nimport {\n  TextMaskCache,\n  clearTextMaskCache,\n  getTextMaskCacheValue,\n  setTextMaskCacheValue,\n} from \"@data-mask/text-mask\";\n\nsetTextMaskCacheValue(\"phone:1\", \"13812345678\");\n\nconst value = getTextMaskCacheValue(\"phone:1\");\n\nTextMaskCache.delete(\"phone:1\");\nclearTextMaskCache();\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `value` | `string \\| number` | `\"\"` | 原始文本；展示原文状态下使用 |\n| `maskedValue` | `string \\| number` | `\"******\"` | 脱敏文本；隐藏状态下使用，模板中使用 `masked-value` |\n| `defaultVisible` | `boolean` | `false` | 是否默认展示原文，模板中使用 `default-visible` |\n| `aesKey` | `string` | 内置默认 AES key | AES-CBC 解密密钥，模板中使用 `aes-key` |\n| `aesIv` | `string` | 内置默认 AES iv | AES-CBC 解密向量，模板中使用 `aes-iv` |\n| `isCache` | `boolean` | `false` | 是否缓存内置 AES 插件的解密结果，模板中使用 `is-cache` |\n| `filter` | `TextMaskFilterPluginInput[]` | `[]` | 当前组件的内容处理插件 |\n| `defaultPluginNames` | `Array<'default-aes-filter' \\| 'default-mask'>` | `['default-aes-filter']` | 当前组件启用的内置插件名称，模板中使用 `default-plugin-names` |\n\n## 导出 API\n\n```ts\nimport {\n  TextMask,\n  DEFAULT_GLOBAL_FILTER_PLUGINS,\n  defaultAesFilterPlugin,\n  defaultMaskPlugin,\n  setGlobalFilterPlugins,\n  addGlobalFilterPlugin,\n  getGlobalFilterPlugins,\n  resetGlobalFilterPlugins,\n  setGlobalFilter,\n  getGlobalFilter,\n  runFilterPlugins,\n  TextMaskCache,\n  setTextMaskCacheValue,\n  getTextMaskCacheValue,\n  clearTextMaskCache,\n} from \"@data-mask/text-mask\";\n```\n\n| API | 说明 |\n| --- | --- |\n| `TextMask` | 文本掩码组件 |\n| `DEFAULT_GLOBAL_FILTER_PLUGINS` | 内置插件对象 |\n| `defaultAesFilterPlugin` | 内置 AES-CBC 解密 plugin |\n| `defaultMaskPlugin` | 内置脱敏 plugin |\n| `setGlobalFilterPlugins(plugins)` | 覆盖全局内容处理 plugins |\n| `addGlobalFilterPlugin(plugin)` | 追加全局内容处理 plugin；如果 plugin 有 `name`，会替换同名 plugin |\n| `getGlobalFilterPlugins()` | 获取当前全局内容处理 plugins |\n| `resetGlobalFilterPlugins()` | 清空全局内容处理 plugins |\n| `setGlobalFilter(filter)` | 兼容旧 API，等价于 `setGlobalFilterPlugins([filter])` |\n| `getGlobalFilter()` | 获取按当前全局 plugins 串行执行的 filter |\n| `runFilterPlugins(value, visible, props, plugins?)` | 串行执行指定 plugins |\n| `TextMaskCache` | 全局缓存 Map |\n| `setTextMaskCacheValue(key, value)` | 写入缓存 |\n| `getTextMaskCacheValue(key)` | 读取缓存；不存在时返回 `null` |\n| `clearTextMaskCache()` | 清空所有缓存 |\n","readmeFilename":"README.md"}