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.
Files changed (68) hide show
  1. package/README.md +119 -164
  2. package/dist/angular.d.mts +1 -1
  3. package/dist/angular.d.ts +1 -1
  4. package/dist/angular.js +69 -13
  5. package/dist/angular.js.map +1 -1
  6. package/dist/angular.mjs +69 -13
  7. package/dist/angular.mjs.map +1 -1
  8. package/dist/astro.d.mts +1 -1
  9. package/dist/astro.d.ts +1 -1
  10. package/dist/astro.js +78 -18
  11. package/dist/astro.js.map +1 -1
  12. package/dist/astro.mjs +78 -18
  13. package/dist/astro.mjs.map +1 -1
  14. package/dist/cli.js +84 -27
  15. package/dist/cli.js.map +1 -1
  16. package/dist/cli.mjs +84 -27
  17. package/dist/cli.mjs.map +1 -1
  18. package/dist/index.d.mts +2 -2
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.js +89 -29
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +89 -29
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/next.d.mts +1 -1
  25. package/dist/next.d.ts +1 -1
  26. package/dist/next.js +71 -15
  27. package/dist/next.js.map +1 -1
  28. package/dist/next.mjs +71 -15
  29. package/dist/next.mjs.map +1 -1
  30. package/dist/nuxt.d.mts +1 -1
  31. package/dist/nuxt.d.ts +1 -1
  32. package/dist/nuxt.js +69 -13
  33. package/dist/nuxt.js.map +1 -1
  34. package/dist/nuxt.mjs +69 -13
  35. package/dist/nuxt.mjs.map +1 -1
  36. package/dist/react.d.mts +1 -1
  37. package/dist/react.d.ts +1 -1
  38. package/dist/react.js +52 -7
  39. package/dist/react.js.map +1 -1
  40. package/dist/react.mjs +52 -7
  41. package/dist/react.mjs.map +1 -1
  42. package/dist/{types-Cn_Qbkmg.d.mts → types-BlLNcw-X.d.mts} +2 -0
  43. package/dist/{types-Cn_Qbkmg.d.ts → types-BlLNcw-X.d.ts} +2 -0
  44. package/dist/vite.d.mts +1 -1
  45. package/dist/vite.d.ts +1 -1
  46. package/dist/vite.js +94 -20
  47. package/dist/vite.js.map +1 -1
  48. package/dist/vite.mjs +94 -20
  49. package/dist/vite.mjs.map +1 -1
  50. package/dist/vue.d.mts +1 -1
  51. package/dist/vue.d.ts +1 -1
  52. package/dist/vue.js +52 -7
  53. package/dist/vue.js.map +1 -1
  54. package/dist/vue.mjs +52 -7
  55. package/dist/vue.mjs.map +1 -1
  56. package/dist/webpack.d.mts +1 -1
  57. package/dist/webpack.d.ts +1 -1
  58. package/dist/webpack.js +69 -13
  59. package/dist/webpack.js.map +1 -1
  60. package/dist/webpack.mjs +69 -13
  61. package/dist/webpack.mjs.map +1 -1
  62. package/dist/widget.d.mts +1 -1
  63. package/dist/widget.d.ts +1 -1
  64. package/dist/widget.js +52 -7
  65. package/dist/widget.js.map +1 -1
  66. package/dist/widget.mjs +52 -7
  67. package/dist/widget.mjs.map +1 -1
  68. package/package.json +1 -1
package/dist/vite.js CHANGED
@@ -86,10 +86,19 @@ function generateRobotsTxt(config) {
86
86
  }
87
87
  lines.push("# Default for all other bots");
88
88
  lines.push("User-agent: *");
89
- lines.push("Allow: /");
89
+ for (const path of config.robots.allow.length > 0 ? config.robots.allow : ["/"]) {
90
+ lines.push(`Allow: ${path}`);
91
+ }
92
+ for (const path of config.robots.disallow) {
93
+ lines.push(`Disallow: ${path}`);
94
+ }
95
+ if (config.robots.crawlDelay > 0) {
96
+ lines.push(`Crawl-delay: ${config.robots.crawlDelay}`);
97
+ }
90
98
  lines.push("");
91
- if (config.url) {
92
- lines.push(`Sitemap: ${config.url}/sitemap.xml`);
99
+ const sitemapUrl = config.robots.sitemap || (config.url ? `${config.url}/sitemap.xml` : "");
100
+ if (sitemapUrl) {
101
+ lines.push(`Sitemap: ${sitemapUrl}`);
93
102
  }
94
103
  lines.push("");
95
104
  lines.push("# AEO (Answer Engine Optimization) files");
@@ -171,7 +180,7 @@ function detectFramework(projectRoot = process.cwd()) {
171
180
  };
172
181
  }
173
182
  function resolveConfig(config = {}) {
174
- 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;
183
+ 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;
175
184
  const frameworkInfo = detectFramework();
176
185
  return {
177
186
  title: config.title || "My Site",
@@ -215,15 +224,16 @@ function resolveConfig(config = {}) {
215
224
  widget: {
216
225
  enabled: ((_A = config.widget) == null ? void 0 : _A.enabled) !== false,
217
226
  position: ((_B = config.widget) == null ? void 0 : _B.position) || "bottom-right",
227
+ size: ((_C = config.widget) == null ? void 0 : _C.size) || "default",
218
228
  theme: {
219
- background: ((_D = (_C = config.widget) == null ? void 0 : _C.theme) == null ? void 0 : _D.background) || "rgba(18, 18, 24, 0.9)",
220
- text: ((_F = (_E = config.widget) == null ? void 0 : _E.theme) == null ? void 0 : _F.text) || "#C0C0C5",
221
- accent: ((_H = (_G = config.widget) == null ? void 0 : _G.theme) == null ? void 0 : _H.accent) || "#E8E8EA",
222
- badge: ((_J = (_I = config.widget) == null ? void 0 : _I.theme) == null ? void 0 : _J.badge) || "#4ADE80"
229
+ background: ((_E = (_D = config.widget) == null ? void 0 : _D.theme) == null ? void 0 : _E.background) || "rgba(18, 18, 24, 0.9)",
230
+ text: ((_G = (_F = config.widget) == null ? void 0 : _F.theme) == null ? void 0 : _G.text) || "#C0C0C5",
231
+ accent: ((_I = (_H = config.widget) == null ? void 0 : _H.theme) == null ? void 0 : _I.accent) || "#E8E8EA",
232
+ badge: ((_K = (_J = config.widget) == null ? void 0 : _J.theme) == null ? void 0 : _K.badge) || "#4ADE80"
223
233
  },
224
- humanLabel: ((_K = config.widget) == null ? void 0 : _K.humanLabel) || "Human",
225
- aiLabel: ((_L = config.widget) == null ? void 0 : _L.aiLabel) || "AI",
226
- showBadge: ((_M = config.widget) == null ? void 0 : _M.showBadge) !== false
234
+ humanLabel: ((_L = config.widget) == null ? void 0 : _L.humanLabel) || "Human",
235
+ aiLabel: ((_M = config.widget) == null ? void 0 : _M.aiLabel) || "AI",
236
+ showBadge: ((_N = config.widget) == null ? void 0 : _N.showBadge) !== false
227
237
  }
228
238
  };
229
239
  }
@@ -280,7 +290,8 @@ function collectMarkdownFiles(dir, base = dir) {
280
290
  for (const entry of entries) {
281
291
  const fullPath = path.join(dir, entry);
282
292
  const stat = fs.statSync(fullPath);
283
- if (stat.isDirectory() && !entry.startsWith(".") && entry !== "node_modules") {
293
+ const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
294
+ if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
284
295
  files.push(...collectMarkdownFiles(fullPath, base));
285
296
  } else if (stat.isFile() && (path.extname(entry) === ".md" || path.extname(entry) === ".mdx")) {
286
297
  const content = fs.readFileSync(fullPath, "utf-8");
@@ -623,7 +634,8 @@ function collectUrls(dir, config, base = dir) {
623
634
  for (const entry of entries) {
624
635
  const fullPath = path.join(dir, entry);
625
636
  const stat = fs.statSync(fullPath);
626
- if (stat.isDirectory() && !entry.startsWith(".") && entry !== "node_modules") {
637
+ const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
638
+ if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
627
639
  urls.push(...collectUrls(fullPath, config, base));
628
640
  } else if (stat.isFile() && (path.extname(entry) === ".md" || path.extname(entry) === ".mdx" || path.extname(entry) === ".html")) {
629
641
  const relativePath = path.relative(base, fullPath);
@@ -851,6 +863,22 @@ function generatePageSchemas(page, config) {
851
863
  }))
852
864
  });
853
865
  }
866
+ if (faqItems.length === 0) {
867
+ const howToSteps = detectHowToSteps(page.content || "");
868
+ if (howToSteps.length > 0) {
869
+ schemas.push({
870
+ "@context": "https://schema.org",
871
+ "@type": "HowTo",
872
+ name: page.title || config.title,
873
+ step: howToSteps.map((s, i) => ({
874
+ "@type": "HowToStep",
875
+ position: i + 1,
876
+ name: s.name,
877
+ text: s.text
878
+ }))
879
+ });
880
+ }
881
+ }
854
882
  const pageType = config.schema.defaultType;
855
883
  const pageSchema = {
856
884
  "@context": "https://schema.org",
@@ -927,12 +955,43 @@ function detectFaqPatterns(content) {
927
955
  }
928
956
  return items;
929
957
  }
958
+ function serializeJsonForHtml(value) {
959
+ return JSON.stringify(value).replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
960
+ }
961
+ function detectHowToSteps(content) {
962
+ const steps = [];
963
+ const lines = content.split("\n");
964
+ for (let i = 0; i < lines.length; i++) {
965
+ const line = lines[i].trim();
966
+ const stepMatch = line.match(/^#{1,6}\s+(?:Step\s+\d+[\s:.-]*|(\d+)[.)]\s*)(.+)$/i);
967
+ if (stepMatch) {
968
+ const name = (stepMatch[2] || stepMatch[1] || "").trim();
969
+ const bodyLines = [];
970
+ for (let j = i + 1; j < lines.length; j++) {
971
+ const nextLine = lines[j].trim();
972
+ if (!nextLine) {
973
+ if (bodyLines.length > 0) break;
974
+ continue;
975
+ }
976
+ if (/^#{1,6}\s/.test(nextLine)) break;
977
+ bodyLines.push(nextLine);
978
+ }
979
+ if (name) {
980
+ steps.push({
981
+ name,
982
+ text: bodyLines.join(" ").slice(0, 500)
983
+ });
984
+ }
985
+ }
986
+ }
987
+ return steps.length >= 2 ? steps : [];
988
+ }
930
989
  function generateJsonLdScript(schemas) {
931
990
  if (schemas.length === 0) return "";
932
991
  if (schemas.length === 1) {
933
- return `<script type="application/ld+json">${JSON.stringify(schemas[0])}</script>`;
992
+ return `<script type="application/ld+json">${serializeJsonForHtml(schemas[0])}</script>`;
934
993
  }
935
- return schemas.map((s) => `<script type="application/ld+json">${JSON.stringify(s)}</script>`).join("\n");
994
+ return schemas.map((s) => `<script type="application/ld+json">${serializeJsonForHtml(s)}</script>`).join("\n");
936
995
  }
937
996
  async function generateAEOFiles(configOrRoot, maybeConfig) {
938
997
  var _a;
@@ -1208,7 +1267,7 @@ function aeoVitePlugin(options = {}) {
1208
1267
  if (result.errors.length > 0) console.error("[aeo.js] Errors:", result.errors);
1209
1268
  }).catch((err) => console.error("[aeo.js] Failed:", err));
1210
1269
  const mdHandler = async (req, res, next) => {
1211
- var _a, _b;
1270
+ var _a;
1212
1271
  if (!((_a = req.url) == null ? void 0 : _a.endsWith(".md"))) return next();
1213
1272
  if (req.headers["x-aeo-internal"]) return next();
1214
1273
  const filename = req.url.startsWith("/") ? req.url.slice(1) : req.url;
@@ -1223,8 +1282,9 @@ function aeoVitePlugin(options = {}) {
1223
1282
  let pagePath = req.url.replace(/\.md$/, "") || "/";
1224
1283
  if (pagePath === "/index") pagePath = "/";
1225
1284
  try {
1226
- const host = req.headers.host || "localhost:5173";
1227
- const protocol = ((_b = req.connection) == null ? void 0 : _b.encrypted) ? "https" : "http";
1285
+ const rawHost = req.headers.host || "localhost:5173";
1286
+ const host = /^(localhost|127\.0\.0\.1)(:\d+)?$/.test(rawHost) ? rawHost : "localhost:5173";
1287
+ const protocol = "http";
1228
1288
  const response = await fetch(`${protocol}://${host}${pagePath}`, {
1229
1289
  headers: { "x-aeo-internal": "1" }
1230
1290
  });
@@ -1340,14 +1400,28 @@ if (typeof window !== 'undefined') {
1340
1400
  description: extractDescription(html),
1341
1401
  content: extractTextFromHtml(html)
1342
1402
  };
1403
+ if (!/rel=["']canonical["']/i.test(result)) {
1404
+ const canonicalUrl = pagePath === "/" ? resolvedConfig.url : `${resolvedConfig.url.replace(/\/$/, "")}${pagePath}`;
1405
+ result = result.replace("</head>", ` <link rel="canonical" href="${canonicalUrl}" />
1406
+ </head>`);
1407
+ }
1408
+ if (!/name=["']description["']/i.test(result)) {
1409
+ const desc = pageEntry.description || resolvedConfig.description;
1410
+ if (desc) {
1411
+ const escDesc = desc.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1412
+ result = result.replace("</head>", ` <meta name="description" content="${escDesc}" />
1413
+ </head>`);
1414
+ }
1415
+ }
1343
1416
  if (resolvedConfig.og.enabled) {
1344
1417
  const ogHtml = generateOGTagsHtml(pageEntry, resolvedConfig);
1345
1418
  result = result.replace("</head>", ` ${ogHtml}
1346
1419
  </head>`);
1347
1420
  }
1348
1421
  if (resolvedConfig.schema.enabled) {
1349
- const schemas = generatePageSchemas(pageEntry, resolvedConfig);
1350
- const jsonLd = generateJsonLdScript(schemas);
1422
+ const siteSchemas = generateSiteSchemas(resolvedConfig);
1423
+ const pageSchemas = generatePageSchemas(pageEntry, resolvedConfig);
1424
+ const jsonLd = generateJsonLdScript([...siteSchemas, ...pageSchemas]);
1351
1425
  if (jsonLd) {
1352
1426
  result = result.replace("</head>", ` ${jsonLd}
1353
1427
  </head>`);