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/README.md
CHANGED
|
@@ -1,39 +1,22 @@
|
|
|
1
|
-
# aeo.js
|
|
2
|
-
|
|
3
|
-
Answer Engine Optimization for the modern web. Make your site discoverable by AI crawlers and LLMs.
|
|
4
|
-
|
|
5
1
|
<p align="center">
|
|
6
|
-
<
|
|
2
|
+
<h1 align="center">aeo.js</h1>
|
|
3
|
+
<p align="center">Answer Engine Optimization for the modern web.<br/>Make your site discoverable by ChatGPT, Claude, Perplexity, and every AI answer engine.</p>
|
|
7
4
|
</p>
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
aeo.js
|
|
14
|
-
|
|
15
|
-
## Features
|
|
16
|
-
|
|
17
|
-
- **`llms.txt` / `llms-full.txt`** -- LLM-readable summaries of your site
|
|
18
|
-
- **`robots.txt`** -- AI-crawler-aware robots directives
|
|
19
|
-
- **`sitemap.xml`** -- Standard sitemap generation
|
|
20
|
-
- **`docs.json`** -- Structured documentation manifest
|
|
21
|
-
- **`ai-index.json`** -- AI-optimized content index
|
|
22
|
-
- **Raw Markdown** -- Per-page `.md` files extracted from your HTML
|
|
23
|
-
- **Human/AI Widget** -- Drop-in toggle showing the AI-readable version of any page
|
|
24
|
-
- **CLI** -- `npx aeo.js generate` to run standalone
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://www.npmjs.com/package/aeo.js"><img src="https://img.shields.io/npm/v/aeo.js?style=flat&colorA=0d0d0d&colorB=1a1a1a" alt="npm version"></a>
|
|
8
|
+
<a href="https://www.npmjs.com/package/aeo.js"><img src="https://img.shields.io/npm/dm/aeo.js?style=flat&colorA=0d0d0d&colorB=1a1a1a" alt="npm downloads"></a>
|
|
9
|
+
<a href="https://github.com/multivmlabs/aeo.js"><img src="https://img.shields.io/github/stars/multivmlabs/aeo.js?style=flat&colorA=0d0d0d&colorB=1a1a1a" alt="GitHub stars"></a>
|
|
10
|
+
<a href="https://github.com/multivmlabs/aeo.js/blob/main/LICENSE"><img src="https://img.shields.io/github/license/multivmlabs/aeo.js?style=flat&colorA=0d0d0d&colorB=1a1a1a" alt="License"></a>
|
|
11
|
+
</p>
|
|
25
12
|
|
|
26
|
-
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://aeojs.org">Documentation</a> · <a href="https://check.aeojs.org">AEO Checker</a> · <a href="https://www.npmjs.com/package/aeo.js">npm</a>
|
|
15
|
+
</p>
|
|
27
16
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
| Next.js | Stable | `aeo.js/next` |
|
|
32
|
-
| Vite / React | Stable | `aeo.js/vite` |
|
|
33
|
-
| Nuxt | Stable | `aeo.js/nuxt` |
|
|
34
|
-
| Angular | Stable | `aeo.js/angular` |
|
|
35
|
-
| Webpack | Stable | `aeo.js/webpack` |
|
|
36
|
-
| Any (CLI) | Stable | `npx aeo.js generate` |
|
|
17
|
+
<p align="center">
|
|
18
|
+
<img src="example.gif" alt="aeo.js in action" width="700">
|
|
19
|
+
</p>
|
|
37
20
|
|
|
38
21
|
## Install
|
|
39
22
|
|
|
@@ -62,12 +45,8 @@ export default defineConfig({
|
|
|
62
45
|
});
|
|
63
46
|
```
|
|
64
47
|
|
|
65
|
-
The widget is automatically injected and persists across View Transitions.
|
|
66
|
-
|
|
67
48
|
### Next.js
|
|
68
49
|
|
|
69
|
-
Wrap your Next.js config with `withAeo`:
|
|
70
|
-
|
|
71
50
|
```js
|
|
72
51
|
// next.config.mjs
|
|
73
52
|
import { withAeo } from 'aeo.js/next';
|
|
@@ -81,7 +60,7 @@ export default withAeo({
|
|
|
81
60
|
});
|
|
82
61
|
```
|
|
83
62
|
|
|
84
|
-
|
|
63
|
+
Add the post-build step to `package.json`:
|
|
85
64
|
|
|
86
65
|
```json
|
|
87
66
|
{
|
|
@@ -91,7 +70,7 @@ After building, run the post-build step to extract content from pre-rendered pag
|
|
|
91
70
|
}
|
|
92
71
|
```
|
|
93
72
|
|
|
94
|
-
### Vite
|
|
73
|
+
### Vite
|
|
95
74
|
|
|
96
75
|
```js
|
|
97
76
|
// vite.config.ts
|
|
@@ -109,16 +88,8 @@ export default defineConfig({
|
|
|
109
88
|
});
|
|
110
89
|
```
|
|
111
90
|
|
|
112
|
-
The Vite plugin:
|
|
113
|
-
- Generates AEO files on `vite dev` and `vite build`
|
|
114
|
-
- Injects the widget automatically
|
|
115
|
-
- Serves dynamic `.md` files in dev (extracts content from your running app)
|
|
116
|
-
- Detects SPA shells and falls back to client-side DOM extraction
|
|
117
|
-
|
|
118
91
|
### Nuxt
|
|
119
92
|
|
|
120
|
-
Add the module to your Nuxt config:
|
|
121
|
-
|
|
122
93
|
```ts
|
|
123
94
|
// nuxt.config.ts
|
|
124
95
|
export default defineNuxtConfig({
|
|
@@ -131,17 +102,8 @@ export default defineNuxtConfig({
|
|
|
131
102
|
});
|
|
132
103
|
```
|
|
133
104
|
|
|
134
|
-
The Nuxt module:
|
|
135
|
-
- Scans your `pages/` directory for routes
|
|
136
|
-
- Generates AEO files during dev and production builds
|
|
137
|
-
- Scans pre-rendered HTML from `.output/public/` for full page content
|
|
138
|
-
- Injects the widget as a client-side Nuxt plugin
|
|
139
|
-
- Adds `<link>` and `<meta>` tags for AEO discoverability
|
|
140
|
-
|
|
141
105
|
### Angular
|
|
142
106
|
|
|
143
|
-
Add a post-build step to your `package.json`:
|
|
144
|
-
|
|
145
107
|
```json
|
|
146
108
|
{
|
|
147
109
|
"scripts": {
|
|
@@ -150,20 +112,6 @@ Add a post-build step to your `package.json`:
|
|
|
150
112
|
}
|
|
151
113
|
```
|
|
152
114
|
|
|
153
|
-
The Angular plugin:
|
|
154
|
-
- Reads `angular.json` to auto-detect the output directory (`dist/<project>/browser/`)
|
|
155
|
-
- Scans route config files (`*.routes.ts`) and component directories for routes
|
|
156
|
-
- Scans pre-rendered HTML from the build output for full page content
|
|
157
|
-
- Injects the widget into `index.html` automatically
|
|
158
|
-
|
|
159
|
-
You can also generate AEO files from source routes without building:
|
|
160
|
-
|
|
161
|
-
```ts
|
|
162
|
-
import { generate } from 'aeo.js/angular';
|
|
163
|
-
|
|
164
|
-
await generate({ title: 'My App', url: 'https://myapp.com' });
|
|
165
|
-
```
|
|
166
|
-
|
|
167
115
|
### Webpack
|
|
168
116
|
|
|
169
117
|
```js
|
|
@@ -181,101 +129,39 @@ module.exports = {
|
|
|
181
129
|
};
|
|
182
130
|
```
|
|
183
131
|
|
|
184
|
-
|
|
132
|
+
### CLI
|
|
185
133
|
|
|
186
|
-
|
|
134
|
+
No framework needed — run standalone:
|
|
187
135
|
|
|
188
136
|
```bash
|
|
189
|
-
|
|
190
|
-
npx aeo.js generate
|
|
191
|
-
|
|
192
|
-
# Generate with options
|
|
193
|
-
npx aeo.js generate --url https://mysite.com --title "My Site" --out public
|
|
194
|
-
|
|
195
|
-
# Create a config file
|
|
137
|
+
npx aeo.js generate --url https://mysite.com --title "My Site"
|
|
196
138
|
npx aeo.js init
|
|
197
|
-
|
|
198
|
-
# Check your setup
|
|
199
139
|
npx aeo.js check
|
|
200
140
|
```
|
|
201
141
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
| Command | Description |
|
|
205
|
-
|---------|-------------|
|
|
206
|
-
| `generate` | Generate all AEO files (robots.txt, llms.txt, sitemap.xml, etc.) |
|
|
207
|
-
| `init` | Create an `aeo.config.ts` configuration file |
|
|
208
|
-
| `check` | Validate your AEO setup and show what would be generated |
|
|
209
|
-
|
|
210
|
-
### Options
|
|
211
|
-
|
|
212
|
-
| Flag | Description |
|
|
213
|
-
|------|-------------|
|
|
214
|
-
| `--out <dir>` | Output directory (default: auto-detected) |
|
|
215
|
-
| `--url <url>` | Site URL |
|
|
216
|
-
| `--title <title>` | Site title |
|
|
217
|
-
| `--no-widget` | Disable widget generation |
|
|
218
|
-
| `--help`, `-h` | Show help |
|
|
219
|
-
| `--version`, `-v` | Show version |
|
|
220
|
-
|
|
221
|
-
## Configuration
|
|
222
|
-
|
|
223
|
-
All framework plugins accept the same config object. You can also use `defineConfig` for standalone configs:
|
|
224
|
-
|
|
225
|
-
```js
|
|
226
|
-
import { defineConfig } from 'aeo.js';
|
|
227
|
-
|
|
228
|
-
export default defineConfig({
|
|
229
|
-
// Required
|
|
230
|
-
title: 'My Site',
|
|
231
|
-
url: 'https://mysite.com',
|
|
232
|
-
|
|
233
|
-
// Optional
|
|
234
|
-
description: 'A description of your site',
|
|
235
|
-
contentDir: 'docs', // Directory with handwritten .md files
|
|
236
|
-
outDir: 'public', // Output directory for generated files
|
|
142
|
+
## Supported Frameworks
|
|
237
143
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
},
|
|
144
|
+
| Framework | Import |
|
|
145
|
+
|-----------|--------|
|
|
146
|
+
| Astro | `aeo.js/astro` |
|
|
147
|
+
| Next.js | `aeo.js/next` |
|
|
148
|
+
| Vite | `aeo.js/vite` |
|
|
149
|
+
| Nuxt | `aeo.js/nuxt` |
|
|
150
|
+
| Angular | `aeo.js/angular` |
|
|
151
|
+
| Webpack | `aeo.js/webpack` |
|
|
152
|
+
| CLI | `npx aeo.js generate` |
|
|
248
153
|
|
|
249
|
-
|
|
250
|
-
robots: {
|
|
251
|
-
allow: ['/'],
|
|
252
|
-
disallow: ['/admin'],
|
|
253
|
-
crawlDelay: 0,
|
|
254
|
-
},
|
|
154
|
+
## Widget
|
|
255
155
|
|
|
256
|
-
|
|
257
|
-
widget: {
|
|
258
|
-
enabled: true,
|
|
259
|
-
position: 'bottom-right', // 'bottom-left' | 'top-right' | 'top-left'
|
|
260
|
-
humanLabel: 'Human',
|
|
261
|
-
aiLabel: 'AI',
|
|
262
|
-
showBadge: true,
|
|
263
|
-
theme: {
|
|
264
|
-
background: 'rgba(18, 18, 24, 0.9)',
|
|
265
|
-
text: '#C0C0C5',
|
|
266
|
-
accent: '#E8E8EA',
|
|
267
|
-
badge: '#4ADE80',
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
```
|
|
156
|
+
The Human/AI widget lets visitors toggle between the normal page and its AI-readable markdown version.
|
|
272
157
|
|
|
273
|
-
|
|
158
|
+
| Default | Small | Icon |
|
|
159
|
+
|---------|-------|------|
|
|
160
|
+
| <img src="widget-default.gif" alt="Default widget" width="220"> | <img src="widget-small.gif" alt="Small widget" width="220"> | <img src="widget-icon.gif" alt="Icon widget" width="220"> |
|
|
274
161
|
|
|
275
|
-
|
|
162
|
+
Framework plugins inject it automatically. For Next.js or manual setups:
|
|
276
163
|
|
|
277
164
|
```tsx
|
|
278
|
-
// app/layout.tsx (or any client component)
|
|
279
165
|
'use client';
|
|
280
166
|
import { useEffect } from 'react';
|
|
281
167
|
|
|
@@ -295,29 +181,98 @@ export function AeoWidgetLoader() {
|
|
|
295
181
|
}
|
|
296
182
|
```
|
|
297
183
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
184
|
+
React and Vue wrapper components are also available:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
import { AeoReactWidget } from 'aeo.js/react';
|
|
188
|
+
|
|
189
|
+
<AeoReactWidget config={{ title: 'My Site', url: 'https://mysite.com' }} />
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```vue
|
|
193
|
+
<script setup>
|
|
194
|
+
import { AeoVueWidget } from 'aeo.js/vue';
|
|
195
|
+
</script>
|
|
196
|
+
|
|
197
|
+
<template>
|
|
198
|
+
<AeoVueWidget :config="{ title: 'My Site', url: 'https://mysite.com' }" />
|
|
199
|
+
</template>
|
|
200
|
+
```
|
|
303
201
|
|
|
304
202
|
## Generated Files
|
|
305
203
|
|
|
306
|
-
After building, your output directory
|
|
204
|
+
After building, your output directory contains:
|
|
307
205
|
|
|
308
206
|
```
|
|
309
207
|
public/
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
208
|
+
├── robots.txt # AI-crawler directives
|
|
209
|
+
├── llms.txt # Short LLM-readable summary
|
|
210
|
+
├── llms-full.txt # Full content for LLMs
|
|
211
|
+
├── sitemap.xml # Standard sitemap
|
|
212
|
+
├── docs.json # Documentation manifest
|
|
213
|
+
├── ai-index.json # AI content index
|
|
214
|
+
├── index.md # Markdown for /
|
|
215
|
+
└── about.md # Markdown for /about
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Configuration
|
|
219
|
+
|
|
220
|
+
```js
|
|
221
|
+
import { defineConfig } from 'aeo.js';
|
|
222
|
+
|
|
223
|
+
export default defineConfig({
|
|
224
|
+
title: 'My Site',
|
|
225
|
+
url: 'https://mysite.com',
|
|
226
|
+
description: 'A description of your site',
|
|
227
|
+
|
|
228
|
+
generators: {
|
|
229
|
+
robotsTxt: true,
|
|
230
|
+
llmsTxt: true,
|
|
231
|
+
llmsFullTxt: true,
|
|
232
|
+
rawMarkdown: true,
|
|
233
|
+
sitemap: true,
|
|
234
|
+
aiIndex: true,
|
|
235
|
+
schema: true,
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
schema: {
|
|
239
|
+
enabled: true,
|
|
240
|
+
organization: { name: 'My Company', url: 'https://mysite.com' },
|
|
241
|
+
defaultType: 'WebPage',
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
og: {
|
|
245
|
+
enabled: true,
|
|
246
|
+
image: 'https://mysite.com/og.png',
|
|
247
|
+
twitterHandle: '@mycompany',
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
widget: {
|
|
251
|
+
enabled: true,
|
|
252
|
+
position: 'bottom-right',
|
|
253
|
+
theme: { accent: '#4ADE80', badge: '#4ADE80' },
|
|
254
|
+
},
|
|
255
|
+
});
|
|
319
256
|
```
|
|
320
257
|
|
|
258
|
+
Full configuration reference → [aeojs.org/reference/configuration](https://aeojs.org/reference/configuration/)
|
|
259
|
+
|
|
260
|
+
## Why AEO?
|
|
261
|
+
|
|
262
|
+
- **58% of searches** end without a click — AI gives the answer directly
|
|
263
|
+
- **40% of Gen Z** prefer AI assistants over traditional search engines
|
|
264
|
+
- **97% of sites** have no `llms.txt` or structured data for AI crawlers
|
|
265
|
+
- **1 minute** to set up with aeo.js
|
|
266
|
+
|
|
267
|
+
If your site isn't optimized for AI engines, you're invisible to a growing share of users who never open a search results page.
|
|
268
|
+
|
|
269
|
+
## Links
|
|
270
|
+
|
|
271
|
+
- [Documentation](https://aeojs.org)
|
|
272
|
+
- [AEO Checker](https://check.aeojs.org)
|
|
273
|
+
- [npm](https://www.npmjs.com/package/aeo.js)
|
|
274
|
+
- [GitHub](https://github.com/multivmlabs/aeo.js)
|
|
275
|
+
|
|
321
276
|
## License
|
|
322
277
|
|
|
323
278
|
MIT
|
package/dist/angular.d.mts
CHANGED
package/dist/angular.d.ts
CHANGED
package/dist/angular.js
CHANGED
|
@@ -79,10 +79,19 @@ function generateRobotsTxt(config) {
|
|
|
79
79
|
}
|
|
80
80
|
lines.push("# Default for all other bots");
|
|
81
81
|
lines.push("User-agent: *");
|
|
82
|
-
|
|
82
|
+
for (const path of config.robots.allow.length > 0 ? config.robots.allow : ["/"]) {
|
|
83
|
+
lines.push(`Allow: ${path}`);
|
|
84
|
+
}
|
|
85
|
+
for (const path of config.robots.disallow) {
|
|
86
|
+
lines.push(`Disallow: ${path}`);
|
|
87
|
+
}
|
|
88
|
+
if (config.robots.crawlDelay > 0) {
|
|
89
|
+
lines.push(`Crawl-delay: ${config.robots.crawlDelay}`);
|
|
90
|
+
}
|
|
83
91
|
lines.push("");
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
const sitemapUrl = config.robots.sitemap || (config.url ? `${config.url}/sitemap.xml` : "");
|
|
93
|
+
if (sitemapUrl) {
|
|
94
|
+
lines.push(`Sitemap: ${sitemapUrl}`);
|
|
86
95
|
}
|
|
87
96
|
lines.push("");
|
|
88
97
|
lines.push("# AEO (Answer Engine Optimization) files");
|
|
@@ -164,7 +173,7 @@ function detectFramework(projectRoot = process.cwd()) {
|
|
|
164
173
|
};
|
|
165
174
|
}
|
|
166
175
|
function resolveConfig(config = {}) {
|
|
167
|
-
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;
|
|
176
|
+
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;
|
|
168
177
|
const frameworkInfo = detectFramework();
|
|
169
178
|
return {
|
|
170
179
|
title: config.title || "My Site",
|
|
@@ -208,15 +217,16 @@ function resolveConfig(config = {}) {
|
|
|
208
217
|
widget: {
|
|
209
218
|
enabled: ((_A = config.widget) == null ? void 0 : _A.enabled) !== false,
|
|
210
219
|
position: ((_B = config.widget) == null ? void 0 : _B.position) || "bottom-right",
|
|
220
|
+
size: ((_C = config.widget) == null ? void 0 : _C.size) || "default",
|
|
211
221
|
theme: {
|
|
212
|
-
background: ((
|
|
213
|
-
text: ((
|
|
214
|
-
accent: ((
|
|
215
|
-
badge: ((
|
|
222
|
+
background: ((_E = (_D = config.widget) == null ? void 0 : _D.theme) == null ? void 0 : _E.background) || "rgba(18, 18, 24, 0.9)",
|
|
223
|
+
text: ((_G = (_F = config.widget) == null ? void 0 : _F.theme) == null ? void 0 : _G.text) || "#C0C0C5",
|
|
224
|
+
accent: ((_I = (_H = config.widget) == null ? void 0 : _H.theme) == null ? void 0 : _I.accent) || "#E8E8EA",
|
|
225
|
+
badge: ((_K = (_J = config.widget) == null ? void 0 : _J.theme) == null ? void 0 : _K.badge) || "#4ADE80"
|
|
216
226
|
},
|
|
217
|
-
humanLabel: ((
|
|
218
|
-
aiLabel: ((
|
|
219
|
-
showBadge: ((
|
|
227
|
+
humanLabel: ((_L = config.widget) == null ? void 0 : _L.humanLabel) || "Human",
|
|
228
|
+
aiLabel: ((_M = config.widget) == null ? void 0 : _M.aiLabel) || "AI",
|
|
229
|
+
showBadge: ((_N = config.widget) == null ? void 0 : _N.showBadge) !== false
|
|
220
230
|
}
|
|
221
231
|
};
|
|
222
232
|
}
|
|
@@ -273,7 +283,8 @@ function collectMarkdownFiles(dir, base = dir) {
|
|
|
273
283
|
for (const entry of entries) {
|
|
274
284
|
const fullPath = path.join(dir, entry);
|
|
275
285
|
const stat = fs.statSync(fullPath);
|
|
276
|
-
|
|
286
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
|
|
287
|
+
if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
|
|
277
288
|
files.push(...collectMarkdownFiles(fullPath, base));
|
|
278
289
|
} else if (stat.isFile() && (path.extname(entry) === ".md" || path.extname(entry) === ".mdx")) {
|
|
279
290
|
const content = fs.readFileSync(fullPath, "utf-8");
|
|
@@ -616,7 +627,8 @@ function collectUrls(dir, config, base = dir) {
|
|
|
616
627
|
for (const entry of entries) {
|
|
617
628
|
const fullPath = path.join(dir, entry);
|
|
618
629
|
const stat = fs.statSync(fullPath);
|
|
619
|
-
|
|
630
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "public", "dist", ".next", ".nuxt", ".output", ".open-next", "coverage", "__tests__", "__mocks__"]);
|
|
631
|
+
if (stat.isDirectory() && !entry.startsWith(".") && !SKIP_DIRS.has(entry)) {
|
|
620
632
|
urls.push(...collectUrls(fullPath, config, base));
|
|
621
633
|
} else if (stat.isFile() && (path.extname(entry) === ".md" || path.extname(entry) === ".mdx" || path.extname(entry) === ".html")) {
|
|
622
634
|
const relativePath = path.relative(base, fullPath);
|
|
@@ -844,6 +856,22 @@ function generatePageSchemas(page, config) {
|
|
|
844
856
|
}))
|
|
845
857
|
});
|
|
846
858
|
}
|
|
859
|
+
if (faqItems.length === 0) {
|
|
860
|
+
const howToSteps = detectHowToSteps(page.content || "");
|
|
861
|
+
if (howToSteps.length > 0) {
|
|
862
|
+
schemas.push({
|
|
863
|
+
"@context": "https://schema.org",
|
|
864
|
+
"@type": "HowTo",
|
|
865
|
+
name: page.title || config.title,
|
|
866
|
+
step: howToSteps.map((s, i) => ({
|
|
867
|
+
"@type": "HowToStep",
|
|
868
|
+
position: i + 1,
|
|
869
|
+
name: s.name,
|
|
870
|
+
text: s.text
|
|
871
|
+
}))
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
}
|
|
847
875
|
const pageType = config.schema.defaultType;
|
|
848
876
|
const pageSchema = {
|
|
849
877
|
"@context": "https://schema.org",
|
|
@@ -920,6 +948,34 @@ function detectFaqPatterns(content) {
|
|
|
920
948
|
}
|
|
921
949
|
return items;
|
|
922
950
|
}
|
|
951
|
+
function detectHowToSteps(content) {
|
|
952
|
+
const steps = [];
|
|
953
|
+
const lines = content.split("\n");
|
|
954
|
+
for (let i = 0; i < lines.length; i++) {
|
|
955
|
+
const line = lines[i].trim();
|
|
956
|
+
const stepMatch = line.match(/^#{1,6}\s+(?:Step\s+\d+[\s:.-]*|(\d+)[.)]\s*)(.+)$/i);
|
|
957
|
+
if (stepMatch) {
|
|
958
|
+
const name = (stepMatch[2] || stepMatch[1] || "").trim();
|
|
959
|
+
const bodyLines = [];
|
|
960
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
961
|
+
const nextLine = lines[j].trim();
|
|
962
|
+
if (!nextLine) {
|
|
963
|
+
if (bodyLines.length > 0) break;
|
|
964
|
+
continue;
|
|
965
|
+
}
|
|
966
|
+
if (/^#{1,6}\s/.test(nextLine)) break;
|
|
967
|
+
bodyLines.push(nextLine);
|
|
968
|
+
}
|
|
969
|
+
if (name) {
|
|
970
|
+
steps.push({
|
|
971
|
+
name,
|
|
972
|
+
text: bodyLines.join(" ").slice(0, 500)
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return steps.length >= 2 ? steps : [];
|
|
978
|
+
}
|
|
923
979
|
async function generateAEOFiles(configOrRoot, maybeConfig) {
|
|
924
980
|
var _a;
|
|
925
981
|
let config;
|