@stackql/docusaurus-plugin-aeo 0.4.0 → 0.4.2
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/CHANGELOG.md +33 -0
- package/README.md +11 -10
- package/package.json +16 -9
- package/src/index.js +7 -3
- package/src/theme/AskAiButton/brand-icons/ChatGpt.jsx +26 -0
- package/src/theme/AskAiButton/brand-icons/Claude.jsx +25 -0
- package/src/theme/AskAiButton/brand-icons/Perplexity.jsx +23 -0
- package/src/theme/AskAiButton/icons.js +18 -64
- package/src/theme/AskAiButton/index.jsx +3 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.2
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **(regression in 0.4.1)** `@lobehub/icons` pins `react: ^19` and pulls `@lobehub/ui` into the import graph via `IconCombine`, which uses React 19's `use()` hook. On React 18 consumers (such as stackql.io), v0.4.1 builds crashed with `Attempted import error: 'use' is not exported from 'react' (imported as 'use')`. Resolved by dropping `@lobehub/icons` entirely and shipping three hand-rolled inline SVG components instead.
|
|
8
|
+
|
|
9
|
+
### Removed
|
|
10
|
+
|
|
11
|
+
- **Gemini support.** `gemini.google.com/app?q=...` silently ignores the `q` parameter and opens an empty prompt box, so the "Ask Gemini" entry rendered a button that appeared to do nothing useful. There is no documented Gemini URL prefill API, and Google has not signaled one is coming. Default `askAi.providerOrder` is now `['claude', 'chatgpt', 'perplexity']`. **Breaking** for consumers with an explicit `askAi.providerOrder` containing `'gemini'`: the build will fail at plugin construction with an error that names this changelog. Remove `'gemini'` from your config.
|
|
12
|
+
- `@lobehub/icons` dependency.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Provider icons are now hand-rolled inline SVGs co-located with the plugin source (`src/theme/AskAiButton/brand-icons/`). Bundle cost across the three components: ~3KB. Claude and Perplexity paths come from [simple-icons](https://simpleicons.org) (CC0-1.0); the OpenAI mark is sourced from the @lobehub/icons project (MIT). Brand colors are hardcoded on each path so MUI's `ListItemIcon` cannot tint them.
|
|
17
|
+
- Default `askAi.promptTemplate` is now self-contained: `'Read {pageUrl}.md and help me understand it. Summarize the key points, then ask me one clarifying question to dig deeper.'` Previous default required the user to type a question after a trailing colon; the new default returns a useful response on its own. Consumers can still override via `askAi.promptTemplate`.
|
|
18
|
+
|
|
19
|
+
## 0.4.1
|
|
20
|
+
|
|
21
|
+
Cosmetic patch. No API, option-shape, behavior, or placement changes.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Provider icons swapped from [simple-icons](https://simpleicons.org) (monochrome) to [@lobehub/icons](https://github.com/lobehub/lobe-icons) (colored brand variants). Resolves the ChatGPT-fallback-glyph issue from v0.3.0-v0.4.0: Claude, Perplexity, and Gemini now render in their brand colors via lobehub's `.Color` variants, and ChatGPT renders the OpenAI mark tinted with ChatGPT green (lobehub does not ship a `.Color` variant for OpenAI as of 5.10.0, so the monochrome mark is tinted inline).
|
|
26
|
+
- `ListItemIcon` now uses `sx={{ minWidth: 32, color: 'inherit' }}` so MUI's default tint does not override the brand colors.
|
|
27
|
+
|
|
28
|
+
### Removed
|
|
29
|
+
|
|
30
|
+
- `simple-icons` dependency.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- `@lobehub/icons` (`^5.10.0`, MIT) as a runtime dependency.
|
|
35
|
+
|
|
3
36
|
## 0.4.0
|
|
4
37
|
|
|
5
38
|
Visual refresh of the Ask AI button (feature 3) to match the look-and-feel of MUI-based dropdown components used elsewhere on consumer sites. No changes to features 1, 2, or 4.
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ module.exports = {
|
|
|
35
35
|
{
|
|
36
36
|
companions: { format: 'raw' },
|
|
37
37
|
llmsTxt: { header: 'StackQL is a SQL interface to cloud and SaaS APIs.' },
|
|
38
|
-
askAi: { providerOrder: ['claude', 'perplexity', 'chatgpt'
|
|
38
|
+
askAi: { providerOrder: ['claude', 'perplexity', 'chatgpt'] },
|
|
39
39
|
verbose: true,
|
|
40
40
|
},
|
|
41
41
|
],
|
|
@@ -184,27 +184,28 @@ Providers and URL patterns:
|
|
|
184
184
|
| Claude | `https://claude.ai/new?q={prompt}` |
|
|
185
185
|
| ChatGPT | `https://chatgpt.com/?q={prompt}` |
|
|
186
186
|
| Perplexity | `https://www.perplexity.ai/search?q={prompt}` |
|
|
187
|
-
| Gemini | `https://gemini.google.com/app?q={prompt}` |
|
|
188
187
|
|
|
189
188
|
Default prompt:
|
|
190
189
|
|
|
191
190
|
```text
|
|
192
|
-
Read https://your-site.example/path/to/page.md and help me
|
|
191
|
+
Read https://your-site.example/path/to/page.md and help me understand it. Summarize the key points, then ask me one clarifying question to dig deeper.
|
|
193
192
|
```
|
|
194
193
|
|
|
195
|
-
The
|
|
194
|
+
The default is self-contained - submitting it as-is yields a useful summary plus a follow-up question. The prompt is prefilled in each provider's input box, so users can still edit or replace it before sending.
|
|
196
195
|
|
|
197
|
-
Provider icons are
|
|
196
|
+
Provider icons are hand-rolled inline SVGs in each provider's brand color (Claude `#D97757`, ChatGPT `#000000`, Perplexity `#21808D`). The Claude and Perplexity SVG paths come from [simple-icons](https://simpleicons.org) (CC0-1.0); the OpenAI mark is sourced from the @lobehub/icons project. Bundle cost is ~3KB across the three components combined.
|
|
198
197
|
|
|
199
|
-
**
|
|
198
|
+
> **Gemini was previously supported but was removed in 0.4.2** because `gemini.google.com` silently ignores URL-encoded prompts, leaving users on an empty prompt box. There is no documented Gemini URL prefill API and Google has not indicated one is coming.
|
|
199
|
+
|
|
200
|
+
**Trademark note.** Brand logos are trademarks of their respective owners; their inclusion in this plugin does not imply endorsement. Consumers using the Ask AI button in commercial contexts should review each provider's brand-usage policy.
|
|
200
201
|
|
|
201
202
|
Options:
|
|
202
203
|
|
|
203
204
|
| Option | Default | Description |
|
|
204
205
|
| --- | --- | --- |
|
|
205
206
|
| `askAi.enabled` | `true` | When `false`, the theme components are not registered. |
|
|
206
|
-
| `askAi.providerOrder` | `['claude', 'chatgpt', 'perplexity'
|
|
207
|
-
| `askAi.promptTemplate` | `'Read {pageUrl}.md and help me
|
|
207
|
+
| `askAi.providerOrder` | `['claude', 'chatgpt', 'perplexity']` | Order of items in the dropdown. Drop entries to hide them. Valid values: `'claude'`, `'chatgpt'`, `'perplexity'`. |
|
|
208
|
+
| `askAi.promptTemplate` | `'Read {pageUrl}.md and help me understand it. Summarize the key points, then ask me one clarifying question to dig deeper.'` | Prompt sent to each provider. `{pageUrl}` is the page's canonical URL (no trailing slash). If feature 1 is disabled, the consumer should remove the `.md` from the template. |
|
|
208
209
|
| `askAi.placement` | `'breadcrumb-row'` | `'breadcrumb-row'` puts the button at the top of every doc/blog page (docs breadcrumb row, or above the blog title). `'none'` does not register any theme components - swizzle the button into your preferred location manually. |
|
|
209
210
|
|
|
210
211
|
The button is built from [MUI](https://mui.com) primitives - outlined `Button` with a `KeyboardArrowDownIcon` caret as the trigger, and a `Menu` of `MenuItem` rows for the providers. Theming reads `--ifm-color-primary` and `--ifm-font-family-base` via MUI's `sx` prop, so dark/light mode work automatically. The MUI `Menu` handles click-outside-to-close and Esc-to-close natively.
|
|
@@ -366,8 +367,8 @@ The `sitemapExclude` helper, by contrast, does work with globs because `@docusau
|
|
|
366
367
|
// Feature 3
|
|
367
368
|
askAi: {
|
|
368
369
|
enabled: true,
|
|
369
|
-
providerOrder: ['claude', 'chatgpt', 'perplexity'
|
|
370
|
-
promptTemplate: 'Read {pageUrl}.md and help me
|
|
370
|
+
providerOrder: ['claude', 'chatgpt', 'perplexity'],
|
|
371
|
+
promptTemplate: 'Read {pageUrl}.md and help me understand it. Summarize the key points, then ask me one clarifying question to dig deeper.',
|
|
371
372
|
placement: 'breadcrumb-row', // 'breadcrumb-row' | 'none'
|
|
372
373
|
},
|
|
373
374
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackql/docusaurus-plugin-aeo",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "AEO (Answer Engine Optimization) helpers for Docusaurus: .md companion files, llms.txt / llms-full.txt, an Ask AI dropdown, and /ai/* route conventions.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -21,22 +21,29 @@
|
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"@docusaurus/core": "^3.0.0",
|
|
24
|
-
"@mui/material": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
25
|
-
"@mui/icons-material": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
26
24
|
"@emotion/react": "^11.0.0",
|
|
27
25
|
"@emotion/styled": "^11.0.0",
|
|
26
|
+
"@mui/icons-material": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
27
|
+
"@mui/material": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
28
28
|
"react": "^18.0.0 || ^19.0.0",
|
|
29
29
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependenciesMeta": {
|
|
32
|
-
"@mui/material": {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"@
|
|
32
|
+
"@mui/material": {
|
|
33
|
+
"optional": false
|
|
34
|
+
},
|
|
35
|
+
"@mui/icons-material": {
|
|
36
|
+
"optional": false
|
|
37
|
+
},
|
|
38
|
+
"@emotion/react": {
|
|
39
|
+
"optional": false
|
|
40
|
+
},
|
|
41
|
+
"@emotion/styled": {
|
|
42
|
+
"optional": false
|
|
43
|
+
}
|
|
36
44
|
},
|
|
37
45
|
"dependencies": {
|
|
38
|
-
"gray-matter": "^4.0.3"
|
|
39
|
-
"simple-icons": "^16.22.0"
|
|
46
|
+
"gray-matter": "^4.0.3"
|
|
40
47
|
},
|
|
41
48
|
"overrides": {
|
|
42
49
|
"serialize-javascript": "^7.0.5",
|
package/src/index.js
CHANGED
|
@@ -12,10 +12,10 @@ const DEFAULT_LLMS_EXCLUDE = [
|
|
|
12
12
|
'/blog/authors/**',
|
|
13
13
|
];
|
|
14
14
|
|
|
15
|
-
const DEFAULT_PROVIDER_ORDER = ['claude', 'chatgpt', 'perplexity'
|
|
15
|
+
const DEFAULT_PROVIDER_ORDER = ['claude', 'chatgpt', 'perplexity'];
|
|
16
16
|
const VALID_PROVIDERS = new Set(DEFAULT_PROVIDER_ORDER);
|
|
17
17
|
const DEFAULT_PROMPT_TEMPLATE =
|
|
18
|
-
'Read {pageUrl}.md and help me
|
|
18
|
+
'Read {pageUrl}.md and help me understand it. Summarize the key points, then ask me one clarifying question to dig deeper.';
|
|
19
19
|
|
|
20
20
|
function normalizeOptions(raw) {
|
|
21
21
|
const opts = raw || {};
|
|
@@ -117,8 +117,12 @@ function validateOptions(opts) {
|
|
|
117
117
|
} else {
|
|
118
118
|
for (const p of opts.askAi.providerOrder) {
|
|
119
119
|
if (!VALID_PROVIDERS.has(p)) {
|
|
120
|
+
const hint =
|
|
121
|
+
p === 'gemini'
|
|
122
|
+
? '. Gemini was removed in 0.4.2 because gemini.google.com does not accept URL-encoded prompts'
|
|
123
|
+
: '';
|
|
120
124
|
errs.push(
|
|
121
|
-
`askAi.providerOrder contains unknown provider "${p}". Valid: ${[...VALID_PROVIDERS].join(', ')}`,
|
|
125
|
+
`askAi.providerOrder contains unknown provider "${p}"${hint}. Valid providers: ${[...VALID_PROVIDERS].join(', ')}`,
|
|
122
126
|
);
|
|
123
127
|
}
|
|
124
128
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// OpenAI / ChatGPT petaled mark. SVG path lifted verbatim from
|
|
2
|
+
// @lobehub/icons (MIT) before the React 19 hard-pin made the
|
|
3
|
+
// runtime install impossible on React 18 hosts. Brand color #000000
|
|
4
|
+
// is hardcoded to match OpenAI's brand guidelines (the black
|
|
5
|
+
// monochrome mark is the canonical one).
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
|
|
9
|
+
const PATH =
|
|
10
|
+
'M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z';
|
|
11
|
+
|
|
12
|
+
export default function ChatGptIcon({ size = 18 }) {
|
|
13
|
+
return (
|
|
14
|
+
<svg
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
width={size}
|
|
17
|
+
height={size}
|
|
18
|
+
viewBox="0 0 24 24"
|
|
19
|
+
role="img"
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
style={{ flex: 'none', lineHeight: 1 }}
|
|
22
|
+
>
|
|
23
|
+
<path d={PATH} fill="#000000" />
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Claude wordmark / petal. SVG path lifted verbatim from simple-icons
|
|
2
|
+
// (CC0-1.0) so the mark is faithful to the brand kit. Brand color
|
|
3
|
+
// #D97757 is hardcoded; ListItemIcon's `color: 'inherit'` keeps MUI
|
|
4
|
+
// from tinting it.
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
const PATH =
|
|
9
|
+
'm4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z';
|
|
10
|
+
|
|
11
|
+
export default function ClaudeIcon({ size = 18 }) {
|
|
12
|
+
return (
|
|
13
|
+
<svg
|
|
14
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
15
|
+
width={size}
|
|
16
|
+
height={size}
|
|
17
|
+
viewBox="0 0 24 24"
|
|
18
|
+
role="img"
|
|
19
|
+
aria-hidden="true"
|
|
20
|
+
style={{ flex: 'none', lineHeight: 1 }}
|
|
21
|
+
>
|
|
22
|
+
<path d={PATH} fill="#D97757" />
|
|
23
|
+
</svg>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Perplexity wordmark. SVG path lifted verbatim from simple-icons
|
|
2
|
+
// (CC0-1.0). Brand color #21808D is hardcoded.
|
|
3
|
+
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
const PATH =
|
|
7
|
+
'M22.3977 7.0896h-2.3106V.0676l-7.5094 6.3542V.1577h-1.1554v6.1966L4.4904 0v7.0896H1.6023v10.3976h2.8882V24l6.932-6.3591v6.2005h1.1554v-6.0469l6.9318 6.1807v-6.4879h2.8882V7.0896zm-3.4657-4.531v4.531h-5.355l5.355-4.531zm-13.2862.0676 4.8691 4.4634H5.6458V2.6262zM2.7576 16.332V8.245h7.8476l-6.1149 6.1147v1.9723H2.7576zm2.8882 5.0404v-3.8852h.0001v-2.6488l5.7763-5.7764v7.0111l-5.7764 5.2993zm12.7086.0248-5.7766-5.1509V9.0618l5.7766 5.7766v6.5588zm2.8882-5.0652h-1.733v-1.9723L13.3948 8.245h7.8478v8.087z';
|
|
8
|
+
|
|
9
|
+
export default function PerplexityIcon({ size = 18 }) {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
+
width={size}
|
|
14
|
+
height={size}
|
|
15
|
+
viewBox="0 0 24 24"
|
|
16
|
+
role="img"
|
|
17
|
+
aria-hidden="true"
|
|
18
|
+
style={{ flex: 'none', lineHeight: 1 }}
|
|
19
|
+
>
|
|
20
|
+
<path d={PATH} fill="#21808D" />
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -1,72 +1,26 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Provider brand icons. Hand-rolled inline SVGs lifted from
|
|
2
|
+
// publicly-available marks (simple-icons paths under CC0-1.0 for
|
|
3
|
+
// Claude and Perplexity; the @lobehub/icons OpenAI Mono path for
|
|
4
|
+
// ChatGPT). Brand color is hardcoded on each path so MUI's
|
|
5
|
+
// ListItemIcon color override doesn't tint them.
|
|
2
6
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
7
|
+
// We hand-roll rather than depend on @lobehub/icons because lobehub
|
|
8
|
+
// pinned react@^19 from 5.x onward, breaking React 18 consumers.
|
|
9
|
+
// simple-icons works on any Node + React but no longer ships an
|
|
10
|
+
// OpenAI mark following a 2024 trademark request, so a unified
|
|
11
|
+
// "single library" path is no longer available - hand-rolled is the
|
|
12
|
+
// only zero-conflict option.
|
|
8
13
|
//
|
|
9
|
-
//
|
|
10
|
-
// so the menu CSS can size them via font-size or width/height and tint
|
|
11
|
-
// them via the surrounding text color. ESM `import` is used so webpack
|
|
12
|
-
// can tree-shake unused simple-icons exports out of the bundle.
|
|
14
|
+
// Bundle cost: ~3KB across the three SVG components combined.
|
|
13
15
|
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
function svg(children) {
|
|
18
|
-
return React.createElement(
|
|
19
|
-
'svg',
|
|
20
|
-
{
|
|
21
|
-
xmlns: 'http://www.w3.org/2000/svg',
|
|
22
|
-
width: '1em',
|
|
23
|
-
height: '1em',
|
|
24
|
-
viewBox: '0 0 24 24',
|
|
25
|
-
fill: 'currentColor',
|
|
26
|
-
role: 'img',
|
|
27
|
-
'aria-hidden': 'true',
|
|
28
|
-
},
|
|
29
|
-
children,
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function fromSimpleIcons(si) {
|
|
34
|
-
if (!si || typeof si.path !== 'string') {
|
|
35
|
-
return GenericAiIcon;
|
|
36
|
-
}
|
|
37
|
-
return function BrandIcon() {
|
|
38
|
-
return svg(React.createElement('path', { d: si.path }));
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Neutral chat-bubble glyph - used when a brand icon isn't available
|
|
43
|
-
// upstream. Not a brand mark, no trademark concerns.
|
|
44
|
-
function GenericAiIcon() {
|
|
45
|
-
return svg(
|
|
46
|
-
React.createElement('path', {
|
|
47
|
-
d: 'M4 4h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-8l-5 4v-4H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2Zm3 6h2v2H7v-2Zm4 0h2v2h-2v-2Zm4 0h2v2h-2v-2Z',
|
|
48
|
-
}),
|
|
49
|
-
);
|
|
50
|
-
}
|
|
16
|
+
import Claude from './brand-icons/Claude.jsx';
|
|
17
|
+
import ChatGpt from './brand-icons/ChatGpt.jsx';
|
|
18
|
+
import Perplexity from './brand-icons/Perplexity.jsx';
|
|
51
19
|
|
|
52
20
|
const icons = {
|
|
53
|
-
claude:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// at the wordmark.
|
|
57
|
-
chatgpt: GenericAiIcon,
|
|
58
|
-
perplexity: fromSimpleIcons(siPerplexity),
|
|
59
|
-
gemini: fromSimpleIcons(siGooglegemini),
|
|
21
|
+
claude: Claude,
|
|
22
|
+
chatgpt: ChatGpt,
|
|
23
|
+
perplexity: Perplexity,
|
|
60
24
|
};
|
|
61
25
|
|
|
62
|
-
if (typeof console !== 'undefined') {
|
|
63
|
-
for (const [name, icon] of Object.entries(icons)) {
|
|
64
|
-
if (icon === GenericAiIcon && name !== 'chatgpt') {
|
|
65
|
-
console.warn(
|
|
66
|
-
`[plugin-aeo] AskAiButton: brand icon for "${name}" missing from simple-icons; using generic AI glyph`,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
26
|
export default icons;
|
|
@@ -15,18 +15,16 @@ const PROVIDER_LABELS = {
|
|
|
15
15
|
claude: 'Ask Claude',
|
|
16
16
|
chatgpt: 'Ask ChatGPT',
|
|
17
17
|
perplexity: 'Ask Perplexity',
|
|
18
|
-
gemini: 'Ask Gemini',
|
|
19
18
|
};
|
|
20
19
|
|
|
21
20
|
const PROVIDER_URLS = {
|
|
22
21
|
claude: 'https://claude.ai/new?q=',
|
|
23
22
|
chatgpt: 'https://chatgpt.com/?q=',
|
|
24
23
|
perplexity: 'https://www.perplexity.ai/search?q=',
|
|
25
|
-
gemini: 'https://gemini.google.com/app?q=',
|
|
26
24
|
};
|
|
27
25
|
|
|
28
26
|
const DEFAULT_PROMPT_TEMPLATE =
|
|
29
|
-
'Read {pageUrl}.md and help me
|
|
27
|
+
'Read {pageUrl}.md and help me understand it. Summarize the key points, then ask me one clarifying question to dig deeper.';
|
|
30
28
|
|
|
31
29
|
export default function AskAiButton() {
|
|
32
30
|
const { siteConfig } = useDocusaurusContext();
|
|
@@ -48,7 +46,7 @@ export default function AskAiButton() {
|
|
|
48
46
|
const order =
|
|
49
47
|
Array.isArray(cfg.providerOrder) && cfg.providerOrder.length > 0
|
|
50
48
|
? cfg.providerOrder
|
|
51
|
-
: ['claude', 'chatgpt', 'perplexity'
|
|
49
|
+
: ['claude', 'chatgpt', 'perplexity'];
|
|
52
50
|
|
|
53
51
|
const handleOpen = (e) => setAnchorEl(e.currentTarget);
|
|
54
52
|
const handleClose = () => setAnchorEl(null);
|
|
@@ -105,7 +103,7 @@ export default function AskAiButton() {
|
|
|
105
103
|
rel="noopener noreferrer"
|
|
106
104
|
onClick={handleClose}
|
|
107
105
|
>
|
|
108
|
-
<ListItemIcon>
|
|
106
|
+
<ListItemIcon sx={{ minWidth: 32, color: 'inherit' }}>
|
|
109
107
|
<Icon />
|
|
110
108
|
</ListItemIcon>
|
|
111
109
|
<ListItemText
|