@cloudcreate/adsense-check 1.2.1 → 1.3.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +130 -3
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -204,6 +204,130 @@ function truncate(s, max) {
204
204
  function renderJsonReport(report) {
205
205
  return JSON.stringify(report, null, 2);
206
206
  }
207
+ var MD_ICONS = {
208
+ pass: "\u2705",
209
+ warn: "\u26A0\uFE0F",
210
+ fail: "\u274C",
211
+ skip: "\u23ED\uFE0F"
212
+ };
213
+ function renderMarkdownReport(report) {
214
+ const lines = [];
215
+ const lang = report.lang;
216
+ const typeKey = `detector.type.${report.siteType}`;
217
+ const typeLabel = t(typeKey, lang);
218
+ lines.push(`# AdSense \u5BA1\u6838\u62A5\u544A`);
219
+ lines.push("");
220
+ lines.push(`| \u9879\u76EE | \u503C |`);
221
+ lines.push(`|------|-----|`);
222
+ lines.push(`| URL | ${report.url} |`);
223
+ lines.push(`| \u65F6\u95F4 | ${report.timestamp} |`);
224
+ lines.push(`| \u7AD9\u70B9\u7C7B\u578B | ${typeLabel} (${report.siteTypeConfidence}) |`);
225
+ if (report.siteTopic) {
226
+ lines.push(`| \u4E3B\u9898 | ${report.siteTopic.topic} |`);
227
+ lines.push(`| \u63CF\u8FF0 | ${report.siteTopic.description} |`);
228
+ }
229
+ if (report.samplingInfo) {
230
+ const s = report.samplingInfo;
231
+ lines.push(`| \u62BD\u6837 | ${s.totalDiscovered} total, ${s.recentCount} recent (6mo), ${s.sampledCount} sampled (${s.samplePct}%, ${s.confidence}) |`);
232
+ }
233
+ lines.push("");
234
+ lines.push(`## \u7EFC\u5408\u8BC4\u5206: ${report.compositeScore}/100`);
235
+ lines.push("");
236
+ const hardFailCount = report.hardCategories.flatMap((c) => c.items).filter((i) => i.status === "fail").length;
237
+ const hardWarnCount = report.hardCategories.flatMap((c) => c.items).filter((i) => i.status === "warn").length;
238
+ const hardLabel = report.hardStatus === "ready" ? "\u2705 PASS" : report.hardStatus === "warn" ? "\u26A0\uFE0F WARN" : "\u274C FAIL";
239
+ lines.push(`### \u786C\u6027\u8981\u6C42 ${hardLabel}`);
240
+ lines.push("");
241
+ for (const cat of report.hardCategories) {
242
+ for (const item of cat.items) {
243
+ lines.push(`- ${MD_ICONS[item.status]} **${item.name}**: ${item.message}`);
244
+ if (item.detail) lines.push(` - ${item.detail}`);
245
+ }
246
+ }
247
+ lines.push("");
248
+ lines.push(`### \u67D4\u6027\u8BC4\u5206 ${report.softScore}/100`);
249
+ lines.push("");
250
+ for (const cat of report.softCategories) {
251
+ const isAiCat = cat.name.includes("AI") || cat.name.includes("ai");
252
+ const score = isAiCat && report.siteAiScore > 0 ? report.siteAiScore : categoryScore(cat);
253
+ lines.push(`- **${cat.name}**: ${score}%`);
254
+ for (const item of cat.items) {
255
+ lines.push(` - ${MD_ICONS[item.status]} ${item.name}: ${item.message}`);
256
+ if (item.detail) lines.push(` - ${item.detail}`);
257
+ }
258
+ }
259
+ lines.push("");
260
+ if (report.aiDimensionAverages) {
261
+ const d = report.aiDimensionAverages;
262
+ lines.push(`### AI \u4EF7\u503C\u5206\u6790`);
263
+ lines.push("");
264
+ lines.push(`| \u7EF4\u5EA6 | \u5747\u5206 |`);
265
+ lines.push(`|------|------|`);
266
+ lines.push(`| Value\uFF08\u4EF7\u503C\uFF09 | ${d.value}/10 |`);
267
+ lines.push(`| Originality\uFF08\u539F\u521B\uFF09 | ${d.originality}/10 |`);
268
+ lines.push(`| Relevance\uFF08\u76F8\u5173\uFF09 | ${d.relevance}/10 |`);
269
+ lines.push(`| Compliance\uFF08\u5408\u89C4\uFF09 | ${d.compliance}/10 |`);
270
+ lines.push("");
271
+ lines.push(`**\u7AD9\u70B9 AI \u8BC4\u5206**: ${report.siteAiScore}/100\uFF08\u51E0\u4F55\u5747\u503C \xD7 \u9875\u9762\u7C7B\u578B\u52A0\u6743\uFF09`);
272
+ lines.push("");
273
+ }
274
+ const hardContrib = Math.round(report.hardStatus === "ready" ? 100 * 0.4 : report.hardCategories.flatMap((c) => c.items).filter((i) => i.status === "pass").length / Math.max(1, report.hardCategories.flatMap((c) => c.items).length) * 100 * 0.4);
275
+ lines.push(`> Hard ${Math.round(hardContrib)}% \xD7 0.4 + Soft ${report.softScore}% \xD7 0.6 - Penalty ${report.warningPenalty} = ${report.compositeScore}`);
276
+ lines.push("");
277
+ if (report.pages.length > 0) {
278
+ lines.push(`### \u9010\u9875\u8BE6\u60C5 (${report.pages.length} pages)`);
279
+ lines.push("");
280
+ const problems = report.pages.filter((p) => p.contentStatus !== "pass" || p.issues.length > 0 || p.ai && p.ai.status !== "pass");
281
+ const ok = report.pages.filter((p) => p.contentStatus === "pass" && p.issues.length === 0 && (!p.ai || p.ai.status === "pass"));
282
+ lines.push(`| \u72B6\u6001 | \u7C7B\u578B | \u8DEF\u5F84 | \u8BC4\u5206 | \u6B63\u6587\u6BD4 | \u6807\u9898 |`);
283
+ lines.push(`|------|------|------|------|--------|------|`);
284
+ for (const p of [...problems, ...ok]) {
285
+ const path = (() => {
286
+ try {
287
+ return new URL(p.url).pathname;
288
+ } catch {
289
+ return p.url;
290
+ }
291
+ })();
292
+ const status = MD_ICONS[p.contentStatus];
293
+ const scoreColor = p.score >= 80 ? "" : p.score >= 50 ? "" : "";
294
+ lines.push(`| ${status} | ${p.pageType} | \`${path}\` | ${p.score}/100 | ${p.contentRatio}% | ${p.title} |`);
295
+ }
296
+ lines.push("");
297
+ const detailPages = problems.filter((p) => p.issues.length > 0 || p.ai && p.ai.status !== "pass");
298
+ if (detailPages.length > 0) {
299
+ lines.push(`#### \u95EE\u9898\u9875\u9762\u8BE6\u60C5`);
300
+ lines.push("");
301
+ for (const p of detailPages) {
302
+ const path = (() => {
303
+ try {
304
+ return new URL(p.url).pathname;
305
+ } catch {
306
+ return p.url;
307
+ }
308
+ })();
309
+ lines.push(`**${path}** (${p.score}/100)`);
310
+ for (const issue of p.issues) lines.push(`- \u26A0\uFE0F ${issue}`);
311
+ if (p.ai) {
312
+ lines.push(`- ${MD_ICONS[p.ai.status]} AI: ${p.ai.assessment}`);
313
+ for (const s of p.ai.suggestions.slice(0, 3)) lines.push(` - -> ${s}`);
314
+ }
315
+ lines.push("");
316
+ }
317
+ }
318
+ }
319
+ if (report.hardStatus === "fail") {
320
+ lines.push(`**\u274C NOT READY** \u2014 ${hardFailCount} \u9879\u5931\u8D25\u9700\u8981\u4FEE\u590D`);
321
+ } else if (report.hardStatus === "warn") {
322
+ lines.push(`**\u26A0\uFE0F NEEDS FIXES** \u2014 ${hardWarnCount} \u9879\u8B66\u544A\u5F85\u4FEE\u590D`);
323
+ } else if (report.warned > 0) {
324
+ lines.push(`**\u26A0\uFE0F MOSTLY READY** \u2014 \u4FEE\u590D ${report.warned} \u9879\u8B66\u544A\u540E\u53EF\u63D0\u4EA4`);
325
+ } else {
326
+ lines.push(`**\u2705 READY** \u2014 \u53EF\u4EE5\u63D0\u4EA4 AdSense \u5BA1\u6838`);
327
+ }
328
+ lines.push("");
329
+ return lines.join("\n");
330
+ }
207
331
 
208
332
  // src/cli.ts
209
333
  function formatTimestamp() {
@@ -397,9 +521,12 @@ program.name("adsense-check").description("Check if a website meets Google AdSen
397
521
  const outDir = join(process.cwd(), opts.output);
398
522
  try {
399
523
  mkdirSync(outDir, { recursive: true });
400
- const path = join(outDir, `${domain}-${ts}.json`);
401
- writeFileSync(path, renderJsonReport(report), "utf-8");
402
- console.log(chalk2.gray(` ${t("report.saved", lang)}: ${path}`));
524
+ const jsonPath = join(outDir, `${domain}-${ts}.json`);
525
+ writeFileSync(jsonPath, renderJsonReport(report), "utf-8");
526
+ const mdPath = join(outDir, `${domain}-${ts}.md`);
527
+ writeFileSync(mdPath, renderMarkdownReport(report), "utf-8");
528
+ console.log(chalk2.gray(` ${t("report.saved", lang)}: ${jsonPath}`));
529
+ console.log(chalk2.gray(` ${t("report.saved", lang)}: ${mdPath}`));
403
530
  } catch {
404
531
  }
405
532
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcreate/adsense-check",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Check if a website meets Google AdSense review requirements",
5
5
  "homepage": "https://cloudcreate.ai",
6
6
  "repository": {