@farming-labs/astro-theme 0.1.113 → 0.1.115

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/astro-theme",
3
- "version": "0.1.113",
3
+ "version": "0.1.115",
4
4
  "description": "Astro UI components for @farming-labs/docs — layout, sidebar, TOC, search, and theme toggle",
5
5
  "keywords": [
6
6
  "astro",
@@ -119,8 +119,8 @@
119
119
  },
120
120
  "dependencies": {
121
121
  "sugar-high": "^0.9.5",
122
- "@farming-labs/astro": "0.1.113",
123
- "@farming-labs/docs": "0.1.113"
122
+ "@farming-labs/docs": "0.1.115",
123
+ "@farming-labs/astro": "0.1.115"
124
124
  },
125
125
  "peerDependencies": {
126
126
  "astro": ">=4.0.0"
@@ -50,27 +50,57 @@ const openDocsEnabled = (() => {
50
50
  })();
51
51
 
52
52
  const DEFAULT_OPEN_PROVIDERS = [
53
- { name: "ChatGPT", urlTemplate: "https://chatgpt.com/?hints=search&q=Read+{url}.md,+I+want+to+ask+questions+about+it." },
54
- { name: "Claude", urlTemplate: "https://claude.ai/new?q=Read+{url}.md,+I+want+to+ask+questions+about+it." },
53
+ { name: "ChatGPT", urlTemplate: "https://chatgpt.com/?q={prompt}" },
54
+ { name: "Claude", urlTemplate: "https://claude.ai/new?q={prompt}" },
55
55
  ];
56
56
 
57
+ const DEFAULT_OPEN_PROMPT = "Read this documentation: {url}";
58
+ const DEFAULT_OPEN_TARGET = "markdown";
59
+ const OPEN_PROVIDER_PRESETS: Record<string, { name: string; urlTemplate: string; target?: string }> = {
60
+ chatgpt: { name: "ChatGPT", urlTemplate: "https://chatgpt.com/?q={prompt}" },
61
+ claude: { name: "Claude", urlTemplate: "https://claude.ai/new?q={prompt}" },
62
+ cursor: { name: "Cursor", urlTemplate: "https://cursor.com/link/prompt?text={prompt}" },
63
+ gemini: { name: "Gemini", urlTemplate: "https://gemini.google.com/app?q={prompt}" },
64
+ copilot: { name: "Copilot", urlTemplate: "https://github.com/copilot?prompt={prompt}" },
65
+ github: { name: "GitHub", urlTemplate: "{githubUrl}", target: "github" },
66
+ };
67
+
57
68
  const openDocsProviders = (() => {
58
69
  const pa = config?.pageActions;
59
70
  const od = pa && typeof pa === "object" && pa.openDocs != null ? pa.openDocs : null;
71
+ const target = od && typeof od === "object" ? (od as { target?: string }).target : undefined;
72
+ const prompt = od && typeof od === "object" ? (od as { prompt?: string }).prompt : undefined;
60
73
  const list =
61
74
  od && typeof od === "object" && "providers" in od
62
- ? (od as { providers?: Array<{ name?: string; urlTemplate?: string }> }).providers
75
+ ? (od as { providers?: Array<string | { id?: string; name?: string; label?: string; urlTemplate?: string; prompt?: string; target?: string; mode?: string }> }).providers
63
76
  : undefined;
64
77
  if (Array.isArray(list) && list.length > 0) {
65
78
  const mapped = list
66
- .map((p) => ({
67
- name: typeof p?.name === "string" ? p.name : "Open",
68
- urlTemplate: typeof (p as { urlTemplate?: string })?.urlTemplate === "string" ? (p as { urlTemplate: string }).urlTemplate : "",
69
- }))
79
+ .map((p) => {
80
+ const id =
81
+ typeof p === "string" ? p.toLowerCase() : (p.id ?? p.name ?? p.label)?.toLowerCase();
82
+ const preset = id ? OPEN_PROVIDER_PRESETS[id] : undefined;
83
+ const cursorApp = id === "cursor" && typeof p === "object" && p.mode === "app";
84
+ const hasCustomUrlTemplate = typeof p === "object" && typeof p.urlTemplate === "string";
85
+ return {
86
+ name: typeof p === "object" ? (p.name ?? p.label ?? preset?.name ?? "Open") : (preset?.name ?? p),
87
+ urlTemplate:
88
+ hasCustomUrlTemplate
89
+ ? p.urlTemplate
90
+ : cursorApp
91
+ ? "cursor://anysphere.cursor-deeplink/prompt?text={prompt}"
92
+ : (preset?.urlTemplate ?? ""),
93
+ target:
94
+ typeof p === "object"
95
+ ? (p.target ?? preset?.target ?? target ?? (hasCustomUrlTemplate ? "page" : undefined))
96
+ : (preset?.target ?? target),
97
+ prompt: typeof p === "object" ? (p.prompt ?? prompt) : prompt,
98
+ };
99
+ })
70
100
  .filter((p) => p.urlTemplate.length > 0);
71
101
  if (mapped.length > 0) return mapped;
72
102
  }
73
- return DEFAULT_OPEN_PROVIDERS;
103
+ return DEFAULT_OPEN_PROVIDERS.map((provider) => ({ ...provider, target, prompt }));
74
104
  })();
75
105
 
76
106
  const pathname = Astro.url.pathname;
@@ -197,6 +227,8 @@ const htmlWithoutFirstH1 = (data.html || "").replace(/<h1[^>]*>[\s\S]*?<\/h1>\s*
197
227
  data-open-provider
198
228
  data-name={provider.name}
199
229
  data-url-template={provider.urlTemplate}
230
+ data-target={provider.target}
231
+ data-prompt={provider.prompt}
200
232
  >
201
233
  <span class="fd-page-action-menu-label">Open in {provider.name}</span>
202
234
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -269,6 +301,8 @@ const htmlWithoutFirstH1 = (data.html || "").replace(/<h1[^>]*>[\s\S]*?<\/h1>\s*
269
301
  data-open-provider
270
302
  data-name={provider.name}
271
303
  data-url-template={provider.urlTemplate}
304
+ data-target={provider.target}
305
+ data-prompt={provider.prompt}
272
306
  >
273
307
  <span class="fd-page-action-menu-label">Open in {provider.name}</span>
274
308
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -416,6 +450,32 @@ const htmlWithoutFirstH1 = (data.html || "").replace(/<h1[^>]*>[\s\S]*?<\/h1>\s*
416
450
  var feedbackSlugVal = typeof feedbackSlug === "string" ? feedbackSlug : "";
417
451
  var feedbackTitleVal = typeof feedbackTitle === "string" ? feedbackTitle : undefined;
418
452
  var feedbackDescriptionVal = typeof feedbackDescription === "string" ? feedbackDescription : undefined;
453
+ var defaultOpenPrompt = "Read this documentation: {url}";
454
+ var defaultOpenTarget = "markdown";
455
+
456
+ function resolveMarkdownUrl(url) {
457
+ try {
458
+ var parsed = new URL(url);
459
+ var cleanPathname = parsed.pathname.replace(/\/+$/, "") || parsed.pathname;
460
+ parsed.pathname = cleanPathname.endsWith(".md") ? cleanPathname : cleanPathname + ".md";
461
+ parsed.search = "";
462
+ parsed.hash = "";
463
+ return parsed.toString();
464
+ } catch (error) {
465
+ var clean = url.replace(/[?#].*$/, "").replace(/\/+$/, "") || url;
466
+ return clean.endsWith(".md") ? clean : clean + ".md";
467
+ }
468
+ }
469
+
470
+ function fillOpenPrompt(template, values) {
471
+ return template
472
+ .replace(/\{pageUrl\}/g, values.pageUrl)
473
+ .replace(/\{markdownUrl\}/g, values.markdownUrl)
474
+ .replace(/\{sourceUrl\}/g, values.sourceUrl)
475
+ .replace(/\{mdxUrl\}/g, values.sourceUrl)
476
+ .replace(/\{githubUrl\}/g, values.githubUrl)
477
+ .replace(/\{url\}/g, values.url);
478
+ }
419
479
 
420
480
  function emitFeedback(data) {
421
481
  var firstError = null;
@@ -493,11 +553,40 @@ const htmlWithoutFirstH1 = (data.html || "").replace(/<h1[^>]*>[\s\S]*?<\/h1>\s*
493
553
  el.addEventListener("click", function (e) {
494
554
  e.preventDefault();
495
555
  var urlTemplate = el.getAttribute("data-url-template") || "";
556
+ var target = el.getAttribute("data-target") || defaultOpenTarget;
557
+ var promptTemplate = el.getAttribute("data-prompt") || defaultOpenPrompt;
558
+ if (/\{githubUrl\}/.test(urlTemplate) && !githubFileUrlVal) {
559
+ var menu = el.closest("[data-dropdown-menu]");
560
+ var triggerEl = document.querySelector("[data-dropdown-trigger]");
561
+ if (menu) menu.hidden = true;
562
+ if (triggerEl) triggerEl.setAttribute("aria-expanded", "false");
563
+ return;
564
+ }
496
565
  var pageUrl = window.location.href;
497
- var mdxUrl = window.location.origin + pathnameVal + (pathnameVal.endsWith("/") ? "page.mdx" : ".mdx");
566
+ var sourceUrl = window.location.origin + pathnameVal + (pathnameVal.endsWith("/") ? "page.mdx" : ".mdx");
567
+ var markdownUrl = resolveMarkdownUrl(pageUrl);
568
+ var targetUrl =
569
+ target === "markdown"
570
+ ? markdownUrl
571
+ : target === "source"
572
+ ? sourceUrl
573
+ : target === "github"
574
+ ? (githubFileUrlVal || pageUrl)
575
+ : pageUrl;
576
+ var prompt = fillOpenPrompt(promptTemplate, {
577
+ url: targetUrl,
578
+ pageUrl: pageUrl,
579
+ markdownUrl: markdownUrl,
580
+ sourceUrl: sourceUrl,
581
+ githubUrl: githubFileUrlVal,
582
+ });
498
583
  var url = urlTemplate
499
- .replace(/\{url\}/g, encodeURIComponent(pageUrl))
500
- .replace(/\{mdxUrl\}/g, encodeURIComponent(mdxUrl))
584
+ .replace(/\{prompt\}/g, encodeURIComponent(prompt))
585
+ .replace(/\{url\}/g, encodeURIComponent(targetUrl))
586
+ .replace(/\{pageUrl\}/g, encodeURIComponent(pageUrl))
587
+ .replace(/\{markdownUrl\}/g, encodeURIComponent(markdownUrl))
588
+ .replace(/\{sourceUrl\}/g, encodeURIComponent(sourceUrl))
589
+ .replace(/\{mdxUrl\}/g, encodeURIComponent(sourceUrl))
501
590
  .replace(/\{githubUrl\}/g, githubFileUrlVal);
502
591
  window.open(url, "_blank", "noopener,noreferrer");
503
592
  var menu = el.closest("[data-dropdown-menu]");