vite-add-cdn-script 0.0.9 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +165 -0
- package/README.md +88 -89
- package/dist/index.js +415 -249
- package/dist/index.umd.cjs +7 -7
- package/index.d.ts +5 -6
- package/package.json +64 -59
package/dist/index.umd.cjs
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
(function(
|
2
|
-
`}}),
|
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(
|
4
|
+
const packNameUrl = JSON.parse('${JSON.stringify(x)}');
|
5
5
|
const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
|
6
|
-
if(nextCur>${t}){return;}
|
7
6
|
|
8
7
|
const key = e.getAttribute("data-key");
|
9
|
-
|
8
|
+
const curPackNameUrl = packNameUrl[key]
|
9
|
+
if(nextCur>=curPackNameUrl.length){return;}
|
10
10
|
// 新的cdn链接
|
11
|
-
const url =
|
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>`+
|
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
|
-
|
4
|
-
|
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,59 +1,64 @@
|
|
1
|
-
{
|
2
|
-
"name": "vite-add-cdn-script",
|
3
|
-
"version": "0.0.
|
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-
|
15
|
-
},
|
16
|
-
"homepage": "https://github.com/baizeteam/baize-
|
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
|
-
"
|
32
|
-
"
|
33
|
-
"
|
34
|
-
"
|
35
|
-
"
|
36
|
-
|
37
|
-
|
38
|
-
"@
|
39
|
-
"
|
40
|
-
"
|
41
|
-
"
|
42
|
-
"
|
43
|
-
"
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"
|
47
|
-
"
|
48
|
-
"
|
49
|
-
"
|
50
|
-
|
51
|
-
|
52
|
-
"
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
"
|
57
|
-
},
|
58
|
-
"
|
59
|
-
|
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
|
+
}
|