@apify/docs-theme 1.0.212 → 1.0.214
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/package.json +3 -1
- package/src/theme/DocItemContent/index.js +13 -7
- package/src/theme/DocItemContent/styles.module.css +17 -0
- package/src/theme/LLMButtons/index.jsx +289 -9
- package/src/theme/LLMButtons/styles.module.css +92 -34
- package/src/theme/LLMButtons/CopyForLLM/index.jsx +0 -71
- package/src/theme/LLMButtons/ViewAsMarkdown/index.jsx +0 -37
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apify/docs-theme",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.214",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@apify/docs-search-modal": "^1.2.2",
|
|
23
|
+
"@apify/ui-library": "^1.97.2",
|
|
24
|
+
"@apify/ui-icons": "^1.19.0",
|
|
23
25
|
"@docusaurus/theme-common": "^3.7.0",
|
|
24
26
|
"@stackql/docusaurus-plugin-hubspot": "^1.1.0",
|
|
25
27
|
"algoliasearch": "^5.19.0",
|
|
@@ -7,6 +7,8 @@ import MDXContent from '@theme/MDXContent';
|
|
|
7
7
|
import clsx from 'clsx';
|
|
8
8
|
import React from 'react';
|
|
9
9
|
|
|
10
|
+
import styles from './styles.module.css';
|
|
11
|
+
|
|
10
12
|
function useSyntheticTitle() {
|
|
11
13
|
const { metadata, frontMatter, contentTitle } = useDoc();
|
|
12
14
|
const shouldRender = !frontMatter.hide_title && typeof contentTitle === 'undefined';
|
|
@@ -62,11 +64,15 @@ export default function DocItemContent({ children }) {
|
|
|
62
64
|
const shouldShowLLMButtons = allowedPaths.some((path) => location.pathname.startsWith(path))
|
|
63
65
|
&& !disallowedPaths.some((path) => location.pathname.includes(path));
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
return (
|
|
68
|
+
<div className={clsx(ThemeClassNames.docs.docMarkdown, 'markdown')}>
|
|
69
|
+
{(syntheticTitle || shouldShowLLMButtons) && (
|
|
70
|
+
<div className={styles.docItemContent}>
|
|
71
|
+
{syntheticTitle && <Heading as="h1">{syntheticTitle}</Heading>}
|
|
72
|
+
{shouldShowLLMButtons && <LLMButtons />}
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
<MDXContent>{children}</MDXContent>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
72
78
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.docItemContent {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
flex-wrap: wrap;
|
|
5
|
+
/* move the h1 margin to padding */
|
|
6
|
+
h1 {
|
|
7
|
+
margin-bottom: 0 !important;
|
|
8
|
+
}
|
|
9
|
+
padding-bottom: calc(
|
|
10
|
+
var(--ifm-h1-vertical-rhythm-bottom) * var(--ifm-leading)
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
@media (max-width: 767px) {
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
align-items: flex-start;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,15 +1,295 @@
|
|
|
1
|
-
import
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import React, { useCallback, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
AnthropicIcon,
|
|
6
|
+
ChatGptIcon,
|
|
7
|
+
CheckIcon,
|
|
8
|
+
ChevronDownIcon,
|
|
9
|
+
CopyIcon,
|
|
10
|
+
ExternalLinkIcon,
|
|
11
|
+
LoaderIcon,
|
|
12
|
+
MarkdownIcon,
|
|
13
|
+
PerplexityIcon,
|
|
14
|
+
} from '@apify/ui-icons';
|
|
15
|
+
import { Menu, Text, theme } from '@apify/ui-library';
|
|
2
16
|
|
|
3
|
-
import CopyForLLM from './CopyForLLM';
|
|
4
17
|
import styles from './styles.module.css';
|
|
5
|
-
import ViewAsMarkdown from './ViewAsMarkdown';
|
|
6
18
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
const DROPDOWN_OPTIONS = [
|
|
20
|
+
{
|
|
21
|
+
label: 'Copy for LLM',
|
|
22
|
+
description: 'Copy page as Markdown for LLMs',
|
|
23
|
+
showExternalIcon: false,
|
|
24
|
+
Icon: CopyIcon,
|
|
25
|
+
value: 'copyForLLM',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: 'View as Markdown',
|
|
29
|
+
description: 'View this page as plain text',
|
|
30
|
+
showExternalIcon: true,
|
|
31
|
+
Icon: MarkdownIcon,
|
|
32
|
+
value: 'viewAsMarkdown',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Open in ChatGPT',
|
|
36
|
+
description: 'Ask questions about this page',
|
|
37
|
+
showExternalIcon: true,
|
|
38
|
+
Icon: ChatGptIcon,
|
|
39
|
+
value: 'openInChatGPT',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
label: 'Open in Claude',
|
|
43
|
+
description: 'Ask questions about this page',
|
|
44
|
+
showExternalIcon: true,
|
|
45
|
+
Icon: AnthropicIcon,
|
|
46
|
+
value: 'openInClaude',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: 'Open in Perplexity',
|
|
50
|
+
description: 'Ask questions about this page',
|
|
51
|
+
showExternalIcon: true,
|
|
52
|
+
Icon: PerplexityIcon,
|
|
53
|
+
value: 'openInPerplexity',
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const getPrompt = (currentUrl) => `Read from ${currentUrl} so I can ask questions about it.`;
|
|
58
|
+
const getMarkdownUrl = (currentUrl) => `${currentUrl}.md`;
|
|
59
|
+
|
|
60
|
+
const onOpenInChatGPTClick = () => {
|
|
61
|
+
if (window.analytics) {
|
|
62
|
+
window.analytics.track('Clicked', {
|
|
63
|
+
app: 'docs',
|
|
64
|
+
button_text: 'Open in ChatGPT',
|
|
65
|
+
element: 'llm-buttons.openInChatGPT',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const prompt = getPrompt(window.location.href);
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
window.open(
|
|
73
|
+
`https://chatgpt.com/?hints=search&q=${encodeURIComponent(prompt)}`,
|
|
74
|
+
'_blank',
|
|
75
|
+
);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error('Error opening ChatGPT:', error);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const onOpenInClaudeClick = () => {
|
|
82
|
+
if (window.analytics) {
|
|
83
|
+
window.analytics.track('Clicked', {
|
|
84
|
+
app: 'docs',
|
|
85
|
+
button_text: 'Open in Claude',
|
|
86
|
+
element: 'llm-buttons.openInClaude',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const prompt = getPrompt(window.location.href);
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
window.open(
|
|
94
|
+
`https://claude.ai/new?q=${encodeURIComponent(prompt)}`,
|
|
95
|
+
'_blank',
|
|
96
|
+
);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error('Error opening Claude:', error);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const onOpenInPerplexityClick = () => {
|
|
103
|
+
if (window.analytics) {
|
|
104
|
+
window.analytics.track('Clicked', {
|
|
105
|
+
app: 'docs',
|
|
106
|
+
button_text: 'Open in Perplexity',
|
|
107
|
+
element: 'llm-buttons.openInPerplexity',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const prompt = getPrompt(window.location.href);
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
window.open(
|
|
115
|
+
`https://www.perplexity.ai/search/new?q=${encodeURIComponent(
|
|
116
|
+
prompt,
|
|
117
|
+
)}`,
|
|
118
|
+
'_blank',
|
|
119
|
+
);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error('Error opening Perplexity:', error);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const onCopyAsMarkdownClick = async ({ setCopyingStatus }) => {
|
|
126
|
+
if (window.analytics) {
|
|
127
|
+
window.analytics.track('Clicked', {
|
|
128
|
+
app: 'docs',
|
|
129
|
+
button_text: 'Copy for LLM',
|
|
130
|
+
element: 'llm-buttons.copyForLLM',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const markdownUrl = getMarkdownUrl(window.location.href);
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
setCopyingStatus('loading');
|
|
138
|
+
|
|
139
|
+
// Fetch the markdown content
|
|
140
|
+
const response = await fetch(markdownUrl);
|
|
141
|
+
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
throw new Error(`Failed to fetch markdown: ${response.status}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const markdownContent = await response.text();
|
|
147
|
+
|
|
148
|
+
// Copy to clipboard
|
|
149
|
+
await navigator.clipboard.writeText(markdownContent);
|
|
150
|
+
|
|
151
|
+
// Show success feedback
|
|
152
|
+
setCopyingStatus('copied');
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error('Failed to copy markdown content:', error);
|
|
155
|
+
} finally {
|
|
156
|
+
setTimeout(() => setCopyingStatus('idle'), 2000);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const onViewAsMarkdownClick = () => {
|
|
161
|
+
if (window.analytics) {
|
|
162
|
+
window.analytics.track('Clicked', {
|
|
163
|
+
app: 'docs',
|
|
164
|
+
button_text: 'View as Markdown',
|
|
165
|
+
element: 'llm-buttons.viewAsMarkdown',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const markdownUrl = getMarkdownUrl(window.location.href);
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
window.open(markdownUrl, '_blank');
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error('Error opening markdown file:', error);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
function getButtonText({ status }) {
|
|
179
|
+
switch (status) {
|
|
180
|
+
case 'loading':
|
|
181
|
+
return 'Copying...';
|
|
182
|
+
case 'copied':
|
|
183
|
+
return 'Copied';
|
|
184
|
+
default:
|
|
185
|
+
return 'Copy for LLM';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const MenuBase = ({
|
|
190
|
+
children,
|
|
191
|
+
ref,
|
|
192
|
+
copyingStatus,
|
|
193
|
+
setCopyingStatus,
|
|
194
|
+
chevronIconRef,
|
|
195
|
+
...props
|
|
196
|
+
}) => (
|
|
197
|
+
<div ref={ref} className={styles.llmButtonWrapper}>
|
|
198
|
+
<div className={styles.llmButton}>
|
|
199
|
+
<div
|
|
200
|
+
className={styles.copyUpIconWrapper}
|
|
201
|
+
onClick={() => onCopyAsMarkdownClick({ setCopyingStatus })}
|
|
202
|
+
>
|
|
203
|
+
{copyingStatus === 'loading' && <LoaderIcon size={16} />}
|
|
204
|
+
{copyingStatus === 'copied' && <CheckIcon size={16} />}
|
|
205
|
+
{copyingStatus === 'idle' && <CopyIcon size={16} />}
|
|
206
|
+
</div>
|
|
207
|
+
<Text
|
|
208
|
+
size="regular"
|
|
209
|
+
onClick={() => onCopyAsMarkdownClick({ setCopyingStatus })}
|
|
210
|
+
className={styles.llmButtonText}
|
|
211
|
+
>
|
|
212
|
+
{getButtonText({ status: copyingStatus })}
|
|
213
|
+
</Text>
|
|
214
|
+
<div {...props} className={styles.chevronIconWrapper}>
|
|
215
|
+
<ChevronDownIcon
|
|
216
|
+
size="16"
|
|
217
|
+
color={theme.color.neutral.icon}
|
|
218
|
+
className={styles.chevronIcon}
|
|
219
|
+
ref={chevronIconRef}
|
|
220
|
+
/>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const Option = ({ Icon, label, description, showExternalIcon }) => (
|
|
227
|
+
<div className={styles.menuOption}>
|
|
228
|
+
<Icon size={16} className={styles.menuOptionIcon} />
|
|
229
|
+
<div className={styles.menuOptionText}>
|
|
230
|
+
<Text size="regular">{label}</Text>
|
|
231
|
+
<Text size="small" color={theme.color.neutral.textSubtle}>
|
|
232
|
+
{description}
|
|
233
|
+
</Text>
|
|
13
234
|
</div>
|
|
235
|
+
{showExternalIcon && (
|
|
236
|
+
<ExternalLinkIcon
|
|
237
|
+
size={16}
|
|
238
|
+
className={styles.menuOptionExternalIcon}
|
|
239
|
+
/>
|
|
240
|
+
)}
|
|
241
|
+
</div>
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
export default function LLMButtons({ isApiReferencePage = false }) {
|
|
245
|
+
const [copyingStatus, setCopyingStatus] = useState('idle');
|
|
246
|
+
const chevronIconRef = React.useRef(null);
|
|
247
|
+
|
|
248
|
+
const onMenuOptionClick = useCallback((value) => {
|
|
249
|
+
switch (value) {
|
|
250
|
+
case 'copyForLLM':
|
|
251
|
+
onCopyAsMarkdownClick({ setCopyingStatus });
|
|
252
|
+
break;
|
|
253
|
+
case 'viewAsMarkdown':
|
|
254
|
+
onViewAsMarkdownClick();
|
|
255
|
+
break;
|
|
256
|
+
case 'openInChatGPT':
|
|
257
|
+
onOpenInChatGPTClick();
|
|
258
|
+
break;
|
|
259
|
+
case 'openInClaude':
|
|
260
|
+
onOpenInClaudeClick();
|
|
261
|
+
break;
|
|
262
|
+
case 'openInPerplexity':
|
|
263
|
+
onOpenInPerplexityClick();
|
|
264
|
+
break;
|
|
265
|
+
default:
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
}, []);
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
<Menu
|
|
272
|
+
className={clsx(styles.llmMenu, {
|
|
273
|
+
[styles.llmMenuApiReferencePage]: isApiReferencePage,
|
|
274
|
+
})}
|
|
275
|
+
onMenuOpen={(isOpen) => chevronIconRef.current?.classList.toggle(
|
|
276
|
+
styles.chevronIconOpen,
|
|
277
|
+
isOpen,
|
|
278
|
+
)
|
|
279
|
+
}
|
|
280
|
+
components={{
|
|
281
|
+
MenuBase: (props) => (
|
|
282
|
+
<MenuBase
|
|
283
|
+
copyingStatus={copyingStatus}
|
|
284
|
+
setCopyingStatus={setCopyingStatus}
|
|
285
|
+
chevronIconRef={chevronIconRef}
|
|
286
|
+
{...props}
|
|
287
|
+
/>
|
|
288
|
+
),
|
|
289
|
+
}}
|
|
290
|
+
onSelect={onMenuOptionClick}
|
|
291
|
+
options={DROPDOWN_OPTIONS}
|
|
292
|
+
renderOption={Option}
|
|
293
|
+
/>
|
|
14
294
|
);
|
|
15
295
|
}
|
|
@@ -1,57 +1,115 @@
|
|
|
1
|
-
.
|
|
1
|
+
:global .menu-list[data-floating-ui-focusable] {
|
|
2
|
+
gap: 0.4rem;
|
|
3
|
+
padding: 0.6rem;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.llmMenu {
|
|
7
|
+
margin-top: 1.2rem;
|
|
8
|
+
width: fit-content;
|
|
9
|
+
|
|
10
|
+
@media (min-width: 768px) {
|
|
11
|
+
margin-left: auto;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.llmButtonWrapper {
|
|
2
16
|
display: flex;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
17
|
+
justify-content: flex-end;
|
|
18
|
+
|
|
19
|
+
@media (min-width: 768px) {
|
|
20
|
+
/* hack to make the dropdown menu align to the right */
|
|
21
|
+
width: 23.3rem;
|
|
22
|
+
}
|
|
7
23
|
}
|
|
8
24
|
|
|
9
|
-
.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
25
|
+
.llmMenuApiReferencePage {
|
|
26
|
+
margin-top: -0.8rem;
|
|
27
|
+
margin-bottom: calc(var(--ifm-h1-vertical-rhythm-bottom) * var(--ifm-leading));
|
|
28
|
+
margin-left: 0 !important;
|
|
29
|
+
.llmButtonWrapper {
|
|
30
|
+
width: fit-content !important;
|
|
31
|
+
}
|
|
13
32
|
}
|
|
14
33
|
|
|
15
34
|
.llmButton {
|
|
35
|
+
width: fit-content;
|
|
36
|
+
display: inline-flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
height: 3rem;
|
|
39
|
+
|
|
16
40
|
display: flex;
|
|
17
41
|
align-items: center;
|
|
18
|
-
|
|
19
|
-
border:
|
|
20
|
-
|
|
42
|
+
border-radius: 8px;
|
|
43
|
+
border: 1px solid var(--color-Neutral_SeparatorSubtle);
|
|
44
|
+
background-color: var(--color-Neutral_BackgroundMuted);
|
|
45
|
+
|
|
21
46
|
cursor: pointer;
|
|
22
|
-
|
|
23
|
-
|
|
47
|
+
transition: background-color 0.2s ease-in-out;
|
|
48
|
+
|
|
49
|
+
&:hover {
|
|
50
|
+
background-color: var(--color-Neutral_BackgroundMuted);
|
|
51
|
+
}
|
|
24
52
|
}
|
|
25
53
|
|
|
26
|
-
.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
54
|
+
.copyUpIconWrapper {
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
padding-left: 0.8rem;
|
|
59
|
+
padding-right: 0.4rem;
|
|
60
|
+
height: 100%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.llmButtonText {
|
|
64
|
+
height: 100%;
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
padding-right: 0.8rem;
|
|
68
|
+
min-width: 9.3rem;
|
|
69
|
+
|
|
70
|
+
/* prevents font size glitch when loading the page */
|
|
71
|
+
margin: 0px;
|
|
72
|
+
font-size: 1.4rem;
|
|
73
|
+
font-weight: 400;
|
|
74
|
+
font-family: Inter, sans-serif;
|
|
35
75
|
}
|
|
36
76
|
|
|
37
|
-
.
|
|
38
|
-
|
|
77
|
+
.chevronIconWrapper {
|
|
78
|
+
border-left: 1px solid var(--color-Neutral_SeparatorSubtle);
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
padding-inline: 0.8rem;
|
|
83
|
+
height: 100%;
|
|
84
|
+
}
|
|
39
85
|
|
|
86
|
+
.chevronIcon {
|
|
87
|
+
transition: transform 0.2s ease-in-out;
|
|
40
88
|
}
|
|
41
89
|
|
|
42
|
-
.
|
|
43
|
-
|
|
90
|
+
.chevronIconOpen {
|
|
91
|
+
transform: rotate(180deg);
|
|
44
92
|
}
|
|
45
93
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
94
|
+
.menuOption {
|
|
95
|
+
padding-block: 0.4rem;
|
|
96
|
+
display: flex;
|
|
97
|
+
gap: 0.4rem;
|
|
49
98
|
}
|
|
50
99
|
|
|
51
|
-
|
|
52
|
-
|
|
100
|
+
.menuOptionIcon {
|
|
101
|
+
flex-shrink: 0;
|
|
102
|
+
margin-top: 0.4rem;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.menuOptionText {
|
|
106
|
+
flex: 1;
|
|
107
|
+
display: flex;
|
|
108
|
+
flex-direction: column;
|
|
109
|
+
gap: 0.2rem;
|
|
53
110
|
}
|
|
54
111
|
|
|
55
|
-
|
|
56
|
-
|
|
112
|
+
.menuOptionExternalIcon {
|
|
113
|
+
flex-shrink: 0;
|
|
114
|
+
margin-top: 0.2rem;
|
|
57
115
|
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import styles from '../styles.module.css';
|
|
4
|
-
|
|
5
|
-
// Custom component for button text
|
|
6
|
-
function ButtonText({ isLoading, isCopied }) {
|
|
7
|
-
if (isLoading) {
|
|
8
|
-
return 'Copying...';
|
|
9
|
-
}
|
|
10
|
-
if (isCopied) {
|
|
11
|
-
return 'Copied!';
|
|
12
|
-
}
|
|
13
|
-
return 'Copy for LLM';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default function CopyForLLM() {
|
|
17
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
18
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
19
|
-
|
|
20
|
-
const handleCopy = async () => {
|
|
21
|
-
if (window.analytics) {
|
|
22
|
-
window.analytics.track('Clicked', {
|
|
23
|
-
app: 'docs',
|
|
24
|
-
button_text: 'Copy for LLM',
|
|
25
|
-
element: 'llm-buttons.copyForLLM',
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
setIsLoading(true);
|
|
31
|
-
|
|
32
|
-
const currentUrl = window.location.href;
|
|
33
|
-
const markdownUrl = `${currentUrl}.md`;
|
|
34
|
-
|
|
35
|
-
// Fetch the markdown content
|
|
36
|
-
const response = await fetch(markdownUrl);
|
|
37
|
-
|
|
38
|
-
if (!response.ok) {
|
|
39
|
-
throw new Error(`Failed to fetch markdown: ${response.status}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const markdownContent = await response.text();
|
|
43
|
-
|
|
44
|
-
// Copy to clipboard
|
|
45
|
-
await navigator.clipboard.writeText(markdownContent);
|
|
46
|
-
|
|
47
|
-
// Show success feedback
|
|
48
|
-
setIsCopied(true);
|
|
49
|
-
setTimeout(() => setIsCopied(false), 2000);
|
|
50
|
-
} catch (error) {
|
|
51
|
-
console.error('Failed to copy markdown content:', error);
|
|
52
|
-
} finally {
|
|
53
|
-
setIsLoading(false);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<button
|
|
59
|
-
className={styles.llmButton}
|
|
60
|
-
title="Copy for LLM"
|
|
61
|
-
onClick={handleCopy}
|
|
62
|
-
disabled={isLoading}
|
|
63
|
-
>
|
|
64
|
-
<span
|
|
65
|
-
className={`${styles.llmButtonIcon} ${styles.llmButtonIconBackgroundCopy}`}
|
|
66
|
-
aria-label="Copy for LLM"
|
|
67
|
-
/>
|
|
68
|
-
<ButtonText isLoading={isLoading} isCopied={isCopied} />
|
|
69
|
-
</button>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import styles from '../styles.module.css';
|
|
4
|
-
|
|
5
|
-
export default function ViewAsMarkdown() {
|
|
6
|
-
const handleClick = () => {
|
|
7
|
-
if (window.analytics) {
|
|
8
|
-
window.analytics.track('Clicked', {
|
|
9
|
-
app: 'docs',
|
|
10
|
-
button_text: 'View as Markdown',
|
|
11
|
-
element: 'llm-buttons.viewAsMarkdown',
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const currentUrl = window.location.href;
|
|
17
|
-
const markdownUrl = `${currentUrl}.md`;
|
|
18
|
-
window.open(markdownUrl, '_blank');
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.error('Error opening markdown file:', error);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<button
|
|
26
|
-
className={styles.llmButton}
|
|
27
|
-
title="View as Markdown"
|
|
28
|
-
onClick={handleClick}
|
|
29
|
-
>
|
|
30
|
-
<span
|
|
31
|
-
className={`${styles.llmButtonIcon} ${styles.llmButtonIconBackgroundMarkdown}`}
|
|
32
|
-
aria-label="View as Markdown"
|
|
33
|
-
/>
|
|
34
|
-
View as Markdown
|
|
35
|
-
</button>
|
|
36
|
-
);
|
|
37
|
-
}
|