aeo.js 0.0.2 → 0.0.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/README.md +132 -17
- package/dist/angular.d.mts +29 -0
- package/dist/angular.d.ts +29 -0
- package/dist/angular.js +1314 -0
- package/dist/angular.js.map +1 -0
- package/dist/angular.mjs +1310 -0
- package/dist/angular.mjs.map +1 -0
- package/dist/astro.d.mts +8 -2
- package/dist/astro.d.ts +8 -2
- package/dist/astro.js +342 -100
- package/dist/astro.js.map +1 -1
- package/dist/astro.mjs +342 -100
- package/dist/astro.mjs.map +1 -1
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1880 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +1878 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +178 -4
- package/dist/index.d.ts +178 -4
- package/dist/index.js +972 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +952 -20
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +2 -17
- package/dist/next.d.ts +2 -17
- package/dist/next.js +262 -73
- package/dist/next.js.map +1 -1
- package/dist/next.mjs +262 -73
- package/dist/next.mjs.map +1 -1
- package/dist/nuxt.d.mts +13 -0
- package/dist/nuxt.d.ts +13 -0
- package/dist/nuxt.js +1344 -0
- package/dist/nuxt.js.map +1 -0
- package/dist/nuxt.mjs +1337 -0
- package/dist/nuxt.mjs.map +1 -0
- package/dist/react.d.mts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/{types-BTY-v-7i.d.mts → types-Cn_Qbkmg.d.mts} +34 -0
- package/dist/{types-BTY-v-7i.d.ts → types-Cn_Qbkmg.d.ts} +34 -0
- package/dist/vite.d.mts +5 -0
- package/dist/vite.d.ts +5 -0
- package/dist/vite.js +1370 -0
- package/dist/vite.js.map +1 -0
- package/dist/vite.mjs +1366 -0
- package/dist/vite.mjs.map +1 -0
- package/dist/vue.d.mts +19 -0
- package/dist/vue.d.ts +19 -0
- package/dist/vue.js +1078 -0
- package/dist/vue.js.map +1 -0
- package/dist/vue.mjs +1072 -0
- package/dist/vue.mjs.map +1 -0
- package/dist/webpack.d.mts +1 -1
- package/dist/webpack.d.ts +1 -1
- package/dist/webpack.js +178 -18
- package/dist/webpack.js.map +1 -1
- package/dist/webpack.mjs +178 -18
- package/dist/webpack.mjs.map +1 -1
- package/dist/widget.d.mts +1 -1
- package/dist/widget.d.ts +1 -1
- package/package.json +48 -2
package/dist/next.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AeoConfig } from './types-
|
|
1
|
+
import { A as AeoConfig } from './types-Cn_Qbkmg.mjs';
|
|
2
2
|
|
|
3
3
|
interface NextAeoConfig {
|
|
4
4
|
aeo?: AeoConfig;
|
|
@@ -7,22 +7,7 @@ interface NextAeoConfig {
|
|
|
7
7
|
[key: string]: any;
|
|
8
8
|
}
|
|
9
9
|
declare function withAeo(nextConfig?: NextAeoConfig): Record<string, any>;
|
|
10
|
-
declare function generateAeoMetadata(config?: AeoConfig): Promise<
|
|
11
|
-
title: string;
|
|
12
|
-
description: string;
|
|
13
|
-
alternates: {
|
|
14
|
-
types: {
|
|
15
|
-
'text/plain': {
|
|
16
|
-
url: string;
|
|
17
|
-
title: string;
|
|
18
|
-
}[];
|
|
19
|
-
'application/json': {
|
|
20
|
-
url: string;
|
|
21
|
-
title: string;
|
|
22
|
-
}[];
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
}>;
|
|
10
|
+
declare function generateAeoMetadata(config?: AeoConfig): Promise<Record<string, any>>;
|
|
26
11
|
/**
|
|
27
12
|
* Post-build function that reads pre-rendered HTML from .next/server/
|
|
28
13
|
* and regenerates AEO files with actual page content.
|
package/dist/next.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AeoConfig } from './types-
|
|
1
|
+
import { A as AeoConfig } from './types-Cn_Qbkmg.js';
|
|
2
2
|
|
|
3
3
|
interface NextAeoConfig {
|
|
4
4
|
aeo?: AeoConfig;
|
|
@@ -7,22 +7,7 @@ interface NextAeoConfig {
|
|
|
7
7
|
[key: string]: any;
|
|
8
8
|
}
|
|
9
9
|
declare function withAeo(nextConfig?: NextAeoConfig): Record<string, any>;
|
|
10
|
-
declare function generateAeoMetadata(config?: AeoConfig): Promise<
|
|
11
|
-
title: string;
|
|
12
|
-
description: string;
|
|
13
|
-
alternates: {
|
|
14
|
-
types: {
|
|
15
|
-
'text/plain': {
|
|
16
|
-
url: string;
|
|
17
|
-
title: string;
|
|
18
|
-
}[];
|
|
19
|
-
'application/json': {
|
|
20
|
-
url: string;
|
|
21
|
-
title: string;
|
|
22
|
-
}[];
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
}>;
|
|
10
|
+
declare function generateAeoMetadata(config?: AeoConfig): Promise<Record<string, any>>;
|
|
26
11
|
/**
|
|
27
12
|
* Post-build function that reads pre-rendered HTML from .next/server/
|
|
28
13
|
* and regenerates AEO files with actual page content.
|
package/dist/next.js
CHANGED
|
@@ -166,7 +166,7 @@ function detectFramework(projectRoot = process.cwd()) {
|
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
168
|
function resolveConfig(config = {}) {
|
|
169
|
-
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;
|
|
169
|
+
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;
|
|
170
170
|
const frameworkInfo = detectFramework();
|
|
171
171
|
return {
|
|
172
172
|
title: config.title || "My Site",
|
|
@@ -182,26 +182,43 @@ function resolveConfig(config = {}) {
|
|
|
182
182
|
rawMarkdown: ((_d = config.generators) == null ? void 0 : _d.rawMarkdown) !== false,
|
|
183
183
|
manifest: ((_e = config.generators) == null ? void 0 : _e.manifest) !== false,
|
|
184
184
|
sitemap: ((_f = config.generators) == null ? void 0 : _f.sitemap) !== false,
|
|
185
|
-
aiIndex: ((_g = config.generators) == null ? void 0 : _g.aiIndex) !== false
|
|
185
|
+
aiIndex: ((_g = config.generators) == null ? void 0 : _g.aiIndex) !== false,
|
|
186
|
+
schema: ((_h = config.generators) == null ? void 0 : _h.schema) !== false
|
|
186
187
|
},
|
|
187
188
|
robots: {
|
|
188
|
-
allow: ((
|
|
189
|
-
disallow: ((
|
|
190
|
-
crawlDelay: ((
|
|
191
|
-
sitemap: ((
|
|
189
|
+
allow: ((_i = config.robots) == null ? void 0 : _i.allow) || ["/"],
|
|
190
|
+
disallow: ((_j = config.robots) == null ? void 0 : _j.disallow) || [],
|
|
191
|
+
crawlDelay: ((_k = config.robots) == null ? void 0 : _k.crawlDelay) || 0,
|
|
192
|
+
sitemap: ((_l = config.robots) == null ? void 0 : _l.sitemap) || ""
|
|
193
|
+
},
|
|
194
|
+
schema: {
|
|
195
|
+
enabled: ((_m = config.schema) == null ? void 0 : _m.enabled) !== false,
|
|
196
|
+
organization: {
|
|
197
|
+
name: ((_o = (_n = config.schema) == null ? void 0 : _n.organization) == null ? void 0 : _o.name) || config.title || "My Site",
|
|
198
|
+
url: ((_q = (_p = config.schema) == null ? void 0 : _p.organization) == null ? void 0 : _q.url) || config.url || "https://example.com",
|
|
199
|
+
logo: ((_s = (_r = config.schema) == null ? void 0 : _r.organization) == null ? void 0 : _s.logo) || "",
|
|
200
|
+
sameAs: ((_u = (_t = config.schema) == null ? void 0 : _t.organization) == null ? void 0 : _u.sameAs) || []
|
|
201
|
+
},
|
|
202
|
+
defaultType: ((_v = config.schema) == null ? void 0 : _v.defaultType) || "WebPage"
|
|
203
|
+
},
|
|
204
|
+
og: {
|
|
205
|
+
enabled: ((_w = config.og) == null ? void 0 : _w.enabled) !== false,
|
|
206
|
+
image: ((_x = config.og) == null ? void 0 : _x.image) || "",
|
|
207
|
+
twitterHandle: ((_y = config.og) == null ? void 0 : _y.twitterHandle) || "",
|
|
208
|
+
type: ((_z = config.og) == null ? void 0 : _z.type) || "website"
|
|
192
209
|
},
|
|
193
210
|
widget: {
|
|
194
|
-
enabled: ((
|
|
195
|
-
position: ((
|
|
211
|
+
enabled: ((_A = config.widget) == null ? void 0 : _A.enabled) !== false,
|
|
212
|
+
position: ((_B = config.widget) == null ? void 0 : _B.position) || "bottom-right",
|
|
196
213
|
theme: {
|
|
197
|
-
background: ((
|
|
198
|
-
text: ((
|
|
199
|
-
accent: ((
|
|
200
|
-
badge: ((
|
|
214
|
+
background: ((_D = (_C = config.widget) == null ? void 0 : _C.theme) == null ? void 0 : _D.background) || "rgba(18, 18, 24, 0.9)",
|
|
215
|
+
text: ((_F = (_E = config.widget) == null ? void 0 : _E.theme) == null ? void 0 : _F.text) || "#C0C0C5",
|
|
216
|
+
accent: ((_H = (_G = config.widget) == null ? void 0 : _G.theme) == null ? void 0 : _H.accent) || "#E8E8EA",
|
|
217
|
+
badge: ((_J = (_I = config.widget) == null ? void 0 : _I.theme) == null ? void 0 : _J.badge) || "#4ADE80"
|
|
201
218
|
},
|
|
202
|
-
humanLabel: ((
|
|
203
|
-
aiLabel: ((
|
|
204
|
-
showBadge: ((
|
|
219
|
+
humanLabel: ((_K = config.widget) == null ? void 0 : _K.humanLabel) || "Human",
|
|
220
|
+
aiLabel: ((_L = config.widget) == null ? void 0 : _L.aiLabel) || "AI",
|
|
221
|
+
showBadge: ((_M = config.widget) == null ? void 0 : _M.showBadge) !== false
|
|
205
222
|
}
|
|
206
223
|
};
|
|
207
224
|
}
|
|
@@ -500,8 +517,8 @@ function generatePageMarkdownFiles(config) {
|
|
|
500
517
|
const generated = [];
|
|
501
518
|
const pages = config.pages || [];
|
|
502
519
|
for (const page of pages) {
|
|
520
|
+
if (!page.content) continue;
|
|
503
521
|
const pageTitle = page.title || (page.pathname === "/" ? config.title : void 0);
|
|
504
|
-
if (!page.content && !pageTitle) continue;
|
|
505
522
|
let filename;
|
|
506
523
|
if (page.pathname === "/") {
|
|
507
524
|
filename = "index.md";
|
|
@@ -771,6 +788,140 @@ function generateAIIndex(config) {
|
|
|
771
788
|
};
|
|
772
789
|
return JSON.stringify(index, null, 2);
|
|
773
790
|
}
|
|
791
|
+
|
|
792
|
+
// src/core/schema.ts
|
|
793
|
+
function generateSchema(config) {
|
|
794
|
+
const output = generateSchemaObjects(config);
|
|
795
|
+
return JSON.stringify(output, null, 2);
|
|
796
|
+
}
|
|
797
|
+
function generateSchemaObjects(config) {
|
|
798
|
+
const siteSchemas = generateSiteSchemas(config);
|
|
799
|
+
const pageSchemas = {};
|
|
800
|
+
for (const page of config.pages) {
|
|
801
|
+
const schemas = generatePageSchemas(page, config);
|
|
802
|
+
if (schemas.length > 0) {
|
|
803
|
+
pageSchemas[page.pathname] = schemas;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
return { site: siteSchemas, pages: pageSchemas };
|
|
807
|
+
}
|
|
808
|
+
function generateSiteSchemas(config) {
|
|
809
|
+
const schemas = [];
|
|
810
|
+
schemas.push({
|
|
811
|
+
"@context": "https://schema.org",
|
|
812
|
+
"@type": "WebSite",
|
|
813
|
+
name: config.title,
|
|
814
|
+
description: config.description || void 0,
|
|
815
|
+
url: config.url
|
|
816
|
+
});
|
|
817
|
+
const org = config.schema.organization;
|
|
818
|
+
if (org.name || org.sameAs.length > 0) {
|
|
819
|
+
const orgSchema = {
|
|
820
|
+
"@context": "https://schema.org",
|
|
821
|
+
"@type": "Organization",
|
|
822
|
+
name: org.name,
|
|
823
|
+
url: org.url
|
|
824
|
+
};
|
|
825
|
+
if (org.logo) orgSchema.logo = org.logo;
|
|
826
|
+
if (org.sameAs.length > 0) orgSchema.sameAs = org.sameAs;
|
|
827
|
+
schemas.push(orgSchema);
|
|
828
|
+
}
|
|
829
|
+
return schemas;
|
|
830
|
+
}
|
|
831
|
+
function generatePageSchemas(page, config) {
|
|
832
|
+
const schemas = [];
|
|
833
|
+
const pageUrl = page.pathname === "/" ? config.url : `${config.url.replace(/\/$/, "")}${page.pathname}`;
|
|
834
|
+
const faqItems = detectFaqPatterns(page.content || "");
|
|
835
|
+
if (faqItems.length > 0) {
|
|
836
|
+
schemas.push({
|
|
837
|
+
"@context": "https://schema.org",
|
|
838
|
+
"@type": "FAQPage",
|
|
839
|
+
mainEntity: faqItems.map(({ question, answer }) => ({
|
|
840
|
+
"@type": "Question",
|
|
841
|
+
name: question,
|
|
842
|
+
acceptedAnswer: {
|
|
843
|
+
"@type": "Answer",
|
|
844
|
+
text: answer
|
|
845
|
+
}
|
|
846
|
+
}))
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
const pageType = config.schema.defaultType;
|
|
850
|
+
const pageSchema = {
|
|
851
|
+
"@context": "https://schema.org",
|
|
852
|
+
"@type": pageType,
|
|
853
|
+
name: page.title || config.title,
|
|
854
|
+
url: pageUrl
|
|
855
|
+
};
|
|
856
|
+
if (page.description) pageSchema.description = page.description;
|
|
857
|
+
if (pageType === "Article") {
|
|
858
|
+
pageSchema.headline = page.title || config.title;
|
|
859
|
+
pageSchema.author = {
|
|
860
|
+
"@type": "Organization",
|
|
861
|
+
name: config.schema.organization.name
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
schemas.push(pageSchema);
|
|
865
|
+
if (page.pathname !== "/") {
|
|
866
|
+
const breadcrumbs = generateBreadcrumbs(page.pathname, config);
|
|
867
|
+
if (breadcrumbs.length > 1) {
|
|
868
|
+
schemas.push({
|
|
869
|
+
"@context": "https://schema.org",
|
|
870
|
+
"@type": "BreadcrumbList",
|
|
871
|
+
itemListElement: breadcrumbs.map((crumb, i) => ({
|
|
872
|
+
"@type": "ListItem",
|
|
873
|
+
position: i + 1,
|
|
874
|
+
name: crumb.name,
|
|
875
|
+
item: crumb.url
|
|
876
|
+
}))
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
return schemas;
|
|
881
|
+
}
|
|
882
|
+
function generateBreadcrumbs(pathname, config) {
|
|
883
|
+
const baseUrl = config.url.replace(/\/$/, "");
|
|
884
|
+
const parts = pathname.split("/").filter(Boolean);
|
|
885
|
+
const crumbs = [
|
|
886
|
+
{ name: "Home", url: baseUrl + "/" }
|
|
887
|
+
];
|
|
888
|
+
let currentPath = "";
|
|
889
|
+
for (const part of parts) {
|
|
890
|
+
currentPath += "/" + part;
|
|
891
|
+
crumbs.push({
|
|
892
|
+
name: part.charAt(0).toUpperCase() + part.slice(1).replace(/-/g, " "),
|
|
893
|
+
url: baseUrl + currentPath
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
return crumbs;
|
|
897
|
+
}
|
|
898
|
+
function detectFaqPatterns(content) {
|
|
899
|
+
const items = [];
|
|
900
|
+
const lines = content.split("\n");
|
|
901
|
+
for (let i = 0; i < lines.length; i++) {
|
|
902
|
+
const line = lines[i].trim();
|
|
903
|
+
const headingMatch = line.match(/^#{1,6}\s+(.+\?)\s*$/);
|
|
904
|
+
if (headingMatch) {
|
|
905
|
+
const answerLines = [];
|
|
906
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
907
|
+
const nextLine = lines[j].trim();
|
|
908
|
+
if (!nextLine) {
|
|
909
|
+
if (answerLines.length > 0) break;
|
|
910
|
+
continue;
|
|
911
|
+
}
|
|
912
|
+
if (/^#{1,6}\s/.test(nextLine)) break;
|
|
913
|
+
answerLines.push(nextLine);
|
|
914
|
+
}
|
|
915
|
+
if (answerLines.length > 0) {
|
|
916
|
+
items.push({
|
|
917
|
+
question: headingMatch[1],
|
|
918
|
+
answer: answerLines.join(" ").slice(0, 500)
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
return items;
|
|
924
|
+
}
|
|
774
925
|
async function generateAEOFiles(configOrRoot, maybeConfig) {
|
|
775
926
|
var _a;
|
|
776
927
|
let config;
|
|
@@ -799,7 +950,7 @@ async function generateAEOFiles(configOrRoot, maybeConfig) {
|
|
|
799
950
|
if (config.generators.llmsTxt) {
|
|
800
951
|
try {
|
|
801
952
|
const content = generateLlmsTxt(config);
|
|
802
|
-
fs.writeFileSync(path.join(outDir, "llms.txt"),
|
|
953
|
+
fs.writeFileSync(path.join(outDir, "llms.txt"), content, "utf-8");
|
|
803
954
|
files.push("llms.txt");
|
|
804
955
|
} catch (e) {
|
|
805
956
|
errors.push(`llms.txt: ${e.message}`);
|
|
@@ -808,7 +959,7 @@ async function generateAEOFiles(configOrRoot, maybeConfig) {
|
|
|
808
959
|
if (config.generators.llmsFullTxt) {
|
|
809
960
|
try {
|
|
810
961
|
const content = generateLlmsFullTxt(config);
|
|
811
|
-
fs.writeFileSync(path.join(outDir, "llms-full.txt"),
|
|
962
|
+
fs.writeFileSync(path.join(outDir, "llms-full.txt"), content, "utf-8");
|
|
812
963
|
files.push("llms-full.txt");
|
|
813
964
|
} catch (e) {
|
|
814
965
|
errors.push(`llms-full.txt: ${e.message}`);
|
|
@@ -859,8 +1010,78 @@ async function generateAEOFiles(configOrRoot, maybeConfig) {
|
|
|
859
1010
|
errors.push(`ai-index.json: ${e.message}`);
|
|
860
1011
|
}
|
|
861
1012
|
}
|
|
1013
|
+
if (config.generators.schema && config.schema.enabled) {
|
|
1014
|
+
try {
|
|
1015
|
+
const content = generateSchema(config);
|
|
1016
|
+
fs.writeFileSync(path.join(outDir, "schema.json"), content, "utf-8");
|
|
1017
|
+
files.push("schema.json");
|
|
1018
|
+
} catch (e) {
|
|
1019
|
+
errors.push(`schema.json: ${e.message}`);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
862
1022
|
return { files, errors };
|
|
863
1023
|
}
|
|
1024
|
+
|
|
1025
|
+
// src/core/html-extract.ts
|
|
1026
|
+
function extractTextFromHtml(html) {
|
|
1027
|
+
let text = html;
|
|
1028
|
+
text = text.replace(/<script[\s\S]*?<\/script>/gi, "");
|
|
1029
|
+
text = text.replace(/<style[\s\S]*?<\/style>/gi, "");
|
|
1030
|
+
text = text.replace(/<svg[\s\S]*?<\/svg>/gi, "");
|
|
1031
|
+
const mainMatch = text.match(/<main[^>]*>([\s\S]*)<\/main>/i);
|
|
1032
|
+
if (mainMatch) {
|
|
1033
|
+
text = mainMatch[1];
|
|
1034
|
+
} else {
|
|
1035
|
+
text = text.replace(/<nav[\s\S]*?<\/nav>/gi, "");
|
|
1036
|
+
text = text.replace(/<header[\s\S]*?<\/header>/gi, "");
|
|
1037
|
+
text = text.replace(/<footer[\s\S]*?<\/footer>/gi, "");
|
|
1038
|
+
}
|
|
1039
|
+
text = text.replace(/<a[^>]+href=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi, (_, url, inner) => {
|
|
1040
|
+
if (/<(?:h[1-6]|div|p|section)[^>]*>/i.test(inner)) {
|
|
1041
|
+
const cleanInner = inner.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
1042
|
+
return `
|
|
1043
|
+
[${cleanInner.slice(0, 120).trim()}](${url})
|
|
1044
|
+
`;
|
|
1045
|
+
}
|
|
1046
|
+
return `[${inner}](${url})`;
|
|
1047
|
+
});
|
|
1048
|
+
text = text.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, "\n\n## $1\n\n");
|
|
1049
|
+
text = text.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, "\n\n## $1\n\n");
|
|
1050
|
+
text = text.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, "\n\n### $1\n\n");
|
|
1051
|
+
text = text.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, "\n\n#### $1\n\n");
|
|
1052
|
+
text = text.replace(/<h5[^>]*>([\s\S]*?)<\/h5>/gi, "\n\n##### $1\n\n");
|
|
1053
|
+
text = text.replace(/<h6[^>]*>([\s\S]*?)<\/h6>/gi, "\n\n###### $1\n\n");
|
|
1054
|
+
text = text.replace(/<a[^>]+href=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi, "[$2]($1)");
|
|
1055
|
+
text = text.replace(/<(?:strong|b)[^>]*>([\s\S]*?)<\/(?:strong|b)>/gi, "**$1**");
|
|
1056
|
+
text = text.replace(/<(?:em|i)[^>]*>([\s\S]*?)<\/(?:em|i)>/gi, "*$1*");
|
|
1057
|
+
text = text.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, "\n- $1");
|
|
1058
|
+
text = text.replace(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/gi, "\n\n> $1\n\n");
|
|
1059
|
+
text = text.replace(/<hr[^>]*\/?>/gi, "\n\n---\n\n");
|
|
1060
|
+
text = text.replace(/<br[^>]*\/?>/gi, "\n");
|
|
1061
|
+
text = text.replace(/<\/p>/gi, "\n\n");
|
|
1062
|
+
text = text.replace(/<p[^>]*>/gi, "");
|
|
1063
|
+
text = text.replace(/<\/?(?:div|section|article|header|main|aside|figure|figcaption|table|thead|tbody|tr|td|th|ul|ol|dl|dt|dd)[^>]*>/gi, "\n");
|
|
1064
|
+
text = text.replace(/<[^>]+>/g, "");
|
|
1065
|
+
text = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/©/g, "(c)");
|
|
1066
|
+
text = text.replace(/[\u{1F1E0}-\u{1FAFF}\u{2600}-\u{27BF}\u{FE00}-\u{FE0F}\u{200D}\u{20E3}]/gu, "");
|
|
1067
|
+
text = text.split("\n").map((l) => l.replace(/\s+/g, " ").trim()).join("\n");
|
|
1068
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
1069
|
+
text = text.replace(/\[[\s\n]+/g, "[").replace(/[\s\n]+\]/g, "]");
|
|
1070
|
+
text = text.replace(/(#{2,6})\s*\n+\s*/g, "$1 ");
|
|
1071
|
+
text = text.replace(/^#{2,6}\s*$/gm, "");
|
|
1072
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
1073
|
+
return text.trim().slice(0, 8e3);
|
|
1074
|
+
}
|
|
1075
|
+
function extractTitle2(html) {
|
|
1076
|
+
var _a, _b;
|
|
1077
|
+
const match = html.match(/<title>([^<]*)<\/title>/i);
|
|
1078
|
+
if (!match) return void 0;
|
|
1079
|
+
return ((_b = (_a = match[1]) == null ? void 0 : _a.split("|")[0]) == null ? void 0 : _b.trim()) || match[1];
|
|
1080
|
+
}
|
|
1081
|
+
function extractDescription(html) {
|
|
1082
|
+
const match = html.match(/<meta\s+name=["']description["']\s+content=["']([^"']*)["']/i);
|
|
1083
|
+
return match == null ? void 0 : match[1];
|
|
1084
|
+
}
|
|
864
1085
|
function scanNextPages(projectRoot) {
|
|
865
1086
|
const pages = [];
|
|
866
1087
|
for (const base of ["app", "src/app"]) {
|
|
@@ -975,7 +1196,7 @@ async function generateAeoMetadata(config) {
|
|
|
975
1196
|
if (process.env.NODE_ENV === "production") {
|
|
976
1197
|
await generateAEOFiles(resolvedConfig);
|
|
977
1198
|
}
|
|
978
|
-
|
|
1199
|
+
const metadata = {
|
|
979
1200
|
title: resolvedConfig.title,
|
|
980
1201
|
description: resolvedConfig.description,
|
|
981
1202
|
alternates: {
|
|
@@ -991,62 +1212,30 @@ async function generateAeoMetadata(config) {
|
|
|
991
1212
|
}
|
|
992
1213
|
}
|
|
993
1214
|
};
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1215
|
+
if (resolvedConfig.og.enabled) {
|
|
1216
|
+
metadata.openGraph = {
|
|
1217
|
+
type: resolvedConfig.og.type,
|
|
1218
|
+
title: resolvedConfig.title,
|
|
1219
|
+
description: resolvedConfig.description,
|
|
1220
|
+
url: resolvedConfig.url,
|
|
1221
|
+
siteName: resolvedConfig.title,
|
|
1222
|
+
...resolvedConfig.og.image ? { images: [{ url: resolvedConfig.og.image }] } : {}
|
|
1223
|
+
};
|
|
1224
|
+
metadata.twitter = {
|
|
1225
|
+
card: resolvedConfig.og.image ? "summary_large_image" : "summary",
|
|
1226
|
+
title: resolvedConfig.title,
|
|
1227
|
+
description: resolvedConfig.description,
|
|
1228
|
+
...resolvedConfig.og.twitterHandle ? { site: resolvedConfig.og.twitterHandle } : {},
|
|
1229
|
+
...resolvedConfig.og.image ? { images: [resolvedConfig.og.image] } : {}
|
|
1230
|
+
};
|
|
1007
1231
|
}
|
|
1008
|
-
|
|
1009
|
-
if (/<(?:h[1-6]|div|p|section)[^>]*>/i.test(inner)) {
|
|
1010
|
-
const cleanInner = inner.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
1011
|
-
return `
|
|
1012
|
-
[${cleanInner.slice(0, 120).trim()}](${url})
|
|
1013
|
-
`;
|
|
1014
|
-
}
|
|
1015
|
-
return `[${inner}](${url})`;
|
|
1016
|
-
});
|
|
1017
|
-
text = text.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, "\n\n## $1\n\n");
|
|
1018
|
-
text = text.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, "\n\n## $1\n\n");
|
|
1019
|
-
text = text.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, "\n\n### $1\n\n");
|
|
1020
|
-
text = text.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, "\n\n#### $1\n\n");
|
|
1021
|
-
text = text.replace(/<h5[^>]*>([\s\S]*?)<\/h5>/gi, "\n\n##### $1\n\n");
|
|
1022
|
-
text = text.replace(/<h6[^>]*>([\s\S]*?)<\/h6>/gi, "\n\n###### $1\n\n");
|
|
1023
|
-
text = text.replace(/<a[^>]+href=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi, "[$2]($1)");
|
|
1024
|
-
text = text.replace(/<(?:strong|b)[^>]*>([\s\S]*?)<\/(?:strong|b)>/gi, "**$1**");
|
|
1025
|
-
text = text.replace(/<(?:em|i)[^>]*>([\s\S]*?)<\/(?:em|i)>/gi, "*$1*");
|
|
1026
|
-
text = text.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, "\n- $1");
|
|
1027
|
-
text = text.replace(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/gi, "\n\n> $1\n\n");
|
|
1028
|
-
text = text.replace(/<hr[^>]*\/?>/gi, "\n\n---\n\n");
|
|
1029
|
-
text = text.replace(/<br[^>]*\/?>/gi, "\n");
|
|
1030
|
-
text = text.replace(/<\/p>/gi, "\n\n");
|
|
1031
|
-
text = text.replace(/<p[^>]*>/gi, "");
|
|
1032
|
-
text = text.replace(/<\/?(?:div|section|article|header|main|aside|figure|figcaption|table|thead|tbody|tr|td|th|ul|ol|dl|dt|dd)[^>]*>/gi, "\n");
|
|
1033
|
-
text = text.replace(/<[^>]+>/g, "");
|
|
1034
|
-
text = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/©/g, "(c)");
|
|
1035
|
-
text = text.replace(/[\u{1F1E0}-\u{1FAFF}\u{2600}-\u{27BF}\u{FE00}-\u{FE0F}\u{200D}\u{20E3}]/gu, "");
|
|
1036
|
-
text = text.split("\n").map((l) => l.replace(/\s+/g, " ").trim()).join("\n");
|
|
1037
|
-
text = text.replace(/\n{3,}/g, "\n\n");
|
|
1038
|
-
text = text.replace(/\[[\s\n]+/g, "[").replace(/[\s\n]+\]/g, "]");
|
|
1039
|
-
text = text.replace(/(#{2,6})\s*\n+\s*/g, "$1 ");
|
|
1040
|
-
text = text.replace(/^#{2,6}\s*$/gm, "");
|
|
1041
|
-
text = text.replace(/\n{3,}/g, "\n\n");
|
|
1042
|
-
return text.trim().slice(0, 8e3);
|
|
1232
|
+
return metadata;
|
|
1043
1233
|
}
|
|
1044
1234
|
function scanNextBuildOutput(projectRoot) {
|
|
1045
1235
|
const pages = [];
|
|
1046
1236
|
const serverAppDir = path.join(projectRoot, ".next", "server", "app");
|
|
1047
1237
|
if (!fs.existsSync(serverAppDir)) return pages;
|
|
1048
1238
|
function walk(dir, basePath = "") {
|
|
1049
|
-
var _a, _b;
|
|
1050
1239
|
try {
|
|
1051
1240
|
const entries = fs.readdirSync(dir);
|
|
1052
1241
|
for (const entry of entries) {
|
|
@@ -1056,14 +1245,14 @@ function scanNextBuildOutput(projectRoot) {
|
|
|
1056
1245
|
walk(fullPath, `${basePath}/${entry}`);
|
|
1057
1246
|
} else if (entry === "index.html") {
|
|
1058
1247
|
const html = fs.readFileSync(fullPath, "utf-8");
|
|
1059
|
-
const
|
|
1060
|
-
const
|
|
1061
|
-
const textContent =
|
|
1248
|
+
const title = extractTitle2(html);
|
|
1249
|
+
const description = extractDescription(html);
|
|
1250
|
+
const textContent = extractTextFromHtml(html);
|
|
1062
1251
|
const pathname = basePath || "/";
|
|
1063
1252
|
pages.push({
|
|
1064
1253
|
pathname,
|
|
1065
|
-
title
|
|
1066
|
-
description
|
|
1254
|
+
title,
|
|
1255
|
+
description,
|
|
1067
1256
|
content: textContent
|
|
1068
1257
|
});
|
|
1069
1258
|
}
|