vite-add-cdn-script 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
package/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
package/README.md CHANGED
@@ -1,89 +1,88 @@
1
- # vite-add-cdn-script
2
-
3
- 这是一个在 vite.js 中使用公共 cdn 的库,包括了 unpkg, jsdelivr 等多个 cdn 资源,如加载失败会自动切换下一个 cdn 进行加载。
4
-
5
- ## 开始
6
-
7
- ### 安装
8
-
9
- ```
10
- pnpm install vite-add-cdn-script rollup-plugin-external-globals -D
11
- ```
12
-
13
- ### 使用
14
-
15
- vite.config.ts
16
-
17
- ```typescript
18
- import { defineConfig } from "vite";
19
- import react from "@vitejs/plugin-react";
20
- import viteAddCdnScript from "vite-add-cdn-script";
21
- import externalGlobals from "rollup-plugin-external-globals";
22
-
23
- // 需要使用cdn库,按顺序添加,如react-router-dom需要依赖react、@remix-run/router、react-router,因此需要放在最后
24
- const externals = {
25
- react: "React",
26
- "react-dom": "ReactDOM",
27
- "@remix-run/router": "@remix-run/router",
28
- "react-router": "react-router",
29
- "react-router-dom": "ReactRouterDOM",
30
- };
31
-
32
- export default defineConfig({
33
- plugins: [react(), viteAddCdnScript({})],
34
- build: {
35
- rollupOptions: {
36
- external: [...Object.keys(externals)],
37
- plugins: [externalGlobals(externals)],
38
- },
39
- },
40
- });
41
- ```
42
-
43
- 使用自定义的 cdn
44
-
45
- ```typescript
46
- import { defineConfig } from "vite";
47
- import react from "@vitejs/plugin-react";
48
- import viteAddCdnScript from "../vite-add-cdn-script/lib/main";
49
- import externalGlobals from "rollup-plugin-external-globals";
50
-
51
- // 需要使用cdn的模块,会按顺序插入脚本,如
52
- const externals = {
53
- react: "React",
54
- "react-dom": "ReactDOM",
55
- };
56
-
57
- export default defineConfig({
58
- plugins: [
59
- react(),
60
- viteAddCdnScript({
61
- customScript: {
62
- react: "<script src='https://cdn.jsdelivr.net/npm/react@17.0.2/umd/react.production.min.js'></script>",
63
- "react-dom":
64
- "<script src='https://cdn.jsdelivr.net/npm/react-dom@17.0.2/umd/react-dom.production.min.js'></script>",
65
- },
66
- }),
67
- ],
68
- base: "./",
69
- build: {
70
- rollupOptions: {
71
- external: [...Object.keys(externals)],
72
- plugins: [externalGlobals(externals)],
73
- },
74
- },
75
- });
76
- ```
77
-
78
- options
79
-
80
- | 参数 | 解析 | 类型 | 默认值 |
81
- | ------------ | ------------------- | --------------------------- | --------------------------------------- |
82
- | customScript | 自定义 cdn 脚本 | { [*key*: string]: string } | 无 |
83
- | retryTimes | 换源重试次数 | number | defaultCdns.length - 1 |
84
- | defaultCdns | 默认使用 cdn 的顺序 | string[] | ["jsdelivr", "unpkg"] |
85
-
86
- ## 注意事项
87
-
88
- - 接入了各大 cdn api 接口进行请求,默认会保存一份 cdn 的缓存在你的根目录中`.cdn-cache.json`。如果发现缓存的资源有问题可以删除该文件,然后重新执行打包流程。
89
- - 按顺序添加 cdn,如 react-router-dom 需要依赖 react、@remix-run/router、react-router,因此需要放在最后。
1
+ # vite-add-cdn-script
2
+
3
+ 这是一个在 vite.js 中使用公共 cdn 的库,包括了 unpkg, jsdelivr 等多个 cdn 资源,如加载失败会自动切换下一个 cdn 进行加载。
4
+
5
+ ## 开始
6
+
7
+ ### 安装
8
+
9
+ ```
10
+ pnpm install vite-add-cdn-script rollup-plugin-external-globals -D
11
+ ```
12
+
13
+ ### 使用
14
+
15
+ vite.config.ts
16
+
17
+ ```typescript
18
+ import { defineConfig } from "vite";
19
+ import react from "@vitejs/plugin-react";
20
+ import viteAddCdnScript from "vite-add-cdn-script";
21
+ import externalGlobals from "rollup-plugin-external-globals";
22
+
23
+ // 需要使用cdn库,按顺序添加,如react-router-dom需要依赖react、@remix-run/router、react-router,因此需要放在最后
24
+ const externals = {
25
+ react: "React",
26
+ "react-dom": "ReactDOM",
27
+ "@remix-run/router": "@remix-run/router",
28
+ "react-router": "react-router",
29
+ "react-router-dom": "ReactRouterDOM",
30
+ };
31
+
32
+ export default defineConfig({
33
+ plugins: [react(), viteAddCdnScript({})],
34
+ build: {
35
+ rollupOptions: {
36
+ external: [...Object.keys(externals)],
37
+ plugins: [externalGlobals(externals)],
38
+ },
39
+ },
40
+ });
41
+ ```
42
+
43
+ 使用自定义的 cdn
44
+
45
+ ```typescript
46
+ import { defineConfig } from "vite";
47
+ import react from "@vitejs/plugin-react";
48
+ import viteAddCdnScript from "../vite-add-cdn-script/lib/main";
49
+ import externalGlobals from "rollup-plugin-external-globals";
50
+
51
+ // 需要使用cdn的模块,会按顺序插入脚本,如
52
+ const externals = {
53
+ react: "React",
54
+ "react-dom": "ReactDOM",
55
+ };
56
+
57
+ export default defineConfig({
58
+ plugins: [
59
+ react(),
60
+ viteAddCdnScript({
61
+ customScript: {
62
+ react: "<script src='https://cdn.jsdelivr.net/npm/react@17.0.2/umd/react.production.min.js'></script>",
63
+ "react-dom":
64
+ "<script src='https://cdn.jsdelivr.net/npm/react-dom@17.0.2/umd/react-dom.production.min.js'></script>",
65
+ },
66
+ }),
67
+ ],
68
+ base: "./",
69
+ build: {
70
+ rollupOptions: {
71
+ external: [...Object.keys(externals)],
72
+ plugins: [externalGlobals(externals)],
73
+ },
74
+ },
75
+ });
76
+ ```
77
+
78
+ options
79
+
80
+ | 参数 | 解析 | 类型 | 默认值 |
81
+ | ------------ | ------------------- | --------------------------- | --------------------- |
82
+ | customScript | 自定义 cdn 脚本 | { [*key*: string]: string } | 无 |
83
+ | defaultCdns | 默认使用 cdn 的顺序 | string[] | ["jsdelivr", "unpkg"] |
84
+
85
+ ## 注意事项
86
+
87
+ - 接入了各大 cdn 的 api 接口进行请求,默认会保存一份 cdn 的缓存在你的根目录中`.cdn-cache.json`。如果发现缓存的资源有问题可以删除该文件,然后重新执行打包流程。
88
+ - 按顺序添加 cdn,如 react-router-dom 需要依赖 react、@remix-run/router、react-router,因此需要放在最后。
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
- var G = Object.defineProperty;
2
- var B = (r, t, e) => t in r ? G(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
- var m = (r, t, e) => (B(r, typeof t != "symbol" ? t + "" : t, e), e);
4
- import O from "node:path";
5
- import U from "node:fs";
6
- import V from "node-fetch";
7
- import J from "semver";
8
- class z {
1
+ var q = Object.defineProperty;
2
+ var G = (r, t, e) => t in r ? q(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
+ var g = (r, t, e) => (G(r, typeof t != "symbol" ? t + "" : t, e), e);
4
+ import A from "node:path";
5
+ import E from "node:fs";
6
+ import O from "node-fetch";
7
+ import V from "semver";
8
+ class B {
9
9
  constructor() {
10
- m(this, "cdnCache", {});
11
- m(this, "cdnCachePath", "");
12
- this.cdnCachePath = O.resolve(process.cwd(), "./.cdn-cache.json");
10
+ g(this, "cdnCache", {});
11
+ g(this, "cdnCachePath", "");
12
+ this.cdnCachePath = A.resolve(process.cwd(), "./.cdn-cache.json");
13
13
  }
14
14
  // 初始化cdn缓存
15
15
  async init() {
16
16
  try {
17
- const t = await U.readFileSync(this.cdnCachePath, "utf-8");
17
+ const t = await E.readFileSync(this.cdnCachePath, "utf-8");
18
18
  this.cdnCache = JSON.parse(t);
19
19
  } catch {
20
- console.log("cdn缓存文件不存在,创建缓存文件"), this.cdnCache = {}, await U.writeFileSync(this.cdnCachePath, "", "utf-8");
20
+ console.log("cdn缓存文件不存在,创建缓存文件"), this.cdnCache = {}, await E.writeFileSync(this.cdnCachePath, "", "utf-8");
21
21
  }
22
22
  }
23
23
  /**
@@ -44,36 +44,36 @@ class z {
44
44
  * 更新cdn缓存
45
45
  */
46
46
  async save() {
47
- await U.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
47
+ await E.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
48
48
  }
49
49
  }
50
- let b;
51
- const K = async () => (b || (b = new z(), await b.init()), b);
50
+ let U;
51
+ const z = async () => (U || (U = new B(), await U.init()), U);
52
52
  class u extends Error {
53
53
  constructor(t) {
54
54
  super(t), this.name = "NetworkError";
55
55
  }
56
56
  }
57
- class C extends u {
57
+ class P extends u {
58
58
  constructor({ packageName: t, version: e, cdn: s }) {
59
59
  super(`${s} ${t}@${e} 网络请求失败`), this.name = "PackageNetworkError";
60
60
  }
61
61
  }
62
- class $ extends Error {
62
+ class m extends Error {
63
63
  constructor({ packageName: t, version: e, cdn: s }) {
64
64
  super(`${s}上没有${t}@${e}的版本`), this.name = "NoVersionError";
65
65
  }
66
66
  }
67
- class W extends Error {
67
+ class K extends Error {
68
68
  constructor({ packageName: t, version: e, cdn: s }) {
69
69
  super(`在 ${s} 中找不到 ${t}@${e} 文件,请检查包名或版本号`), this.name = "GetFileListError";
70
70
  }
71
71
  }
72
- class X {
72
+ class N {
73
73
  constructor(t) {
74
- m(this, "_max");
75
- m(this, "_count");
76
- m(this, "_taskQueue");
74
+ g(this, "_max");
75
+ g(this, "_count");
76
+ g(this, "_taskQueue");
77
77
  this._max = t || 5, this._count = 0, this._taskQueue = [];
78
78
  }
79
79
  /**
@@ -105,18 +105,18 @@ class X {
105
105
  };
106
106
  }
107
107
  }
108
- const D = new X(5), M = async (r) => {
108
+ const _ = new N(5), J = async (r) => {
109
109
  try {
110
- const t = await V(r, { method: "HEAD", redirect: "manual" });
111
- return t.status >= 300 && t.status < 400 ? await M(t.headers.get("location") || "") : r;
110
+ const t = await O(r, { method: "HEAD", redirect: "manual" });
111
+ return t.status >= 300 && t.status < 400 ? await J(t.headers.get("location") || "") : r;
112
112
  } catch (t) {
113
113
  throw Promise.reject(new u(t.message));
114
114
  }
115
- }, Y = {
115
+ }, W = {
116
116
  //get请求封装
117
117
  get: async (r) => {
118
118
  try {
119
- const t = await V(r);
119
+ const t = await O(r);
120
120
  if (t.ok) {
121
121
  const e = t.headers.get("content-type"), s = await t.text();
122
122
  return e && e.includes("application/json") ? JSON.parse(s) : s;
@@ -126,23 +126,23 @@ const D = new X(5), M = async (r) => {
126
126
  throw new u(t.message);
127
127
  }
128
128
  }
129
- }, y = {
130
- get: D.call.bind(D, Y.get)
131
- }, Z = async (r, t) => {
129
+ }, $ = {
130
+ get: _.call.bind(_, W.get)
131
+ }, X = async (r, t) => {
132
132
  try {
133
- const e = await y.get(`https://api.bootcdn.cn/libraries/${r}`);
133
+ const e = await $.get(`https://api.bootcdn.cn/libraries/${r}`);
134
134
  if (e.length === 0)
135
- throw new $({
135
+ throw new m({
136
136
  packageName: r,
137
137
  version: t,
138
138
  cdn: "bootcdn"
139
139
  });
140
140
  const s = e[0], o = s.assets.reverse().find((c) => {
141
- if (J.satisfies(c.version, t))
141
+ if (V.satisfies(c.version, t))
142
142
  return !0;
143
143
  });
144
144
  if (!o)
145
- throw new $({
145
+ throw new m({
146
146
  packageName: r,
147
147
  version: t,
148
148
  cdn: "bootcdn"
@@ -151,32 +151,32 @@ const D = new X(5), M = async (r) => {
151
151
  name: "/" + c
152
152
  })), recommendFileName: s.filename, version: o.version };
153
153
  } catch (e) {
154
- throw e instanceof u ? new C({
154
+ throw e instanceof u ? new P({
155
155
  packageName: r,
156
156
  version: t,
157
157
  cdn: "unpkg"
158
158
  }) : e;
159
159
  }
160
- }, N = (r, t, e) => `https://cdn.bootcdn.net/ajax/libs/${r}/${t}${e}`, tt = {
161
- getFileList: Z,
162
- getUrl: N
160
+ }, Y = (r, t, e) => `https://cdn.bootcdn.net/ajax/libs/${r}/${t}${e}`, Z = {
161
+ getFileList: X,
162
+ getUrl: Y
163
163
  };
164
- async function I(r, t, e = !1) {
164
+ async function M(r, t, e = !1) {
165
165
  try {
166
166
  if (!e && t.match(/^\D/)) {
167
- const n = await rt(r, t);
167
+ const n = await et(r, t);
168
168
  for (let o of n)
169
- if (J.satisfies(o, t))
170
- return I(r, o, !0);
171
- throw new $({
169
+ if (V.satisfies(o, t))
170
+ return M(r, o, !0);
171
+ throw new m({
172
172
  packageName: r,
173
173
  version: t,
174
174
  cdn: "cdnjs"
175
175
  });
176
176
  }
177
- const s = await y.get(`https://api.cdnjs.com/libraries/${r}/${t}`);
177
+ const s = await $.get(`https://api.cdnjs.com/libraries/${r}/${t}`);
178
178
  if (s.error)
179
- throw new $({
179
+ throw new m({
180
180
  packageName: r,
181
181
  version: t,
182
182
  cdn: "cdnjs"
@@ -188,62 +188,62 @@ async function I(r, t, e = !1) {
188
188
  version: t
189
189
  };
190
190
  } catch (s) {
191
- throw s instanceof u ? new C({
191
+ throw s instanceof u ? new P({
192
192
  packageName: r,
193
193
  version: t,
194
194
  cdn: "unpkg"
195
195
  }) : s;
196
196
  }
197
197
  }
198
- const et = (r, t, e) => `https://cdnjs.cloudflare.com/ajax/libs/${r}/${t}${e}`, rt = async (r, t) => {
198
+ const tt = (r, t, e) => `https://cdnjs.cloudflare.com/ajax/libs/${r}/${t}${e}`, et = async (r, t) => {
199
199
  try {
200
- return (await y.get(`https://api.cdnjs.com/libraries/${r}?fields=versions`)).versions;
200
+ return (await $.get(`https://api.cdnjs.com/libraries/${r}?fields=versions`)).versions;
201
201
  } catch (e) {
202
- throw e instanceof u ? new C({
202
+ throw e instanceof u ? new P({
203
203
  packageName: r,
204
204
  version: t,
205
205
  cdn: "unpkg"
206
206
  }) : e;
207
207
  }
208
- }, st = {
209
- getFileList: I,
210
- getUrl: et
211
- }, T = (r, t = "") => r.reduce((e, s) => (s.type === "file" ? e.push({ name: `${t}/${s.name}` }) : s.files && e.push(...T(s.files, `${t}/${s.name}`)), e), []);
208
+ }, rt = {
209
+ getFileList: M,
210
+ getUrl: tt
211
+ }, I = (r, t = "") => r.reduce((e, s) => (s.type === "file" ? e.push({ name: `${t}/${s.name}` }) : s.files && e.push(...I(s.files, `${t}/${s.name}`)), e), []);
212
212
  async function Q(r, t, e = !1) {
213
213
  try {
214
214
  if (!e && t.match(/^\D/)) {
215
- const n = await ot(r, t);
215
+ const n = await nt(r, t);
216
216
  if (typeof n == "string")
217
217
  return Q(r, n, !0);
218
- throw new $({
218
+ throw new m({
219
219
  packageName: r,
220
220
  version: t,
221
221
  cdn: "jsdelivr"
222
222
  });
223
223
  }
224
- const s = await y.get(`https://data.jsdelivr.com/v1/packages/npm/${r}@${t}`);
224
+ const s = await $.get(`https://data.jsdelivr.com/v1/packages/npm/${r}@${t}`);
225
225
  if (s.status)
226
- throw new $({
226
+ throw new m({
227
227
  packageName: r,
228
228
  version: t,
229
229
  cdn: "jsdelivr"
230
230
  });
231
- return { fileList: T(s.files), version: t };
231
+ return { fileList: I(s.files), version: t };
232
232
  } catch (s) {
233
- throw s instanceof u ? new C({
233
+ throw s instanceof u ? new P({
234
234
  packageName: r,
235
235
  version: t,
236
236
  cdn: "unpkg"
237
237
  }) : s;
238
238
  }
239
239
  }
240
- const nt = (r, t, e) => `https://cdn.jsdelivr.net/npm/${r}@${t}${e}`, ot = async (r, t) => {
240
+ const st = (r, t, e) => `https://cdn.jsdelivr.net/npm/${r}@${t}${e}`, nt = async (r, t) => {
241
241
  try {
242
- return (await y.get(
242
+ return (await $.get(
243
243
  `https://data.jsdelivr.com/v1/packages/npm/${r}/resolved?specifier=${t}`
244
244
  )).version;
245
245
  } catch (e) {
246
- throw e instanceof u ? new C({
246
+ throw e instanceof u ? new P({
247
247
  packageName: r,
248
248
  version: t,
249
249
  cdn: "unpkg"
@@ -252,61 +252,61 @@ const nt = (r, t, e) => `https://cdn.jsdelivr.net/npm/${r}@${t}${e}`, ot = async
252
252
  }, ct = {
253
253
  getFileList: Q,
254
254
  // 拼接url
255
- getUrl: nt
256
- }, H = (r) => r.reduce((t, e) => (e.type === "file" ? t.push({ name: e.path }) : e.files && t.push(...H(e.files)), t), []);
257
- async function it(r, t) {
255
+ getUrl: st
256
+ }, T = (r) => r.reduce((t, e) => (e.type === "file" ? t.push({ name: e.path }) : e.files && t.push(...T(e.files)), t), []);
257
+ async function ot(r, t) {
258
258
  var e;
259
259
  try {
260
- const n = (e = (await M(`https://unpkg.com/${r}@${t}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)"))) == null ? void 0 : e[0];
260
+ const n = (e = (await J(`https://unpkg.com/${r}@${t}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)"))) == null ? void 0 : e[0];
261
261
  if (n) {
262
- const o = await y.get(`https://unpkg.com/${r}@${n}/?meta`);
263
- return { fileList: H(o.files || []), version: n };
262
+ const o = await $.get(`https://unpkg.com/${r}@${n}/?meta`);
263
+ return { fileList: T(o.files || []), version: n };
264
264
  } else
265
- throw new $({
265
+ throw new m({
266
266
  packageName: r,
267
267
  version: t,
268
268
  cdn: "unpkg"
269
269
  });
270
270
  } catch (s) {
271
- throw s instanceof u ? new C({
271
+ throw s instanceof u ? new P({
272
272
  packageName: r,
273
273
  version: t,
274
274
  cdn: "unpkg"
275
275
  }) : s;
276
276
  }
277
277
  }
278
- function at(r, t, e) {
278
+ function it(r, t, e) {
279
279
  return `https://unpkg.com/${r}@${t}${e}`;
280
280
  }
281
- const lt = {
282
- getFileList: it,
283
- getUrl: at
284
- }, ut = async (r) => {
281
+ const at = {
282
+ getFileList: ot,
283
+ getUrl: it
284
+ }, lt = async (r) => {
285
285
  try {
286
286
  const t = /^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;
287
287
  if (t.test(r)) {
288
288
  const e = r.replace(t, (s, n) => `${n}package.json`);
289
- return await y.get(e);
289
+ return await $.get(e);
290
290
  } else
291
291
  throw new Error(`${r} 不是正确的url`);
292
292
  } catch (t) {
293
293
  throw t;
294
294
  }
295
- }, dt = (r, t) => {
295
+ }, ut = (r, t) => {
296
296
  var e, s;
297
297
  return ((e = r.dependencies) == null ? void 0 : e[t]) || ((s = r.devDependencies) == null ? void 0 : s[t]);
298
- }, ht = async (r, t, e) => {
298
+ }, dt = async (r, t, e) => {
299
299
  if (!t.match(/\d+(.\d+)?(.\d+)?/))
300
300
  throw new Error(`${r} version ${t} is not valid`);
301
- const n = await R[e].getFileList(r, t), o = ft(n, r);
301
+ const n = await D[e].getFileList(r, t), o = ht(n, r);
302
302
  if (!o)
303
- throw new W({
303
+ throw new K({
304
304
  packageName: r,
305
305
  version: t,
306
306
  cdn: e
307
307
  });
308
- return R[e].getUrl(r, n.version, o);
309
- }, ft = ({ fileList: r }, t) => {
308
+ return D[e].getUrl(r, n.version, o);
309
+ }, ht = ({ fileList: r }, t) => {
310
310
  var o, a;
311
311
  let e = [
312
312
  `umd/${t}.production.min.js`,
@@ -328,16 +328,16 @@ const lt = {
328
328
  const s = ["runtime", "compiler", ".esm", ".cjs", "development"].filter((c) => !t.includes(c));
329
329
  let n = "";
330
330
  for (let c of e)
331
- if (c instanceof RegExp ? n = ((o = r.find((i) => c.test(i.name) && !s.some((l) => i.name.includes(l)))) == null ? void 0 : o.name) || "" : n = ((a = r.find((i) => i.name.includes(c) && !s.some((l) => i.name.includes(l)))) == null ? void 0 : a.name) || "", n)
331
+ if (c instanceof RegExp ? n = ((o = r.find((i) => c.test(i.name) && !s.some((f) => i.name.includes(f)))) == null ? void 0 : o.name) || "" : n = ((a = r.find((i) => i.name.includes(c) && !s.some((f) => i.name.includes(f)))) == null ? void 0 : a.name) || "", n)
332
332
  break;
333
333
  return n;
334
- }, R = {
334
+ }, D = {
335
335
  jsdelivr: ct,
336
- bootcdn: tt,
337
- cdnjs: st,
338
- unpkg: lt
336
+ bootcdn: Z,
337
+ cdnjs: rt,
338
+ unpkg: at
339
339
  };
340
- function pt(r, t) {
340
+ function ft(r, t) {
341
341
  const e = r.replace(/^\D/, "").split("."), s = t.replace(/^\D/, "").split("."), n = Math.max(e.length, s.length);
342
342
  for (; e.length < n; )
343
343
  e.push("0");
@@ -352,15 +352,15 @@ function pt(r, t) {
352
352
  }
353
353
  return 0;
354
354
  }
355
- function wt(r, t) {
355
+ function pt(r, t) {
356
356
  for (let e in t)
357
- Object.prototype.hasOwnProperty.call(t, e) && (r[e] ? pt(r[e], t[e]) === -1 && (r[e] = t[e]) : r[e] = t[e]);
357
+ Object.prototype.hasOwnProperty.call(t, e) && (r[e] ? ft(r[e], t[e]) === -1 && (r[e] = t[e]) : r[e] = t[e]);
358
358
  return r;
359
359
  }
360
- class gt {
360
+ class wt {
361
361
  constructor() {
362
362
  // 打印记录
363
- m(this, "logList", []);
363
+ g(this, "logList", []);
364
364
  }
365
365
  // 打印方法
366
366
  log(t) {
@@ -390,7 +390,7 @@ class gt {
390
390
  // 打印全部
391
391
  consoleAll() {
392
392
  this.logList.forEach((t) => {
393
- console[t.type](`${q} ${t.message}`);
393
+ console[t.type](`${H} ${t.message}`);
394
394
  });
395
395
  }
396
396
  // 清除打印记录
@@ -398,18 +398,18 @@ class gt {
398
398
  this.logList = [];
399
399
  }
400
400
  }
401
- const q = "vite-add-cdn-script", S = new gt();
402
- async function A({
401
+ const H = "vite-add-cdn-script", b = new wt();
402
+ async function R({
403
403
  external: r,
404
404
  packageData: t,
405
405
  customScript: e,
406
406
  defaultCdns: s
407
407
  }) {
408
408
  let n = [], o = !1;
409
- const a = await K();
409
+ const a = await z();
410
410
  return await Promise.all(
411
411
  r.map(async (c) => {
412
- const i = dt(t, c);
412
+ const i = ut(t, c);
413
413
  if (e[c])
414
414
  return {
415
415
  urls: [],
@@ -420,28 +420,28 @@ async function A({
420
420
  urls: [],
421
421
  key: c
422
422
  };
423
- const l = a.getCdnCache(c, i);
424
- if (l)
423
+ const f = a.getCdnCache(c, i);
424
+ if (f)
425
425
  return {
426
- urls: l,
426
+ urls: f,
427
427
  key: c
428
428
  };
429
429
  {
430
430
  o = !0, console.log(`从网络获取${c}${i}的cdn地址`);
431
- const L = await Promise.allSettled(
432
- s.map(async (w) => await ht(c, i, w))
433
- ).then((w) => w.filter((f) => {
434
- if (f.status === "fulfilled")
435
- return f.value, !0;
436
- S.warn(f.reason.toString());
437
- }).map((f) => f.value));
438
- if (L.length === 0)
431
+ const d = await Promise.allSettled(
432
+ s.map(async (j) => await dt(c, i, j))
433
+ ).then((j) => j.filter((l) => {
434
+ if (l.status === "fulfilled")
435
+ return l.value, !0;
436
+ b.warn(l.reason.toString());
437
+ }).map((l) => l.value));
438
+ if (d.length === 0)
439
439
  throw new Error(`获取${c} ${i}的cdn地址失败`);
440
- const d = {
441
- urls: L,
440
+ const y = {
441
+ urls: d,
442
442
  key: c
443
443
  };
444
- return a.setCdnCache(c, i, d.urls), d;
444
+ return a.setCdnCache(c, i, y.urls), y;
445
445
  }
446
446
  })
447
447
  ).then((c) => (o && a.save(), {
@@ -450,93 +450,93 @@ async function A({
450
450
  }));
451
451
  }
452
452
  function Pt(r) {
453
- const { customScript: t = {}, retryTimes: e = 1, defaultCdns: s = ["jsdelivr", "unpkg"] } = r;
454
- let n;
453
+ const { customScript: t = {}, defaultCdns: e = ["jsdelivr", "unpkg"] } = r;
454
+ let s;
455
455
  return {
456
- name: q,
456
+ name: H,
457
457
  enforce: "pre",
458
458
  apply: "build",
459
- config(o) {
460
- n = o;
459
+ config(n) {
460
+ s = n;
461
461
  },
462
- async transformIndexHtml(o) {
463
- var c, i;
464
- if (!s || s.length === 0)
462
+ async transformIndexHtml(n) {
463
+ var a, c;
464
+ if (!e || e.length === 0)
465
465
  throw new Error("defaultCdns不能为空");
466
- const a = O.resolve(process.cwd(), "package.json");
466
+ const o = A.resolve(process.cwd(), "package.json");
467
467
  try {
468
- const l = U.readFileSync(a, "utf-8"), L = JSON.parse(l), d = (i = (c = n.build) == null ? void 0 : c.rollupOptions) == null ? void 0 : i.external;
468
+ const i = E.readFileSync(o, "utf-8"), f = JSON.parse(i), d = (c = (a = s.build) == null ? void 0 : a.rollupOptions) == null ? void 0 : c.external;
469
469
  if (!d)
470
- return o;
471
- let w = [];
470
+ return n;
471
+ let y = [];
472
472
  if (typeof d == "string")
473
- w = [d];
473
+ y = [d];
474
474
  else if (Array.isArray(d))
475
- w = d.filter((g) => typeof g == "string");
475
+ y = d.filter((w) => typeof w == "string");
476
476
  else if (typeof d == "object")
477
- return o;
478
- const f = {};
479
- let k = "";
480
- const { urls: v, noVersionPackages: _ } = await A({
481
- external: w,
482
- packageData: L,
477
+ return n;
478
+ const j = {};
479
+ let l = "";
480
+ const { urls: S, noVersionPackages: F } = await R({
481
+ external: y,
482
+ packageData: f,
483
483
  customScript: t,
484
- defaultCdns: s
484
+ defaultCdns: e
485
485
  });
486
- if (_.length > 0) {
487
- const g = { dependencies: {} };
486
+ if (F.length > 0) {
487
+ const w = { dependencies: {} };
488
488
  await Promise.allSettled(
489
- v.map(async (h) => {
489
+ S.map(async (h) => {
490
490
  if (!h)
491
491
  return;
492
- const { key: j, urls: F } = h, P = t[j] || F[0];
493
- if (!P)
492
+ const { key: C, urls: v } = h, k = t[C] || v[0];
493
+ if (!k)
494
494
  return;
495
- const x = await ut(P);
496
- wt(g.dependencies, x.dependencies);
495
+ const x = await lt(k);
496
+ pt(w.dependencies, x.dependencies);
497
497
  })
498
498
  ).then((h) => {
499
- h.forEach((j) => {
500
- j.status === "rejected" && S.warn(j.reason.toString());
499
+ h.forEach((C) => {
500
+ C.status === "rejected" && b.warn(C.reason.toString());
501
501
  });
502
502
  });
503
- const { urls: E, noVersionPackages: p } = await A({
504
- external: _,
505
- packageData: g,
503
+ const { urls: L, noVersionPackages: p } = await R({
504
+ external: F,
505
+ packageData: w,
506
506
  customScript: t,
507
- defaultCdns: s
507
+ defaultCdns: e
508
508
  });
509
- if (E.map((h) => {
510
- var P;
509
+ if (L.map((h) => {
510
+ var k;
511
511
  if (!h)
512
512
  return;
513
- const { urls: j, key: F } = h;
514
- (P = v.find((x) => (x == null ? void 0 : x.key) === F)) == null || P.urls.push(...j);
513
+ const { urls: C, key: v } = h;
514
+ (k = S.find((x) => (x == null ? void 0 : x.key) === v)) == null || k.urls.push(...C);
515
515
  }), p.length > 0)
516
516
  throw console.error(`找不到${p.join(",")}的版本`), new Error(`找不到${p.join(",")}的版本`);
517
517
  }
518
- return S.consoleAll(), v.forEach((g) => {
519
- if (!g)
518
+ return b.consoleAll(), S.forEach((w) => {
519
+ if (!w)
520
520
  return;
521
- const { urls: E, key: p } = g;
521
+ const { urls: L, key: p } = w;
522
522
  if (t[p])
523
- k += t[p];
523
+ l += t[p];
524
524
  else {
525
- f[p] = E;
526
- const h = E[0];
527
- k += `<script src="${h}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${p}"><\/script>
525
+ j[p] = L;
526
+ const h = L[0];
527
+ l += `<script src="${h}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${p}"><\/script>
528
528
  `;
529
529
  }
530
- }), k = `<script>
530
+ }), l = `<script>
531
531
  function errorCDN(e) {
532
- const packNameUrl = JSON.parse('${JSON.stringify(f)}');
532
+ const packNameUrl = JSON.parse('${JSON.stringify(j)}');
533
533
  const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
534
- if(nextCur>${e}){return;}
535
534
 
536
535
  const key = e.getAttribute("data-key");
537
- if(nextCur>=packNameUrl[key].length){return;}
536
+ const curPackNameUrl = packNameUrl[key]
537
+ if(nextCur>=curPackNameUrl.length){return;}
538
538
  // 新的cdn链接
539
- const url = packNameUrl[key][nextCur]
539
+ const url = curPackNameUrl[nextCur]
540
540
  // 克隆原标签
541
541
  const tagName = e.tagName
542
542
  const cdnDOM = document.createElement(tagName);
@@ -549,14 +549,14 @@ function Pt(r) {
549
549
  document.head.appendChild(cdnDOM);
550
550
  e.remove();
551
551
  }
552
- <\/script>` + k, o = o.replace("</head>", `${k}</head>`), o;
553
- } catch (l) {
554
- S.consoleAll(), console.error("vite-add-cdn-script error:", l.message), process.exit(1);
552
+ <\/script>` + l, n = n.replace("</head>", `${l}</head>`), n;
553
+ } catch (i) {
554
+ b.consoleAll(), console.error("vite-add-cdn-script error:", i.message), process.exit(1);
555
555
  }
556
556
  }
557
557
  };
558
558
  }
559
559
  export {
560
560
  Pt as default,
561
- q as libName
561
+ H as libName
562
562
  };
@@ -1,14 +1,14 @@
1
- (function(c,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("node:path"),require("node:fs"),require("node-fetch"),require("semver")):typeof define=="function"&&define.amd?define(["exports","node:path","node:fs","node-fetch","semver"],l):(c=typeof globalThis<"u"?globalThis:c||self,l(c.index={},c.path,c.fs,c.fetch,c.semver))})(this,function(c,l,d,R,A){"use strict";var wt=Object.defineProperty;var gt=(c,l,d)=>l in c?wt(c,l,{enumerable:!0,configurable:!0,writable:!0,value:d}):c[l]=d;var k=(c,l,d)=>(gt(c,typeof l!="symbol"?l+"":l,d),d);class B{constructor(){k(this,"cdnCache",{});k(this,"cdnCachePath","");this.cdnCachePath=l.resolve(process.cwd(),"./.cdn-cache.json")}async init(){try{const t=await d.readFileSync(this.cdnCachePath,"utf-8");this.cdnCache=JSON.parse(t)}catch{console.log("cdn缓存文件不存在,创建缓存文件"),this.cdnCache={},await d.writeFileSync(this.cdnCachePath,"","utf-8")}}getCdnCache(t,e){var n;return(n=this.cdnCache[t])==null?void 0:n[e]}setCdnCache(t,e,n){this.cdnCache[t]?this.cdnCache[t][e]=n:this.cdnCache[t]={[e]:n}}async save(){await d.writeFileSync(this.cdnCachePath,JSON.stringify(this.cdnCache),"utf-8")}}let b;const z=async()=>(b||(b=new B,await b.init()),b);class h extends Error{constructor(t){super(t),this.name="NetworkError"}}class P extends h{constructor({packageName:t,version:e,cdn:n}){super(`${n} ${t}@${e} 网络请求失败`),this.name="PackageNetworkError"}}class $ extends Error{constructor({packageName:t,version:e,cdn:n}){super(`${n}上没有${t}@${e}的版本`),this.name="NoVersionError"}}class K extends Error{constructor({packageName:t,version:e,cdn:n}){super(`在 ${n} 中找不到 ${t}@${e} 文件,请检查包名或版本号`),this.name="GetFileListError"}}class W{constructor(t){k(this,"_max");k(this,"_count");k(this,"_taskQueue");this._max=t||5,this._count=0,this._taskQueue=[]}call(t,...e){return new Promise((n,s)=>{const i=this._createTask(t,e,n,s);this._count>=this._max?this._taskQueue.push(i):i()})}_createTask(t,e,n,s){return()=>{t(...e).then(n).catch(s).finally(()=>{this._count--,this._taskQueue.length&&this._taskQueue.shift()()}),this._count++}}}const V=new W(5),J=async r=>{try{const t=await R(r,{method:"HEAD",redirect:"manual"});return t.status>=300&&t.status<400?await J(t.headers.get("location")||""):r}catch(t){throw Promise.reject(new h(t.message))}},X={get:async r=>{try{const t=await R(r);if(t.ok){const e=t.headers.get("content-type"),n=await t.text();return e&&e.includes("application/json")?JSON.parse(n):n}else throw new h(`请求失败,状态码:${t.status}`)}catch(t){throw new h(t.message)}}},y={get:V.call.bind(V,X.get)},Y={getFileList:async(r,t)=>{try{const e=await y.get(`https://api.bootcdn.cn/libraries/${r}`);if(e.length===0)throw new $({packageName:r,version:t,cdn:"bootcdn"});const n=e[0],i=n.assets.reverse().find(o=>{if(A.satisfies(o.version,t))return!0});if(!i)throw new $({packageName:r,version:t,cdn:"bootcdn"});return{fileList:i.files.map(o=>({name:"/"+o})),recommendFileName:n.filename,version:i.version}}catch(e){throw e instanceof h?new P({packageName:r,version:t,cdn:"unpkg"}):e}},getUrl:(r,t,e)=>`https://cdn.bootcdn.net/ajax/libs/${r}/${t}${e}`};async function M(r,t,e=!1){try{if(!e&&t.match(/^\D/)){const s=await N(r,t);for(let i of s)if(A.satisfies(i,t))return M(r,i,!0);throw new $({packageName:r,version:t,cdn:"cdnjs"})}const n=await y.get(`https://api.cdnjs.com/libraries/${r}/${t}`);if(n.error)throw new $({packageName:r,version:t,cdn:"cdnjs"});return{fileList:n.rawFiles.map(s=>({name:"/"+s})),version:t}}catch(n){throw n instanceof h?new P({packageName:r,version:t,cdn:"unpkg"}):n}}const Z=(r,t,e)=>`https://cdnjs.cloudflare.com/ajax/libs/${r}/${t}${e}`,N=async(r,t)=>{try{return(await y.get(`https://api.cdnjs.com/libraries/${r}?fields=versions`)).versions}catch(e){throw e instanceof h?new P({packageName:r,version:t,cdn:"unpkg"}):e}},tt={getFileList:M,getUrl:Z},T=(r,t="")=>r.reduce((e,n)=>(n.type==="file"?e.push({name:`${t}/${n.name}`}):n.files&&e.push(...T(n.files,`${t}/${n.name}`)),e),[]);async function I(r,t,e=!1){try{if(!e&&t.match(/^\D/)){const s=await rt(r,t);if(typeof s=="string")return I(r,s,!0);throw new $({packageName:r,version:t,cdn:"jsdelivr"})}const n=await y.get(`https://data.jsdelivr.com/v1/packages/npm/${r}@${t}`);if(n.status)throw new $({packageName:r,version:t,cdn:"jsdelivr"});return{fileList:T(n.files),version:t}}catch(n){throw n instanceof h?new P({packageName:r,version:t,cdn:"unpkg"}):n}}const et=(r,t,e)=>`https://cdn.jsdelivr.net/npm/${r}@${t}${e}`,rt=async(r,t)=>{try{return(await y.get(`https://data.jsdelivr.com/v1/packages/npm/${r}/resolved?specifier=${t}`)).version}catch(e){throw e instanceof h?new P({packageName:r,version:t,cdn:"unpkg"}):e}},nt={getFileList:I,getUrl:et},q=r=>r.reduce((t,e)=>(e.type==="file"?t.push({name:e.path}):e.files&&t.push(...q(e.files)),t),[]);async function st(r,t){var e;try{const s=(e=(await J(`https://unpkg.com/${r}@${t}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)")))==null?void 0:e[0];if(s){const i=await y.get(`https://unpkg.com/${r}@${s}/?meta`);return{fileList:q(i.files||[]),version:s}}else throw new $({packageName:r,version:t,cdn:"unpkg"})}catch(n){throw n instanceof h?new P({packageName:r,version:t,cdn:"unpkg"}):n}}function it(r,t,e){return`https://unpkg.com/${r}@${t}${e}`}const ot={getFileList:st,getUrl:it},ct=async r=>{try{const t=/^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;if(t.test(r)){const e=r.replace(t,(n,s)=>`${s}package.json`);return await y.get(e)}else throw new Error(`${r} 不是正确的url`)}catch(t){throw t}},at=(r,t)=>{var e,n;return((e=r.dependencies)==null?void 0:e[t])||((n=r.devDependencies)==null?void 0:n[t])},lt=async(r,t,e)=>{if(!t.match(/\d+(.\d+)?(.\d+)?/))throw new Error(`${r} version ${t} is not valid`);const s=await Q[e].getFileList(r,t),i=ut(s,r);if(!i)throw new K({packageName:r,version:t,cdn:e});return Q[e].getUrl(r,s.version,i)},ut=({fileList:r},t)=>{var i,u;let e=[`umd/${t}.production.min.js`,/umd\/.+?\.production\.min\.js$/,/dist\/.+?\.production\.min\.js$/,/dist\/.+?\.umd\.min\.js$/,`dist/${t}.prod.min.js`,/dist\/.+?\.global.prod.min.js/,`dist/${t}.min.js`,/.+?\.global.prod.min.js/,/.+?.global.prod.js/,/lib\/.+?\.min\.js$/,/dist\/.+?\.min\.js$/,/index\.min\.js$/,/index\.js$/,/\.min\.js$/,/\.js$/];const n=["runtime","compiler",".esm",".cjs","development"].filter(o=>!t.includes(o));let s="";for(let o of e)if(o instanceof RegExp?s=((i=r.find(a=>o.test(a.name)&&!n.some(f=>a.name.includes(f))))==null?void 0:i.name)||"":s=((u=r.find(a=>a.name.includes(o)&&!n.some(f=>a.name.includes(f))))==null?void 0:u.name)||"",s)break;return s},Q={jsdelivr:nt,bootcdn:Y,cdnjs:tt,unpkg:ot};function dt(r,t){const e=r.replace(/^\D/,"").split("."),n=t.replace(/^\D/,"").split("."),s=Math.max(e.length,n.length);for(;e.length<s;)e.push("0");for(;n.length<s;)n.push("0");for(let i=0;i<s;i++){const u=parseInt(e[i],10),o=parseInt(n[i],10);if(u>o)return 1;if(u<o)return-1}return 0}function ht(r,t){for(let e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]?dt(r[e],t[e])===-1&&(r[e]=t[e]):r[e]=t[e]);return r}class ft{constructor(){k(this,"logList",[])}log(t){this.logList.push({type:"log",message:t})}warn(t){this.logList.push({type:"warn",message:t})}error(t){this.logList.push({type:"error",message:t})}info(t){this.logList.push({type:"info",message:t})}consoleAll(){this.logList.forEach(t=>{console[t.type](`${F} ${t.message}`)})}clear(){this.logList=[]}}const F="vite-add-cdn-script",v=new ft;async function H({external:r,packageData:t,customScript:e,defaultCdns:n}){let s=[],i=!1;const u=await z();return await Promise.all(r.map(async o=>{const a=at(t,o);if(e[o])return{urls:[],key:o};if(!a)return s.push(o),{urls:[],key:o};const f=u.getCdnCache(o,a);if(f)return{urls:f,key:o};{i=!0,console.log(`从网络获取${o}${a}的cdn地址`);const S=await Promise.allSettled(n.map(async j=>await lt(o,a,j))).then(j=>j.filter(g=>{if(g.status==="fulfilled")return g.value,!0;v.warn(g.reason.toString())}).map(g=>g.value));if(S.length===0)throw new Error(`获取${o} ${a}的cdn地址失败`);const p={urls:S,key:o};return u.setCdnCache(o,a,p.urls),p}})).then(o=>(i&&u.save(),{urls:o,noVersionPackages:s}))}function pt(r){const{customScript:t={},retryTimes:e=1,defaultCdns:n=["jsdelivr","unpkg"]}=r;let s;return{name:F,enforce:"pre",apply:"build",config(i){s=i},async transformIndexHtml(i){var o,a;if(!n||n.length===0)throw new Error("defaultCdns不能为空");const u=l.resolve(process.cwd(),"package.json");try{const f=d.readFileSync(u,"utf-8"),S=JSON.parse(f),p=(a=(o=s.build)==null?void 0:o.rollupOptions)==null?void 0:a.external;if(!p)return i;let j=[];if(typeof p=="string")j=[p];else if(Array.isArray(p))j=p.filter(C=>typeof C=="string");else if(typeof p=="object")return i;const g={};let L="";const{urls:D,noVersionPackages:G}=await H({external:j,packageData:S,customScript:t,defaultCdns:n});if(G.length>0){const C={dependencies:{}};await Promise.allSettled(D.map(async w=>{if(!w)return;const{key:x,urls:O}=w,E=t[x]||O[0];if(!E)return;const U=await ct(E);ht(C.dependencies,U.dependencies)})).then(w=>{w.forEach(x=>{x.status==="rejected"&&v.warn(x.reason.toString())})});const{urls:_,noVersionPackages:m}=await H({external:G,packageData:C,customScript:t,defaultCdns:n});if(_.map(w=>{var E;if(!w)return;const{urls:x,key:O}=w;(E=D.find(U=>(U==null?void 0:U.key)===O))==null||E.urls.push(...x)}),m.length>0)throw console.error(`找不到${m.join(",")}的版本`),new Error(`找不到${m.join(",")}的版本`)}return v.consoleAll(),D.forEach(C=>{if(!C)return;const{urls:_,key:m}=C;if(t[m])L+=t[m];else{g[m]=_;const w=_[0];L+=`<script src="${w}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${m}"><\/script>
2
- `}}),L=`<script>
1
+ (function(o,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("node:path"),require("node:fs"),require("node-fetch"),require("semver")):typeof define=="function"&&define.amd?define(["exports","node:path","node:fs","node-fetch","semver"],l):(o=typeof globalThis<"u"?globalThis:o||self,l(o.index={},o.path,o.fs,o.fetch,o.semver))})(this,function(o,l,h,O,R){"use strict";var pt=Object.defineProperty;var wt=(o,l,h)=>l in o?pt(o,l,{enumerable:!0,configurable:!0,writable:!0,value:h}):o[l]=h;var C=(o,l,h)=>(wt(o,typeof l!="symbol"?l+"":l,h),h);class G{constructor(){C(this,"cdnCache",{});C(this,"cdnCachePath","");this.cdnCachePath=l.resolve(process.cwd(),"./.cdn-cache.json")}async init(){try{const t=await h.readFileSync(this.cdnCachePath,"utf-8");this.cdnCache=JSON.parse(t)}catch{console.log("cdn缓存文件不存在,创建缓存文件"),this.cdnCache={},await h.writeFileSync(this.cdnCachePath,"","utf-8")}}getCdnCache(t,e){var n;return(n=this.cdnCache[t])==null?void 0:n[e]}setCdnCache(t,e,n){this.cdnCache[t]?this.cdnCache[t][e]=n:this.cdnCache[t]={[e]:n}}async save(){await h.writeFileSync(this.cdnCachePath,JSON.stringify(this.cdnCache),"utf-8")}}let b;const B=async()=>(b||(b=new G,await b.init()),b);class f extends Error{constructor(t){super(t),this.name="NetworkError"}}class P extends f{constructor({packageName:t,version:e,cdn:n}){super(`${n} ${t}@${e} 网络请求失败`),this.name="PackageNetworkError"}}class $ extends Error{constructor({packageName:t,version:e,cdn:n}){super(`${n}上没有${t}@${e}的版本`),this.name="NoVersionError"}}class N extends Error{constructor({packageName:t,version:e,cdn:n}){super(`在 ${n} 中找不到 ${t}@${e} 文件,请检查包名或版本号`),this.name="GetFileListError"}}class z{constructor(t){C(this,"_max");C(this,"_count");C(this,"_taskQueue");this._max=t||5,this._count=0,this._taskQueue=[]}call(t,...e){return new Promise((n,s)=>{const c=this._createTask(t,e,n,s);this._count>=this._max?this._taskQueue.push(c):c()})}_createTask(t,e,n,s){return()=>{t(...e).then(n).catch(s).finally(()=>{this._count--,this._taskQueue.length&&this._taskQueue.shift()()}),this._count++}}}const A=new z(5),V=async r=>{try{const t=await O(r,{method:"HEAD",redirect:"manual"});return t.status>=300&&t.status<400?await V(t.headers.get("location")||""):r}catch(t){throw Promise.reject(new f(t.message))}},K={get:async r=>{try{const t=await O(r);if(t.ok){const e=t.headers.get("content-type"),n=await t.text();return e&&e.includes("application/json")?JSON.parse(n):n}else throw new f(`请求失败,状态码:${t.status}`)}catch(t){throw new f(t.message)}}},y={get:A.call.bind(A,K.get)},W={getFileList:async(r,t)=>{try{const e=await y.get(`https://api.bootcdn.cn/libraries/${r}`);if(e.length===0)throw new $({packageName:r,version:t,cdn:"bootcdn"});const n=e[0],c=n.assets.reverse().find(i=>{if(R.satisfies(i.version,t))return!0});if(!c)throw new $({packageName:r,version:t,cdn:"bootcdn"});return{fileList:c.files.map(i=>({name:"/"+i})),recommendFileName:n.filename,version:c.version}}catch(e){throw e instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):e}},getUrl:(r,t,e)=>`https://cdn.bootcdn.net/ajax/libs/${r}/${t}${e}`};async function J(r,t,e=!1){try{if(!e&&t.match(/^\D/)){const s=await Y(r,t);for(let c of s)if(R.satisfies(c,t))return J(r,c,!0);throw new $({packageName:r,version:t,cdn:"cdnjs"})}const n=await y.get(`https://api.cdnjs.com/libraries/${r}/${t}`);if(n.error)throw new $({packageName:r,version:t,cdn:"cdnjs"});return{fileList:n.rawFiles.map(s=>({name:"/"+s})),version:t}}catch(n){throw n instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):n}}const X=(r,t,e)=>`https://cdnjs.cloudflare.com/ajax/libs/${r}/${t}${e}`,Y=async(r,t)=>{try{return(await y.get(`https://api.cdnjs.com/libraries/${r}?fields=versions`)).versions}catch(e){throw e instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):e}},Z={getFileList:J,getUrl:X},M=(r,t="")=>r.reduce((e,n)=>(n.type==="file"?e.push({name:`${t}/${n.name}`}):n.files&&e.push(...M(n.files,`${t}/${n.name}`)),e),[]);async function I(r,t,e=!1){try{if(!e&&t.match(/^\D/)){const s=await et(r,t);if(typeof s=="string")return I(r,s,!0);throw new $({packageName:r,version:t,cdn:"jsdelivr"})}const n=await y.get(`https://data.jsdelivr.com/v1/packages/npm/${r}@${t}`);if(n.status)throw new $({packageName:r,version:t,cdn:"jsdelivr"});return{fileList:M(n.files),version:t}}catch(n){throw n instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):n}}const tt=(r,t,e)=>`https://cdn.jsdelivr.net/npm/${r}@${t}${e}`,et=async(r,t)=>{try{return(await y.get(`https://data.jsdelivr.com/v1/packages/npm/${r}/resolved?specifier=${t}`)).version}catch(e){throw e instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):e}},rt={getFileList:I,getUrl:tt},T=r=>r.reduce((t,e)=>(e.type==="file"?t.push({name:e.path}):e.files&&t.push(...T(e.files)),t),[]);async function nt(r,t){var e;try{const s=(e=(await V(`https://unpkg.com/${r}@${t}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)")))==null?void 0:e[0];if(s){const c=await y.get(`https://unpkg.com/${r}@${s}/?meta`);return{fileList:T(c.files||[]),version:s}}else throw new $({packageName:r,version:t,cdn:"unpkg"})}catch(n){throw n instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):n}}function st(r,t,e){return`https://unpkg.com/${r}@${t}${e}`}const it={getFileList:nt,getUrl:st},ct=async r=>{try{const t=/^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;if(t.test(r)){const e=r.replace(t,(n,s)=>`${s}package.json`);return await y.get(e)}else throw new Error(`${r} 不是正确的url`)}catch(t){throw t}},ot=(r,t)=>{var e,n;return((e=r.dependencies)==null?void 0:e[t])||((n=r.devDependencies)==null?void 0:n[t])},at=async(r,t,e)=>{if(!t.match(/\d+(.\d+)?(.\d+)?/))throw new Error(`${r} version ${t} is not valid`);const s=await q[e].getFileList(r,t),c=lt(s,r);if(!c)throw new N({packageName:r,version:t,cdn:e});return q[e].getUrl(r,s.version,c)},lt=({fileList:r},t)=>{var c,u;let e=[`umd/${t}.production.min.js`,/umd\/.+?\.production\.min\.js$/,/dist\/.+?\.production\.min\.js$/,/dist\/.+?\.umd\.min\.js$/,`dist/${t}.prod.min.js`,/dist\/.+?\.global.prod.min.js/,`dist/${t}.min.js`,/.+?\.global.prod.min.js/,/.+?.global.prod.js/,/lib\/.+?\.min\.js$/,/dist\/.+?\.min\.js$/,/index\.min\.js$/,/index\.js$/,/\.min\.js$/,/\.js$/];const n=["runtime","compiler",".esm",".cjs","development"].filter(i=>!t.includes(i));let s="";for(let i of e)if(i instanceof RegExp?s=((c=r.find(a=>i.test(a.name)&&!n.some(g=>a.name.includes(g))))==null?void 0:c.name)||"":s=((u=r.find(a=>a.name.includes(i)&&!n.some(g=>a.name.includes(g))))==null?void 0:u.name)||"",s)break;return s},q={jsdelivr:rt,bootcdn:W,cdnjs:Z,unpkg:it};function ut(r,t){const e=r.replace(/^\D/,"").split("."),n=t.replace(/^\D/,"").split("."),s=Math.max(e.length,n.length);for(;e.length<s;)e.push("0");for(;n.length<s;)n.push("0");for(let c=0;c<s;c++){const u=parseInt(e[c],10),i=parseInt(n[c],10);if(u>i)return 1;if(u<i)return-1}return 0}function dt(r,t){for(let e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]?ut(r[e],t[e])===-1&&(r[e]=t[e]):r[e]=t[e]);return r}class ht{constructor(){C(this,"logList",[])}log(t){this.logList.push({type:"log",message:t})}warn(t){this.logList.push({type:"warn",message:t})}error(t){this.logList.push({type:"error",message:t})}info(t){this.logList.push({type:"info",message:t})}consoleAll(){this.logList.forEach(t=>{console[t.type](`${_} ${t.message}`)})}clear(){this.logList=[]}}const _="vite-add-cdn-script",v=new ht;async function Q({external:r,packageData:t,customScript:e,defaultCdns:n}){let s=[],c=!1;const u=await B();return await Promise.all(r.map(async i=>{const a=ot(t,i);if(e[i])return{urls:[],key:i};if(!a)return s.push(i),{urls:[],key:i};const g=u.getCdnCache(i,a);if(g)return{urls:g,key:i};{c=!0,console.log(`从网络获取${i}${a}的cdn地址`);const p=await Promise.allSettled(n.map(async x=>await at(i,a,x))).then(x=>x.filter(d=>{if(d.status==="fulfilled")return d.value,!0;v.warn(d.reason.toString())}).map(d=>d.value));if(p.length===0)throw new Error(`获取${i} ${a}的cdn地址失败`);const k={urls:p,key:i};return u.setCdnCache(i,a,k.urls),k}})).then(i=>(c&&u.save(),{urls:i,noVersionPackages:s}))}function ft(r){const{customScript:t={},defaultCdns:e=["jsdelivr","unpkg"]}=r;let n;return{name:_,enforce:"pre",apply:"build",config(s){n=s},async transformIndexHtml(s){var u,i;if(!e||e.length===0)throw new Error("defaultCdns不能为空");const c=l.resolve(process.cwd(),"package.json");try{const a=h.readFileSync(c,"utf-8"),g=JSON.parse(a),p=(i=(u=n.build)==null?void 0:u.rollupOptions)==null?void 0:i.external;if(!p)return s;let k=[];if(typeof p=="string")k=[p];else if(Array.isArray(p))k=p.filter(j=>typeof j=="string");else if(typeof p=="object")return s;const x={};let d="";const{urls:F,noVersionPackages:H}=await Q({external:k,packageData:g,customScript:t,defaultCdns:e});if(H.length>0){const j={dependencies:{}};await Promise.allSettled(F.map(async w=>{if(!w)return;const{key:L,urls:D}=w,U=t[L]||D[0];if(!U)return;const E=await ct(U);dt(j.dependencies,E.dependencies)})).then(w=>{w.forEach(L=>{L.status==="rejected"&&v.warn(L.reason.toString())})});const{urls:S,noVersionPackages:m}=await Q({external:H,packageData:j,customScript:t,defaultCdns:e});if(S.map(w=>{var U;if(!w)return;const{urls:L,key:D}=w;(U=F.find(E=>(E==null?void 0:E.key)===D))==null||U.urls.push(...L)}),m.length>0)throw console.error(`找不到${m.join(",")}的版本`),new Error(`找不到${m.join(",")}的版本`)}return v.consoleAll(),F.forEach(j=>{if(!j)return;const{urls:S,key:m}=j;if(t[m])d+=t[m];else{x[m]=S;const w=S[0];d+=`<script src="${w}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${m}"><\/script>
2
+ `}}),d=`<script>
3
3
  function errorCDN(e) {
4
- const packNameUrl = JSON.parse('${JSON.stringify(g)}');
4
+ const packNameUrl = JSON.parse('${JSON.stringify(x)}');
5
5
  const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
6
- if(nextCur>${e}){return;}
7
6
 
8
7
  const key = e.getAttribute("data-key");
9
- if(nextCur>=packNameUrl[key].length){return;}
8
+ const curPackNameUrl = packNameUrl[key]
9
+ if(nextCur>=curPackNameUrl.length){return;}
10
10
  // 新的cdn链接
11
- const url = packNameUrl[key][nextCur]
11
+ const url = curPackNameUrl[nextCur]
12
12
  // 克隆原标签
13
13
  const tagName = e.tagName
14
14
  const cdnDOM = document.createElement(tagName);
@@ -21,4 +21,4 @@
21
21
  document.head.appendChild(cdnDOM);
22
22
  e.remove();
23
23
  }
24
- <\/script>`+L,i=i.replace("</head>",`${L}</head>`),i}catch(f){v.consoleAll(),console.error("vite-add-cdn-script error:",f.message),process.exit(1)}}}}c.default=pt,c.libName=F,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
24
+ <\/script>`+d,s=s.replace("</head>",`${d}</head>`),s}catch(a){v.consoleAll(),console.error("vite-add-cdn-script error:",a.message),process.exit(1)}}}}o.default=ft,o.libName=_,Object.defineProperties(o,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- interface IOptions {
2
- customScript?: { [key: string]: string };
3
- retryTimes?: number;
4
- defaultCdns?: string[];
5
- }
6
- export default function viteAddCdnScript(options: IOptions);
1
+ interface IOptions {
2
+ customScript?: { [key: string]: string };
3
+ defaultCdns?: string[];
4
+ }
5
+ export default function viteAddCdnScript(options: IOptions);
package/package.json CHANGED
@@ -1,64 +1,64 @@
1
- {
2
- "name": "vite-add-cdn-script",
3
- "version": "0.0.10",
4
- "keywords": [
5
- "vite",
6
- "cdn",
7
- "cdn-script",
8
- "auto-add-cdn",
9
- "vite-add-cdn-script"
10
- ],
11
- "description": "A plugin for vite to add cdn script to index.html",
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://github.com/baizeteam/baize-vite-plugin.git"
15
- },
16
- "homepage": "https://github.com/baizeteam/baize-vite-plugin/tree/master/package/vite-add-cdn-script#readme",
17
- "author": "baizeteam",
18
- "type": "module",
19
- "files": [
20
- "dist",
21
- "index.d.ts"
22
- ],
23
- "main": "./dist/index.umd.cjs",
24
- "module": "./dist/index.js",
25
- "types": "./index.d.ts",
26
- "exports": {
27
- "types": "./index.d.ts",
28
- "import": "./dist/index.js",
29
- "require": "./dist/index.js"
30
- },
31
- "scripts": {
32
- "dev": "vite",
33
- "build:page": "tsc && cross-env BUILD_MODE=page vite build",
34
- "build": "tsc && cross-env BUILD_MODE=lib vite build",
35
- "test": "jest"
36
- },
37
- "devDependencies": {
38
- "@jest/globals": "^29.7.0",
39
- "@types/node": "^20.12.11",
40
- "@types/node-fetch": "2",
41
- "@types/react": "^18.3.2",
42
- "@types/react-dom": "^18.3.0",
43
- "@types/semver": "^7.5.8",
44
- "@vitejs/plugin-react": "^4.2.1",
45
- "cross-env": "^7.0.3",
46
- "jest": "^29.7.0",
47
- "react": "^18.2.0",
48
- "react-dom": "^18.2.0",
49
- "react-router-dom": "^6.23.1",
50
- "rollup-plugin-external-globals": "^0.10.0",
51
- "rollup-plugin-node-externals": "^7.1.2",
52
- "ts-jest": "^29.1.4",
53
- "ts-node": "^10.9.2",
54
- "typescript": "^5.4.5",
55
- "vite": "^5.2.11"
56
- },
57
- "publishConfig": {
58
- "registry": "https://registry.npmjs.org/"
59
- },
60
- "dependencies": {
61
- "node-fetch": "2",
62
- "semver": "^7.6.2"
63
- }
64
- }
1
+ {
2
+ "name": "vite-add-cdn-script",
3
+ "version": "0.0.11",
4
+ "keywords": [
5
+ "vite",
6
+ "cdn",
7
+ "cdn-script",
8
+ "auto-add-cdn",
9
+ "vite-add-cdn-script"
10
+ ],
11
+ "description": "A plugin for vite to add cdn script to index.html",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/baizeteam/baize-package.git"
15
+ },
16
+ "homepage": "https://github.com/baizeteam/baize-package/tree/release/package/vite-add-cdn-script#readme",
17
+ "author": "baizeteam",
18
+ "type": "module",
19
+ "files": [
20
+ "dist",
21
+ "index.d.ts"
22
+ ],
23
+ "main": "./dist/index.umd.cjs",
24
+ "module": "./dist/index.js",
25
+ "types": "./index.d.ts",
26
+ "exports": {
27
+ "types": "./index.d.ts",
28
+ "import": "./dist/index.js",
29
+ "require": "./dist/index.js"
30
+ },
31
+ "devDependencies": {
32
+ "@jest/globals": "^29.7.0",
33
+ "@types/node": "^20.12.11",
34
+ "@types/node-fetch": "2",
35
+ "@types/react": "^18.3.2",
36
+ "@types/react-dom": "^18.3.0",
37
+ "@types/semver": "^7.5.8",
38
+ "@vitejs/plugin-react": "^4.2.1",
39
+ "cross-env": "^7.0.3",
40
+ "jest": "^29.7.0",
41
+ "react": "^18.2.0",
42
+ "react-dom": "^18.2.0",
43
+ "react-router-dom": "^6.23.1",
44
+ "rollup-plugin-external-globals": "^0.10.0",
45
+ "rollup-plugin-node-externals": "^7.1.2",
46
+ "ts-jest": "^29.1.4",
47
+ "ts-node": "^10.9.2",
48
+ "typescript": "^5.4.5",
49
+ "vite": "^5.2.11"
50
+ },
51
+ "publishConfig": {
52
+ "registry": "https://registry.npmjs.org/"
53
+ },
54
+ "dependencies": {
55
+ "node-fetch": "2",
56
+ "semver": "^7.6.2"
57
+ },
58
+ "scripts": {
59
+ "dev": "vite",
60
+ "build:page": "tsc && cross-env BUILD_MODE=page vite build",
61
+ "build": "tsc && cross-env BUILD_MODE=lib vite build",
62
+ "test": "jest"
63
+ }
64
+ }