aeo.js 0.0.7 → 0.0.9
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/README.md +119 -164
- package/dist/angular.d.mts +1 -1
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +69 -13
- package/dist/angular.js.map +1 -1
- package/dist/angular.mjs +69 -13
- package/dist/angular.mjs.map +1 -1
- package/dist/astro.d.mts +1 -1
- package/dist/astro.d.ts +1 -1
- package/dist/astro.js +78 -18
- package/dist/astro.js.map +1 -1
- package/dist/astro.mjs +78 -18
- package/dist/astro.mjs.map +1 -1
- package/dist/cli.js +84 -27
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +84 -27
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +89 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +89 -29
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +71 -15
- package/dist/next.js.map +1 -1
- package/dist/next.mjs +71 -15
- package/dist/next.mjs.map +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/nuxt.js +69 -13
- package/dist/nuxt.js.map +1 -1
- package/dist/nuxt.mjs +69 -13
- package/dist/nuxt.mjs.map +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +52 -7
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +52 -7
- package/dist/react.mjs.map +1 -1
- package/dist/{types-Cn_Qbkmg.d.mts → types-BlLNcw-X.d.mts} +2 -0
- package/dist/{types-Cn_Qbkmg.d.ts → types-BlLNcw-X.d.ts} +2 -0
- package/dist/vite.d.mts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +94 -20
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +94 -20
- package/dist/vite.mjs.map +1 -1
- package/dist/vue.d.mts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +52 -7
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +52 -7
- package/dist/vue.mjs.map +1 -1
- package/dist/webpack.d.mts +1 -1
- package/dist/webpack.d.ts +1 -1
- package/dist/webpack.js +69 -13
- package/dist/webpack.js.map +1 -1
- package/dist/webpack.mjs +69 -13
- package/dist/webpack.mjs.map +1 -1
- package/dist/widget.d.mts +1 -1
- package/dist/widget.d.ts +1 -1
- package/dist/widget.js +52 -7
- package/dist/widget.js.map +1 -1
- package/dist/widget.mjs +52 -7
- package/dist/widget.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -78,10 +78,19 @@ function generateRobotsTxt(config) {
|
|
|
78
78
|
}
|
|
79
79
|
lines.push("# Default for all other bots");
|
|
80
80
|
lines.push("User-agent: *");
|
|
81
|
-
|
|
81
|
+
for (const path of config.robots.allow.length > 0 ? config.robots.allow : ["/"]) {
|
|
82
|
+
lines.push(`Allow: ${path}`);
|
|
83
|
+
}
|
|
84
|
+
for (const path of config.robots.disallow) {
|
|
85
|
+
lines.push(`Disallow: ${path}`);
|
|
86
|
+
}
|
|
87
|
+
if (config.robots.crawlDelay > 0) {
|
|
88
|
+
lines.push(`Crawl-delay: ${config.robots.crawlDelay}`);
|
|
89
|
+
}
|
|
82
90
|
lines.push("");
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
const sitemapUrl = config.robots.sitemap || (config.url ? `${config.url}/sitemap.xml` : "");
|
|
92
|
+
if (sitemapUrl) {
|
|
93
|
+
lines.push(`Sitemap: ${sitemapUrl}`);
|
|
85
94
|
}
|
|
86
95
|
lines.push("");
|
|
87
96
|
lines.push("# AEO (Answer Engine Optimization) files");
|
|
@@ -163,7 +172,7 @@ function detectFramework(projectRoot = process.cwd()) {
|
|
|
163
172
|
};
|
|
164
173
|
}
|
|
165
174
|
function resolveConfig(config = {}) {
|
|
166
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M;
|
|
175
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N;
|
|
167
176
|
const frameworkInfo = detectFramework();
|
|
168
177
|
return {
|
|
169
178
|
title: config.title || "My Site",
|
|
@@ -207,15 +216,16 @@ function resolveConfig(config = {}) {
|
|
|
207
216
|
widget: {
|
|
208
217
|
enabled: ((_A = config.widget) == null ? void 0 : _A.enabled) !== false,
|
|
209
218
|
position: ((_B = config.widget) == null ? void 0 : _B.position) || "bottom-right",
|
|
219
|
+
size: ((_C = config.widget) == null ? void 0 : _C.size) || "default",
|
|
210
220
|
theme: {
|
|
211
|
-
background: ((
|
|
212
|
-
text: ((
|
|
213
|
-
accent: ((
|
|
214
|
-
badge: ((
|
|
221
|
+
background: ((_E = (_D = config.widget) == null ? void 0 : _D.theme) == null ? void 0 : _E.background) || "rgba(18, 18, 24, 0.9)",
|
|
222
|
+
text: ((_G = (_F = config.widget) == null ? void 0 : _F.theme) == null ? void 0 : _G.text) || "#C0C0C5",
|
|
223
|
+
accent: ((_I = (_H = config.widget) == null ? void 0 : _H.theme) == null ? void 0 : _I.accent) || "#E8E8EA",
|
|
224
|
+
badge: ((_K = (_J = config.widget) == null ? void 0 : _J.theme) == null ? void 0 : _K.badge) || "#4ADE80"
|
|
215
225
|
},
|
|
216
|
-
humanLabel: ((
|
|
217
|
-
aiLabel: ((
|
|
218
|
-
showBadge: ((
|
|
226
|
+
humanLabel: ((_L = config.widget) == null ? void 0 : _L.humanLabel) || "Human",
|
|
227
|
+
aiLabel: ((_M = config.widget) == null ? void 0 : _M.aiLabel) || "AI",
|
|
228
|
+
showBadge: ((_N = config.widget) == null ? void 0 : _N.showBadge) !== false
|
|
219
229
|
}
|
|
220
230
|
};
|
|
221
231
|
}
|
|
@@ -272,7 +282,8 @@ function collectMarkdownFiles(dir, base = dir) {
|
|
|
272
282
|
for (const entry of entries) {
|
|
273
283
|
const fullPath = join(dir, entry);
|
|
274
284
|
const stat = statSync(fullPath);
|
|
275
|
-
|
|
285
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
|
|
286
|
+
if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
|
|
276
287
|
files.push(...collectMarkdownFiles(fullPath, base));
|
|
277
288
|
} else if (stat.isFile() && (extname(entry) === ".md" || extname(entry) === ".mdx")) {
|
|
278
289
|
const content = readFileSync(fullPath, "utf-8");
|
|
@@ -615,7 +626,8 @@ function collectUrls(dir, config, base = dir) {
|
|
|
615
626
|
for (const entry of entries) {
|
|
616
627
|
const fullPath = join(dir, entry);
|
|
617
628
|
const stat = statSync(fullPath);
|
|
618
|
-
|
|
629
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
|
|
630
|
+
if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
|
|
619
631
|
urls.push(...collectUrls(fullPath, config, base));
|
|
620
632
|
} else if (stat.isFile() && (extname(entry) === ".md" || extname(entry) === ".mdx" || extname(entry) === ".html")) {
|
|
621
633
|
const relativePath = relative(base, fullPath);
|
|
@@ -843,6 +855,22 @@ function generatePageSchemas(page, config) {
|
|
|
843
855
|
}))
|
|
844
856
|
});
|
|
845
857
|
}
|
|
858
|
+
if (faqItems.length === 0) {
|
|
859
|
+
const howToSteps = detectHowToSteps(page.content || "");
|
|
860
|
+
if (howToSteps.length > 0) {
|
|
861
|
+
schemas.push({
|
|
862
|
+
"@context": "https://schema.org",
|
|
863
|
+
"@type": "HowTo",
|
|
864
|
+
name: page.title || config.title,
|
|
865
|
+
step: howToSteps.map((s, i) => ({
|
|
866
|
+
"@type": "HowToStep",
|
|
867
|
+
position: i + 1,
|
|
868
|
+
name: s.name,
|
|
869
|
+
text: s.text
|
|
870
|
+
}))
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
}
|
|
846
874
|
const pageType = config.schema.defaultType;
|
|
847
875
|
const pageSchema = {
|
|
848
876
|
"@context": "https://schema.org",
|
|
@@ -919,6 +947,34 @@ function detectFaqPatterns(content) {
|
|
|
919
947
|
}
|
|
920
948
|
return items;
|
|
921
949
|
}
|
|
950
|
+
function detectHowToSteps(content) {
|
|
951
|
+
const steps = [];
|
|
952
|
+
const lines = content.split("\n");
|
|
953
|
+
for (let i = 0; i < lines.length; i++) {
|
|
954
|
+
const line = lines[i].trim();
|
|
955
|
+
const stepMatch = line.match(/^#{1,6}\s+(?:Step\s+\d+[\s:.-]*|(\d+)[.)]\s*)(.+)$/i);
|
|
956
|
+
if (stepMatch) {
|
|
957
|
+
const name = (stepMatch[2] || stepMatch[1] || "").trim();
|
|
958
|
+
const bodyLines = [];
|
|
959
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
960
|
+
const nextLine = lines[j].trim();
|
|
961
|
+
if (!nextLine) {
|
|
962
|
+
if (bodyLines.length > 0) break;
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
if (/^#{1,6}\s/.test(nextLine)) break;
|
|
966
|
+
bodyLines.push(nextLine);
|
|
967
|
+
}
|
|
968
|
+
if (name) {
|
|
969
|
+
steps.push({
|
|
970
|
+
name,
|
|
971
|
+
text: bodyLines.join(" ").slice(0, 500)
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
return steps.length >= 2 ? steps : [];
|
|
977
|
+
}
|
|
922
978
|
async function generateAEOFiles(configOrRoot, maybeConfig) {
|
|
923
979
|
var _a;
|
|
924
980
|
let config;
|
|
@@ -1128,15 +1184,18 @@ function auditSchemaPresence(config, issues, suggestions) {
|
|
|
1128
1184
|
if (!hasLogo) {
|
|
1129
1185
|
suggestions.push("Add schema.organization.logo for richer search results and AI knowledge");
|
|
1130
1186
|
}
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1187
|
+
const hasFaqOrHowTo = config.pages.some((p) => {
|
|
1188
|
+
const content = p.content || "";
|
|
1189
|
+
return /^#{1,6}\s+.+\?\s*$/m.test(content) || /^#{1,6}\s+(?:Step\s+\d+[\s:.-]|How\s+to)/im.test(content);
|
|
1190
|
+
});
|
|
1191
|
+
checks.push({ label: "FAQPage or HowTo schema", passed: hasFaqOrHowTo, points: hasFaqOrHowTo ? 4 : 0 });
|
|
1192
|
+
if (!hasFaqOrHowTo) {
|
|
1193
|
+
suggestions.push("Add FAQ sections (question headings) or step-by-step content to auto-generate FAQPage/HowTo schema");
|
|
1135
1194
|
}
|
|
1136
|
-
const
|
|
1137
|
-
checks.push({ label: "
|
|
1138
|
-
if (!
|
|
1139
|
-
|
|
1195
|
+
const hasArticleOrWebPage = schemaEnabled && (config.schema.defaultType === "Article" || config.schema.defaultType === "WebPage");
|
|
1196
|
+
checks.push({ label: "Article/WebPage schema", passed: hasArticleOrWebPage, points: hasArticleOrWebPage ? 4 : 0 });
|
|
1197
|
+
if (!hasArticleOrWebPage && schemaEnabled) {
|
|
1198
|
+
suggestions.push('Set schema.defaultType to "Article" or "WebPage" for per-page structured data');
|
|
1140
1199
|
}
|
|
1141
1200
|
return {
|
|
1142
1201
|
name: "Schema Presence",
|
|
@@ -1175,12 +1234,10 @@ function auditMetaQuality(config, issues, suggestions) {
|
|
|
1175
1234
|
if (!goodTitleCoverage && config.pages.length > 0) {
|
|
1176
1235
|
issues.push({ category: "Meta Quality", severity: "warning", message: `Only ${pagesWithTitles.length}/${config.pages.length} pages have titles`, fix: "Add titles to all pages" });
|
|
1177
1236
|
}
|
|
1178
|
-
const
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
if (!goodDescCoverage && config.pages.length > 0) {
|
|
1183
|
-
suggestions.push(`Only ${pagesWithDesc.length}/${config.pages.length} pages have descriptions \u2014 add per-page descriptions`);
|
|
1237
|
+
const hasOgImage = !!config.og.image;
|
|
1238
|
+
checks.push({ label: "OG image configured", passed: hasOgImage, points: hasOgImage ? 4 : 0 });
|
|
1239
|
+
if (!hasOgImage) {
|
|
1240
|
+
suggestions.push("Set og.image for richer social sharing previews and AI citation cards");
|
|
1184
1241
|
}
|
|
1185
1242
|
return {
|
|
1186
1243
|
name: "Meta Quality",
|