@cloudcome/utils-browser 1.2.13 → 1.2.14

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/README.md CHANGED
@@ -5,14 +5,120 @@
5
5
  [![Codacy Badge](https://app.codacy.com/project/badge/Grade/4fa1acaeb717469caddfe21a84c50bb2)](https://app.codacy.com/gh/cloudcome/utils/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
6
6
  [![Codacy Badge](https://app.codacy.com/project/badge/Coverage/4fa1acaeb717469caddfe21a84c50bb2)](https://app.codacy.com/gh/cloudcome/utils/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
7
7
 
8
+ 跨平台、多框架的 TypeScript 工具函数库,覆盖浏览器、Node.js、Vue、React、UniApp 等环境。
9
+
10
+ ## 包列表
8
11
 
9
12
  | 名称 | 版本 | 描述 |
10
13
  | --- | --- | --- |
11
- | @cloudcome/utils-core | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-core.svg)](https://npmjs.com/package/@cloudcome/utils-core) | 核心工具库 |
12
- | @cloudcome/utils-browser | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-browser.svg)](https://npmjs.com/package/@cloudcome/utils-browser) | 浏览器工具库 |
13
- | @cloudcome/utils-node| [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-node.svg)](https://npmjs.com/package/@cloudcome/utils-node) | Node.js 工具库 |
14
- | @cloudcome/utils-vue| [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-vue.svg)](https://npmjs.com/package/@cloudcome/utils-vue) | Vue 工具库 |
15
- | @cloudcome/utils-react| [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-react.svg)](https://npmjs.com/package/@cloudcome/utils-react) | React 工具库 |
16
- | @cloudcome/utils-uni| [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-uni.svg)](https://npmjs.com/package/@cloudcome/utils-uni) | UniApp 工具库 |
14
+ | [@cloudcome/utils-core](./packages/utils-core) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-core.svg)](https://npmjs.com/package/@cloudcome/utils-core) | 核心工具库,与运行环境无关的通用工具 |
15
+ | [@cloudcome/utils-browser](./packages/utils-browser) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-browser.svg)](https://npmjs.com/package/@cloudcome/utils-browser) | 浏览器端工具(DOM、Canvas、Cookie、剪贴板等) |
16
+ | [@cloudcome/utils-node](./packages/utils-node) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-node.svg)](https://npmjs.com/package/@cloudcome/utils-node) | Node.js 端工具(Base64、加密等) |
17
+ | [@cloudcome/utils-vue](./packages/utils-vue) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-vue.svg)](https://npmjs.com/package/@cloudcome/utils-vue) | Vue 3 工具库(组合式函数、组件、请求等) |
18
+ | [@cloudcome/utils-react](./packages/utils-react) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-react.svg)](https://npmjs.com/package/@cloudcome/utils-react) | React 工具库 |
19
+ | [@cloudcome/utils-uni](./packages/utils-uni) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-uni.svg)](https://npmjs.com/package/@cloudcome/utils-uni) | UniApp 工具库(云函数、数据库、页面等) |
20
+ | [@cloudcome/docs](./packages/docs) | - | VitePress 文档站点 |
21
+
22
+ ## 功能概览
23
+
24
+ ### @cloudcome/utils-core
25
+
26
+ 核心工具库,提供以下子模块:
27
+
28
+ | 子模块 | 导入路径 | 功能 |
29
+ | --- | --- | --- |
30
+ | array | `@cloudcome/utils-core/array` | 数组操作 |
31
+ | async | `@cloudcome/utils-core/async` | 异步工具 |
32
+ | base64 | `@cloudcome/utils-core/base64` | Base64 编解码 |
33
+ | cache | `@cloudcome/utils-core/cache` | 缓存工具 |
34
+ | color | `@cloudcome/utils-core/color` | 颜色转换(RGB/HSL/HSV/HWB/LAB/XYZ)、对比度、亮度、混合 |
35
+ | crypto | `@cloudcome/utils-core/crypto` | 加密(MD5、SHA1、SHA256、SHA512) |
36
+ | date | `@cloudcome/utils-core/date` | 日期解析、格式化、时区、相对时间、周/天计算 |
37
+ | dict | `@cloudcome/utils-core/dict` | 字典/映射工具 |
38
+ | easing | `@cloudcome/utils-core/easing` | 缓动函数 |
39
+ | emitter | `@cloudcome/utils-core/emitter` | 事件发射器 |
40
+ | env | `@cloudcome/utils-core/env` | 环境检测 |
41
+ | error | `@cloudcome/utils-core/error` | 错误处理 |
42
+ | exception | `@cloudcome/utils-core/exception` | 异常处理 |
43
+ | function | `@cloudcome/utils-core/function` | 函数工具 |
44
+ | number | `@cloudcome/utils-core/number` | 数字工具 |
45
+ | object | `@cloudcome/utils-core/object` | 对象遍历、深层 get/set、合并、类型判断 |
46
+ | path | `@cloudcome/utils-core/path` | 路径工具 |
47
+ | promise | `@cloudcome/utils-core/promise` | Promise 工具 |
48
+ | qs | `@cloudcome/utils-core/qs` | 查询字符串解析与序列化 |
49
+ | regexp | `@cloudcome/utils-core/regexp` | 正则表达式工具 |
50
+ | string | `@cloudcome/utils-core/string` | 字符串工具 |
51
+ | time | `@cloudcome/utils-core/time` | 时间单位转换 |
52
+ | timer | `@cloudcome/utils-core/timer` | 定时器工具 |
53
+ | tree | `@cloudcome/utils-core/tree` | 树结构操作 |
54
+ | try | `@cloudcome/utils-core/try` | 安全调用(try-catch 包装,支持同步/异步/柯里化) |
55
+ | type | `@cloudcome/utils-core/type` | 类型判断 |
56
+ | types | `@cloudcome/utils-core/types` | 公共类型定义 |
57
+ | unique | `@cloudcome/utils-core/unique` | 唯一 ID 生成 |
58
+ | url | `@cloudcome/utils-core/url` | URL 解析与构建 |
59
+ | version | `@cloudcome/utils-core/version` | 版本号比较 |
60
+
61
+ ### @cloudcome/utils-browser
62
+
63
+ 浏览器端工具库,依赖 `@cloudcome/utils-core`:
64
+
65
+ | 子模块 | 导入路径 | 功能 |
66
+ | --- | --- | --- |
67
+ | base64 | `@cloudcome/utils-browser/base64` | 浏览器端 Base64 编解码 |
68
+ | cache | `@cloudcome/utils-browser/cache` | 浏览器缓存(localStorage/sessionStorage) |
69
+ | canvas | `@cloudcome/utils-browser/canvas` | Canvas 操作 |
70
+ | clipboard | `@cloudcome/utils-browser/clipboard` | 剪贴板读写 |
71
+ | cookie | `@cloudcome/utils-browser/cookie` | Cookie 读写 |
72
+ | dom | `@cloudcome/utils-browser/dom` | DOM 操作 |
73
+ | download | `@cloudcome/utils-browser/download` | 文件下载 |
74
+ | image | `@cloudcome/utils-browser/image` | 图片处理 |
75
+ | timer | `@cloudcome/utils-browser/timer` | 浏览器端定时器 |
76
+ | video | `@cloudcome/utils-browser/video` | 视频处理 |
77
+
78
+ ### @cloudcome/utils-node
79
+
80
+ Node.js 端工具库:
81
+
82
+ | 子模块 | 导入路径 | 功能 |
83
+ | --- | --- | --- |
84
+ | base64 | `@cloudcome/utils-node/base64` | Node.js 端 Base64 编解码 |
85
+ | crypto | `@cloudcome/utils-node/crypto` | Node.js 端加密工具 |
86
+
87
+ ### @cloudcome/utils-vue
88
+
89
+ Vue 3 工具库,依赖 `@cloudcome/utils-core` 和 `vue`:
90
+
91
+ | 子模块 | 导入路径 | 功能 |
92
+ | --- | --- | --- |
93
+ | async | `@cloudcome/utils-vue/async` | Vue 异步组合式函数 |
94
+ | component | `@cloudcome/utils-vue/component` | 组件工具(生命周期等) |
95
+ | event | `@cloudcome/utils-vue/event` | 事件工具 |
96
+ | request | `@cloudcome/utils-vue/request` | 请求组合式函数(useRequest) |
97
+ | shared | `@cloudcome/utils-vue/shared` | 共享工具 |
98
+ | state | `@cloudcome/utils-vue/state` | 状态管理工具 |
99
+ | time | `@cloudcome/utils-vue/time` | 时间相关组合式函数 |
100
+ | types | `@cloudcome/utils-vue/types` | 类型定义 |
101
+
102
+ ### @cloudcome/utils-react
103
+
104
+ React 工具库。
105
+
106
+ ### @cloudcome/utils-uni
107
+
108
+ UniApp 工具库,依赖 `@cloudcome/utils-core`、`@cloudcome/utils-vue`:
109
+
110
+ | 子模块 | 导入路径 | 功能 |
111
+ | --- | --- | --- |
112
+ | app | `@cloudcome/utils-uni/app` | App 相关工具 |
113
+ | client | `@cloudcome/utils-uni/client` | 客户端工具 |
114
+ | cloud | `@cloudcome/utils-uni/cloud` | 云函数工具(调用、错误处理、uni-id 等) |
115
+ | database | `@cloudcome/utils-uni/database` | 数据库操作(CRUD、事务、分页、upsert 等) |
116
+ | page | `@cloudcome/utils-uni/page` | 页面相关工具 |
117
+
118
+ ## 开发
119
+
120
+ 详见 [DEVELOPMENT.md](./DEVELOPMENT.md)。
17
121
 
122
+ ## 许可
18
123
 
124
+ [MIT](LICENSE)
@@ -9,8 +9,11 @@ function copyText(text) {
9
9
  document.body.appendChild(textArea);
10
10
  textArea.focus();
11
11
  textArea.select();
12
- document.execCommand("copy");
13
- document.body.removeChild(textArea);
12
+ try {
13
+ document.execCommand("copy");
14
+ } finally {
15
+ document.body.removeChild(textArea);
16
+ }
14
17
  }
15
18
  exports.copyText = copyText;
16
19
  //# sourceMappingURL=clipboard.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard.cjs","sources":["../src/clipboard.ts"],"sourcesContent":["/**\n * 将文本复制到剪贴板\n * 该方法使用传统的 execCommand 方法实现文本复制\n *\n * @param text - 要复制到剪贴板的文本内容\n * @returns void\n *\n * @example\n * // 基本用法\n * await copyText('Hello World');\n *\n * @example\n * // 处理复制结果\n * copyText('Hello World')\n * .then(() => console.log('复制成功'))\n * .catch(() => console.error('复制失败'));\n */\nexport function copyText(text: string) {\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-9999px';\n textArea.style.top = '-9999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n document.execCommand('copy');\n document.body.removeChild(textArea);\n}\n"],"names":[],"mappings":";;AAiBO,SAAS,SAAS,MAAc;AAC/B,QAAA,WAAW,SAAS,cAAc,UAAU;AAClD,WAAS,QAAQ;AACjB,WAAS,MAAM,WAAW;AAC1B,WAAS,MAAM,OAAO;AACtB,WAAS,MAAM,MAAM;AACZ,WAAA,KAAK,YAAY,QAAQ;AAClC,WAAS,MAAM;AACf,WAAS,OAAO;AAChB,WAAS,YAAY,MAAM;AAClB,WAAA,KAAK,YAAY,QAAQ;AACpC;;"}
1
+ {"version":3,"file":"clipboard.cjs","sources":["../src/clipboard.ts"],"sourcesContent":["/**\n * 将文本复制到剪贴板\n * 该方法使用传统的 execCommand 方法实现文本复制\n *\n * @param text - 要复制到剪贴板的文本内容\n * @returns void\n *\n * @example\n * // 基本用法\n * await copyText('Hello World');\n *\n * @example\n * // 处理复制结果\n * copyText('Hello World')\n * .then(() => console.log('复制成功'))\n * .catch(() => console.error('复制失败'));\n */\nexport function copyText(text: string) {\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-9999px';\n textArea.style.top = '-9999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n try {\n document.execCommand('copy');\n } finally {\n document.body.removeChild(textArea);\n }\n}\n"],"names":[],"mappings":";;AAiBO,SAAS,SAAS,MAAc;AAC/B,QAAA,WAAW,SAAS,cAAc,UAAU;AAClD,WAAS,QAAQ;AACjB,WAAS,MAAM,WAAW;AAC1B,WAAS,MAAM,OAAO;AACtB,WAAS,MAAM,MAAM;AACZ,WAAA,KAAK,YAAY,QAAQ;AAClC,WAAS,MAAM;AACf,WAAS,OAAO;AACZ,MAAA;AACF,aAAS,YAAY,MAAM;AAAA,EAAA,UAC3B;AACS,aAAA,KAAK,YAAY,QAAQ;AAAA,EAAA;AAEtC;;"}
@@ -7,8 +7,11 @@ function copyText(text) {
7
7
  document.body.appendChild(textArea);
8
8
  textArea.focus();
9
9
  textArea.select();
10
- document.execCommand("copy");
11
- document.body.removeChild(textArea);
10
+ try {
11
+ document.execCommand("copy");
12
+ } finally {
13
+ document.body.removeChild(textArea);
14
+ }
12
15
  }
13
16
  export {
14
17
  copyText
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard.mjs","sources":["../src/clipboard.ts"],"sourcesContent":["/**\n * 将文本复制到剪贴板\n * 该方法使用传统的 execCommand 方法实现文本复制\n *\n * @param text - 要复制到剪贴板的文本内容\n * @returns void\n *\n * @example\n * // 基本用法\n * await copyText('Hello World');\n *\n * @example\n * // 处理复制结果\n * copyText('Hello World')\n * .then(() => console.log('复制成功'))\n * .catch(() => console.error('复制失败'));\n */\nexport function copyText(text: string) {\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-9999px';\n textArea.style.top = '-9999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n document.execCommand('copy');\n document.body.removeChild(textArea);\n}\n"],"names":[],"mappings":"AAiBO,SAAS,SAAS,MAAc;AAC/B,QAAA,WAAW,SAAS,cAAc,UAAU;AAClD,WAAS,QAAQ;AACjB,WAAS,MAAM,WAAW;AAC1B,WAAS,MAAM,OAAO;AACtB,WAAS,MAAM,MAAM;AACZ,WAAA,KAAK,YAAY,QAAQ;AAClC,WAAS,MAAM;AACf,WAAS,OAAO;AAChB,WAAS,YAAY,MAAM;AAClB,WAAA,KAAK,YAAY,QAAQ;AACpC;"}
1
+ {"version":3,"file":"clipboard.mjs","sources":["../src/clipboard.ts"],"sourcesContent":["/**\n * 将文本复制到剪贴板\n * 该方法使用传统的 execCommand 方法实现文本复制\n *\n * @param text - 要复制到剪贴板的文本内容\n * @returns void\n *\n * @example\n * // 基本用法\n * await copyText('Hello World');\n *\n * @example\n * // 处理复制结果\n * copyText('Hello World')\n * .then(() => console.log('复制成功'))\n * .catch(() => console.error('复制失败'));\n */\nexport function copyText(text: string) {\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-9999px';\n textArea.style.top = '-9999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n try {\n document.execCommand('copy');\n } finally {\n document.body.removeChild(textArea);\n }\n}\n"],"names":[],"mappings":"AAiBO,SAAS,SAAS,MAAc;AAC/B,QAAA,WAAW,SAAS,cAAc,UAAU;AAClD,WAAS,QAAQ;AACjB,WAAS,MAAM,WAAW;AAC1B,WAAS,MAAM,OAAO;AACtB,WAAS,MAAM,MAAM;AACZ,WAAA,KAAK,YAAY,QAAQ;AAClC,WAAS,MAAM;AACf,WAAS,OAAO;AACZ,MAAA;AACF,aAAS,YAAY,MAAM;AAAA,EAAA,UAC3B;AACS,aAAA,KAAK,YAAY,QAAQ;AAAA,EAAA;AAEtC;"}
package/dist/cookie.cjs CHANGED
@@ -6,15 +6,19 @@ function cookieGet(name) {
6
6
  for (let i = 0; i < cookies.length; i++) {
7
7
  const cookie = cookies[i].trim();
8
8
  if (cookie.startsWith(`${name}=`)) {
9
- return decodeURIComponent(cookie.slice(name.length + 1));
9
+ try {
10
+ return decodeURIComponent(cookie.slice(name.length + 1));
11
+ } catch {
12
+ return cookie.slice(name.length + 1);
13
+ }
10
14
  }
11
15
  }
12
16
  return "";
13
17
  }
14
18
  function cookieSet(name, value, options) {
15
- const { expires, maxAge, path, domain, httpOnly, sameSite, secure } = options || {};
19
+ const { expires, maxAge, path, domain, sameSite, secure } = options || {};
16
20
  let cookie = `${name}=${encodeURIComponent(value)}`;
17
- const expiresAt = expires ? date.dateParse(expires) : maxAge ? date.dateParse(Date.now() + maxAge) : null;
21
+ const expiresAt = expires ? date.dateParse(expires) : maxAge ? date.dateParse(Date.now() + maxAge * 1e3) : null;
18
22
  const metas = [];
19
23
  if (expiresAt) {
20
24
  metas.push(["expires", expiresAt.toISOString()]);
@@ -25,9 +29,6 @@ function cookieSet(name, value, options) {
25
29
  if (domain) {
26
30
  metas.push(["domain", domain]);
27
31
  }
28
- if (httpOnly) {
29
- metas.push(["httpOnly", "true"]);
30
- }
31
32
  if (sameSite) {
32
33
  metas.push(["sameSite", sameSite]);
33
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cookie.cjs","sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n return decodeURIComponent(cookie.slice(name.length + 1));\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * 是否启用 HttpOnly 标志,防止 JavaScript 访问。\n */\n httpOnly?: boolean;\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(name: string, value: string, options?: CookieOptions) {\n const { expires, maxAge, path, domain, httpOnly, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge) : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (httpOnly) {\n metas.push(['httpOnly', 'true']);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"names":["dateParse","value"],"mappings":";;;AAQO,SAAS,UAAU,MAAc;AACtC,QAAM,UAAU,SAAS,OAAO,MAAM,GAAG;AAEzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC,EAAE,KAAK;AAE/B,QAAI,OAAO,WAAW,GAAG,IAAI,GAAG,GAAG;AACjC,aAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC;AAAA,IAAA;AAAA,EACzD;AAGK,SAAA;AACT;AAmDgB,SAAA,UAAU,MAAc,OAAe,SAAyB;AACxE,QAAA,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,UAAU,WAAW,WAAW,CAAC;AAClF,MAAI,SAAS,GAAG,IAAI,IAAI,mBAAmB,KAAK,CAAC;AAE3C,QAAA,YAAY,UAAUA,KAAA,UAAU,OAAO,IAAI,SAASA,KAAA,UAAU,KAAK,QAAQ,MAAM,IAAI;AAC3F,QAAM,QAA4B,CAAC;AAEnC,MAAI,WAAW;AACb,UAAM,KAAK,CAAC,WAAW,UAAU,YAAa,CAAA,CAAC;AAAA,EAAA;AAGjD,MAAI,MAAM;AACR,UAAM,KAAK,CAAC,QAAQ,IAAI,CAAC;AAAA,EAAA;AAG3B,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,MAAI,UAAU;AACZ,UAAM,KAAK,CAAC,YAAY,MAAM,CAAC;AAAA,EAAA;AAGjC,MAAI,UAAU;AACZ,UAAM,KAAK,CAAC,YAAY,QAAQ,CAAC;AAAA,EAAA;AAGnC,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,aAAW,CAAC,KAAKC,MAAK,KAAK,OAAO;AACtB,cAAA,KAAK,GAAG,IAAIA,MAAK;AAAA,EAAA;AAG7B,WAAS,SAAS;AACpB;AAMO,SAAS,UAAU,MAAc;AACtC,YAAU,MAAM,IAAI;AAAA,IAClB,SAAS;AAAA,EAAA,CACV;AACH;;;;"}
1
+ {"version":3,"file":"cookie.cjs","sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n try {\n return decodeURIComponent(cookie.slice(name.length + 1));\n } catch {\n return cookie.slice(name.length + 1);\n }\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(name: string, value: string, options?: CookieOptions) {\n const { expires, maxAge, path, domain, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge * 1000) : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"names":["dateParse","value"],"mappings":";;;AAQO,SAAS,UAAU,MAAc;AACtC,QAAM,UAAU,SAAS,OAAO,MAAM,GAAG;AAEzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC,EAAE,KAAK;AAE/B,QAAI,OAAO,WAAW,GAAG,IAAI,GAAG,GAAG;AAC7B,UAAA;AACF,eAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC;AAAA,MAAA,QACjD;AACN,eAAO,OAAO,MAAM,KAAK,SAAS,CAAC;AAAA,MAAA;AAAA,IACrC;AAAA,EACF;AAGK,SAAA;AACT;AA8CgB,SAAA,UAAU,MAAc,OAAe,SAAyB;AACxE,QAAA,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,WAAW,WAAW,CAAC;AACxE,MAAI,SAAS,GAAG,IAAI,IAAI,mBAAmB,KAAK,CAAC;AAEjD,QAAM,YAAY,UAAUA,eAAU,OAAO,IAAI,SAASA,eAAU,KAAK,IAAI,IAAI,SAAS,GAAI,IAAI;AAClG,QAAM,QAA4B,CAAC;AAEnC,MAAI,WAAW;AACb,UAAM,KAAK,CAAC,WAAW,UAAU,YAAa,CAAA,CAAC;AAAA,EAAA;AAGjD,MAAI,MAAM;AACR,UAAM,KAAK,CAAC,QAAQ,IAAI,CAAC;AAAA,EAAA;AAG3B,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,MAAI,UAAU;AACZ,UAAM,KAAK,CAAC,YAAY,QAAQ,CAAC;AAAA,EAAA;AAGnC,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,aAAW,CAAC,KAAKC,MAAK,KAAK,OAAO;AACtB,cAAA,KAAK,GAAG,IAAIA,MAAK;AAAA,EAAA;AAG7B,WAAS,SAAS;AACpB;AAMO,SAAS,UAAU,MAAc;AACtC,YAAU,MAAM,IAAI;AAAA,IAClB,SAAS;AAAA,EAAA,CACV;AACH;;;;"}
package/dist/cookie.d.ts CHANGED
@@ -32,10 +32,6 @@ export type CookieOptions = {
32
32
  * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。
33
33
  */
34
34
  sameSite?: 'strict' | 'lax' | 'none';
35
- /**
36
- * 是否启用 HttpOnly 标志,防止 JavaScript 访问。
37
- */
38
- httpOnly?: boolean;
39
35
  /**
40
36
  * Cookie 的最大存活时间(秒)。
41
37
  */
package/dist/cookie.mjs CHANGED
@@ -4,15 +4,19 @@ function cookieGet(name) {
4
4
  for (let i = 0; i < cookies.length; i++) {
5
5
  const cookie = cookies[i].trim();
6
6
  if (cookie.startsWith(`${name}=`)) {
7
- return decodeURIComponent(cookie.slice(name.length + 1));
7
+ try {
8
+ return decodeURIComponent(cookie.slice(name.length + 1));
9
+ } catch {
10
+ return cookie.slice(name.length + 1);
11
+ }
8
12
  }
9
13
  }
10
14
  return "";
11
15
  }
12
16
  function cookieSet(name, value, options) {
13
- const { expires, maxAge, path, domain, httpOnly, sameSite, secure } = options || {};
17
+ const { expires, maxAge, path, domain, sameSite, secure } = options || {};
14
18
  let cookie = `${name}=${encodeURIComponent(value)}`;
15
- const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge) : null;
19
+ const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge * 1e3) : null;
16
20
  const metas = [];
17
21
  if (expiresAt) {
18
22
  metas.push(["expires", expiresAt.toISOString()]);
@@ -23,9 +27,6 @@ function cookieSet(name, value, options) {
23
27
  if (domain) {
24
28
  metas.push(["domain", domain]);
25
29
  }
26
- if (httpOnly) {
27
- metas.push(["httpOnly", "true"]);
28
- }
29
30
  if (sameSite) {
30
31
  metas.push(["sameSite", sameSite]);
31
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cookie.mjs","sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n return decodeURIComponent(cookie.slice(name.length + 1));\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * 是否启用 HttpOnly 标志,防止 JavaScript 访问。\n */\n httpOnly?: boolean;\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(name: string, value: string, options?: CookieOptions) {\n const { expires, maxAge, path, domain, httpOnly, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge) : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (httpOnly) {\n metas.push(['httpOnly', 'true']);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"names":["value"],"mappings":";AAQO,SAAS,UAAU,MAAc;AACtC,QAAM,UAAU,SAAS,OAAO,MAAM,GAAG;AAEzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC,EAAE,KAAK;AAE/B,QAAI,OAAO,WAAW,GAAG,IAAI,GAAG,GAAG;AACjC,aAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC;AAAA,IAAA;AAAA,EACzD;AAGK,SAAA;AACT;AAmDgB,SAAA,UAAU,MAAc,OAAe,SAAyB;AACxE,QAAA,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,UAAU,WAAW,WAAW,CAAC;AAClF,MAAI,SAAS,GAAG,IAAI,IAAI,mBAAmB,KAAK,CAAC;AAE3C,QAAA,YAAY,UAAU,UAAU,OAAO,IAAI,SAAS,UAAU,KAAK,QAAQ,MAAM,IAAI;AAC3F,QAAM,QAA4B,CAAC;AAEnC,MAAI,WAAW;AACb,UAAM,KAAK,CAAC,WAAW,UAAU,YAAa,CAAA,CAAC;AAAA,EAAA;AAGjD,MAAI,MAAM;AACR,UAAM,KAAK,CAAC,QAAQ,IAAI,CAAC;AAAA,EAAA;AAG3B,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,MAAI,UAAU;AACZ,UAAM,KAAK,CAAC,YAAY,MAAM,CAAC;AAAA,EAAA;AAGjC,MAAI,UAAU;AACZ,UAAM,KAAK,CAAC,YAAY,QAAQ,CAAC;AAAA,EAAA;AAGnC,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,aAAW,CAAC,KAAKA,MAAK,KAAK,OAAO;AACtB,cAAA,KAAK,GAAG,IAAIA,MAAK;AAAA,EAAA;AAG7B,WAAS,SAAS;AACpB;AAMO,SAAS,UAAU,MAAc;AACtC,YAAU,MAAM,IAAI;AAAA,IAClB,SAAS;AAAA,EAAA,CACV;AACH;"}
1
+ {"version":3,"file":"cookie.mjs","sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n try {\n return decodeURIComponent(cookie.slice(name.length + 1));\n } catch {\n return cookie.slice(name.length + 1);\n }\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(name: string, value: string, options?: CookieOptions) {\n const { expires, maxAge, path, domain, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge * 1000) : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"names":["value"],"mappings":";AAQO,SAAS,UAAU,MAAc;AACtC,QAAM,UAAU,SAAS,OAAO,MAAM,GAAG;AAEzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC,EAAE,KAAK;AAE/B,QAAI,OAAO,WAAW,GAAG,IAAI,GAAG,GAAG;AAC7B,UAAA;AACF,eAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC;AAAA,MAAA,QACjD;AACN,eAAO,OAAO,MAAM,KAAK,SAAS,CAAC;AAAA,MAAA;AAAA,IACrC;AAAA,EACF;AAGK,SAAA;AACT;AA8CgB,SAAA,UAAU,MAAc,OAAe,SAAyB;AACxE,QAAA,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,WAAW,WAAW,CAAC;AACxE,MAAI,SAAS,GAAG,IAAI,IAAI,mBAAmB,KAAK,CAAC;AAEjD,QAAM,YAAY,UAAU,UAAU,OAAO,IAAI,SAAS,UAAU,KAAK,IAAI,IAAI,SAAS,GAAI,IAAI;AAClG,QAAM,QAA4B,CAAC;AAEnC,MAAI,WAAW;AACb,UAAM,KAAK,CAAC,WAAW,UAAU,YAAa,CAAA,CAAC;AAAA,EAAA;AAGjD,MAAI,MAAM;AACR,UAAM,KAAK,CAAC,QAAQ,IAAI,CAAC;AAAA,EAAA;AAG3B,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,MAAI,UAAU;AACZ,UAAM,KAAK,CAAC,YAAY,QAAQ,CAAC;AAAA,EAAA;AAGnC,MAAI,QAAQ;AACV,UAAM,KAAK,CAAC,UAAU,MAAM,CAAC;AAAA,EAAA;AAG/B,aAAW,CAAC,KAAKA,MAAK,KAAK,OAAO;AACtB,cAAA,KAAK,GAAG,IAAIA,MAAK;AAAA,EAAA;AAG7B,WAAS,SAAS;AACpB;AAMO,SAAS,UAAU,MAAc;AACtC,YAAU,MAAM,IAAI;AAAA,IAClB,SAAS;AAAA,EAAA,CACV;AACH;"}
package/dist/download.cjs CHANGED
@@ -8,8 +8,11 @@ function downloadURL(url, filename) {
8
8
  }
9
9
  function downloadBlob(blob, filename) {
10
10
  const url = URL.createObjectURL(blob);
11
- downloadURL(url, filename);
12
- URL.revokeObjectURL(url);
11
+ try {
12
+ downloadURL(url, filename);
13
+ } finally {
14
+ URL.revokeObjectURL(url);
15
+ }
13
16
  }
14
17
  exports.downloadBlob = downloadBlob;
15
18
  exports.downloadURL = downloadURL;
@@ -1 +1 @@
1
- {"version":3,"file":"download.cjs","sources":["../src/download.ts"],"sourcesContent":["/**\n * 下载 URL\n * @param {string} url\n * @param {string} filename\n */\nexport function downloadURL(url: string, filename?: string) {\n const a = document.createElement('a');\n a.href = url;\n a.download = filename || '';\n a.click();\n}\n\n/**\n * 下载 Blob 对象\n * @param blob Blob 对象\n * @param filename 文件名\n */\nexport function downloadBlob(blob: Blob, filename?: string) {\n const url = URL.createObjectURL(blob);\n downloadURL(url, filename);\n URL.revokeObjectURL(url);\n}\n"],"names":[],"mappings":";;AAKgB,SAAA,YAAY,KAAa,UAAmB;AACpD,QAAA,IAAI,SAAS,cAAc,GAAG;AACpC,IAAE,OAAO;AACT,IAAE,WAAW,YAAY;AACzB,IAAE,MAAM;AACV;AAOgB,SAAA,aAAa,MAAY,UAAmB;AACpD,QAAA,MAAM,IAAI,gBAAgB,IAAI;AACpC,cAAY,KAAK,QAAQ;AACzB,MAAI,gBAAgB,GAAG;AACzB;;;"}
1
+ {"version":3,"file":"download.cjs","sources":["../src/download.ts"],"sourcesContent":["/**\n * 下载 URL\n * @param {string} url\n * @param {string} filename\n */\nexport function downloadURL(url: string, filename?: string) {\n const a = document.createElement('a');\n a.href = url;\n a.download = filename || '';\n a.click();\n}\n\n/**\n * 下载 Blob 对象\n * @param blob Blob 对象\n * @param filename 文件名\n */\nexport function downloadBlob(blob: Blob, filename?: string) {\n const url = URL.createObjectURL(blob);\n try {\n downloadURL(url, filename);\n } finally {\n URL.revokeObjectURL(url);\n }\n}\n"],"names":[],"mappings":";;AAKgB,SAAA,YAAY,KAAa,UAAmB;AACpD,QAAA,IAAI,SAAS,cAAc,GAAG;AACpC,IAAE,OAAO;AACT,IAAE,WAAW,YAAY;AACzB,IAAE,MAAM;AACV;AAOgB,SAAA,aAAa,MAAY,UAAmB;AACpD,QAAA,MAAM,IAAI,gBAAgB,IAAI;AAChC,MAAA;AACF,gBAAY,KAAK,QAAQ;AAAA,EAAA,UACzB;AACA,QAAI,gBAAgB,GAAG;AAAA,EAAA;AAE3B;;;"}
package/dist/download.mjs CHANGED
@@ -6,8 +6,11 @@ function downloadURL(url, filename) {
6
6
  }
7
7
  function downloadBlob(blob, filename) {
8
8
  const url = URL.createObjectURL(blob);
9
- downloadURL(url, filename);
10
- URL.revokeObjectURL(url);
9
+ try {
10
+ downloadURL(url, filename);
11
+ } finally {
12
+ URL.revokeObjectURL(url);
13
+ }
11
14
  }
12
15
  export {
13
16
  downloadBlob,
@@ -1 +1 @@
1
- {"version":3,"file":"download.mjs","sources":["../src/download.ts"],"sourcesContent":["/**\n * 下载 URL\n * @param {string} url\n * @param {string} filename\n */\nexport function downloadURL(url: string, filename?: string) {\n const a = document.createElement('a');\n a.href = url;\n a.download = filename || '';\n a.click();\n}\n\n/**\n * 下载 Blob 对象\n * @param blob Blob 对象\n * @param filename 文件名\n */\nexport function downloadBlob(blob: Blob, filename?: string) {\n const url = URL.createObjectURL(blob);\n downloadURL(url, filename);\n URL.revokeObjectURL(url);\n}\n"],"names":[],"mappings":"AAKgB,SAAA,YAAY,KAAa,UAAmB;AACpD,QAAA,IAAI,SAAS,cAAc,GAAG;AACpC,IAAE,OAAO;AACT,IAAE,WAAW,YAAY;AACzB,IAAE,MAAM;AACV;AAOgB,SAAA,aAAa,MAAY,UAAmB;AACpD,QAAA,MAAM,IAAI,gBAAgB,IAAI;AACpC,cAAY,KAAK,QAAQ;AACzB,MAAI,gBAAgB,GAAG;AACzB;"}
1
+ {"version":3,"file":"download.mjs","sources":["../src/download.ts"],"sourcesContent":["/**\n * 下载 URL\n * @param {string} url\n * @param {string} filename\n */\nexport function downloadURL(url: string, filename?: string) {\n const a = document.createElement('a');\n a.href = url;\n a.download = filename || '';\n a.click();\n}\n\n/**\n * 下载 Blob 对象\n * @param blob Blob 对象\n * @param filename 文件名\n */\nexport function downloadBlob(blob: Blob, filename?: string) {\n const url = URL.createObjectURL(blob);\n try {\n downloadURL(url, filename);\n } finally {\n URL.revokeObjectURL(url);\n }\n}\n"],"names":[],"mappings":"AAKgB,SAAA,YAAY,KAAa,UAAmB;AACpD,QAAA,IAAI,SAAS,cAAc,GAAG;AACpC,IAAE,OAAO;AACT,IAAE,WAAW,YAAY;AACzB,IAAE,MAAM;AACV;AAOgB,SAAA,aAAa,MAAY,UAAmB;AACpD,QAAA,MAAM,IAAI,gBAAgB,IAAI;AAChC,MAAA;AACF,gBAAY,KAAK,QAAQ;AAAA,EAAA,UACzB;AACA,QAAI,gBAAgB,GAAG;AAAA,EAAA;AAE3B;"}
package/dist/image.cjs CHANGED
@@ -4,7 +4,10 @@ const dom = require("./dom.cjs");
4
4
  async function imageLoad(url) {
5
5
  return new Promise((resolve, reject) => {
6
6
  const image = new Image();
7
+ let finished = false;
7
8
  const onFinish = (isError) => {
9
+ if (finished) return;
10
+ finished = true;
8
11
  image.onload = image.onerror = null;
9
12
  document.body.removeChild(image);
10
13
  isError ? reject(new Error("图片加载失败")) : resolve(image);
@@ -1 +1 @@
1
- {"version":3,"file":"image.cjs","sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n const onFinish = (isError?: boolean) => {\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n isError ? reject(new Error('图片加载失败')) : resolve(image);\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"names":["setStyle"],"mappings":";;;AAUA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,IAAI,MAAM;AAClB,UAAA,WAAW,CAAC,YAAsB;AAChC,YAAA,SAAS,MAAM,UAAU;AACtB,eAAA,KAAK,YAAY,KAAK;AAC/B,gBAAU,OAAO,IAAI,MAAM,QAAQ,CAAC,IAAI,QAAQ,KAAK;AAAA,IACvD;AACM,UAAA,SAAS,MAAM,SAAS;AACxB,UAAA,UAAU,MAAM,SAAS,IAAI;AACnC,UAAM,cAAc;AACpB,UAAM,MAAM;AAGZA,QAAAA,SAAS,OAAO;AAAA,MACd,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,IAAA,CACZ;AACQ,aAAA,KAAK,YAAY,KAAK;AAE/B,QAAI,MAAM,YAAY,MAAM,QAAQ,EAAY,UAAA;AAAA,EAAA,CACjD;AACH;;"}
1
+ {"version":3,"file":"image.cjs","sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n let finished = false;\n const onFinish = (isError?: boolean) => {\n if (finished) return;\n finished = true;\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n isError ? reject(new Error('图片加载失败')) : resolve(image);\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"names":["setStyle"],"mappings":";;;AAUA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,IAAI,MAAM;AACxB,QAAI,WAAW;AACT,UAAA,WAAW,CAAC,YAAsB;AACtC,UAAI,SAAU;AACH,iBAAA;AACL,YAAA,SAAS,MAAM,UAAU;AACtB,eAAA,KAAK,YAAY,KAAK;AAC/B,gBAAU,OAAO,IAAI,MAAM,QAAQ,CAAC,IAAI,QAAQ,KAAK;AAAA,IACvD;AACM,UAAA,SAAS,MAAM,SAAS;AACxB,UAAA,UAAU,MAAM,SAAS,IAAI;AACnC,UAAM,cAAc;AACpB,UAAM,MAAM;AAGZA,QAAAA,SAAS,OAAO;AAAA,MACd,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,IAAA,CACZ;AACQ,aAAA,KAAK,YAAY,KAAK;AAE/B,QAAI,MAAM,YAAY,MAAM,QAAQ,EAAY,UAAA;AAAA,EAAA,CACjD;AACH;;"}
package/dist/image.mjs CHANGED
@@ -2,7 +2,10 @@ import { setStyle } from "./dom.mjs";
2
2
  async function imageLoad(url) {
3
3
  return new Promise((resolve, reject) => {
4
4
  const image = new Image();
5
+ let finished = false;
5
6
  const onFinish = (isError) => {
7
+ if (finished) return;
8
+ finished = true;
6
9
  image.onload = image.onerror = null;
7
10
  document.body.removeChild(image);
8
11
  isError ? reject(new Error("图片加载失败")) : resolve(image);
@@ -1 +1 @@
1
- {"version":3,"file":"image.mjs","sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n const onFinish = (isError?: boolean) => {\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n isError ? reject(new Error('图片加载失败')) : resolve(image);\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"names":[],"mappings":";AAUA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,IAAI,MAAM;AAClB,UAAA,WAAW,CAAC,YAAsB;AAChC,YAAA,SAAS,MAAM,UAAU;AACtB,eAAA,KAAK,YAAY,KAAK;AAC/B,gBAAU,OAAO,IAAI,MAAM,QAAQ,CAAC,IAAI,QAAQ,KAAK;AAAA,IACvD;AACM,UAAA,SAAS,MAAM,SAAS;AACxB,UAAA,UAAU,MAAM,SAAS,IAAI;AACnC,UAAM,cAAc;AACpB,UAAM,MAAM;AAGZ,aAAS,OAAO;AAAA,MACd,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,IAAA,CACZ;AACQ,aAAA,KAAK,YAAY,KAAK;AAE/B,QAAI,MAAM,YAAY,MAAM,QAAQ,EAAY,UAAA;AAAA,EAAA,CACjD;AACH;"}
1
+ {"version":3,"file":"image.mjs","sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n let finished = false;\n const onFinish = (isError?: boolean) => {\n if (finished) return;\n finished = true;\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n isError ? reject(new Error('图片加载失败')) : resolve(image);\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"names":[],"mappings":";AAUA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,IAAI,MAAM;AACxB,QAAI,WAAW;AACT,UAAA,WAAW,CAAC,YAAsB;AACtC,UAAI,SAAU;AACH,iBAAA;AACL,YAAA,SAAS,MAAM,UAAU;AACtB,eAAA,KAAK,YAAY,KAAK;AAC/B,gBAAU,OAAO,IAAI,MAAM,QAAQ,CAAC,IAAI,QAAQ,KAAK;AAAA,IACvD;AACM,UAAA,SAAS,MAAM,SAAS;AACxB,UAAA,UAAU,MAAM,SAAS,IAAI;AACnC,UAAM,cAAc;AACpB,UAAM,MAAM;AAGZ,aAAS,OAAO;AAAA,MACd,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,IAAA,CACZ;AACQ,aAAA,KAAK,YAAY,KAAK;AAE/B,QAAI,MAAM,YAAY,MAAM,QAAQ,EAAY,UAAA;AAAA,EAAA,CACjD;AACH;"}
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const VERSION = "1.2.12";
3
+ const VERSION = "1.2.13";
4
4
  exports.VERSION = VERSION;
5
5
  //# sourceMappingURL=index.cjs.map
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- const VERSION = "1.2.12";
1
+ const VERSION = "1.2.13";
2
2
  export {
3
3
  VERSION
4
4
  };
package/dist/video.cjs CHANGED
@@ -3,11 +3,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  async function videoLoad(url) {
4
4
  return new Promise((resolve, reject) => {
5
5
  const video = document.createElement("video");
6
+ const onFinish = (isError) => {
7
+ video.onload = video.onerror = null;
8
+ isError ? reject(new Error("视频加载失败")) : resolve(video);
9
+ };
6
10
  video.src = url;
7
11
  video.crossOrigin = "anonymous";
8
12
  video.currentTime = 1;
9
- video.onloadedmetadata = () => resolve(video);
10
- video.onerror = () => reject(new Error("视频加载失败"));
13
+ video.onloadedmetadata = () => onFinish();
14
+ video.onerror = () => onFinish(true);
11
15
  });
12
16
  }
13
17
  exports.videoLoad = videoLoad;
@@ -1 +1 @@
1
- {"version":3,"file":"video.cjs","sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => resolve(video);\n video.onerror = () => reject(new Error('视频加载失败'));\n });\n}\n"],"names":[],"mappings":";;AAQA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,SAAS,cAAc,OAAO;AAE5C,UAAM,MAAM;AACZ,UAAM,cAAc;AACpB,UAAM,cAAc;AACd,UAAA,mBAAmB,MAAM,QAAQ,KAAK;AAC5C,UAAM,UAAU,MAAM,OAAO,IAAI,MAAM,QAAQ,CAAC;AAAA,EAAA,CACjD;AACH;;"}
1
+ {"version":3,"file":"video.cjs","sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n const onFinish = (isError?: boolean) => {\n video.onload = video.onerror = null;\n isError ? reject(new Error('视频加载失败')) : resolve(video);\n };\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => onFinish();\n video.onerror = () => onFinish(true);\n });\n}\n"],"names":[],"mappings":";;AAQA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,SAAS,cAAc,OAAO;AACtC,UAAA,WAAW,CAAC,YAAsB;AAChC,YAAA,SAAS,MAAM,UAAU;AAC/B,gBAAU,OAAO,IAAI,MAAM,QAAQ,CAAC,IAAI,QAAQ,KAAK;AAAA,IACvD;AAEA,UAAM,MAAM;AACZ,UAAM,cAAc;AACpB,UAAM,cAAc;AACd,UAAA,mBAAmB,MAAM,SAAS;AAClC,UAAA,UAAU,MAAM,SAAS,IAAI;AAAA,EAAA,CACpC;AACH;;"}
package/dist/video.mjs CHANGED
@@ -1,11 +1,15 @@
1
1
  async function videoLoad(url) {
2
2
  return new Promise((resolve, reject) => {
3
3
  const video = document.createElement("video");
4
+ const onFinish = (isError) => {
5
+ video.onload = video.onerror = null;
6
+ isError ? reject(new Error("视频加载失败")) : resolve(video);
7
+ };
4
8
  video.src = url;
5
9
  video.crossOrigin = "anonymous";
6
10
  video.currentTime = 1;
7
- video.onloadedmetadata = () => resolve(video);
8
- video.onerror = () => reject(new Error("视频加载失败"));
11
+ video.onloadedmetadata = () => onFinish();
12
+ video.onerror = () => onFinish(true);
9
13
  });
10
14
  }
11
15
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"video.mjs","sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => resolve(video);\n video.onerror = () => reject(new Error('视频加载失败'));\n });\n}\n"],"names":[],"mappings":"AAQA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,SAAS,cAAc,OAAO;AAE5C,UAAM,MAAM;AACZ,UAAM,cAAc;AACpB,UAAM,cAAc;AACd,UAAA,mBAAmB,MAAM,QAAQ,KAAK;AAC5C,UAAM,UAAU,MAAM,OAAO,IAAI,MAAM,QAAQ,CAAC;AAAA,EAAA,CACjD;AACH;"}
1
+ {"version":3,"file":"video.mjs","sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n const onFinish = (isError?: boolean) => {\n video.onload = video.onerror = null;\n isError ? reject(new Error('视频加载失败')) : resolve(video);\n };\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => onFinish();\n video.onerror = () => onFinish(true);\n });\n}\n"],"names":[],"mappings":"AAQA,eAAsB,UAAU,KAAa;AAC3C,SAAO,IAAI,QAA0B,CAAC,SAAS,WAAW;AAClD,UAAA,QAAQ,SAAS,cAAc,OAAO;AACtC,UAAA,WAAW,CAAC,YAAsB;AAChC,YAAA,SAAS,MAAM,UAAU;AAC/B,gBAAU,OAAO,IAAI,MAAM,QAAQ,CAAC,IAAI,QAAQ,KAAK;AAAA,IACvD;AAEA,UAAM,MAAM;AACZ,UAAM,cAAc;AACpB,UAAM,cAAc;AACd,UAAA,mBAAmB,MAAM,SAAS;AAClC,UAAA,UAAU,MAAM,SAAS,IAAI;AAAA,EAAA,CACpC;AACH;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcome/utils-browser",
3
- "version": "1.2.13",
3
+ "version": "1.2.14",
4
4
  "description": "cloudcome utils for browser",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -106,7 +106,7 @@
106
106
  "dist"
107
107
  ],
108
108
  "dependencies": {
109
- "@cloudcome/utils-core": "~1.18.1"
109
+ "@cloudcome/utils-core": "~1.18.2"
110
110
  },
111
111
  "repository": {
112
112
  "type": "git",