@operstack/audit 0.19.2 → 0.19.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@operstack/audit",
3
- "version": "0.19.2",
3
+ "version": "0.19.3",
4
4
  "description": "SEO, AEO and GEO audit generator: collect public signals from a site into audit.json, let an analyst or an agent fill the narrative, render the OperStack report as HTML and PDF.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -80,5 +80,21 @@ const CLOSED = 'User-agent: GPTBot\nDisallow: /\n\nUser-agent: ClaudeBot\nDisall
80
80
  ok('в английском нет кириллицы', !/[А-Яа-яЁё]/.test(blockedNote({ status: 403, challenged: true, robotsText: OPEN, lang: 'en' }).text));
81
81
  }
82
82
 
83
+ // ---- несуществующий адрес: человек чаще всего просто опечатался
84
+ //
85
+ // Стояло «Сайт ответил ничем на https://…»: и коряво, и бесполезно. Человек, который ошибся в
86
+ // букве, должен узнать об этом первым делом, а не гадать, что с его сайтом.
87
+ {
88
+ const { checkVisibility } = await import('./visibility.mjs');
89
+ for (const lang of ['ru', 'en']) {
90
+ const v = await checkVisibility('https://takogo-domena-tochno-net-4f7a2b9c.ru/', { budgetMs: 8500, samplePages: 3, lang });
91
+ ok(`${lang}: балла у несуществующего адреса нет`, v.ok === false);
92
+ ok(`${lang}: названа вероятная причина, опечатка`, lang === 'ru' ? /опечатка в адресе/.test(v.error) : /typo in the address/.test(v.error));
93
+ ok(`${lang}: сказано, что делать`, lang === 'ru' ? /проверьте написание/.test(v.error) : /check the spelling/.test(v.error));
94
+ ok(`${lang}: нет старого «ответил ничем»`, lang === 'ru' ? !/ответил ничем/.test(v.error) : !/answered nothing/.test(v.error));
95
+ ok(`${lang}: чужого языка нет`, lang === 'ru' ? !/[A-Za-z]{5}/.test(v.error.replace(/https?:\/\/[^\s]+/g, '')) : !/[А-Яа-яЁё]/.test(v.error));
96
+ }
97
+ }
98
+
83
99
  if (bad) { console.error(`\n${bad} тест(ов) упало`); process.exit(1); }
84
100
  console.log('\nпро чужой сайт говорим только измеренное');
@@ -48,7 +48,9 @@ export const MESSAGES = {
48
48
  en: {
49
49
  badInput: 'Enter a public site address, for example example.com',
50
50
  tooSlow: 'The site took too long to answer',
51
- badAnswer: (status, url) => `The site answered ${status || 'nothing'} for ${url}`,
51
+ badAnswer: (status, url) => `The site answered ${status} for ${url}`,
52
+ // Чаще всего это опечатка в адресе, и сказать об этом надо первым делом, а не после разбора.
53
+ unreachable: (url) => `Nothing answered at ${url}. Most often that is a typo in the address: check the spelling, and if the site really is there, it may be down right now.`,
52
54
  botWall: (status) => `The site refuses unknown clients (HTTP ${status}), so this check could not read a single page.`,
53
55
  botChallenge: (status) => `The site sits behind a browser challenge (Cloudflare, HTTP ${status}), so this check could not read a single page.`,
54
56
  // Что мы знаем про роботов ИИ, когда нас самих развернули: ровно то, что написано в правилах
@@ -98,7 +100,8 @@ export const MESSAGES = {
98
100
  ru: {
99
101
  badInput: 'Введите адрес публичного сайта, например example.ru',
100
102
  tooSlow: 'Сайт слишком долго не отвечал',
101
- badAnswer: (status, url) => `Сайт ответил ${status ? `кодом ${status}` : 'ничем'} на ${url}`,
103
+ badAnswer: (status, url) => `Сайт ответил кодом ${status} на ${url}`,
104
+ unreachable: (url) => `По адресу ${url} никто не ответил. Чаще всего это опечатка в адресе: проверьте написание. Если сайт там действительно есть, значит он сейчас недоступен.`,
102
105
  botWall: (status) => `Сайт отказывает незнакомым клиентам (код ${status}), поэтому прочитать хотя бы одну страницу проверка не смогла.`,
103
106
  botChallenge: (status) => `Сайт закрыт проверкой браузера (Cloudflare, код ${status}), поэтому прочитать хотя бы одну страницу проверка не смогла.`,
104
107
  rulesAllowBots: (list) => ` Правила самого сайта роботов ИИ при этом пускают (${list}), а защита такого типа проверенных роботов нередко пропускает. Пустят ли их на деле, решает защита, а не эта проверка, поэтому в плюс или в минус сайту это не зачтено.`,
@@ -403,8 +406,9 @@ export async function checkVisibility(input, { budgetMs = 8500, lang = 'en', sam
403
406
  */
404
407
  const note = blockedNote({ status: home.status, challenged, blocked, robotsText: robotsRes.ok ? robotsRes.text : null, lang });
405
408
  const error = home.error === 'timeout' ? T.tooSlow
406
- : blocked ? note.text
407
- : T.badAnswer(home.status, url);
409
+ : home.error === 'unreachable' || !home.status ? T.unreachable(url)
410
+ : blocked ? note.text
411
+ : T.badAnswer(home.status, url);
408
412
  // `botsBlocked` говорит только про написанные правила, а не про поведение защиты: по нему
409
413
  // нельзя утверждать, что робота не пустили, можно лишь, что ему не разрешали.
410
414
  return { ok: false, blocked, challenged, status: home.status, error, botsBlocked: note.botsBlocked };