livemark 0.22.0 → 0.23.0
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/README.md
CHANGED
|
@@ -101,7 +101,7 @@ Livemark is meant to look great with zero configuration and stay out of your way
|
|
|
101
101
|
|
|
102
102
|
Full documentation lives at **[livemark.dev](https://livemark.dev)**:
|
|
103
103
|
|
|
104
|
-
- [
|
|
104
|
+
- [Authoring reference](https://livemark.dev/authoring/) — every Markdown / MDX feature with examples
|
|
105
105
|
- [Customization](https://livemark.dev/customization/) — every knob, with copy-pasteable snippets
|
|
106
106
|
- [Changelog](https://livemark.dev/changelog/) — release notes
|
|
107
107
|
- [Contributing](https://livemark.dev/contributing/) — local setup and PR flow
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useCallback } from "react";
|
|
3
3
|
import { Eye, Pencil, Copy, Check, ExternalLink } from "lucide-react";
|
|
4
|
+
const LLM_PROMPT = "Read {url}, I want to ask questions about it.";
|
|
4
5
|
/** Toolbar with action buttons displayed for the article content */
|
|
5
6
|
export function PageToolbar(props) {
|
|
6
7
|
const [copied, setCopied] = useState(false);
|
|
@@ -16,19 +17,20 @@ export function PageToolbar(props) {
|
|
|
16
17
|
setCopied(true);
|
|
17
18
|
setTimeout(() => setCopied(false), 2000);
|
|
18
19
|
}, [props.content]);
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const openIn = (base, extra) => {
|
|
21
|
+
const q = LLM_PROMPT.replace("{url}", window.location.href);
|
|
22
|
+
const params = new URLSearchParams({ ...extra, q });
|
|
23
|
+
window.open(`${base}?${params}`, "_blank", "noopener,noreferrer");
|
|
24
|
+
};
|
|
23
25
|
const buttonClass = "flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors";
|
|
24
26
|
return (_jsx(_Fragment, { children: _jsxs("div", { className: "mb-6 flex flex-col gap-2 text-sm", children: [
|
|
25
27
|
_jsx("p", { className: "text-sm font-medium mb-1", children: "Actions" }), sourceHref ? (_jsxs("a", { href: sourceHref, target: "_blank", rel: "noopener noreferrer", className: buttonClass, children: [
|
|
26
28
|
_jsx(SourceIcon, { className: "size-3.5" }), sourceLabel] })) : (_jsxs("span", { className: `${buttonClass} opacity-50 cursor-not-allowed hover:text-muted-foreground`, "aria-disabled": "true", children: [
|
|
27
|
-
_jsx(SourceIcon, { className: "size-3.5" }), sourceLabel] })), _jsxs("button", { type: "button", onClick: handleCopy, className: buttonClass, children: [copied ? (_jsx(Check, { className: "size-3.5" })) : (_jsx(Copy, { className: "size-3.5" })), "Copy Markdown"] }), _jsxs("button", { type: "button", onClick: () =>
|
|
29
|
+
_jsx(SourceIcon, { className: "size-3.5" }), sourceLabel] })), _jsxs("button", { type: "button", onClick: handleCopy, className: buttonClass, children: [copied ? (_jsx(Check, { className: "size-3.5" })) : (_jsx(Copy, { className: "size-3.5" })), "Copy Markdown"] }), _jsxs("button", { type: "button", onClick: () => openIn("https://chatgpt.com/", { hints: "search" }), className: buttonClass, children: [
|
|
28
30
|
_jsx(ExternalLink, { className: "size-3.5" }),
|
|
29
|
-
"Open in ChatGPT"] }), _jsxs("button", { type: "button", onClick: () =>
|
|
31
|
+
"Open in ChatGPT"] }), _jsxs("button", { type: "button", onClick: () => openIn("https://claude.ai/new"), className: buttonClass, children: [
|
|
30
32
|
_jsx(ExternalLink, { className: "size-3.5" }),
|
|
31
33
|
"Open in Claude"] })
|
|
32
34
|
] }) }));
|
|
33
35
|
}
|
|
34
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFnZVRvb2xiYXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zb3VyY2UvY29tcG9uZW50cy9QYWdlVG9vbGJhci50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sT0FBTyxDQUFBO0FBQzdDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBRXJFLE1BQU0sVUFBVSxHQUFHLCtDQUErQyxDQUFBO0FBRWxFLG9FQUFvRTtBQUNwRSxNQUFNLFVBQVUsV0FBVyxDQUFDLEtBSzNCO0lBQ0MsTUFBTSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDM0MsTUFBTSxVQUFVLEdBQ2QsS0FBSyxDQUFDLFNBQVM7UUFDZixDQUFDLEtBQUssQ0FBQyxJQUFJO1lBQ1QsQ0FBQyxDQUFDLGtEQUFrRCxLQUFLLENBQUMsSUFBSSxFQUFFO1lBQ2hFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUNoQixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsWUFBWSxLQUFLLE1BQU0sQ0FBQTtJQUM1QyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQTtJQUNoRSxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFBO0lBRXhDLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUU7UUFDbEMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQzVDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNmLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUE7SUFDMUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7SUFFbkIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxJQUFZLEVBQUUsS0FBOEIsRUFBRSxFQUFFO1FBQzlELE1BQU0sQ0FBQyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDM0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFlLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ25ELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksTUFBTSxFQUFFLEVBQUUsUUFBUSxFQUFFLHFCQUFxQixDQUFDLENBQUE7SUFDbkUsQ0FBQyxDQUFBO0lBRUQsTUFBTSxXQUFXLEdBQ2YsaUdBQWlHLENBQUE7SUFFbkcsT0FBTyxDQUNMLDRCQUNFLGVBQUssU0FBUyxFQUFDLGtDQUFrQztnQkFDL0MsWUFBRyxTQUFTLEVBQUMsMEJBQTBCLHdCQUFZLEVBQ2xELFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FDWixhQUNFLElBQUksRUFBRSxVQUFVLEVBQ2hCLE1BQU0sRUFBQyxRQUFRLEVBQ2YsR0FBRyxFQUFDLHFCQUFxQixFQUN6QixTQUFTLEVBQUUsV0FBVzt3QkFFdEIsS0FBQyxVQUFVLElBQUMsU0FBUyxFQUFDLFVBQVUsR0FBRyxFQUNsQyxXQUFXLElBQ1YsQ0FDTCxDQUFDLENBQUMsQ0FBQyxDQUNGLGdCQUNFLFNBQVMsRUFBRSxHQUFHLFdBQVcsNERBQTRELG1CQUN2RSxNQUFNO3dCQUVwQixLQUFDLFVBQVUsSUFBQyxTQUFTLEVBQUMsVUFBVSxHQUFHLEVBQ2xDLFdBQVcsSUFDUCxDQUNSLEVBQ0Qsa0JBQVEsSUFBSSxFQUFDLFFBQVEsRUFBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxXQUFXLGFBQzlELE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FDUixLQUFDLEtBQUssSUFBQyxTQUFTLEVBQUMsVUFBVSxHQUFHLENBQy9CLENBQUMsQ0FBQyxDQUFDLENBQ0YsS0FBQyxJQUFJLElBQUMsU0FBUyxFQUFDLFVBQVUsR0FBRyxDQUM5QixxQkFFTSxFQUNULGtCQUNFLElBQUksRUFBQyxRQUFRLEVBQ2IsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUNsRSxTQUFTLEVBQUUsV0FBVzt3QkFFdEIsS0FBQyxZQUFZLElBQUMsU0FBUyxFQUFDLFVBQVUsR0FBRzs2Q0FFOUIsRUFDVCxrQkFDRSxJQUFJLEVBQUMsUUFBUSxFQUNiLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLENBQUMsRUFDOUMsU0FBUyxFQUFFLFdBQVc7d0JBRXRCLEtBQUMsWUFBWSxJQUFDLFNBQVMsRUFBQyxVQUFVLEdBQUc7NENBRTlCO2dCQUNMLEdBQ0wsQ0FDSixDQUFBO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZVN0YXRlLCB1c2VDYWxsYmFjayB9IGZyb20gXCJyZWFjdFwiXG5pbXBvcnQgeyBFeWUsIFBlbmNpbCwgQ29weSwgQ2hlY2ssIEV4dGVybmFsTGluayB9IGZyb20gXCJsdWNpZGUtcmVhY3RcIlxuXG5jb25zdCBMTE1fUFJPTVBUID0gXCJSZWFkIHt1cmx9LCBJIHdhbnQgdG8gYXNrIHF1ZXN0aW9ucyBhYm91dCBpdC5cIlxuXG4vKiogVG9vbGJhciB3aXRoIGFjdGlvbiBidXR0b25zIGRpc3BsYXllZCBmb3IgdGhlIGFydGljbGUgY29udGVudCAqL1xuZXhwb3J0IGZ1bmN0aW9uIFBhZ2VUb29sYmFyKHByb3BzOiB7XG4gIGZpbGU/OiBzdHJpbmdcbiAgc291cmNlVXJsPzogc3RyaW5nXG4gIHNvdXJjZUFjdGlvbj86IFwiZWRpdFwiIHwgXCJ2aWV3XCJcbiAgY29udGVudDogc3RyaW5nXG59KSB7XG4gIGNvbnN0IFtjb3BpZWQsIHNldENvcGllZF0gPSB1c2VTdGF0ZShmYWxzZSlcbiAgY29uc3Qgc291cmNlSHJlZiA9XG4gICAgcHJvcHMuc291cmNlVXJsID8/XG4gICAgKHByb3BzLmZpbGVcbiAgICAgID8gYGh0dHBzOi8vZ2l0aHViLmNvbS9kYXRpc3RocS9saXZlbWFyay9lZGl0L21haW4vJHtwcm9wcy5maWxlfWBcbiAgICAgIDogdW5kZWZpbmVkKVxuICBjb25zdCBpc1ZpZXcgPSBwcm9wcy5zb3VyY2VBY3Rpb24gPT09IFwidmlld1wiXG4gIGNvbnN0IHNvdXJjZUxhYmVsID0gaXNWaWV3ID8gXCJWaWV3IG9uIEdpdEh1YlwiIDogXCJFZGl0IG9uIEdpdEh1YlwiXG4gIGNvbnN0IFNvdXJjZUljb24gPSBpc1ZpZXcgPyBFeWUgOiBQZW5jaWxcblxuICBjb25zdCBoYW5kbGVDb3B5ID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHByb3BzLmNvbnRlbnQpXG4gICAgc2V0Q29waWVkKHRydWUpXG4gICAgc2V0VGltZW91dCgoKSA9PiBzZXRDb3BpZWQoZmFsc2UpLCAyMDAwKVxuICB9LCBbcHJvcHMuY29udGVudF0pXG5cbiAgY29uc3Qgb3BlbkluID0gKGJhc2U6IHN0cmluZywgZXh0cmE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KSA9PiB7XG4gICAgY29uc3QgcSA9IExMTV9QUk9NUFQucmVwbGFjZShcInt1cmx9XCIsIHdpbmRvdy5sb2NhdGlvbi5ocmVmKVxuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoeyAuLi5leHRyYSwgcSB9KVxuICAgIHdpbmRvdy5vcGVuKGAke2Jhc2V9PyR7cGFyYW1zfWAsIFwiX2JsYW5rXCIsIFwibm9vcGVuZXIsbm9yZWZlcnJlclwiKVxuICB9XG5cbiAgY29uc3QgYnV0dG9uQ2xhc3MgPVxuICAgIFwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTEuNSB0ZXh0LXNtIHRleHQtbXV0ZWQtZm9yZWdyb3VuZCBob3Zlcjp0ZXh0LWZvcmVncm91bmQgdHJhbnNpdGlvbi1jb2xvcnNcIlxuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwibWItNiBmbGV4IGZsZXgtY29sIGdhcC0yIHRleHQtc21cIj5cbiAgICAgICAgPHAgY2xhc3NOYW1lPVwidGV4dC1zbSBmb250LW1lZGl1bSBtYi0xXCI+QWN0aW9uczwvcD5cbiAgICAgICAge3NvdXJjZUhyZWYgPyAoXG4gICAgICAgICAgPGFcbiAgICAgICAgICAgIGhyZWY9e3NvdXJjZUhyZWZ9XG4gICAgICAgICAgICB0YXJnZXQ9XCJfYmxhbmtcIlxuICAgICAgICAgICAgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiXG4gICAgICAgICAgICBjbGFzc05hbWU9e2J1dHRvbkNsYXNzfVxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxTb3VyY2VJY29uIGNsYXNzTmFtZT1cInNpemUtMy41XCIgLz5cbiAgICAgICAgICAgIHtzb3VyY2VMYWJlbH1cbiAgICAgICAgICA8L2E+XG4gICAgICAgICkgOiAoXG4gICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgIGNsYXNzTmFtZT17YCR7YnV0dG9uQ2xhc3N9IG9wYWNpdHktNTAgY3Vyc29yLW5vdC1hbGxvd2VkIGhvdmVyOnRleHQtbXV0ZWQtZm9yZWdyb3VuZGB9XG4gICAgICAgICAgICBhcmlhLWRpc2FibGVkPVwidHJ1ZVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPFNvdXJjZUljb24gY2xhc3NOYW1lPVwic2l6ZS0zLjVcIiAvPlxuICAgICAgICAgICAge3NvdXJjZUxhYmVsfVxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgKX1cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgb25DbGljaz17aGFuZGxlQ29weX0gY2xhc3NOYW1lPXtidXR0b25DbGFzc30+XG4gICAgICAgICAge2NvcGllZCA/IChcbiAgICAgICAgICAgIDxDaGVjayBjbGFzc05hbWU9XCJzaXplLTMuNVwiIC8+XG4gICAgICAgICAgKSA6IChcbiAgICAgICAgICAgIDxDb3B5IGNsYXNzTmFtZT1cInNpemUtMy41XCIgLz5cbiAgICAgICAgICApfVxuICAgICAgICAgIENvcHkgTWFya2Rvd25cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBvcGVuSW4oXCJodHRwczovL2NoYXRncHQuY29tL1wiLCB7IGhpbnRzOiBcInNlYXJjaFwiIH0pfVxuICAgICAgICAgIGNsYXNzTmFtZT17YnV0dG9uQ2xhc3N9XG4gICAgICAgID5cbiAgICAgICAgICA8RXh0ZXJuYWxMaW5rIGNsYXNzTmFtZT1cInNpemUtMy41XCIgLz5cbiAgICAgICAgICBPcGVuIGluIENoYXRHUFRcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBvcGVuSW4oXCJodHRwczovL2NsYXVkZS5haS9uZXdcIil9XG4gICAgICAgICAgY2xhc3NOYW1lPXtidXR0b25DbGFzc31cbiAgICAgICAgPlxuICAgICAgICAgIDxFeHRlcm5hbExpbmsgY2xhc3NOYW1lPVwic2l6ZS0zLjVcIiAvPlxuICAgICAgICAgIE9wZW4gaW4gQ2xhdWRlXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC8+XG4gIClcbn1cbiJdfQ==
|
package/package.json
CHANGED
|
@@ -92,6 +92,6 @@ After authoring, run:
|
|
|
92
92
|
|
|
93
93
|
## References
|
|
94
94
|
|
|
95
|
-
- Full frontmatter reference: `docs/
|
|
95
|
+
- Full frontmatter reference: `docs/authoring/frontmatter.md`.
|
|
96
96
|
- Schema source of truth: `website/models/article.ts`.
|
|
97
97
|
- Transform pipeline: `website/content-collections.ts`.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { useState, useCallback } from "react"
|
|
2
2
|
import { Eye, Pencil, Copy, Check, ExternalLink } from "lucide-react"
|
|
3
3
|
|
|
4
|
+
const LLM_PROMPT = "Read {url}, I want to ask questions about it."
|
|
5
|
+
|
|
4
6
|
/** Toolbar with action buttons displayed for the article content */
|
|
5
7
|
export function PageToolbar(props: {
|
|
6
8
|
file?: string
|
|
@@ -24,13 +26,11 @@ export function PageToolbar(props: {
|
|
|
24
26
|
setTimeout(() => setCopied(false), 2000)
|
|
25
27
|
}, [props.content])
|
|
26
28
|
|
|
27
|
-
const
|
|
28
|
-
(url
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
[props.content],
|
|
33
|
-
)
|
|
29
|
+
const openIn = (base: string, extra?: Record<string, string>) => {
|
|
30
|
+
const q = LLM_PROMPT.replace("{url}", window.location.href)
|
|
31
|
+
const params = new URLSearchParams({ ...extra, q })
|
|
32
|
+
window.open(`${base}?${params}`, "_blank", "noopener,noreferrer")
|
|
33
|
+
}
|
|
34
34
|
|
|
35
35
|
const buttonClass =
|
|
36
36
|
"flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
@@ -68,7 +68,7 @@ export function PageToolbar(props: {
|
|
|
68
68
|
</button>
|
|
69
69
|
<button
|
|
70
70
|
type="button"
|
|
71
|
-
onClick={() =>
|
|
71
|
+
onClick={() => openIn("https://chatgpt.com/", { hints: "search" })}
|
|
72
72
|
className={buttonClass}
|
|
73
73
|
>
|
|
74
74
|
<ExternalLink className="size-3.5" />
|
|
@@ -76,7 +76,7 @@ export function PageToolbar(props: {
|
|
|
76
76
|
</button>
|
|
77
77
|
<button
|
|
78
78
|
type="button"
|
|
79
|
-
onClick={() =>
|
|
79
|
+
onClick={() => openIn("https://claude.ai/new")}
|
|
80
80
|
className={buttonClass}
|
|
81
81
|
>
|
|
82
82
|
<ExternalLink className="size-3.5" />
|