@farming-labs/svelte-theme 0.1.112 → 0.1.114

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/svelte-theme",
3
- "version": "0.1.112",
3
+ "version": "0.1.114",
4
4
  "description": "Svelte UI components for @farming-labs/docs — layout, sidebar, TOC, search, and theme toggle",
5
5
  "keywords": [
6
6
  "docs",
@@ -122,8 +122,8 @@
122
122
  "dependencies": {
123
123
  "gray-matter": "^4.0.3",
124
124
  "sugar-high": "^0.9.5",
125
- "@farming-labs/docs": "0.1.112",
126
- "@farming-labs/svelte": "0.1.112"
125
+ "@farming-labs/docs": "0.1.114",
126
+ "@farming-labs/svelte": "0.1.114"
127
127
  },
128
128
  "peerDependencies": {
129
129
  "svelte": ">=5.0.0"
@@ -4,10 +4,21 @@
4
4
  import { toDocsMarkdownUrl } from "@farming-labs/docs";
5
5
 
6
6
  const DEFAULT_OPEN_PROVIDERS = [
7
- { name: "ChatGPT", urlTemplate: "https://chatgpt.com/?hints=search&q=Read+{mdxUrl},+I+want+to+ask+questions+about+it." },
8
- { name: "Claude", urlTemplate: "https://claude.ai/new?q=Read+{mdxUrl},+I+want+to+ask+questions+about+it." },
7
+ { name: "ChatGPT", urlTemplate: "https://chatgpt.com/?q={prompt}" },
8
+ { name: "Claude", urlTemplate: "https://claude.ai/new?q={prompt}" },
9
9
  ];
10
10
 
11
+ const DEFAULT_OPEN_PROMPT = "Read this documentation: {url}";
12
+ const DEFAULT_OPEN_TARGET = "markdown";
13
+ const OPEN_PROVIDER_PRESETS = {
14
+ chatgpt: { name: "ChatGPT", urlTemplate: "https://chatgpt.com/?q={prompt}" },
15
+ claude: { name: "Claude", urlTemplate: "https://claude.ai/new?q={prompt}" },
16
+ cursor: { name: "Cursor", urlTemplate: "https://cursor.com/link/prompt?text={prompt}" },
17
+ gemini: { name: "Gemini", urlTemplate: "https://gemini.google.com/app?q={prompt}" },
18
+ copilot: { name: "Copilot", urlTemplate: "https://github.com/copilot?prompt={prompt}" },
19
+ github: { name: "GitHub", urlTemplate: "{githubUrl}", target: "github" },
20
+ };
21
+
11
22
  let { data, config = null } = $props();
12
23
 
13
24
  let openDropdownMenu = $state(false);
@@ -39,6 +50,30 @@
39
50
  config?.staticExport ? null : toDocsMarkdownUrl(pageUrl, { locale: data.locale })
40
51
  );
41
52
 
53
+ function resolveMarkdownUrl(url) {
54
+ try {
55
+ const parsed = new URL(url);
56
+ const pathname = parsed.pathname.replace(/\/+$/, "") || parsed.pathname;
57
+ parsed.pathname = pathname.endsWith(".md") ? pathname : `${pathname}.md`;
58
+ parsed.search = "";
59
+ parsed.hash = "";
60
+ return parsed.toString();
61
+ } catch {
62
+ const clean = url.replace(/[?#].*$/, "").replace(/\/+$/, "") || url;
63
+ return clean.endsWith(".md") ? clean : `${clean}.md`;
64
+ }
65
+ }
66
+
67
+ function fillOpenPrompt(template, values) {
68
+ return template
69
+ .replace(/\{pageUrl\}/g, values.pageUrl)
70
+ .replace(/\{markdownUrl\}/g, values.markdownUrl)
71
+ .replace(/\{sourceUrl\}/g, values.sourceUrl)
72
+ .replace(/\{mdxUrl\}/g, values.sourceUrl)
73
+ .replace(/\{githubUrl\}/g, values.githubUrl)
74
+ .replace(/\{url\}/g, values.url);
75
+ }
76
+
42
77
  let breadcrumbEnabled = $derived.by(() => {
43
78
  const bc = config?.breadcrumb;
44
79
  if (bc === undefined || bc === true) return true;
@@ -83,17 +118,36 @@
83
118
  let openDocsProviders = $derived.by(() => {
84
119
  const pa = config?.pageActions;
85
120
  const od = pa && typeof pa === "object" && pa.openDocs != null ? pa.openDocs : null;
121
+ const target = od && typeof od === "object" ? od.target : undefined;
122
+ const prompt = od && typeof od === "object" ? od.prompt : undefined;
86
123
  const list = od && typeof od === "object" && "providers" in od ? od.providers : undefined;
87
124
  if (Array.isArray(list) && list.length > 0) {
88
125
  const mapped = list
89
- .map((p) => ({
90
- name: typeof p?.name === "string" ? p.name : "Open",
91
- urlTemplate: typeof p?.urlTemplate === "string" ? p.urlTemplate : "",
92
- }))
126
+ .map((p) => {
127
+ const id =
128
+ typeof p === "string" ? p.toLowerCase() : (p.id ?? p.name ?? p.label)?.toLowerCase();
129
+ const preset = id ? OPEN_PROVIDER_PRESETS[id] : undefined;
130
+ const cursorApp = id === "cursor" && typeof p === "object" && p.mode === "app";
131
+ const hasCustomUrlTemplate = typeof p === "object" && typeof p.urlTemplate === "string";
132
+ return {
133
+ name: typeof p === "object" ? (p.name ?? p.label ?? preset?.name ?? "Open") : (preset?.name ?? p),
134
+ urlTemplate:
135
+ hasCustomUrlTemplate
136
+ ? p.urlTemplate
137
+ : cursorApp
138
+ ? "cursor://anysphere.cursor-deeplink/prompt?text={prompt}"
139
+ : (preset?.urlTemplate ?? ""),
140
+ target:
141
+ typeof p === "object"
142
+ ? (p.target ?? preset?.target ?? target ?? (hasCustomUrlTemplate ? "page" : undefined))
143
+ : (preset?.target ?? target),
144
+ prompt: typeof p === "object" ? (p.prompt ?? prompt) : prompt,
145
+ };
146
+ })
93
147
  .filter((p) => p.urlTemplate.length > 0);
94
148
  if (mapped.length > 0) return mapped;
95
149
  }
96
- return DEFAULT_OPEN_PROVIDERS;
150
+ return DEFAULT_OPEN_PROVIDERS.map((provider) => ({ ...provider, target, prompt }));
97
151
  });
98
152
 
99
153
  let pageActionsPosition = $derived(
@@ -223,13 +277,38 @@
223
277
  function openInProvider(provider) {
224
278
  const pathname = typeof window !== "undefined" ? window.location.pathname : "";
225
279
  const pageUrl = typeof window !== "undefined" ? window.location.href : "";
226
- const mdxUrl = typeof window !== "undefined"
280
+ const sourceUrl = typeof window !== "undefined"
227
281
  ? window.location.origin + pathname + (pathname.endsWith("/") ? "page.mdx" : ".mdx")
228
282
  : "";
283
+ const markdownUrl = resolveMarkdownUrl(pageUrl);
229
284
  const githubUrl = data.editOnGithub || "";
285
+ if (/\{githubUrl\}/.test(provider.urlTemplate) && !githubUrl) {
286
+ closeDropdown();
287
+ return;
288
+ }
289
+ const target = provider.target ?? DEFAULT_OPEN_TARGET;
290
+ const targetUrl =
291
+ target === "markdown"
292
+ ? markdownUrl
293
+ : target === "source"
294
+ ? sourceUrl
295
+ : target === "github"
296
+ ? (githubUrl || pageUrl)
297
+ : pageUrl;
298
+ const prompt = fillOpenPrompt(provider.prompt ?? DEFAULT_OPEN_PROMPT, {
299
+ url: targetUrl,
300
+ pageUrl,
301
+ markdownUrl,
302
+ sourceUrl,
303
+ githubUrl,
304
+ });
230
305
  const url = provider.urlTemplate
231
- .replace(/\{url\}/g, encodeURIComponent(pageUrl))
232
- .replace(/\{mdxUrl\}/g, encodeURIComponent(mdxUrl))
306
+ .replace(/\{prompt\}/g, encodeURIComponent(prompt))
307
+ .replace(/\{url\}/g, encodeURIComponent(targetUrl))
308
+ .replace(/\{pageUrl\}/g, encodeURIComponent(pageUrl))
309
+ .replace(/\{markdownUrl\}/g, encodeURIComponent(markdownUrl))
310
+ .replace(/\{sourceUrl\}/g, encodeURIComponent(sourceUrl))
311
+ .replace(/\{mdxUrl\}/g, encodeURIComponent(sourceUrl))
233
312
  .replace(/\{githubUrl\}/g, githubUrl);
234
313
  if (typeof window !== "undefined") window.open(url, "_blank", "noopener,noreferrer");
235
314
  closeDropdown();