@stackql/docusaurus-plugin-aeo 0.4.1 → 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 CHANGED
@@ -1,5 +1,21 @@
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
+
3
19
  ## 0.4.1
4
20
 
5
21
  Cosmetic patch. No API, option-shape, behavior, or placement changes.
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', 'gemini'] },
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 with the following question about it:
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 trailing space is intentional - the cursor lands ready for the user to type.
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 real brand SVGs in each provider's brand color, sourced from [@lobehub/icons](https://github.com/lobehub/lobe-icons). Claude, Perplexity, and Gemini render via their `.Color` variants directly; OpenAI ships only a monochrome mark, so the ChatGPT row uses that mark tinted with the ChatGPT brand green so it visually pairs with the colored icons.
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
- **Trademark note.** Brand logos are trademarks of their respective owners; their inclusion via @lobehub/icons does not imply endorsement. Consumers using the Ask AI button in commercial contexts should review each provider's brand-usage policy.
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', 'gemini']` | Order of items in the dropdown. Drop entries to hide them. |
207
- | `askAi.promptTemplate` | `'Read {pageUrl}.md and help me with the following question about it: '` | 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. |
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', 'gemini'],
370
- promptTemplate: 'Read {pageUrl}.md and help me with the following question about it: ',
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.1",
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": {
@@ -43,7 +43,6 @@
43
43
  }
44
44
  },
45
45
  "dependencies": {
46
- "@lobehub/icons": "^5.10.0",
47
46
  "gray-matter": "^4.0.3"
48
47
  },
49
48
  "overrides": {
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', 'gemini'];
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 with the following question about it: ';
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,45 +1,26 @@
1
- // Brand icons for the four supported AI providers, sourced from
2
- // @lobehub/icons. Each provider's package exports a default Mono
3
- // component with .Color, .Text, .Combine, .Avatar attached as
4
- // properties. We prefer .Color (multi-color brand variant) when the
5
- // provider ships one; OpenAI does not, so we fall back to Mono and
6
- // tint it with the ChatGPT brand green via inline style.
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.
7
6
  //
8
- // Deep import paths (@lobehub/icons/es/<Provider>) are used because
9
- // the package does not declare a subpath exports map; the deep path
10
- // is stable across the 5.x line and tree-shakes cleanly because each
11
- // per-provider module's dependency footprint is just React.
12
-
13
- import React from 'react';
14
- import ClaudeIcons from '@lobehub/icons/es/Claude';
15
- import OpenAIIcons from '@lobehub/icons/es/OpenAI';
16
- import PerplexityIcons from '@lobehub/icons/es/Perplexity';
17
- import GeminiIcons from '@lobehub/icons/es/Gemini';
18
-
19
- const ICON_SIZE = 18;
20
-
21
- // OpenAI ships only the monochrome mark (Color variant absent from
22
- // @lobehub/icons as of 5.10.0). Use the known ChatGPT brand green so
23
- // the row visually matches the other three colored marks.
24
- const CHATGPT_GREEN = '#10A37F';
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.
13
+ //
14
+ // Bundle cost: ~3KB across the three SVG components combined.
25
15
 
26
- function makeColorIcon(IconNamespace, fallbackColor) {
27
- const Component = IconNamespace.Color || IconNamespace;
28
- const usingFallback = !IconNamespace.Color;
29
- return function Icon() {
30
- const props = { size: ICON_SIZE };
31
- if (usingFallback && fallbackColor) {
32
- props.style = { color: fallbackColor };
33
- }
34
- return React.createElement(Component, props);
35
- };
36
- }
16
+ import Claude from './brand-icons/Claude.jsx';
17
+ import ChatGpt from './brand-icons/ChatGpt.jsx';
18
+ import Perplexity from './brand-icons/Perplexity.jsx';
37
19
 
38
20
  const icons = {
39
- claude: makeColorIcon(ClaudeIcons),
40
- chatgpt: makeColorIcon(OpenAIIcons, CHATGPT_GREEN),
41
- perplexity: makeColorIcon(PerplexityIcons),
42
- gemini: makeColorIcon(GeminiIcons),
21
+ claude: Claude,
22
+ chatgpt: ChatGpt,
23
+ perplexity: Perplexity,
43
24
  };
44
25
 
45
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 with the following question about it: ';
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', 'gemini'];
49
+ : ['claude', 'chatgpt', 'perplexity'];
52
50
 
53
51
  const handleOpen = (e) => setAnchorEl(e.currentTarget);
54
52
  const handleClose = () => setAnchorEl(null);