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/vite.mjs
CHANGED
|
@@ -83,10 +83,19 @@ function generateRobotsTxt(config) {
|
|
|
83
83
|
}
|
|
84
84
|
lines.push("# Default for all other bots");
|
|
85
85
|
lines.push("User-agent: *");
|
|
86
|
-
|
|
86
|
+
for (const path2 of config.robots.allow.length > 0 ? config.robots.allow : ["/"]) {
|
|
87
|
+
lines.push(`Allow: ${path2}`);
|
|
88
|
+
}
|
|
89
|
+
for (const path2 of config.robots.disallow) {
|
|
90
|
+
lines.push(`Disallow: ${path2}`);
|
|
91
|
+
}
|
|
92
|
+
if (config.robots.crawlDelay > 0) {
|
|
93
|
+
lines.push(`Crawl-delay: ${config.robots.crawlDelay}`);
|
|
94
|
+
}
|
|
87
95
|
lines.push("");
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
const sitemapUrl = config.robots.sitemap || (config.url ? `${config.url}/sitemap.xml` : "");
|
|
97
|
+
if (sitemapUrl) {
|
|
98
|
+
lines.push(`Sitemap: ${sitemapUrl}`);
|
|
90
99
|
}
|
|
91
100
|
lines.push("");
|
|
92
101
|
lines.push("# AEO (Answer Engine Optimization) files");
|
|
@@ -168,7 +177,7 @@ function detectFramework(projectRoot = process.cwd()) {
|
|
|
168
177
|
};
|
|
169
178
|
}
|
|
170
179
|
function resolveConfig(config = {}) {
|
|
171
|
-
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;
|
|
180
|
+
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;
|
|
172
181
|
const frameworkInfo = detectFramework();
|
|
173
182
|
return {
|
|
174
183
|
title: config.title || "My Site",
|
|
@@ -212,15 +221,16 @@ function resolveConfig(config = {}) {
|
|
|
212
221
|
widget: {
|
|
213
222
|
enabled: ((_A = config.widget) == null ? void 0 : _A.enabled) !== false,
|
|
214
223
|
position: ((_B = config.widget) == null ? void 0 : _B.position) || "bottom-right",
|
|
224
|
+
size: ((_C = config.widget) == null ? void 0 : _C.size) || "default",
|
|
215
225
|
theme: {
|
|
216
|
-
background: ((
|
|
217
|
-
text: ((
|
|
218
|
-
accent: ((
|
|
219
|
-
badge: ((
|
|
226
|
+
background: ((_E = (_D = config.widget) == null ? void 0 : _D.theme) == null ? void 0 : _E.background) || "rgba(18, 18, 24, 0.9)",
|
|
227
|
+
text: ((_G = (_F = config.widget) == null ? void 0 : _F.theme) == null ? void 0 : _G.text) || "#C0C0C5",
|
|
228
|
+
accent: ((_I = (_H = config.widget) == null ? void 0 : _H.theme) == null ? void 0 : _I.accent) || "#E8E8EA",
|
|
229
|
+
badge: ((_K = (_J = config.widget) == null ? void 0 : _J.theme) == null ? void 0 : _K.badge) || "#4ADE80"
|
|
220
230
|
},
|
|
221
|
-
humanLabel: ((
|
|
222
|
-
aiLabel: ((
|
|
223
|
-
showBadge: ((
|
|
231
|
+
humanLabel: ((_L = config.widget) == null ? void 0 : _L.humanLabel) || "Human",
|
|
232
|
+
aiLabel: ((_M = config.widget) == null ? void 0 : _M.aiLabel) || "AI",
|
|
233
|
+
showBadge: ((_N = config.widget) == null ? void 0 : _N.showBadge) !== false
|
|
224
234
|
}
|
|
225
235
|
};
|
|
226
236
|
}
|
|
@@ -277,7 +287,8 @@ function collectMarkdownFiles(dir, base = dir) {
|
|
|
277
287
|
for (const entry of entries) {
|
|
278
288
|
const fullPath = join(dir, entry);
|
|
279
289
|
const stat = statSync(fullPath);
|
|
280
|
-
|
|
290
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
|
|
291
|
+
if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
|
|
281
292
|
files.push(...collectMarkdownFiles(fullPath, base));
|
|
282
293
|
} else if (stat.isFile() && (extname(entry) === ".md" || extname(entry) === ".mdx")) {
|
|
283
294
|
const content = readFileSync(fullPath, "utf-8");
|
|
@@ -620,7 +631,8 @@ function collectUrls(dir, config, base = dir) {
|
|
|
620
631
|
for (const entry of entries) {
|
|
621
632
|
const fullPath = join(dir, entry);
|
|
622
633
|
const stat = statSync(fullPath);
|
|
623
|
-
|
|
634
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
|
|
635
|
+
if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
|
|
624
636
|
urls.push(...collectUrls(fullPath, config, base));
|
|
625
637
|
} else if (stat.isFile() && (extname(entry) === ".md" || extname(entry) === ".mdx" || extname(entry) === ".html")) {
|
|
626
638
|
const relativePath = relative(base, fullPath);
|
|
@@ -848,6 +860,22 @@ function generatePageSchemas(page, config) {
|
|
|
848
860
|
}))
|
|
849
861
|
});
|
|
850
862
|
}
|
|
863
|
+
if (faqItems.length === 0) {
|
|
864
|
+
const howToSteps = detectHowToSteps(page.content || "");
|
|
865
|
+
if (howToSteps.length > 0) {
|
|
866
|
+
schemas.push({
|
|
867
|
+
"@context": "https://schema.org",
|
|
868
|
+
"@type": "HowTo",
|
|
869
|
+
name: page.title || config.title,
|
|
870
|
+
step: howToSteps.map((s, i) => ({
|
|
871
|
+
"@type": "HowToStep",
|
|
872
|
+
position: i + 1,
|
|
873
|
+
name: s.name,
|
|
874
|
+
text: s.text
|
|
875
|
+
}))
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
}
|
|
851
879
|
const pageType = config.schema.defaultType;
|
|
852
880
|
const pageSchema = {
|
|
853
881
|
"@context": "https://schema.org",
|
|
@@ -924,12 +952,43 @@ function detectFaqPatterns(content) {
|
|
|
924
952
|
}
|
|
925
953
|
return items;
|
|
926
954
|
}
|
|
955
|
+
function serializeJsonForHtml(value) {
|
|
956
|
+
return JSON.stringify(value).replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
957
|
+
}
|
|
958
|
+
function detectHowToSteps(content) {
|
|
959
|
+
const steps = [];
|
|
960
|
+
const lines = content.split("\n");
|
|
961
|
+
for (let i = 0; i < lines.length; i++) {
|
|
962
|
+
const line = lines[i].trim();
|
|
963
|
+
const stepMatch = line.match(/^#{1,6}\s+(?:Step\s+\d+[\s:.-]*|(\d+)[.)]\s*)(.+)$/i);
|
|
964
|
+
if (stepMatch) {
|
|
965
|
+
const name = (stepMatch[2] || stepMatch[1] || "").trim();
|
|
966
|
+
const bodyLines = [];
|
|
967
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
968
|
+
const nextLine = lines[j].trim();
|
|
969
|
+
if (!nextLine) {
|
|
970
|
+
if (bodyLines.length > 0) break;
|
|
971
|
+
continue;
|
|
972
|
+
}
|
|
973
|
+
if (/^#{1,6}\s/.test(nextLine)) break;
|
|
974
|
+
bodyLines.push(nextLine);
|
|
975
|
+
}
|
|
976
|
+
if (name) {
|
|
977
|
+
steps.push({
|
|
978
|
+
name,
|
|
979
|
+
text: bodyLines.join(" ").slice(0, 500)
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
return steps.length >= 2 ? steps : [];
|
|
985
|
+
}
|
|
927
986
|
function generateJsonLdScript(schemas) {
|
|
928
987
|
if (schemas.length === 0) return "";
|
|
929
988
|
if (schemas.length === 1) {
|
|
930
|
-
return `<script type="application/ld+json">${
|
|
989
|
+
return `<script type="application/ld+json">${serializeJsonForHtml(schemas[0])}</script>`;
|
|
931
990
|
}
|
|
932
|
-
return schemas.map((s) => `<script type="application/ld+json">${
|
|
991
|
+
return schemas.map((s) => `<script type="application/ld+json">${serializeJsonForHtml(s)}</script>`).join("\n");
|
|
933
992
|
}
|
|
934
993
|
async function generateAEOFiles(configOrRoot, maybeConfig) {
|
|
935
994
|
var _a;
|
|
@@ -1205,7 +1264,7 @@ function aeoVitePlugin(options = {}) {
|
|
|
1205
1264
|
if (result.errors.length > 0) console.error("[aeo.js] Errors:", result.errors);
|
|
1206
1265
|
}).catch((err) => console.error("[aeo.js] Failed:", err));
|
|
1207
1266
|
const mdHandler = async (req, res, next) => {
|
|
1208
|
-
var _a
|
|
1267
|
+
var _a;
|
|
1209
1268
|
if (!((_a = req.url) == null ? void 0 : _a.endsWith(".md"))) return next();
|
|
1210
1269
|
if (req.headers["x-aeo-internal"]) return next();
|
|
1211
1270
|
const filename = req.url.startsWith("/") ? req.url.slice(1) : req.url;
|
|
@@ -1220,8 +1279,9 @@ function aeoVitePlugin(options = {}) {
|
|
|
1220
1279
|
let pagePath = req.url.replace(/\.md$/, "") || "/";
|
|
1221
1280
|
if (pagePath === "/index") pagePath = "/";
|
|
1222
1281
|
try {
|
|
1223
|
-
const
|
|
1224
|
-
const
|
|
1282
|
+
const rawHost = req.headers.host || "localhost:5173";
|
|
1283
|
+
const host = /^(localhost|127\.0\.0\.1)(:\d+)?$/.test(rawHost) ? rawHost : "localhost:5173";
|
|
1284
|
+
const protocol = "http";
|
|
1225
1285
|
const response = await fetch(`${protocol}://${host}${pagePath}`, {
|
|
1226
1286
|
headers: { "x-aeo-internal": "1" }
|
|
1227
1287
|
});
|
|
@@ -1337,14 +1397,28 @@ if (typeof window !== 'undefined') {
|
|
|
1337
1397
|
description: extractDescription(html),
|
|
1338
1398
|
content: extractTextFromHtml(html)
|
|
1339
1399
|
};
|
|
1400
|
+
if (!/rel=["']canonical["']/i.test(result)) {
|
|
1401
|
+
const canonicalUrl = pagePath === "/" ? resolvedConfig.url : `${resolvedConfig.url.replace(/\/$/, "")}${pagePath}`;
|
|
1402
|
+
result = result.replace("</head>", ` <link rel="canonical" href="${canonicalUrl}" />
|
|
1403
|
+
</head>`);
|
|
1404
|
+
}
|
|
1405
|
+
if (!/name=["']description["']/i.test(result)) {
|
|
1406
|
+
const desc = pageEntry.description || resolvedConfig.description;
|
|
1407
|
+
if (desc) {
|
|
1408
|
+
const escDesc = desc.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
1409
|
+
result = result.replace("</head>", ` <meta name="description" content="${escDesc}" />
|
|
1410
|
+
</head>`);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1340
1413
|
if (resolvedConfig.og.enabled) {
|
|
1341
1414
|
const ogHtml = generateOGTagsHtml(pageEntry, resolvedConfig);
|
|
1342
1415
|
result = result.replace("</head>", ` ${ogHtml}
|
|
1343
1416
|
</head>`);
|
|
1344
1417
|
}
|
|
1345
1418
|
if (resolvedConfig.schema.enabled) {
|
|
1346
|
-
const
|
|
1347
|
-
const
|
|
1419
|
+
const siteSchemas = generateSiteSchemas(resolvedConfig);
|
|
1420
|
+
const pageSchemas = generatePageSchemas(pageEntry, resolvedConfig);
|
|
1421
|
+
const jsonLd = generateJsonLdScript([...siteSchemas, ...pageSchemas]);
|
|
1348
1422
|
if (jsonLd) {
|
|
1349
1423
|
result = result.replace("</head>", ` ${jsonLd}
|
|
1350
1424
|
</head>`);
|