meodp 0.2.0 → 0.2.2
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/dist/check/cli.cjs +2 -2
- package/dist/check/cli.mjs +2 -2
- package/dist/check/index.cjs +2 -2
- package/dist/check/index.mjs +2 -2
- package/dist/cli/main.cjs +3 -2
- package/dist/cli/main.mjs +3 -2
- package/dist/notify/cli.cjs +1 -1
- package/dist/notify/cli.mjs +1 -1
- package/dist/shared/{meodp.80ff918d.mjs → meodp.3d3c487c.mjs} +1 -1
- package/dist/shared/{meodp.2b00b0ae.cjs → meodp.5f2d144f.cjs} +4 -1
- package/dist/shared/{meodp.9c706389.mjs → meodp.72d12ced.mjs} +4 -1
- package/dist/shared/{meodp.c4c70565.cjs → meodp.a993456e.cjs} +1 -1
- package/package.json +3 -2
package/dist/check/cli.cjs
CHANGED
|
@@ -7,8 +7,8 @@ const process = require('node:process');
|
|
|
7
7
|
const node_util = require('node:util');
|
|
8
8
|
const jsYaml = require('js-yaml');
|
|
9
9
|
const load = require('../shared/meodp.63483e20.cjs');
|
|
10
|
-
const check_index = require('../shared/meodp.
|
|
11
|
-
const report = require('../shared/meodp.
|
|
10
|
+
const check_index = require('../shared/meodp.a993456e.cjs');
|
|
11
|
+
const report = require('../shared/meodp.5f2d144f.cjs');
|
|
12
12
|
require('c12');
|
|
13
13
|
require('node:timers/promises');
|
|
14
14
|
require('linkinator');
|
package/dist/check/cli.mjs
CHANGED
|
@@ -5,8 +5,8 @@ import process from 'node:process';
|
|
|
5
5
|
import { parseArgs } from 'node:util';
|
|
6
6
|
import { load } from 'js-yaml';
|
|
7
7
|
import { l as loadProjectConfig } from '../shared/meodp.f96d0510.mjs';
|
|
8
|
-
import { p as planReporters, c as checkSitemap, a as checkLinks, w as writeReporters, n as normalizeTargets, b as waitForReport } from '../shared/meodp.
|
|
9
|
-
import { r as readReport, s as saveReport } from '../shared/meodp.
|
|
8
|
+
import { p as planReporters, c as checkSitemap, a as checkLinks, w as writeReporters, n as normalizeTargets, b as waitForReport } from '../shared/meodp.3d3c487c.mjs';
|
|
9
|
+
import { r as readReport, s as saveReport } from '../shared/meodp.72d12ced.mjs';
|
|
10
10
|
import 'c12';
|
|
11
11
|
import 'node:timers/promises';
|
|
12
12
|
import 'linkinator';
|
package/dist/check/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const check_index = require('../shared/meodp.
|
|
4
|
-
const report = require('../shared/meodp.
|
|
3
|
+
const check_index = require('../shared/meodp.a993456e.cjs');
|
|
4
|
+
const report = require('../shared/meodp.5f2d144f.cjs');
|
|
5
5
|
require('node:timers/promises');
|
|
6
6
|
require('linkinator');
|
|
7
7
|
require('node:os');
|
package/dist/check/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { a as checkLinks, c as checkSitemap, r as readSitemapUrls, b as waitForReport, w as writeReporters } from '../shared/meodp.
|
|
2
|
-
export { f as formatReport, p as parseReport, r as readReport, s as saveReport, a as writeReportSite, w as writeReports } from '../shared/meodp.
|
|
1
|
+
export { a as checkLinks, c as checkSitemap, r as readSitemapUrls, b as waitForReport, w as writeReporters } from '../shared/meodp.3d3c487c.mjs';
|
|
2
|
+
export { f as formatReport, p as parseReport, r as readReport, s as saveReport, a as writeReportSite, w as writeReports } from '../shared/meodp.72d12ced.mjs';
|
|
3
3
|
import 'node:timers/promises';
|
|
4
4
|
import 'linkinator';
|
|
5
5
|
import 'node:os';
|
package/dist/cli/main.cjs
CHANGED
|
@@ -8,7 +8,7 @@ const process__default = /*#__PURE__*/_interopDefaultCompat(process);
|
|
|
8
8
|
|
|
9
9
|
const name = "meodp";
|
|
10
10
|
const type = "module";
|
|
11
|
-
const version = "0.2.
|
|
11
|
+
const version = "0.2.2";
|
|
12
12
|
const description = "Check website and friend-link availability with sitemap discovery, history, and portable reports.";
|
|
13
13
|
const author = {
|
|
14
14
|
name: "YunYouJun",
|
|
@@ -109,6 +109,7 @@ const scripts = {
|
|
|
109
109
|
"test:e2e": "tsx scripts/build-report-viewer.ts && playwright test",
|
|
110
110
|
typecheck: "tsx scripts/build-report-viewer.ts && tsc --noEmit -p tsconfig.json",
|
|
111
111
|
prepack: "npm run build",
|
|
112
|
+
"verify:package": "pnpm build && tsx scripts/verify-package.ts",
|
|
112
113
|
release: "npm version --no-git-tag-version"
|
|
113
114
|
};
|
|
114
115
|
const peerDependencies = {
|
|
@@ -128,7 +129,7 @@ const peerDependenciesMeta = {
|
|
|
128
129
|
}
|
|
129
130
|
};
|
|
130
131
|
const dependencies = {
|
|
131
|
-
c12: "^
|
|
132
|
+
c12: "^3.3.4",
|
|
132
133
|
"cli-progress": "^3.12.0",
|
|
133
134
|
consola: "^3.2.3",
|
|
134
135
|
"date-fns": "^4.1.0",
|
package/dist/cli/main.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import process from 'node:process';
|
|
|
2
2
|
|
|
3
3
|
const name = "meodp";
|
|
4
4
|
const type = "module";
|
|
5
|
-
const version = "0.2.
|
|
5
|
+
const version = "0.2.2";
|
|
6
6
|
const description = "Check website and friend-link availability with sitemap discovery, history, and portable reports.";
|
|
7
7
|
const author = {
|
|
8
8
|
name: "YunYouJun",
|
|
@@ -103,6 +103,7 @@ const scripts = {
|
|
|
103
103
|
"test:e2e": "tsx scripts/build-report-viewer.ts && playwright test",
|
|
104
104
|
typecheck: "tsx scripts/build-report-viewer.ts && tsc --noEmit -p tsconfig.json",
|
|
105
105
|
prepack: "npm run build",
|
|
106
|
+
"verify:package": "pnpm build && tsx scripts/verify-package.ts",
|
|
106
107
|
release: "npm version --no-git-tag-version"
|
|
107
108
|
};
|
|
108
109
|
const peerDependencies = {
|
|
@@ -122,7 +123,7 @@ const peerDependenciesMeta = {
|
|
|
122
123
|
}
|
|
123
124
|
};
|
|
124
125
|
const dependencies = {
|
|
125
|
-
c12: "^
|
|
126
|
+
c12: "^3.3.4",
|
|
126
127
|
"cli-progress": "^3.12.0",
|
|
127
128
|
consola: "^3.2.3",
|
|
128
129
|
"date-fns": "^4.1.0",
|
package/dist/notify/cli.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const process = require('node:process');
|
|
4
4
|
const node_util = require('node:util');
|
|
5
|
-
const report = require('../shared/meodp.
|
|
5
|
+
const report = require('../shared/meodp.5f2d144f.cjs');
|
|
6
6
|
const load = require('../shared/meodp.63483e20.cjs');
|
|
7
7
|
const notify_feishu = require('./feishu.cjs');
|
|
8
8
|
const notify_index = require('./index.cjs');
|
package/dist/notify/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import { parseArgs } from 'node:util';
|
|
3
|
-
import { r as readReport } from '../shared/meodp.
|
|
3
|
+
import { r as readReport } from '../shared/meodp.72d12ced.mjs';
|
|
4
4
|
import { l as loadProjectConfig } from '../shared/meodp.f96d0510.mjs';
|
|
5
5
|
import { createFeishuCard, sendFeishuNotification } from './feishu.mjs';
|
|
6
6
|
import { createNotification } from './index.mjs';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { setTimeout } from 'node:timers/promises';
|
|
2
2
|
import { LinkChecker } from 'linkinator';
|
|
3
3
|
import { hostname } from 'node:os';
|
|
4
|
-
import { p as parseReport, c as createReportHtml, f as formatReport } from './meodp.
|
|
4
|
+
import { p as parseReport, c as createReportHtml, f as formatReport } from './meodp.72d12ced.mjs';
|
|
5
5
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
6
6
|
import { dirname, resolve, join } from 'node:path';
|
|
7
7
|
import process from 'node:process';
|
|
@@ -92,7 +92,7 @@ function parseReport(data) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
const viewerScript = '"use strict";(()=>{function H(e){let t=d=>{throw new TypeError(`Invalid or unsupported report: ${d}`)},n=d=>!d||typeof d!="object"||Array.isArray(d)?t("expected an object"):d,s=(d,r)=>typeof d=="string"?d:t(r),o=(d,r,p=0)=>typeof d=="number"&&Number.isSafeInteger(d)&&d>=p?d:t(r),c=(d,r)=>typeof d=="boolean"?d:t(r),i=(d,r)=>{let p=s(d,r);return Number.isFinite(Date.parse(p))?p:t(r)},u=d=>{let r=s(d,"URL");try{let p=new URL(r);if(!["https:","http:"].includes(p.protocol)||p.username||p.password)return t("URL must use HTTP(S) without credentials")}catch{return t("URL")}return r},h=n(e);if(h.schemaVersion!==1||!Array.isArray(h.results))return t("schemaVersion or results");let L=h.results.map(d=>{let r=n(d);if(!["reachable","restricted","unavailable"].includes(String(r.status))||!Array.isArray(r.redirects))return t("status or redirects");let p={url:u(r.url),finalUrl:u(r.finalUrl),status:r.status,checkedAt:i(r.checkedAt,"checkedAt"),durationMs:typeof r.durationMs=="number"&&Number.isFinite(r.durationMs)&&r.durationMs>=0?r.durationMs:t("durationMs"),attempts:o(r.attempts,"attempts",1),consecutiveFailures:o(r.consecutiveFailures,"consecutiveFailures"),changed:c(r.changed,"changed"),recovered:c(r.recovered,"recovered"),redirects:r.redirects.map(z=>{let A=n(z);return{url:u(A.url),status:o(A.status,"redirect status",100),location:s(A.location,"redirect location")}})};if(r.name!==void 0&&(p.name=s(r.name,"name")),r.httpStatus!==void 0&&(p.httpStatus=o(r.httpStatus,"httpStatus",100)),r.reason!==void 0){if(!["http","dns","tls","timeout","network","redirect"].includes(String(r.reason)))return t("reason");p.reason=r.reason}return r.detail!==void 0&&(p.detail=s(r.detail,"detail")),r.firstFailureAt!==void 0&&(p.firstFailureAt=i(r.firstFailureAt,"firstFailureAt")),r.lastSuccessAt!==void 0&&(p.lastSuccessAt=i(r.lastSuccessAt,"lastSuccessAt")),p}),m={total:L.length,reachable:0,restricted:0,unavailable:0,redirected:0,recovered:0};for(let d of L)m[d.status]++,m.redirected+=+(d.redirects.length>0),m.recovered+=Number(d.recovered);let P=n(h.summary);for(let[d,r]of Object.entries(m))if(P[d]!==r)return t(`summary.${d} does not match results`);return{schemaVersion:1,observer:s(h.observer,"observer"),startedAt:i(h.startedAt,"startedAt"),completedAt:i(h.completedAt,"completedAt"),summary:m,results:L}}var T={reachable:"\\u53EF\\u8BBF\\u95EE",restricted:"\\u8BBF\\u95EE\\u53D7\\u9650",unavailable:"\\u6682\\u4E0D\\u53EF\\u8FBE",redirected:"\\u6709\\u8DF3\\u8F6C",recovered:"\\u5DF2\\u6062\\u590D",all:"\\u5168\\u90E8"},O={http:"HTTP",dns:"DNS",tls:"TLS",timeout:"\\u8D85\\u65F6",network:"\\u7F51\\u7EDC\\u9519\\u8BEF",redirect:"\\u8DF3\\u8F6C\\u5F02\\u5E38"},k=20,N=10*1024*1024,l=e=>document.getElementById(e),$=l("import-dialog"),R=l("search"),w=l("sort"),V=l("rows"),x=l("data-url"),S=l("file"),f,v="all",g=0,y=0;function a(e,t,n){let s=document.createElement(e);return t!==void 0&&(s.textContent=t),n&&(s.className=n),s}function E(e){return e?new Date(e).toLocaleString("zh-CN",{hour12:!1}):"\\u2014"}function B(e){return e<1e3?`${Math.round(e)} ms`:`${(e/1e3).toFixed(1)} s`}function M(e="",t=!1){let n=l("message");n.textContent=e,n.hidden=!e,n.className=t?"error-message":"info-message"}function I(e,t=e){let n=a("a",t);return n.href=e,n.target="_blank",n.rel="noopener noreferrer",n}function j(){let e=f?.summary,t=l("metrics");t.replaceChildren();for(let s of["all","reachable","restricted","unavailable"]){let o=a("div",void 0,`metric ${s}`);o.append(a("span",s==="all"?"\\u5168\\u90E8\\u7AD9\\u70B9":T[s]),a("strong",String(e?e[s==="all"?"total":s]:"\\u2014"))),t.append(o)}let n=l("distribution");if(n.replaceChildren(),e?.total)for(let s of["reachable","restricted","unavailable"]){let o=a("span",void 0,s);o.style.width=`${e[s]/e.total*100}%`,n.append(o)}l("metadata").textContent=f?`${E(f.completedAt)} \\xB7 ${f.observer}`:"\\u52A0\\u8F7D\\u68C0\\u6D4B\\u6570\\u636E\\uFF0C\\u67E5\\u770B\\u7AD9\\u70B9\\u53EF\\u8BBF\\u95EE\\u6027\\u3002",l("download").disabled=!f}function U(){let e=l("filters");e.replaceChildren();let t=["all","unavailable","restricted","reachable","redirected"];f?.summary.recovered&&t.push("recovered");for(let n of t){let s=f?.summary[n==="all"?"total":n]??0,o=a("button",void 0,v===n?"selected":"");o.type="button",o.dataset.filter=n,o.setAttribute("aria-pressed",String(v===n)),o.append(a("span",T[n]),a("span",String(s),"filter-count")),o.addEventListener("click",()=>{v=n,g=0,U(),b(),l("filters").querySelector(`[data-filter="${n}"]`)?.focus()}),e.append(o)}}function q(e){let t=a("div",void 0,"detail-body");t.append(a("h3","\\u68C0\\u6D4B\\u8BE6\\u60C5"));let n=a("dl",void 0,"facts"),s=[["\\u8FDE\\u7EED\\u5931\\u8D25",`${e.consecutiveFailures} \\u6B21`],["\\u8BF7\\u6C42\\u5C1D\\u8BD5",`${e.attempts} \\u6B21`],["\\u6700\\u540E\\u6210\\u529F",E(e.lastSuccessAt)],["\\u9996\\u6B21\\u8FDE\\u7EED\\u5931\\u8D25",E(e.firstFailureAt)],["\\u68C0\\u6D4B\\u65F6\\u95F4",E(e.checkedAt)],["\\u8017\\u65F6",B(e.durationMs)],["HTTP / \\u539F\\u56E0",String(e.httpStatus??(e.reason?O[e.reason]:"\\u2014"))],["\\u72B6\\u6001\\u53D8\\u5316",e.recovered?"\\u672C\\u6B21\\u6062\\u590D\\u8BBF\\u95EE":e.changed?"\\u72B6\\u6001\\u6216\\u6700\\u7EC8 URL \\u5DF2\\u53D8\\u5316":"\\u65E0\\u53D8\\u5316"]];for(let[o,c]of s){let i=a("div");i.append(a("dt",o),a("dd",c)),n.append(i)}if(t.append(n),e.detail&&t.append(a("h4","\\u9519\\u8BEF\\u4FE1\\u606F"),a("pre",e.detail)),t.append(a("h4","\\u6700\\u7EC8 URL"),I(e.finalUrl)),e.redirects.length){t.append(a("h4","\\u8DF3\\u8F6C\\u94FE"));let o=a("ol",void 0,"redirect-chain");for(let c of e.redirects){let i=a("li");i.append(a("strong",String(c.status)),a("span",`${c.url} \\u2192 ${c.location}`)),o.append(i)}t.append(o)}return t}function K(e,t){let n=a("tr",void 0,"result-row"),s=a("td",void 0,"site");s.append(I(e.url,e.name||new URL(e.url).hostname),a("span",e.url,"site-url"));let o=a("td");o.append(a("span",T[e.status],`status ${e.status}`)),e.redirects.length&&o.append(a("span",`${e.redirects.length} \\u6B21\\u8DF3\\u8F6C`,"row-note")),e.recovered&&o.append(a("span","\\u672C\\u6B21\\u6062\\u590D","row-note"));let c=a("td",void 0,"detail-toggle"),i=a("button","\\u203A");i.type="button",i.setAttribute("aria-label",`\\u67E5\\u770B ${e.name||e.url} \\u7684\\u68C0\\u6D4B\\u8BE6\\u60C5`),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-controls",`detail-${t}`);let u=a("tr",void 0,"detail-row");u.hidden=!0,u.id=`detail-${t}`;let h=a("td");return h.colSpan=5,u.append(h),i.addEventListener("click",()=>{u.hidden=!u.hidden,i.setAttribute("aria-expanded",String(!u.hidden)),n.classList.toggle("expanded",!u.hidden),!u.hidden&&!h.childNodes.length&&h.append(q(e))}),c.append(i),n.append(s,o,a("td",String(e.httpStatus??(e.reason?O[e.reason]:"\\u2014")),"technical"),a("td",B(e.durationMs),"technical"),c),[n,u]}function b(){let e=R.value.trim().toLocaleLowerCase(),t=(f?.results??[]).filter(c=>(v==="all"||(v==="redirected"?c.redirects.length>0:v==="recovered"?c.recovered:c.status===v))&&`${c.name??""} ${c.url} ${c.finalUrl}`.toLocaleLowerCase().includes(e)),n={unavailable:0,restricted:1,reachable:2};w.value==="severity"&&t.sort((c,i)=>n[c.status]-n[i.status]),w.value==="duration"&&t.sort((c,i)=>i.durationMs-c.durationMs),w.value==="failures"&&t.sort((c,i)=>i.consecutiveFailures-c.consecutiveFailures),w.value==="name"&&t.sort((c,i)=>(c.name||c.url).localeCompare(i.name||i.url,"zh-CN")),g=Math.max(0,Math.min(g,Math.ceil(t.length/k)-1));let s=g*k;V.replaceChildren(...t.slice(s,s+k).flatMap((c,i)=>K(c,s+i))),l("table").hidden=!t.length;let o=l("empty");o.hidden=t.length>0,f&&o.replaceChildren(a("strong",f.results.length?"\\u6CA1\\u6709\\u5339\\u914D\\u7684\\u7AD9\\u70B9":"\\u8FD9\\u4EFD\\u62A5\\u544A\\u4E2D\\u6CA1\\u6709\\u7AD9\\u70B9"),a("span",f.results.length?"\\u8BD5\\u8BD5\\u5176\\u4ED6\\u5173\\u952E\\u8BCD\\u6216\\u72B6\\u6001\\u7B5B\\u9009\\u3002":"\\u52A0\\u8F7D\\u5176\\u4ED6\\u62A5\\u544A\\u4EE5\\u67E5\\u770B\\u68C0\\u6D4B\\u7ED3\\u679C\\u3002")),l("result-count").textContent=`\\u663E\\u793A ${t.length?s+1:0}\\u2013${Math.min(s+k,t.length)}\\uFF0C\\u5171 ${t.length} \\u4E2A\\u7AD9\\u70B9`,l("previous").disabled=g===0,l("next").disabled=s+k>=t.length}function C(e){let t=H(e);if(t.results.length>5e4)throw new Error("\\u62A5\\u544A\\u8D85\\u8FC7 50,000 \\u4E2A\\u7AD9\\u70B9\\uFF0C\\u8BF7\\u62C6\\u5206\\u540E\\u52A0\\u8F7D\\u3002");f=t,v="all",g=0,R.value="",w.value="original",j(),U(),b()}function F(e){M(`\\u52A0\\u8F7D\\u5931\\u8D25\\uFF1A${e instanceof Error?e.message:String(e)}\\u3002${f?"\\u5DF2\\u4FDD\\u7559\\u5F53\\u524D\\u62A5\\u544A\\u3002":""}`,!0)}async function D(e){let t=++y;$.close();try{if(e.size>N)throw new Error("JSON \\u6587\\u4EF6\\u4E0D\\u80FD\\u8D85\\u8FC7 10 MiB");let n=await e.text();if(t!==y)return;C(JSON.parse(n)),M(`\\u5DF2\\u52A0\\u8F7D ${e.name}`)}catch(n){t===y&&F(n)}S.value=""}async function J(e,t=!1){let n=++y;$.close(),(!t||!f)&&M("\\u6B63\\u5728\\u52A0\\u8F7D\\u62A5\\u544A\\u6570\\u636E\\u2026");try{let s=new URL(e,window.location.href);if(!["http:","https:"].includes(s.protocol)||s.username||s.password)throw new Error("\\u8BF7\\u4F7F\\u7528\\u4E0D\\u542B\\u8D26\\u53F7\\u5BC6\\u7801\\u7684 HTTP(S) \\u6570\\u636E URL\\uFF1B\\u672C\\u5730\\u62A5\\u544A\\u53EF\\u9009\\u62E9\\u6587\\u4EF6\\u52A0\\u8F7D");let o=await fetch(s,{credentials:"omit",cache:"no-store",signal:AbortSignal.timeout(15e3),referrerPolicy:"no-referrer"});if(!o.ok)throw new Error(`HTTP ${o.status}`);if(!o.body)throw new Error("\\u6570\\u636E\\u4E3A\\u7A7A");let c=o.body.getReader(),i=[],u=0;for(;;){let{done:L,value:m}=await c.read();if(L)break;if(u+=m.byteLength,u>N)throw await c.cancel(),new Error("JSON \\u6587\\u4EF6\\u4E0D\\u80FD\\u8D85\\u8FC7 10 MiB");i.push(m)}let h=await new Blob(i).text();if(n!==y)return;C(JSON.parse(h)),x.value=e,M(t?"":"\\u5DF2\\u52A0\\u8F7D\\u6700\\u65B0\\u62A5\\u544A\\u6570\\u636E\\u3002")}catch(s){n===y&&F(s)}}l("open-import").addEventListener("click",()=>$.showModal());l("empty-import").addEventListener("click",()=>S.click());S.addEventListener("change",()=>{S.files?.[0]&&D(S.files[0])});l("url-form").addEventListener("submit",e=>{e.preventDefault(),J(x.value.trim())});R.addEventListener("input",()=>{g=0,b()});w.addEventListener("change",()=>{g=0,b()});l("previous").addEventListener("click",()=>{g--,b()});l("next").addEventListener("click",()=>{g++,b()});l("download").addEventListener("click",()=>{if(!f)return;let e=URL.createObjectURL(new Blob([JSON.stringify(f,null,2)],{type:"application/json"})),t=a("a");t.href=e,t.download="report.json",t.click(),setTimeout(()=>URL.revokeObjectURL(e),1e3)});document.addEventListener("dragover",e=>{e.preventDefault()});document.addEventListener("drop",e=>{e.preventDefault();let t=e.dataTransfer?.files[0];t&&D(t)});j();U();b();try{let e=JSON.parse(l("meodp-data").textContent||"{}");e.report&&C(e.report),typeof e.dataUrl=="string"&&(x.value=e.dataUrl,window.location.protocol!=="file:"&&J(e.dataUrl,!0))}catch(e){F(e)}})();\n';
|
|
95
|
-
const viewerCss = ":root {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;\n color: #172033;\n background: #fff;\n font-synthesis: none;\n --muted: #66758a;\n --line: #e2e8f0;\n --blue: #2563eb;\n --green: #14805e;\n --amber: #98600b;\n --red: #ca4853;\n}\n* {\n box-sizing: border-box;\n}\nbody {\n margin: 0;\n font-size: 15px;\n line-height: 1.5;\n}\nbutton,\ninput,\nselect {\n font: inherit;\n font-size: 14px;\n}\nbutton,\nselect {\n cursor: pointer;\n}\nbutton {\n background: #fff;\n color: var(--muted);\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 9px 16px;\n transition: background 0.15s;\n}\nbutton:hover:not(:disabled) {\n background: #f1f6ff;\n color: var(--blue);\n}\nbutton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.primary {\n background: var(--blue);\n border-color: var(--blue);\n color: #fff;\n}\n.primary:hover:not(:disabled) {\n background: #1d4ed8;\n color: #fff;\n}\n:focus-visible {\n outline: 3px solid #93b6ff;\n outline-offset: 3px;\n}\ninput,\nselect {\n color: #172033;\n background: #fff;\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 11px 14px;\n min-width: 0;\n}\ninput::placeholder {\n color: var(--muted);\n}\nheader {\n border-bottom: 1px solid var(--line);\n}\n.header-inner {\n max-width: 1248px;\n padding: 14px 24px;\n margin: auto;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n.wordmark {\n font-size: 23px;\n font-weight: 750;\n letter-spacing: -0.8px;\n}\n.actions {\n display: flex;\n gap: 12px;\n}\nmain {\n max-width: 1248px;\n margin: 0 auto;\n padding: 36px 24px 48px;\n}\nh1 {\n font-size: 34px;\n line-height: 1.3;\n letter-spacing: -1px;\n margin: 0 0 6px;\n}\nh2 {\n font-size: 22px;\n margin: 0;\n}\nh3 {\n font-size: 14px;\n margin: 0 0 16px;\n}\nh4 {\n font-size: 13px;\n margin: 18px 0 8px;\n color: var(--muted);\n}\np {\n margin: 8px 0;\n}\n.muted,\n.note {\n color: var(--muted);\n}\n#metadata {\n overflow-wrap: anywhere;\n}\n.note {\n font-size: 13px;\n}\n.metrics {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n margin: 26px 0 16px;\n}\n.metric {\n padding: 0 32px;\n border-left: 1px solid var(--line);\n}\n.metric:first-child {\n padding-left: 0;\n border: 0;\n}\n.metric > span {\n color: var(--muted);\n font-size: 14px;\n display: block;\n}\n.metric > strong {\n font-size: 38px;\n font-weight: 650;\n line-height: 1.25;\n font-variant-numeric: tabular-nums;\n}\n.reachable {\n color: var(--green);\n}\n.restricted {\n color: var(--amber);\n}\n.unavailable {\n color: var(--red);\n}\n.distribution {\n height: 8px;\n display: flex;\n overflow: hidden;\n border-radius: 3px;\n background: #f1f5f9;\n}\n.distribution > span + span {\n border-left: 1px solid white;\n}\n.distribution .reachable {\n background: var(--green);\n}\n.distribution .restricted {\n background: #b47713;\n}\n.distribution .unavailable {\n background: var(--red);\n}\n#results {\n margin-top: 28px;\n}\n#filters {\n display: flex;\n gap: 18px;\n border-bottom: 1px solid var(--line);\n overflow-x: auto;\n}\n#filters button {\n padding: 12px 4px;\n border: none;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n white-space: nowrap;\n}\n#filters button.selected {\n color: var(--blue);\n border-bottom-color: var(--blue);\n font-weight: 600;\n}\n.filter-count {\n margin-left: 10px;\n font-variant-numeric: tabular-nums;\n}\n.toolbar {\n display: flex;\n gap: 14px;\n margin: 14px 0;\n}\n.search {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n position: relative;\n}\n.search > svg {\n position: absolute;\n left: 14px;\n font-size: 25px;\n color: var(--muted);\n line-height: 1;\n}\n.search input {\n width: 100%;\n padding-left: 44px;\n}\n.toolbar select {\n width: 200px;\n}\ntable {\n border-collapse: collapse;\n width: 100%;\n table-layout: fixed;\n font-size: 14px;\n}\nth {\n background: #f7f9fc;\n text-align: left;\n font-weight: 600;\n color: #43516a;\n padding: 12px 16px;\n}\nth:first-child {\n width: 37%;\n border-radius: 5px 0 0 5px;\n}\nth:nth-child(2) {\n width: 18%;\n}\nth:nth-child(3) {\n width: 21%;\n}\nth:nth-child(4) {\n width: 15%;\n}\nth:last-child {\n width: 9%;\n border-radius: 0 5px 5px 0;\n}\ntd {\n padding: 12px 16px;\n border-bottom: 1px solid var(--line);\n vertical-align: middle;\n font-variant-numeric: tabular-nums;\n}\na {\n color: inherit;\n text-decoration: none;\n}\na:hover {\n color: var(--blue);\n text-decoration: underline;\n}\n.site a {\n font-size: 15px;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n.site-url {\n display: block;\n font-size: 13px;\n color: var(--muted);\n overflow-wrap: anywhere;\n}\n.status {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n white-space: nowrap;\n}\n.status::before {\n content: '';\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: currentColor;\n flex-shrink: 0;\n}\n.row-note {\n display: block;\n color: var(--muted);\n font-size: 12px;\n margin-left: 18px;\n}\n.detail-toggle,\n.detail-heading {\n text-align: right;\n}\n.detail-toggle button {\n border: 0;\n font-size: 26px;\n line-height: 1;\n padding: 5px 12px;\n color: #172033;\n min-width: 40px;\n min-height: 40px;\n}\n.detail-toggle button[aria-expanded='true'] {\n transform: rotate(90deg);\n}\n.result-row:hover,\n.result-row.expanded {\n background: #fafcff;\n}\n.detail-row > td {\n padding: 0;\n}\n.detail-body {\n padding: 22px 24px;\n background: #f0f6ff;\n overflow-wrap: anywhere;\n}\n.facts {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px 24px;\n margin: 0;\n}\ndt {\n color: var(--muted);\n font-size: 12px;\n}\ndd {\n margin: 4px 0 0;\n font-size: 14px;\n}\npre {\n font-size: 13px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: #ae3440;\n margin: 0;\n}\n.detail-body a {\n color: var(--blue);\n}\n.redirect-chain {\n padding-left: 20px;\n margin: 8px 0 0;\n}\n.redirect-chain li {\n padding: 4px 0;\n}\n.redirect-chain strong {\n margin-right: 12px;\n}\n.pagination {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 16px;\n color: var(--muted);\n font-size: 13px;\n}\n.pagination > div {\n display: flex;\n gap: 12px;\n}\n.pagination button {\n padding: 7px 12px;\n}\n.empty {\n padding: 64px 16px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n color: var(--muted);\n text-align: center;\n border-block: 1px solid var(--line);\n}\n.empty span {\n font-size: 13px;\n}\n[hidden] {\n display: none !important;\n}\n#message {\n padding: 12px 16px;\n border-radius: 6px;\n overflow-wrap: anywhere;\n margin: 20px 0 0;\n font-size: 14px;\n}\n.error-message {\n background: #fff2f3;\n color: #ad3440;\n}\n.info-message {\n background: #eff6ff;\n color: #255aab;\n}\ndialog {\n width: min(560px, calc(100% - 32px));\n border: 1px solid var(--line);\n border-radius: 12px;\n padding: 28px;\n color: #172033;\n box-shadow: 0 24px 80px #17203325;\n}\ndialog::backdrop {\n background: #17203360;\n}\n.dialog-heading {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n}\n.dialog-heading button {\n border: 0;\n font-size: 24px;\n line-height: 1;\n padding: 8px;\n}\n.file-label {\n display: block;\n margin: 24px 0;\n font-weight: 600;\n}\n.file-label input {\n margin-top: 10px;\n display: block;\n width: 100%;\n font-weight: 400;\n}\n#url-form > label {\n display: block;\n margin-bottom: 10px;\n font-weight: 600;\n}\n.url-controls {\n display: flex;\n gap: 8px;\n margin-bottom: 14px;\n}\n.url-controls input {\n flex: 1;\n}\n.sr-only,\n.skip-link:not(:focus) {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n.skip-link:focus {\n display: block;\n padding: 8px;\n}\nnoscript {\n display: block;\n padding: 24px;\n}\n@media (max-width: 700px) {\n main {\n padding: 28px 18px;\n }\n .header-inner {\n padding: 12px 18px;\n }\n .wordmark {\n font-size: 21px;\n }\n .actions {\n gap: 8px;\n }\n .actions button {\n padding: 8px 10px;\n font-size: 13px;\n }\n h1 {\n font-size: 27px;\n letter-spacing: -0.5px;\n }\n #metadata {\n font-size: 13px;\n }\n .metrics {\n grid-template-columns: repeat(2, 1fr);\n gap: 20px 0;\n }\n .metric {\n padding-left: 24px;\n }\n .metric:nth-child(3) {\n padding-left: 0;\n border: 0;\n }\n .metric > strong {\n font-size: 32px;\n }\n #filters {\n gap: 16px;\n }\n .toolbar {\n flex-wrap: wrap;\n gap: 10px;\n }\n .search {\n flex-basis: 100%;\n }\n .toolbar select {\n width: 100%;\n }\n .technical {\n display: none;\n }\n th,\n td {\n padding: 12px 8px;\n }\n th:first-child {\n width: 55%;\n }\n th:nth-child(2) {\n width: 31%;\n }\n th:last-child {\n width: 14%;\n }\n .status {\n gap: 6px;\n font-size: 13px;\n }\n .site a {\n font-size: 14px;\n }\n .site-url {\n font-size: 12px;\n }\n .detail-toggle button {\n padding: 5px 8px;\n }\n .detail-body {\n padding: 20px 16px;\n }\n .facts {\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n }\n .pagination {\n align-items: flex-start;\n flex-wrap: wrap;\n }\n dialog {\n padding: 20px;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n * {\n transition: none !important;\n }\n}\n";
|
|
95
|
+
const viewerCss = ":root {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;\n color: #172033;\n background: #fff;\n font-synthesis: none;\n --muted: #66758a;\n --line: #e2e8f0;\n --blue: #2563eb;\n --green: #14805e;\n --amber: #98600b;\n --red: #ca4853;\n}\n* {\n box-sizing: border-box;\n}\nbody {\n margin: 0;\n font-size: 15px;\n line-height: 1.5;\n}\nbutton,\ninput,\nselect {\n font: inherit;\n font-size: 14px;\n}\nbutton,\nselect {\n cursor: pointer;\n}\nbutton {\n background: #fff;\n color: var(--muted);\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 9px 16px;\n transition: background 0.15s;\n}\nbutton:hover:not(:disabled) {\n background: #f1f6ff;\n color: var(--blue);\n}\nbutton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.primary {\n background: var(--blue);\n border-color: var(--blue);\n color: #fff;\n}\n.primary:hover:not(:disabled) {\n background: #1d4ed8;\n color: #fff;\n}\n:focus-visible {\n outline: 3px solid #93b6ff;\n outline-offset: 3px;\n}\ninput,\nselect {\n color: #172033;\n background: #fff;\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 11px 14px;\n min-width: 0;\n}\ninput::placeholder {\n color: var(--muted);\n}\nheader {\n border-bottom: 1px solid var(--line);\n}\n.header-inner {\n max-width: 1248px;\n padding: 14px 24px;\n margin: auto;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n.wordmark {\n font-size: 23px;\n font-weight: 750;\n letter-spacing: -0.8px;\n}\n.actions {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-left: auto;\n}\n.github-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 40px;\n height: 40px;\n border-radius: 6px;\n color: var(--muted);\n}\n.github-link:hover {\n background: #f1f6ff;\n color: var(--blue);\n}\nmain {\n max-width: 1248px;\n margin: 0 auto;\n padding: 36px 24px 48px;\n}\nh1 {\n font-size: 34px;\n line-height: 1.3;\n letter-spacing: -1px;\n margin: 0 0 6px;\n}\nh2 {\n font-size: 22px;\n margin: 0;\n}\nh3 {\n font-size: 14px;\n margin: 0 0 16px;\n}\nh4 {\n font-size: 13px;\n margin: 18px 0 8px;\n color: var(--muted);\n}\np {\n margin: 8px 0;\n}\n.muted,\n.note {\n color: var(--muted);\n}\n#metadata {\n overflow-wrap: anywhere;\n}\n.note {\n font-size: 13px;\n}\n.metrics {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n margin: 26px 0 16px;\n}\n.metric {\n padding: 0 32px;\n border-left: 1px solid var(--line);\n}\n.metric:first-child {\n padding-left: 0;\n border: 0;\n}\n.metric > span {\n color: var(--muted);\n font-size: 14px;\n display: block;\n}\n.metric > strong {\n font-size: 38px;\n font-weight: 650;\n line-height: 1.25;\n font-variant-numeric: tabular-nums;\n}\n.reachable {\n color: var(--green);\n}\n.restricted {\n color: var(--amber);\n}\n.unavailable {\n color: var(--red);\n}\n.distribution {\n height: 8px;\n display: flex;\n overflow: hidden;\n border-radius: 3px;\n background: #f1f5f9;\n}\n.distribution > span + span {\n border-left: 1px solid white;\n}\n.distribution .reachable {\n background: var(--green);\n}\n.distribution .restricted {\n background: #b47713;\n}\n.distribution .unavailable {\n background: var(--red);\n}\n#results {\n margin-top: 28px;\n}\n#filters {\n display: flex;\n gap: 18px;\n border-bottom: 1px solid var(--line);\n overflow-x: auto;\n}\n#filters button {\n padding: 12px 4px;\n border: none;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n white-space: nowrap;\n}\n#filters button.selected {\n color: var(--blue);\n border-bottom-color: var(--blue);\n font-weight: 600;\n}\n.filter-count {\n margin-left: 10px;\n font-variant-numeric: tabular-nums;\n}\n.toolbar {\n display: flex;\n gap: 14px;\n margin: 14px 0;\n}\n.search {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n position: relative;\n}\n.search > svg {\n position: absolute;\n left: 14px;\n font-size: 25px;\n color: var(--muted);\n line-height: 1;\n}\n.search input {\n width: 100%;\n padding-left: 44px;\n}\n.toolbar select {\n width: 200px;\n}\ntable {\n border-collapse: collapse;\n width: 100%;\n table-layout: fixed;\n font-size: 14px;\n}\nth {\n background: #f7f9fc;\n text-align: left;\n font-weight: 600;\n color: #43516a;\n padding: 12px 16px;\n}\nth:first-child {\n width: 37%;\n border-radius: 5px 0 0 5px;\n}\nth:nth-child(2) {\n width: 18%;\n}\nth:nth-child(3) {\n width: 21%;\n}\nth:nth-child(4) {\n width: 15%;\n}\nth:last-child {\n width: 9%;\n border-radius: 0 5px 5px 0;\n}\ntd {\n padding: 12px 16px;\n border-bottom: 1px solid var(--line);\n vertical-align: middle;\n font-variant-numeric: tabular-nums;\n}\na {\n color: inherit;\n text-decoration: none;\n}\na:hover {\n color: var(--blue);\n text-decoration: underline;\n}\n.site a {\n font-size: 15px;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n.site-url {\n display: block;\n font-size: 13px;\n color: var(--muted);\n overflow-wrap: anywhere;\n}\n.status {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n white-space: nowrap;\n}\n.status::before {\n content: '';\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: currentColor;\n flex-shrink: 0;\n}\n.row-note {\n display: block;\n color: var(--muted);\n font-size: 12px;\n margin-left: 18px;\n}\n.detail-toggle,\n.detail-heading {\n text-align: right;\n}\n.detail-toggle button {\n border: 0;\n font-size: 26px;\n line-height: 1;\n padding: 5px 12px;\n color: #172033;\n min-width: 40px;\n min-height: 40px;\n}\n.detail-toggle button[aria-expanded='true'] {\n transform: rotate(90deg);\n}\n.result-row:hover,\n.result-row.expanded {\n background: #fafcff;\n}\n.detail-row > td {\n padding: 0;\n}\n.detail-body {\n padding: 22px 24px;\n background: #f0f6ff;\n overflow-wrap: anywhere;\n}\n.facts {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px 24px;\n margin: 0;\n}\ndt {\n color: var(--muted);\n font-size: 12px;\n}\ndd {\n margin: 4px 0 0;\n font-size: 14px;\n}\npre {\n font-size: 13px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: #ae3440;\n margin: 0;\n}\n.detail-body a {\n color: var(--blue);\n}\n.redirect-chain {\n padding-left: 20px;\n margin: 8px 0 0;\n}\n.redirect-chain li {\n padding: 4px 0;\n}\n.redirect-chain strong {\n margin-right: 12px;\n}\n.pagination {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 16px;\n color: var(--muted);\n font-size: 13px;\n}\n.pagination > div {\n display: flex;\n gap: 12px;\n}\n.pagination button {\n padding: 7px 12px;\n}\n.empty {\n padding: 64px 16px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n color: var(--muted);\n text-align: center;\n border-block: 1px solid var(--line);\n}\n.empty span {\n font-size: 13px;\n}\n[hidden] {\n display: none !important;\n}\n#message {\n padding: 12px 16px;\n border-radius: 6px;\n overflow-wrap: anywhere;\n margin: 20px 0 0;\n font-size: 14px;\n}\n.error-message {\n background: #fff2f3;\n color: #ad3440;\n}\n.info-message {\n background: #eff6ff;\n color: #255aab;\n}\ndialog {\n width: min(560px, calc(100% - 32px));\n border: 1px solid var(--line);\n border-radius: 12px;\n padding: 28px;\n color: #172033;\n box-shadow: 0 24px 80px #17203325;\n}\ndialog::backdrop {\n background: #17203360;\n}\n.dialog-heading {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n}\n.dialog-heading button {\n border: 0;\n font-size: 24px;\n line-height: 1;\n padding: 8px;\n}\n.file-label {\n display: block;\n margin: 24px 0;\n font-weight: 600;\n}\n.file-label input {\n margin-top: 10px;\n display: block;\n width: 100%;\n font-weight: 400;\n}\n#url-form > label {\n display: block;\n margin-bottom: 10px;\n font-weight: 600;\n}\n.url-controls {\n display: flex;\n gap: 8px;\n margin-bottom: 14px;\n}\n.url-controls input {\n flex: 1;\n}\n.sr-only,\n.skip-link:not(:focus) {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n.skip-link:focus {\n display: block;\n padding: 8px;\n}\nnoscript {\n display: block;\n padding: 24px;\n}\n@media (max-width: 700px) {\n main {\n padding: 28px 18px;\n }\n .header-inner {\n padding: 12px 18px;\n }\n .wordmark {\n font-size: 21px;\n }\n .actions {\n gap: 8px;\n }\n .actions button {\n padding: 8px 10px;\n font-size: 13px;\n }\n h1 {\n font-size: 27px;\n letter-spacing: -0.5px;\n }\n #metadata {\n font-size: 13px;\n }\n .metrics {\n grid-template-columns: repeat(2, 1fr);\n gap: 20px 0;\n }\n .metric {\n padding-left: 24px;\n }\n .metric:nth-child(3) {\n padding-left: 0;\n border: 0;\n }\n .metric > strong {\n font-size: 32px;\n }\n #filters {\n gap: 16px;\n }\n .toolbar {\n flex-wrap: wrap;\n gap: 10px;\n }\n .search {\n flex-basis: 100%;\n }\n .toolbar select {\n width: 100%;\n }\n .technical {\n display: none;\n }\n th,\n td {\n padding: 12px 8px;\n }\n th:first-child {\n width: 55%;\n }\n th:nth-child(2) {\n width: 31%;\n }\n th:last-child {\n width: 14%;\n }\n .status {\n gap: 6px;\n font-size: 13px;\n }\n .site a {\n font-size: 14px;\n }\n .site-url {\n font-size: 12px;\n }\n .detail-toggle button {\n padding: 5px 8px;\n }\n .detail-body {\n padding: 20px 16px;\n }\n .facts {\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n }\n .pagination {\n align-items: flex-start;\n flex-wrap: wrap;\n }\n dialog {\n padding: 20px;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n * {\n transition: none !important;\n }\n}\n";
|
|
96
96
|
|
|
97
97
|
function createReportHtml(report, options = {}) {
|
|
98
98
|
if (options.dataUrl !== void 0) {
|
|
@@ -115,6 +115,9 @@ function createReportHtml(report, options = {}) {
|
|
|
115
115
|
<a class="skip-link" href="#results">\u8DF3\u5230\u68C0\u6D4B\u7ED3\u679C</a>
|
|
116
116
|
<header><div class="header-inner"><span class="wordmark">meodp</span><div class="actions">
|
|
117
117
|
<button id="open-import" type="button">\u52A0\u8F7D JSON</button><button id="download" class="primary" type="button" disabled>\u4E0B\u8F7D JSON</button>
|
|
118
|
+
<a class="github-link" href="https://github.com/YunYouJun/meodp" target="_blank" rel="noopener noreferrer" aria-label="meodp GitHub \u4ED3\u5E93\uFF08\u5728\u65B0\u6807\u7B7E\u9875\u6253\u5F00\uFF09" title="meodp on GitHub">
|
|
119
|
+
<svg width="22" height="22" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.65 7.65 0 0 1 2-.27c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg>
|
|
120
|
+
</a>
|
|
118
121
|
</div></div></header>
|
|
119
122
|
<main>
|
|
120
123
|
<section aria-labelledby="report-title"><h1 id="report-title">\u53CB\u94FE\u53EF\u8BBF\u95EE\u6027\u62A5\u544A</h1><p id="metadata" class="muted">\u52A0\u8F7D\u68C0\u6D4B\u6570\u636E\uFF0C\u67E5\u770B\u7AD9\u70B9\u53EF\u8BBF\u95EE\u6027\u3002</p>
|
|
@@ -90,7 +90,7 @@ function parseReport(data) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
const viewerScript = '"use strict";(()=>{function H(e){let t=d=>{throw new TypeError(`Invalid or unsupported report: ${d}`)},n=d=>!d||typeof d!="object"||Array.isArray(d)?t("expected an object"):d,s=(d,r)=>typeof d=="string"?d:t(r),o=(d,r,p=0)=>typeof d=="number"&&Number.isSafeInteger(d)&&d>=p?d:t(r),c=(d,r)=>typeof d=="boolean"?d:t(r),i=(d,r)=>{let p=s(d,r);return Number.isFinite(Date.parse(p))?p:t(r)},u=d=>{let r=s(d,"URL");try{let p=new URL(r);if(!["https:","http:"].includes(p.protocol)||p.username||p.password)return t("URL must use HTTP(S) without credentials")}catch{return t("URL")}return r},h=n(e);if(h.schemaVersion!==1||!Array.isArray(h.results))return t("schemaVersion or results");let L=h.results.map(d=>{let r=n(d);if(!["reachable","restricted","unavailable"].includes(String(r.status))||!Array.isArray(r.redirects))return t("status or redirects");let p={url:u(r.url),finalUrl:u(r.finalUrl),status:r.status,checkedAt:i(r.checkedAt,"checkedAt"),durationMs:typeof r.durationMs=="number"&&Number.isFinite(r.durationMs)&&r.durationMs>=0?r.durationMs:t("durationMs"),attempts:o(r.attempts,"attempts",1),consecutiveFailures:o(r.consecutiveFailures,"consecutiveFailures"),changed:c(r.changed,"changed"),recovered:c(r.recovered,"recovered"),redirects:r.redirects.map(z=>{let A=n(z);return{url:u(A.url),status:o(A.status,"redirect status",100),location:s(A.location,"redirect location")}})};if(r.name!==void 0&&(p.name=s(r.name,"name")),r.httpStatus!==void 0&&(p.httpStatus=o(r.httpStatus,"httpStatus",100)),r.reason!==void 0){if(!["http","dns","tls","timeout","network","redirect"].includes(String(r.reason)))return t("reason");p.reason=r.reason}return r.detail!==void 0&&(p.detail=s(r.detail,"detail")),r.firstFailureAt!==void 0&&(p.firstFailureAt=i(r.firstFailureAt,"firstFailureAt")),r.lastSuccessAt!==void 0&&(p.lastSuccessAt=i(r.lastSuccessAt,"lastSuccessAt")),p}),m={total:L.length,reachable:0,restricted:0,unavailable:0,redirected:0,recovered:0};for(let d of L)m[d.status]++,m.redirected+=+(d.redirects.length>0),m.recovered+=Number(d.recovered);let P=n(h.summary);for(let[d,r]of Object.entries(m))if(P[d]!==r)return t(`summary.${d} does not match results`);return{schemaVersion:1,observer:s(h.observer,"observer"),startedAt:i(h.startedAt,"startedAt"),completedAt:i(h.completedAt,"completedAt"),summary:m,results:L}}var T={reachable:"\\u53EF\\u8BBF\\u95EE",restricted:"\\u8BBF\\u95EE\\u53D7\\u9650",unavailable:"\\u6682\\u4E0D\\u53EF\\u8FBE",redirected:"\\u6709\\u8DF3\\u8F6C",recovered:"\\u5DF2\\u6062\\u590D",all:"\\u5168\\u90E8"},O={http:"HTTP",dns:"DNS",tls:"TLS",timeout:"\\u8D85\\u65F6",network:"\\u7F51\\u7EDC\\u9519\\u8BEF",redirect:"\\u8DF3\\u8F6C\\u5F02\\u5E38"},k=20,N=10*1024*1024,l=e=>document.getElementById(e),$=l("import-dialog"),R=l("search"),w=l("sort"),V=l("rows"),x=l("data-url"),S=l("file"),f,v="all",g=0,y=0;function a(e,t,n){let s=document.createElement(e);return t!==void 0&&(s.textContent=t),n&&(s.className=n),s}function E(e){return e?new Date(e).toLocaleString("zh-CN",{hour12:!1}):"\\u2014"}function B(e){return e<1e3?`${Math.round(e)} ms`:`${(e/1e3).toFixed(1)} s`}function M(e="",t=!1){let n=l("message");n.textContent=e,n.hidden=!e,n.className=t?"error-message":"info-message"}function I(e,t=e){let n=a("a",t);return n.href=e,n.target="_blank",n.rel="noopener noreferrer",n}function j(){let e=f?.summary,t=l("metrics");t.replaceChildren();for(let s of["all","reachable","restricted","unavailable"]){let o=a("div",void 0,`metric ${s}`);o.append(a("span",s==="all"?"\\u5168\\u90E8\\u7AD9\\u70B9":T[s]),a("strong",String(e?e[s==="all"?"total":s]:"\\u2014"))),t.append(o)}let n=l("distribution");if(n.replaceChildren(),e?.total)for(let s of["reachable","restricted","unavailable"]){let o=a("span",void 0,s);o.style.width=`${e[s]/e.total*100}%`,n.append(o)}l("metadata").textContent=f?`${E(f.completedAt)} \\xB7 ${f.observer}`:"\\u52A0\\u8F7D\\u68C0\\u6D4B\\u6570\\u636E\\uFF0C\\u67E5\\u770B\\u7AD9\\u70B9\\u53EF\\u8BBF\\u95EE\\u6027\\u3002",l("download").disabled=!f}function U(){let e=l("filters");e.replaceChildren();let t=["all","unavailable","restricted","reachable","redirected"];f?.summary.recovered&&t.push("recovered");for(let n of t){let s=f?.summary[n==="all"?"total":n]??0,o=a("button",void 0,v===n?"selected":"");o.type="button",o.dataset.filter=n,o.setAttribute("aria-pressed",String(v===n)),o.append(a("span",T[n]),a("span",String(s),"filter-count")),o.addEventListener("click",()=>{v=n,g=0,U(),b(),l("filters").querySelector(`[data-filter="${n}"]`)?.focus()}),e.append(o)}}function q(e){let t=a("div",void 0,"detail-body");t.append(a("h3","\\u68C0\\u6D4B\\u8BE6\\u60C5"));let n=a("dl",void 0,"facts"),s=[["\\u8FDE\\u7EED\\u5931\\u8D25",`${e.consecutiveFailures} \\u6B21`],["\\u8BF7\\u6C42\\u5C1D\\u8BD5",`${e.attempts} \\u6B21`],["\\u6700\\u540E\\u6210\\u529F",E(e.lastSuccessAt)],["\\u9996\\u6B21\\u8FDE\\u7EED\\u5931\\u8D25",E(e.firstFailureAt)],["\\u68C0\\u6D4B\\u65F6\\u95F4",E(e.checkedAt)],["\\u8017\\u65F6",B(e.durationMs)],["HTTP / \\u539F\\u56E0",String(e.httpStatus??(e.reason?O[e.reason]:"\\u2014"))],["\\u72B6\\u6001\\u53D8\\u5316",e.recovered?"\\u672C\\u6B21\\u6062\\u590D\\u8BBF\\u95EE":e.changed?"\\u72B6\\u6001\\u6216\\u6700\\u7EC8 URL \\u5DF2\\u53D8\\u5316":"\\u65E0\\u53D8\\u5316"]];for(let[o,c]of s){let i=a("div");i.append(a("dt",o),a("dd",c)),n.append(i)}if(t.append(n),e.detail&&t.append(a("h4","\\u9519\\u8BEF\\u4FE1\\u606F"),a("pre",e.detail)),t.append(a("h4","\\u6700\\u7EC8 URL"),I(e.finalUrl)),e.redirects.length){t.append(a("h4","\\u8DF3\\u8F6C\\u94FE"));let o=a("ol",void 0,"redirect-chain");for(let c of e.redirects){let i=a("li");i.append(a("strong",String(c.status)),a("span",`${c.url} \\u2192 ${c.location}`)),o.append(i)}t.append(o)}return t}function K(e,t){let n=a("tr",void 0,"result-row"),s=a("td",void 0,"site");s.append(I(e.url,e.name||new URL(e.url).hostname),a("span",e.url,"site-url"));let o=a("td");o.append(a("span",T[e.status],`status ${e.status}`)),e.redirects.length&&o.append(a("span",`${e.redirects.length} \\u6B21\\u8DF3\\u8F6C`,"row-note")),e.recovered&&o.append(a("span","\\u672C\\u6B21\\u6062\\u590D","row-note"));let c=a("td",void 0,"detail-toggle"),i=a("button","\\u203A");i.type="button",i.setAttribute("aria-label",`\\u67E5\\u770B ${e.name||e.url} \\u7684\\u68C0\\u6D4B\\u8BE6\\u60C5`),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-controls",`detail-${t}`);let u=a("tr",void 0,"detail-row");u.hidden=!0,u.id=`detail-${t}`;let h=a("td");return h.colSpan=5,u.append(h),i.addEventListener("click",()=>{u.hidden=!u.hidden,i.setAttribute("aria-expanded",String(!u.hidden)),n.classList.toggle("expanded",!u.hidden),!u.hidden&&!h.childNodes.length&&h.append(q(e))}),c.append(i),n.append(s,o,a("td",String(e.httpStatus??(e.reason?O[e.reason]:"\\u2014")),"technical"),a("td",B(e.durationMs),"technical"),c),[n,u]}function b(){let e=R.value.trim().toLocaleLowerCase(),t=(f?.results??[]).filter(c=>(v==="all"||(v==="redirected"?c.redirects.length>0:v==="recovered"?c.recovered:c.status===v))&&`${c.name??""} ${c.url} ${c.finalUrl}`.toLocaleLowerCase().includes(e)),n={unavailable:0,restricted:1,reachable:2};w.value==="severity"&&t.sort((c,i)=>n[c.status]-n[i.status]),w.value==="duration"&&t.sort((c,i)=>i.durationMs-c.durationMs),w.value==="failures"&&t.sort((c,i)=>i.consecutiveFailures-c.consecutiveFailures),w.value==="name"&&t.sort((c,i)=>(c.name||c.url).localeCompare(i.name||i.url,"zh-CN")),g=Math.max(0,Math.min(g,Math.ceil(t.length/k)-1));let s=g*k;V.replaceChildren(...t.slice(s,s+k).flatMap((c,i)=>K(c,s+i))),l("table").hidden=!t.length;let o=l("empty");o.hidden=t.length>0,f&&o.replaceChildren(a("strong",f.results.length?"\\u6CA1\\u6709\\u5339\\u914D\\u7684\\u7AD9\\u70B9":"\\u8FD9\\u4EFD\\u62A5\\u544A\\u4E2D\\u6CA1\\u6709\\u7AD9\\u70B9"),a("span",f.results.length?"\\u8BD5\\u8BD5\\u5176\\u4ED6\\u5173\\u952E\\u8BCD\\u6216\\u72B6\\u6001\\u7B5B\\u9009\\u3002":"\\u52A0\\u8F7D\\u5176\\u4ED6\\u62A5\\u544A\\u4EE5\\u67E5\\u770B\\u68C0\\u6D4B\\u7ED3\\u679C\\u3002")),l("result-count").textContent=`\\u663E\\u793A ${t.length?s+1:0}\\u2013${Math.min(s+k,t.length)}\\uFF0C\\u5171 ${t.length} \\u4E2A\\u7AD9\\u70B9`,l("previous").disabled=g===0,l("next").disabled=s+k>=t.length}function C(e){let t=H(e);if(t.results.length>5e4)throw new Error("\\u62A5\\u544A\\u8D85\\u8FC7 50,000 \\u4E2A\\u7AD9\\u70B9\\uFF0C\\u8BF7\\u62C6\\u5206\\u540E\\u52A0\\u8F7D\\u3002");f=t,v="all",g=0,R.value="",w.value="original",j(),U(),b()}function F(e){M(`\\u52A0\\u8F7D\\u5931\\u8D25\\uFF1A${e instanceof Error?e.message:String(e)}\\u3002${f?"\\u5DF2\\u4FDD\\u7559\\u5F53\\u524D\\u62A5\\u544A\\u3002":""}`,!0)}async function D(e){let t=++y;$.close();try{if(e.size>N)throw new Error("JSON \\u6587\\u4EF6\\u4E0D\\u80FD\\u8D85\\u8FC7 10 MiB");let n=await e.text();if(t!==y)return;C(JSON.parse(n)),M(`\\u5DF2\\u52A0\\u8F7D ${e.name}`)}catch(n){t===y&&F(n)}S.value=""}async function J(e,t=!1){let n=++y;$.close(),(!t||!f)&&M("\\u6B63\\u5728\\u52A0\\u8F7D\\u62A5\\u544A\\u6570\\u636E\\u2026");try{let s=new URL(e,window.location.href);if(!["http:","https:"].includes(s.protocol)||s.username||s.password)throw new Error("\\u8BF7\\u4F7F\\u7528\\u4E0D\\u542B\\u8D26\\u53F7\\u5BC6\\u7801\\u7684 HTTP(S) \\u6570\\u636E URL\\uFF1B\\u672C\\u5730\\u62A5\\u544A\\u53EF\\u9009\\u62E9\\u6587\\u4EF6\\u52A0\\u8F7D");let o=await fetch(s,{credentials:"omit",cache:"no-store",signal:AbortSignal.timeout(15e3),referrerPolicy:"no-referrer"});if(!o.ok)throw new Error(`HTTP ${o.status}`);if(!o.body)throw new Error("\\u6570\\u636E\\u4E3A\\u7A7A");let c=o.body.getReader(),i=[],u=0;for(;;){let{done:L,value:m}=await c.read();if(L)break;if(u+=m.byteLength,u>N)throw await c.cancel(),new Error("JSON \\u6587\\u4EF6\\u4E0D\\u80FD\\u8D85\\u8FC7 10 MiB");i.push(m)}let h=await new Blob(i).text();if(n!==y)return;C(JSON.parse(h)),x.value=e,M(t?"":"\\u5DF2\\u52A0\\u8F7D\\u6700\\u65B0\\u62A5\\u544A\\u6570\\u636E\\u3002")}catch(s){n===y&&F(s)}}l("open-import").addEventListener("click",()=>$.showModal());l("empty-import").addEventListener("click",()=>S.click());S.addEventListener("change",()=>{S.files?.[0]&&D(S.files[0])});l("url-form").addEventListener("submit",e=>{e.preventDefault(),J(x.value.trim())});R.addEventListener("input",()=>{g=0,b()});w.addEventListener("change",()=>{g=0,b()});l("previous").addEventListener("click",()=>{g--,b()});l("next").addEventListener("click",()=>{g++,b()});l("download").addEventListener("click",()=>{if(!f)return;let e=URL.createObjectURL(new Blob([JSON.stringify(f,null,2)],{type:"application/json"})),t=a("a");t.href=e,t.download="report.json",t.click(),setTimeout(()=>URL.revokeObjectURL(e),1e3)});document.addEventListener("dragover",e=>{e.preventDefault()});document.addEventListener("drop",e=>{e.preventDefault();let t=e.dataTransfer?.files[0];t&&D(t)});j();U();b();try{let e=JSON.parse(l("meodp-data").textContent||"{}");e.report&&C(e.report),typeof e.dataUrl=="string"&&(x.value=e.dataUrl,window.location.protocol!=="file:"&&J(e.dataUrl,!0))}catch(e){F(e)}})();\n';
|
|
93
|
-
const viewerCss = ":root {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;\n color: #172033;\n background: #fff;\n font-synthesis: none;\n --muted: #66758a;\n --line: #e2e8f0;\n --blue: #2563eb;\n --green: #14805e;\n --amber: #98600b;\n --red: #ca4853;\n}\n* {\n box-sizing: border-box;\n}\nbody {\n margin: 0;\n font-size: 15px;\n line-height: 1.5;\n}\nbutton,\ninput,\nselect {\n font: inherit;\n font-size: 14px;\n}\nbutton,\nselect {\n cursor: pointer;\n}\nbutton {\n background: #fff;\n color: var(--muted);\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 9px 16px;\n transition: background 0.15s;\n}\nbutton:hover:not(:disabled) {\n background: #f1f6ff;\n color: var(--blue);\n}\nbutton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.primary {\n background: var(--blue);\n border-color: var(--blue);\n color: #fff;\n}\n.primary:hover:not(:disabled) {\n background: #1d4ed8;\n color: #fff;\n}\n:focus-visible {\n outline: 3px solid #93b6ff;\n outline-offset: 3px;\n}\ninput,\nselect {\n color: #172033;\n background: #fff;\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 11px 14px;\n min-width: 0;\n}\ninput::placeholder {\n color: var(--muted);\n}\nheader {\n border-bottom: 1px solid var(--line);\n}\n.header-inner {\n max-width: 1248px;\n padding: 14px 24px;\n margin: auto;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n.wordmark {\n font-size: 23px;\n font-weight: 750;\n letter-spacing: -0.8px;\n}\n.actions {\n display: flex;\n gap: 12px;\n}\nmain {\n max-width: 1248px;\n margin: 0 auto;\n padding: 36px 24px 48px;\n}\nh1 {\n font-size: 34px;\n line-height: 1.3;\n letter-spacing: -1px;\n margin: 0 0 6px;\n}\nh2 {\n font-size: 22px;\n margin: 0;\n}\nh3 {\n font-size: 14px;\n margin: 0 0 16px;\n}\nh4 {\n font-size: 13px;\n margin: 18px 0 8px;\n color: var(--muted);\n}\np {\n margin: 8px 0;\n}\n.muted,\n.note {\n color: var(--muted);\n}\n#metadata {\n overflow-wrap: anywhere;\n}\n.note {\n font-size: 13px;\n}\n.metrics {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n margin: 26px 0 16px;\n}\n.metric {\n padding: 0 32px;\n border-left: 1px solid var(--line);\n}\n.metric:first-child {\n padding-left: 0;\n border: 0;\n}\n.metric > span {\n color: var(--muted);\n font-size: 14px;\n display: block;\n}\n.metric > strong {\n font-size: 38px;\n font-weight: 650;\n line-height: 1.25;\n font-variant-numeric: tabular-nums;\n}\n.reachable {\n color: var(--green);\n}\n.restricted {\n color: var(--amber);\n}\n.unavailable {\n color: var(--red);\n}\n.distribution {\n height: 8px;\n display: flex;\n overflow: hidden;\n border-radius: 3px;\n background: #f1f5f9;\n}\n.distribution > span + span {\n border-left: 1px solid white;\n}\n.distribution .reachable {\n background: var(--green);\n}\n.distribution .restricted {\n background: #b47713;\n}\n.distribution .unavailable {\n background: var(--red);\n}\n#results {\n margin-top: 28px;\n}\n#filters {\n display: flex;\n gap: 18px;\n border-bottom: 1px solid var(--line);\n overflow-x: auto;\n}\n#filters button {\n padding: 12px 4px;\n border: none;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n white-space: nowrap;\n}\n#filters button.selected {\n color: var(--blue);\n border-bottom-color: var(--blue);\n font-weight: 600;\n}\n.filter-count {\n margin-left: 10px;\n font-variant-numeric: tabular-nums;\n}\n.toolbar {\n display: flex;\n gap: 14px;\n margin: 14px 0;\n}\n.search {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n position: relative;\n}\n.search > svg {\n position: absolute;\n left: 14px;\n font-size: 25px;\n color: var(--muted);\n line-height: 1;\n}\n.search input {\n width: 100%;\n padding-left: 44px;\n}\n.toolbar select {\n width: 200px;\n}\ntable {\n border-collapse: collapse;\n width: 100%;\n table-layout: fixed;\n font-size: 14px;\n}\nth {\n background: #f7f9fc;\n text-align: left;\n font-weight: 600;\n color: #43516a;\n padding: 12px 16px;\n}\nth:first-child {\n width: 37%;\n border-radius: 5px 0 0 5px;\n}\nth:nth-child(2) {\n width: 18%;\n}\nth:nth-child(3) {\n width: 21%;\n}\nth:nth-child(4) {\n width: 15%;\n}\nth:last-child {\n width: 9%;\n border-radius: 0 5px 5px 0;\n}\ntd {\n padding: 12px 16px;\n border-bottom: 1px solid var(--line);\n vertical-align: middle;\n font-variant-numeric: tabular-nums;\n}\na {\n color: inherit;\n text-decoration: none;\n}\na:hover {\n color: var(--blue);\n text-decoration: underline;\n}\n.site a {\n font-size: 15px;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n.site-url {\n display: block;\n font-size: 13px;\n color: var(--muted);\n overflow-wrap: anywhere;\n}\n.status {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n white-space: nowrap;\n}\n.status::before {\n content: '';\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: currentColor;\n flex-shrink: 0;\n}\n.row-note {\n display: block;\n color: var(--muted);\n font-size: 12px;\n margin-left: 18px;\n}\n.detail-toggle,\n.detail-heading {\n text-align: right;\n}\n.detail-toggle button {\n border: 0;\n font-size: 26px;\n line-height: 1;\n padding: 5px 12px;\n color: #172033;\n min-width: 40px;\n min-height: 40px;\n}\n.detail-toggle button[aria-expanded='true'] {\n transform: rotate(90deg);\n}\n.result-row:hover,\n.result-row.expanded {\n background: #fafcff;\n}\n.detail-row > td {\n padding: 0;\n}\n.detail-body {\n padding: 22px 24px;\n background: #f0f6ff;\n overflow-wrap: anywhere;\n}\n.facts {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px 24px;\n margin: 0;\n}\ndt {\n color: var(--muted);\n font-size: 12px;\n}\ndd {\n margin: 4px 0 0;\n font-size: 14px;\n}\npre {\n font-size: 13px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: #ae3440;\n margin: 0;\n}\n.detail-body a {\n color: var(--blue);\n}\n.redirect-chain {\n padding-left: 20px;\n margin: 8px 0 0;\n}\n.redirect-chain li {\n padding: 4px 0;\n}\n.redirect-chain strong {\n margin-right: 12px;\n}\n.pagination {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 16px;\n color: var(--muted);\n font-size: 13px;\n}\n.pagination > div {\n display: flex;\n gap: 12px;\n}\n.pagination button {\n padding: 7px 12px;\n}\n.empty {\n padding: 64px 16px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n color: var(--muted);\n text-align: center;\n border-block: 1px solid var(--line);\n}\n.empty span {\n font-size: 13px;\n}\n[hidden] {\n display: none !important;\n}\n#message {\n padding: 12px 16px;\n border-radius: 6px;\n overflow-wrap: anywhere;\n margin: 20px 0 0;\n font-size: 14px;\n}\n.error-message {\n background: #fff2f3;\n color: #ad3440;\n}\n.info-message {\n background: #eff6ff;\n color: #255aab;\n}\ndialog {\n width: min(560px, calc(100% - 32px));\n border: 1px solid var(--line);\n border-radius: 12px;\n padding: 28px;\n color: #172033;\n box-shadow: 0 24px 80px #17203325;\n}\ndialog::backdrop {\n background: #17203360;\n}\n.dialog-heading {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n}\n.dialog-heading button {\n border: 0;\n font-size: 24px;\n line-height: 1;\n padding: 8px;\n}\n.file-label {\n display: block;\n margin: 24px 0;\n font-weight: 600;\n}\n.file-label input {\n margin-top: 10px;\n display: block;\n width: 100%;\n font-weight: 400;\n}\n#url-form > label {\n display: block;\n margin-bottom: 10px;\n font-weight: 600;\n}\n.url-controls {\n display: flex;\n gap: 8px;\n margin-bottom: 14px;\n}\n.url-controls input {\n flex: 1;\n}\n.sr-only,\n.skip-link:not(:focus) {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n.skip-link:focus {\n display: block;\n padding: 8px;\n}\nnoscript {\n display: block;\n padding: 24px;\n}\n@media (max-width: 700px) {\n main {\n padding: 28px 18px;\n }\n .header-inner {\n padding: 12px 18px;\n }\n .wordmark {\n font-size: 21px;\n }\n .actions {\n gap: 8px;\n }\n .actions button {\n padding: 8px 10px;\n font-size: 13px;\n }\n h1 {\n font-size: 27px;\n letter-spacing: -0.5px;\n }\n #metadata {\n font-size: 13px;\n }\n .metrics {\n grid-template-columns: repeat(2, 1fr);\n gap: 20px 0;\n }\n .metric {\n padding-left: 24px;\n }\n .metric:nth-child(3) {\n padding-left: 0;\n border: 0;\n }\n .metric > strong {\n font-size: 32px;\n }\n #filters {\n gap: 16px;\n }\n .toolbar {\n flex-wrap: wrap;\n gap: 10px;\n }\n .search {\n flex-basis: 100%;\n }\n .toolbar select {\n width: 100%;\n }\n .technical {\n display: none;\n }\n th,\n td {\n padding: 12px 8px;\n }\n th:first-child {\n width: 55%;\n }\n th:nth-child(2) {\n width: 31%;\n }\n th:last-child {\n width: 14%;\n }\n .status {\n gap: 6px;\n font-size: 13px;\n }\n .site a {\n font-size: 14px;\n }\n .site-url {\n font-size: 12px;\n }\n .detail-toggle button {\n padding: 5px 8px;\n }\n .detail-body {\n padding: 20px 16px;\n }\n .facts {\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n }\n .pagination {\n align-items: flex-start;\n flex-wrap: wrap;\n }\n dialog {\n padding: 20px;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n * {\n transition: none !important;\n }\n}\n";
|
|
93
|
+
const viewerCss = ":root {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;\n color: #172033;\n background: #fff;\n font-synthesis: none;\n --muted: #66758a;\n --line: #e2e8f0;\n --blue: #2563eb;\n --green: #14805e;\n --amber: #98600b;\n --red: #ca4853;\n}\n* {\n box-sizing: border-box;\n}\nbody {\n margin: 0;\n font-size: 15px;\n line-height: 1.5;\n}\nbutton,\ninput,\nselect {\n font: inherit;\n font-size: 14px;\n}\nbutton,\nselect {\n cursor: pointer;\n}\nbutton {\n background: #fff;\n color: var(--muted);\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 9px 16px;\n transition: background 0.15s;\n}\nbutton:hover:not(:disabled) {\n background: #f1f6ff;\n color: var(--blue);\n}\nbutton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.primary {\n background: var(--blue);\n border-color: var(--blue);\n color: #fff;\n}\n.primary:hover:not(:disabled) {\n background: #1d4ed8;\n color: #fff;\n}\n:focus-visible {\n outline: 3px solid #93b6ff;\n outline-offset: 3px;\n}\ninput,\nselect {\n color: #172033;\n background: #fff;\n border: 1px solid #d6deea;\n border-radius: 6px;\n padding: 11px 14px;\n min-width: 0;\n}\ninput::placeholder {\n color: var(--muted);\n}\nheader {\n border-bottom: 1px solid var(--line);\n}\n.header-inner {\n max-width: 1248px;\n padding: 14px 24px;\n margin: auto;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n.wordmark {\n font-size: 23px;\n font-weight: 750;\n letter-spacing: -0.8px;\n}\n.actions {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-left: auto;\n}\n.github-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 40px;\n height: 40px;\n border-radius: 6px;\n color: var(--muted);\n}\n.github-link:hover {\n background: #f1f6ff;\n color: var(--blue);\n}\nmain {\n max-width: 1248px;\n margin: 0 auto;\n padding: 36px 24px 48px;\n}\nh1 {\n font-size: 34px;\n line-height: 1.3;\n letter-spacing: -1px;\n margin: 0 0 6px;\n}\nh2 {\n font-size: 22px;\n margin: 0;\n}\nh3 {\n font-size: 14px;\n margin: 0 0 16px;\n}\nh4 {\n font-size: 13px;\n margin: 18px 0 8px;\n color: var(--muted);\n}\np {\n margin: 8px 0;\n}\n.muted,\n.note {\n color: var(--muted);\n}\n#metadata {\n overflow-wrap: anywhere;\n}\n.note {\n font-size: 13px;\n}\n.metrics {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n margin: 26px 0 16px;\n}\n.metric {\n padding: 0 32px;\n border-left: 1px solid var(--line);\n}\n.metric:first-child {\n padding-left: 0;\n border: 0;\n}\n.metric > span {\n color: var(--muted);\n font-size: 14px;\n display: block;\n}\n.metric > strong {\n font-size: 38px;\n font-weight: 650;\n line-height: 1.25;\n font-variant-numeric: tabular-nums;\n}\n.reachable {\n color: var(--green);\n}\n.restricted {\n color: var(--amber);\n}\n.unavailable {\n color: var(--red);\n}\n.distribution {\n height: 8px;\n display: flex;\n overflow: hidden;\n border-radius: 3px;\n background: #f1f5f9;\n}\n.distribution > span + span {\n border-left: 1px solid white;\n}\n.distribution .reachable {\n background: var(--green);\n}\n.distribution .restricted {\n background: #b47713;\n}\n.distribution .unavailable {\n background: var(--red);\n}\n#results {\n margin-top: 28px;\n}\n#filters {\n display: flex;\n gap: 18px;\n border-bottom: 1px solid var(--line);\n overflow-x: auto;\n}\n#filters button {\n padding: 12px 4px;\n border: none;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n white-space: nowrap;\n}\n#filters button.selected {\n color: var(--blue);\n border-bottom-color: var(--blue);\n font-weight: 600;\n}\n.filter-count {\n margin-left: 10px;\n font-variant-numeric: tabular-nums;\n}\n.toolbar {\n display: flex;\n gap: 14px;\n margin: 14px 0;\n}\n.search {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n position: relative;\n}\n.search > svg {\n position: absolute;\n left: 14px;\n font-size: 25px;\n color: var(--muted);\n line-height: 1;\n}\n.search input {\n width: 100%;\n padding-left: 44px;\n}\n.toolbar select {\n width: 200px;\n}\ntable {\n border-collapse: collapse;\n width: 100%;\n table-layout: fixed;\n font-size: 14px;\n}\nth {\n background: #f7f9fc;\n text-align: left;\n font-weight: 600;\n color: #43516a;\n padding: 12px 16px;\n}\nth:first-child {\n width: 37%;\n border-radius: 5px 0 0 5px;\n}\nth:nth-child(2) {\n width: 18%;\n}\nth:nth-child(3) {\n width: 21%;\n}\nth:nth-child(4) {\n width: 15%;\n}\nth:last-child {\n width: 9%;\n border-radius: 0 5px 5px 0;\n}\ntd {\n padding: 12px 16px;\n border-bottom: 1px solid var(--line);\n vertical-align: middle;\n font-variant-numeric: tabular-nums;\n}\na {\n color: inherit;\n text-decoration: none;\n}\na:hover {\n color: var(--blue);\n text-decoration: underline;\n}\n.site a {\n font-size: 15px;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n.site-url {\n display: block;\n font-size: 13px;\n color: var(--muted);\n overflow-wrap: anywhere;\n}\n.status {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n white-space: nowrap;\n}\n.status::before {\n content: '';\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: currentColor;\n flex-shrink: 0;\n}\n.row-note {\n display: block;\n color: var(--muted);\n font-size: 12px;\n margin-left: 18px;\n}\n.detail-toggle,\n.detail-heading {\n text-align: right;\n}\n.detail-toggle button {\n border: 0;\n font-size: 26px;\n line-height: 1;\n padding: 5px 12px;\n color: #172033;\n min-width: 40px;\n min-height: 40px;\n}\n.detail-toggle button[aria-expanded='true'] {\n transform: rotate(90deg);\n}\n.result-row:hover,\n.result-row.expanded {\n background: #fafcff;\n}\n.detail-row > td {\n padding: 0;\n}\n.detail-body {\n padding: 22px 24px;\n background: #f0f6ff;\n overflow-wrap: anywhere;\n}\n.facts {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px 24px;\n margin: 0;\n}\ndt {\n color: var(--muted);\n font-size: 12px;\n}\ndd {\n margin: 4px 0 0;\n font-size: 14px;\n}\npre {\n font-size: 13px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: #ae3440;\n margin: 0;\n}\n.detail-body a {\n color: var(--blue);\n}\n.redirect-chain {\n padding-left: 20px;\n margin: 8px 0 0;\n}\n.redirect-chain li {\n padding: 4px 0;\n}\n.redirect-chain strong {\n margin-right: 12px;\n}\n.pagination {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 16px;\n color: var(--muted);\n font-size: 13px;\n}\n.pagination > div {\n display: flex;\n gap: 12px;\n}\n.pagination button {\n padding: 7px 12px;\n}\n.empty {\n padding: 64px 16px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n color: var(--muted);\n text-align: center;\n border-block: 1px solid var(--line);\n}\n.empty span {\n font-size: 13px;\n}\n[hidden] {\n display: none !important;\n}\n#message {\n padding: 12px 16px;\n border-radius: 6px;\n overflow-wrap: anywhere;\n margin: 20px 0 0;\n font-size: 14px;\n}\n.error-message {\n background: #fff2f3;\n color: #ad3440;\n}\n.info-message {\n background: #eff6ff;\n color: #255aab;\n}\ndialog {\n width: min(560px, calc(100% - 32px));\n border: 1px solid var(--line);\n border-radius: 12px;\n padding: 28px;\n color: #172033;\n box-shadow: 0 24px 80px #17203325;\n}\ndialog::backdrop {\n background: #17203360;\n}\n.dialog-heading {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n}\n.dialog-heading button {\n border: 0;\n font-size: 24px;\n line-height: 1;\n padding: 8px;\n}\n.file-label {\n display: block;\n margin: 24px 0;\n font-weight: 600;\n}\n.file-label input {\n margin-top: 10px;\n display: block;\n width: 100%;\n font-weight: 400;\n}\n#url-form > label {\n display: block;\n margin-bottom: 10px;\n font-weight: 600;\n}\n.url-controls {\n display: flex;\n gap: 8px;\n margin-bottom: 14px;\n}\n.url-controls input {\n flex: 1;\n}\n.sr-only,\n.skip-link:not(:focus) {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n.skip-link:focus {\n display: block;\n padding: 8px;\n}\nnoscript {\n display: block;\n padding: 24px;\n}\n@media (max-width: 700px) {\n main {\n padding: 28px 18px;\n }\n .header-inner {\n padding: 12px 18px;\n }\n .wordmark {\n font-size: 21px;\n }\n .actions {\n gap: 8px;\n }\n .actions button {\n padding: 8px 10px;\n font-size: 13px;\n }\n h1 {\n font-size: 27px;\n letter-spacing: -0.5px;\n }\n #metadata {\n font-size: 13px;\n }\n .metrics {\n grid-template-columns: repeat(2, 1fr);\n gap: 20px 0;\n }\n .metric {\n padding-left: 24px;\n }\n .metric:nth-child(3) {\n padding-left: 0;\n border: 0;\n }\n .metric > strong {\n font-size: 32px;\n }\n #filters {\n gap: 16px;\n }\n .toolbar {\n flex-wrap: wrap;\n gap: 10px;\n }\n .search {\n flex-basis: 100%;\n }\n .toolbar select {\n width: 100%;\n }\n .technical {\n display: none;\n }\n th,\n td {\n padding: 12px 8px;\n }\n th:first-child {\n width: 55%;\n }\n th:nth-child(2) {\n width: 31%;\n }\n th:last-child {\n width: 14%;\n }\n .status {\n gap: 6px;\n font-size: 13px;\n }\n .site a {\n font-size: 14px;\n }\n .site-url {\n font-size: 12px;\n }\n .detail-toggle button {\n padding: 5px 8px;\n }\n .detail-body {\n padding: 20px 16px;\n }\n .facts {\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n }\n .pagination {\n align-items: flex-start;\n flex-wrap: wrap;\n }\n dialog {\n padding: 20px;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n * {\n transition: none !important;\n }\n}\n";
|
|
94
94
|
|
|
95
95
|
function createReportHtml(report, options = {}) {
|
|
96
96
|
if (options.dataUrl !== void 0) {
|
|
@@ -113,6 +113,9 @@ function createReportHtml(report, options = {}) {
|
|
|
113
113
|
<a class="skip-link" href="#results">\u8DF3\u5230\u68C0\u6D4B\u7ED3\u679C</a>
|
|
114
114
|
<header><div class="header-inner"><span class="wordmark">meodp</span><div class="actions">
|
|
115
115
|
<button id="open-import" type="button">\u52A0\u8F7D JSON</button><button id="download" class="primary" type="button" disabled>\u4E0B\u8F7D JSON</button>
|
|
116
|
+
<a class="github-link" href="https://github.com/YunYouJun/meodp" target="_blank" rel="noopener noreferrer" aria-label="meodp GitHub \u4ED3\u5E93\uFF08\u5728\u65B0\u6807\u7B7E\u9875\u6253\u5F00\uFF09" title="meodp on GitHub">
|
|
117
|
+
<svg width="22" height="22" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.65 7.65 0 0 1 2-.27c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg>
|
|
118
|
+
</a>
|
|
116
119
|
</div></div></header>
|
|
117
120
|
<main>
|
|
118
121
|
<section aria-labelledby="report-title"><h1 id="report-title">\u53CB\u94FE\u53EF\u8BBF\u95EE\u6027\u62A5\u544A</h1><p id="metadata" class="muted">\u52A0\u8F7D\u68C0\u6D4B\u6570\u636E\uFF0C\u67E5\u770B\u7AD9\u70B9\u53EF\u8BBF\u95EE\u6027\u3002</p>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const promises = require('node:timers/promises');
|
|
4
4
|
const linkinator = require('linkinator');
|
|
5
5
|
const node_os = require('node:os');
|
|
6
|
-
const report = require('./meodp.
|
|
6
|
+
const report = require('./meodp.5f2d144f.cjs');
|
|
7
7
|
const promises$1 = require('node:fs/promises');
|
|
8
8
|
const path = require('node:path');
|
|
9
9
|
const process = require('node:process');
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meodp",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"description": "Check website and friend-link availability with sitemap discovery, history, and portable reports.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "YunYouJun",
|
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
"test:e2e": "tsx scripts/build-report-viewer.ts && playwright test",
|
|
103
103
|
"typecheck": "tsx scripts/build-report-viewer.ts && tsc --noEmit -p tsconfig.json",
|
|
104
104
|
"prepack": "npm run build",
|
|
105
|
+
"verify:package": "pnpm build && tsx scripts/verify-package.ts",
|
|
105
106
|
"release": "npm version --no-git-tag-version"
|
|
106
107
|
},
|
|
107
108
|
"peerDependencies": {
|
|
@@ -121,7 +122,7 @@
|
|
|
121
122
|
}
|
|
122
123
|
},
|
|
123
124
|
"dependencies": {
|
|
124
|
-
"c12": "^
|
|
125
|
+
"c12": "^3.3.4",
|
|
125
126
|
"cli-progress": "^3.12.0",
|
|
126
127
|
"consola": "^3.2.3",
|
|
127
128
|
"date-fns": "^4.1.0",
|