@operstack/audit 0.15.2 → 0.15.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 +2 -2
- package/src/collect.mjs +1 -1
- package/src/prompts.mjs +10 -6
- package/src/test-prompts.mjs +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@operstack/audit",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.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",
|
|
@@ -46,4 +46,4 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"node-html-parser": "^9.0.4"
|
|
48
48
|
}
|
|
49
|
-
}
|
|
49
|
+
}
|
package/src/collect.mjs
CHANGED
|
@@ -325,7 +325,7 @@ export async function collect(startUrl, { pages = 20, log = () => {}, backlinks
|
|
|
325
325
|
checks.push(row('og', 'technical', 'Open Graph and Twitter cards', hp.og.title && hp.og.image ? (hp.twitter ? 'ok' : 'warn') : 'warn', [hp.og.title ? 'og:title' : '', hp.og.image ? 'og:image' : '', hp.twitter ? `twitter:${hp.twitter}` : ''].filter(Boolean).join(', ') || 'none'));
|
|
326
326
|
checks.push(row('schema', 'aeo', 'Structured data on homepage', hp.schemaTypes.length ? (hp.schemaTypes.includes('(invalid JSON-LD)') ? 'warn' : 'ok') : 'warn', hp.schemaTypes.join(', ') || 'no JSON-LD'));
|
|
327
327
|
checks.push(row('faq-schema', 'aeo', 'FAQPage schema', good.some((p) => p.schemaTypes.includes('FAQPage')) ? 'ok' : 'warn', good.some((p) => p.schemaTypes.includes('FAQPage')) ? `present on ${good.filter((p) => p.schemaTypes.includes('FAQPage')).length} sampled page(s)` : 'not found in the sample'));
|
|
328
|
-
checks.push(row('org-schema', 'geo', 'Organization or business schema', good.some((p) => p.schemaTypes.some((t) => /Organization|LocalBusiness|RealEstateAgent|
|
|
328
|
+
checks.push(row('org-schema', 'geo', 'Organization or business schema', good.some((p) => p.schemaTypes.some((t) => /Organization|Corporation|NGO|EducationalOrganization|GovernmentOrganization|MedicalOrganization|LocalBusiness|RealEstateAgent|Dentist|Physician|Hospital|Pharmacy|VeterinaryCare|LegalService|Attorney|Notary|AccountingService|InsuranceAgency|FinancialService|BankOrCreditUnion|AutomotiveBusiness|AutoRepair|AutoDealer|HomeAndConstructionBusiness|Plumber|Electrician|RoofingContractor|HVACBusiness|HousePainter|Locksmith|MovingCompany|GeneralContractor|Restaurant|FoodEstablishment|CafeOrCoffeeShop|Bakery|BarOrPub|LodgingBusiness|Hotel|TravelAgency|HealthAndBeautyBusiness|BeautySalon|HairSalon|DaySpa|NailSalon|TattooParlor|SportsActivityLocation|HealthClub|Gym|ProfessionalService|Store|ClothingStore|GroceryStore|HardwareStore|FurnitureStore|JewelryStore|PetStore|ChildCare|Electrician|EmploymentAgency|SelfStorage|Library|Museum|EntertainmentBusiness|MedicalClinic|DentalClinic|Optician|PhysicalTherapy|NutritionService|EmergencyService|ITService|WebDesignService|MarketingAgency|AdvertisingAgency|SoftwareApplication/.test(t))) ? 'ok' : 'warn', good.some((p) => p.schemaTypes.some((t) => /Organization|Corporation|NGO|EducationalOrganization|GovernmentOrganization|MedicalOrganization|LocalBusiness|RealEstateAgent|Dentist|Physician|Hospital|Pharmacy|VeterinaryCare|LegalService|Attorney|Notary|AccountingService|InsuranceAgency|FinancialService|BankOrCreditUnion|AutomotiveBusiness|AutoRepair|AutoDealer|HomeAndConstructionBusiness|Plumber|Electrician|RoofingContractor|HVACBusiness|HousePainter|Locksmith|MovingCompany|GeneralContractor|Restaurant|FoodEstablishment|CafeOrCoffeeShop|Bakery|BarOrPub|LodgingBusiness|Hotel|TravelAgency|HealthAndBeautyBusiness|BeautySalon|HairSalon|DaySpa|NailSalon|TattooParlor|SportsActivityLocation|HealthClub|Gym|ProfessionalService|Store|ClothingStore|GroceryStore|HardwareStore|FurnitureStore|JewelryStore|PetStore|ChildCare|Electrician|EmploymentAgency|SelfStorage|Library|Museum|EntertainmentBusiness|MedicalClinic|DentalClinic|Optician|PhysicalTherapy|NutritionService|EmergencyService|ITService|WebDesignService|MarketingAgency|AdvertisingAgency|SoftwareApplication/.test(t))) ? 'present' : 'not found: answer engines have no entity to attach the site to'));
|
|
329
329
|
checks.push(row('resources', 'technical', 'Page weight (homepage)', hp.scripts > 30 ? 'bad' : hp.scripts > 15 ? 'warn' : 'ok', `${hp.scripts} script file(s), ${hp.stylesheets} stylesheet(s), ${hp.images} image(s)`));
|
|
330
330
|
if (hp.generator) checks.push(row('cms', 'overview', 'CMS', 'na', hp.generator));
|
|
331
331
|
checks.push(row('hreflang', 'technical', 'hreflang', hp.hreflang ? 'ok' : 'na', hp.hreflang ? `${hp.hreflang} alternate(s)` : 'none (single language)'));
|
package/src/prompts.mjs
CHANGED
|
@@ -162,11 +162,15 @@ export function renderAgentPrompts(audit, opts = {}) {
|
|
|
162
162
|
const host = audit.meta?.host || '';
|
|
163
163
|
const list = agentPrompts(audit, opts);
|
|
164
164
|
const intro = lang === 'ru'
|
|
165
|
-
? [`#
|
|
166
|
-
'
|
|
167
|
-
'
|
|
168
|
-
|
|
169
|
-
'
|
|
170
|
-
|
|
165
|
+
? [`# Что поправить на сайте: ${host}`, '',
|
|
166
|
+
'Ниже список задач, по одной на каждую найденную проблему. Каждая написана обычными словами, и её можно отдать кому угодно: тому, кто делал вам сайт, или помощнику вроде ChatGPT, Claude или Cursor.', '',
|
|
167
|
+
'**Как пользоваться.** Скопируйте одну задачу целиком, вместе со строками «Сейчас» и «Как проверить»: без них исполнитель не поймёт, откуда начинать и чем закончить. Отдайте её, дождитесь результата, сверьтесь со строкой «Как проверить» и берите следующую.', '',
|
|
168
|
+
'По одной за раз, это важно. Помощник, которому дали десять задач сразу, делает первую и половину остальных.', '',
|
|
169
|
+
'Кода знать не нужно. Ваше дело сказать, что сделать, и посмотреть на результат.', '']
|
|
170
|
+
: [`# What to fix on your site: ${host}`, '',
|
|
171
|
+
'Below is a list of tasks, one for every problem found. Each is written in plain words and can be handed to anyone: whoever built your site, or an assistant like ChatGPT, Claude or Cursor.', '',
|
|
172
|
+
'**How to use it.** Copy one task whole, including the "Now" and "How to check" lines: without them nobody knows where to start or when it is done. Hand it over, wait for the result, check it against "How to check", then take the next one.', '',
|
|
173
|
+
'One at a time, and this matters. An assistant given ten tasks at once does the first and half of the rest.', '',
|
|
174
|
+
'You do not need to know any code. Your job is to say what to do and look at the result.', ''];
|
|
171
175
|
return [intro.join('\n').trimEnd(), ...list.map((x) => x.text)].join('\n\n');
|
|
172
176
|
}
|
package/src/test-prompts.mjs
CHANGED
|
@@ -53,8 +53,10 @@ is('у каждой чинимой проверки есть внятное за
|
|
|
53
53
|
|
|
54
54
|
// Шапка файла объясняет, как этим пользоваться
|
|
55
55
|
const head = renderAgentPrompts(audit([c('robots', 'bad', 'robots', 'закрыт')]), { lang: 'ru' });
|
|
56
|
-
|
|
57
|
-
ok('
|
|
56
|
+
// Проверяем смысл, а не точную формулировку: шапку переписывали под покупателя без терминала.
|
|
57
|
+
ok('шапка объясняет, что копировать задачу целиком', /задачу целиком/i.test(head) && /Сейчас/.test(head) && /Как проверить/.test(head));
|
|
58
|
+
ok('и предупреждает делать по одной', /по одной за раз/i.test(head));
|
|
59
|
+
ok('и обещает, что код знать не нужно', /кода знать не нужно/i.test(head));
|
|
58
60
|
ok('в файле нет пустых сдвоенных строк', !/\n\n\n/.test(head));
|
|
59
61
|
|
|
60
62
|
if (bad) { console.error(`\n${bad} тест(ов) упало`); process.exit(1); }
|