put the code copy button into the markdown processor
This commit is contained in:
parent
7f75bba052
commit
b9accda035
20 changed files with 176 additions and 211 deletions
2
.pnp.cjs
generated
2
.pnp.cjs
generated
|
|
@ -50,6 +50,7 @@ const RAW_RUNTIME_STATE =
|
|||
["astro-breadcrumbs", "virtual:a9b1222052dffa20c83605ac26b64fd717aa2982dc89da74b78301a8333c50a120c12db3f68c240302341b52215e986347cefceb71633b5918936083bd9430ce#npm:3.3.1"],\
|
||||
["astro-icon", "npm:1.1.5"],\
|
||||
["hast-util-from-html", "npm:2.0.3"],\
|
||||
["hastscript", "npm:9.0.1"],\
|
||||
["jsonc-parser", "npm:3.3.1"],\
|
||||
["pagefind", "npm:1.4.0"],\
|
||||
["quickshell-docs", "workspace:."],\
|
||||
|
|
@ -6380,6 +6381,7 @@ const RAW_RUNTIME_STATE =
|
|||
["astro-breadcrumbs", "virtual:a9b1222052dffa20c83605ac26b64fd717aa2982dc89da74b78301a8333c50a120c12db3f68c240302341b52215e986347cefceb71633b5918936083bd9430ce#npm:3.3.1"],\
|
||||
["astro-icon", "npm:1.1.5"],\
|
||||
["hast-util-from-html", "npm:2.0.3"],\
|
||||
["hastscript", "npm:9.0.1"],\
|
||||
["jsonc-parser", "npm:3.3.1"],\
|
||||
["pagefind", "npm:1.4.0"],\
|
||||
["quickshell-docs", "workspace:."],\
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
"astro-breadcrumbs": "^3.3.1",
|
||||
"astro-icon": "^1.1.5",
|
||||
"hast-util-from-html": "^2.0.3",
|
||||
"hastscript": "^9.0.1",
|
||||
"rehype": "^13.0.2",
|
||||
"remark-github-blockquote-alert": "^2.0.0",
|
||||
"solid-js": "^1.9.10",
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -3,51 +3,34 @@
|
|||
---
|
||||
|
||||
<script>
|
||||
setTimeout(() => {
|
||||
// code copy
|
||||
let blocks = document.querySelectorAll("pre");
|
||||
if (blocks.length > 0) {
|
||||
blocks.forEach((block) => {
|
||||
let button = document.createElement("button");
|
||||
button.className = "copy-button";
|
||||
button.innerHTML = `<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 256 256"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M200 32h-36.26a47.92 47.92 0 0 0-71.48 0H56a16 16 0 0 0-16 16v168a16 16 0 0 0 16 16h144a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16m-72 0a32 32 0 0 1 32 32H96a32 32 0 0 1 32-32m72 184H56V48h26.75A47.9 47.9 0 0 0 80 64v8a8 8 0 0 0 8 8h80a8 8 0 0 0 8-8v-8a47.9 47.9 0 0 0-2.75-16H200Z"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
button.onclick = () => {
|
||||
let snippet = block.innerText ?? "";
|
||||
navigator.clipboard.writeText(snippet);
|
||||
button.classList.toggle("copied");
|
||||
setTimeout(() => button.classList.remove("copied"), 1000);
|
||||
};
|
||||
block.appendChild(button);
|
||||
});
|
||||
}
|
||||
}, 3001)
|
||||
// setTimeout(() => {
|
||||
// // code copy
|
||||
// let blocks = document.querySelectorAll("pre");
|
||||
// if (blocks.length > 0) {
|
||||
// blocks.forEach((block) => {
|
||||
// let button = document.createElement("button");
|
||||
// button.className = "copy-button";
|
||||
// button.innerHTML = `<svg
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// width="1em"
|
||||
// height="1em"
|
||||
// viewBox="0 0 256 256"
|
||||
// >
|
||||
// <path
|
||||
// fill="currentColor"
|
||||
// d="M200 32h-36.26a47.92 47.92 0 0 0-71.48 0H56a16 16 0 0 0-16 16v168a16 16 0 0 0 16 16h144a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16m-72 0a32 32 0 0 1 32 32H96a32 32 0 0 1 32-32m72 184H56V48h26.75A47.9 47.9 0 0 0 80 64v8a8 8 0 0 0 8 8h80a8 8 0 0 0 8-8v-8a47.9 47.9 0 0 0-2.75-16H200Z"
|
||||
// />
|
||||
// </svg>
|
||||
// `;
|
||||
// button.onclick = () => {
|
||||
// let snippet = block.innerText ?? "";
|
||||
// navigator.clipboard.writeText(snippet);
|
||||
// button.classList.toggle("copied");
|
||||
// setTimeout(() => button.classList.remove("copied"), 1000);
|
||||
// };
|
||||
// block.appendChild(button);
|
||||
// });
|
||||
// }
|
||||
// }, 3001)
|
||||
|
||||
// heading copy
|
||||
let headings = document.getElementsByClassName("heading")
|
||||
if (headings.length > 0) {
|
||||
for (const heading of headings) {
|
||||
let button = heading.querySelector("span")
|
||||
if (button) {
|
||||
button.onclick = () => {
|
||||
let link = window.location.href.split("#")[0];
|
||||
link += `#-${heading.textContent?.slice(10).trimEnd().replaceAll(" ", "-").toLowerCase()}`;
|
||||
window.location.href = link
|
||||
navigator.clipboard.writeText(link);
|
||||
heading.classList.toggle("copied")
|
||||
setTimeout(() => heading.classList.remove("copied"), 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -2,38 +2,38 @@
|
|||
import { Icon } from "astro-icon/components";
|
||||
|
||||
const videos = [
|
||||
{
|
||||
author: '<a href="https://github.com/soramanew">soramane</a>',
|
||||
source: "https://github.com/caelestia-dots/shell",
|
||||
path: "/assets/showcase/soramane.mp4",
|
||||
installable: true,
|
||||
},
|
||||
{
|
||||
author: '<a href="https://github.com/end-4">end_4</a>',
|
||||
source: "https://github.com/end-4/dots-hyprland",
|
||||
path: "/assets/showcase/end4.mp4",
|
||||
installable: true,
|
||||
},
|
||||
{
|
||||
author: '<a href="https://outfoxxed.me">outfoxxed</a>',
|
||||
source:
|
||||
"https://git.outfoxxed.me/outfoxxed/nixnew/src/branch/master/modules/user/modules/quickshell",
|
||||
path: "/assets/showcase/outfoxxed.mp4",
|
||||
},
|
||||
{
|
||||
author:
|
||||
'<a href="https://github.com/pfaj/">pfaj</a> and <a href="https://github.com/bdebiase">bdebiase</a>',
|
||||
path: "/assets/showcase/pfaj-bdeblase.mp4",
|
||||
},
|
||||
{
|
||||
author: '<a href="https://github.com/flickowoa">flicko</a>',
|
||||
source: "https://github.com/flickowoa/zephyr",
|
||||
path: "/assets/showcase/flicko.mp4",
|
||||
},
|
||||
{
|
||||
author: '<a href="https://vaxry.net">vaxry</a>',
|
||||
path: "/assets/showcase/vaxry.mp4",
|
||||
},
|
||||
{
|
||||
author: '<a href="https://github.com/soramanew">soramane</a>',
|
||||
source: "https://github.com/caelestia-dots/shell",
|
||||
path: "/assets/showcase/soramane.mp4",
|
||||
installable: true,
|
||||
},
|
||||
{
|
||||
author: '<a href="https://github.com/end-4">end_4</a>',
|
||||
source: "https://github.com/end-4/dots-hyprland",
|
||||
path: "/assets/showcase/end4.mp4",
|
||||
installable: true,
|
||||
},
|
||||
{
|
||||
author: '<a href="https://outfoxxed.me">outfoxxed</a>',
|
||||
source:
|
||||
"https://git.outfoxxed.me/outfoxxed/nixnew/src/branch/master/modules/user/modules/quickshell",
|
||||
path: "/assets/showcase/outfoxxed.mp4",
|
||||
},
|
||||
{
|
||||
author:
|
||||
'<a href="https://github.com/pfaj/">pfaj</a> and <a href="https://github.com/bdebiase">bdebiase</a>',
|
||||
path: "/assets/showcase/pfaj-bdeblase.mp4",
|
||||
},
|
||||
{
|
||||
author: '<a href="https://github.com/flickowoa">flicko</a>',
|
||||
source: "https://github.com/flickowoa/zephyr",
|
||||
path: "/assets/showcase/flicko.mp4",
|
||||
},
|
||||
{
|
||||
author: '<a href="https://vaxry.net">vaxry</a>',
|
||||
path: "/assets/showcase/vaxry.mp4",
|
||||
},
|
||||
];
|
||||
---
|
||||
<div class="marquee">
|
||||
|
|
|
|||
9
src/config/_types/codeblock.ts
Normal file
9
src/config/_types/codeblock.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
interface CopyButtonOptions {
|
||||
duration?: number;
|
||||
copyIcon?: string;
|
||||
successIcon?: string;
|
||||
display?: "hover" | "ready";
|
||||
cssVariables?: string;
|
||||
}
|
||||
|
||||
export type { CopyButtonOptions };
|
||||
|
|
@ -13,6 +13,7 @@ import type {
|
|||
VersionsData,
|
||||
} from "./module";
|
||||
import type { SearchLists } from "./search";
|
||||
import type { CopyButtonOptions } from "./codeblock";
|
||||
|
||||
export type {
|
||||
QMLTypeLinkObject,
|
||||
|
|
@ -28,4 +29,5 @@ export type {
|
|||
VersionData,
|
||||
VersionsData,
|
||||
SearchLists,
|
||||
CopyButtonOptions,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@ import { remarkAlert } from "remark-github-blockquote-alert";
|
|||
import rehypeShiki from "@shikijs/rehype";
|
||||
import sectionize from "@hbsnow/rehype-sectionize";
|
||||
import type { ShikiTransformer } from "shiki";
|
||||
import { h } from "hastscript";
|
||||
|
||||
import {
|
||||
getQMLTypeLinkObject,
|
||||
getQMLTypeLink,
|
||||
getIconForLink,
|
||||
} from "./helpers.ts";
|
||||
import type { CopyButtonOptions } from "@_types";
|
||||
|
||||
let currentVersion = "NOVERSION";
|
||||
|
||||
|
|
@ -155,7 +157,54 @@ const shikiRewriteTypelinks: ShikiTransformer = {
|
|||
},
|
||||
};
|
||||
|
||||
export const markdownConfig: AstroMarkdownOptions = {
|
||||
const shikiCopyButton: ShikiTransformer = {
|
||||
name: "copy-button",
|
||||
pre(node) {
|
||||
const options: CopyButtonOptions = {
|
||||
duration: 3000,
|
||||
};
|
||||
const button = h(
|
||||
"button",
|
||||
{
|
||||
class: "copy-button",
|
||||
role: "button",
|
||||
"aria-label": "Copy to clipboard",
|
||||
"alia-live": "polite",
|
||||
// "data-code": removeCodeAnnotations(this.source),
|
||||
onclick: `
|
||||
navigator.clipboard.writeText(this.dataset.code);
|
||||
this.classList.add('copied');
|
||||
this.setAttribute('aria-pressed', 'true');
|
||||
setTimeout(() => { this.classList.remove('copied'); this.setAttribute('aria-pressed', 'false');}, ${options.duration})
|
||||
`,
|
||||
},
|
||||
[
|
||||
h("span", { class: "ready" }),
|
||||
h("span", { class: "success" }),
|
||||
h(
|
||||
"svg",
|
||||
{
|
||||
class: "copy-icon",
|
||||
role: "icon",
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
width: "1em",
|
||||
height: "1em",
|
||||
viewBox: "0 0 256 256",
|
||||
},
|
||||
[
|
||||
h("path", {
|
||||
fill: "currentColor",
|
||||
d: "M200 32h-36.26a47.92 47.92 0 0 0-71.48 0H56a16 16 0 0 0-16 16v168a16 16 0 0 0 16 16h144a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16m-72 0a32 32 0 0 1 32 32H96a32 32 0 0 1 32-32m72 184H56V48h26.75A47.9 47.9 0 0 0 80 64v8a8 8 0 0 0 8 8h80a8 8 0 0 0 8-8v-8a47.9 47.9 0 0 0-2.75-16H200Z",
|
||||
}),
|
||||
]
|
||||
),
|
||||
]
|
||||
);
|
||||
node.children.splice(0, 0, button);
|
||||
},
|
||||
};
|
||||
|
||||
const markdownConfig: AstroMarkdownOptions = {
|
||||
syntaxHighlight: false,
|
||||
remarkPlugins: [
|
||||
remarkParseAtTypes,
|
||||
|
|
@ -182,7 +231,7 @@ export const markdownConfig: AstroMarkdownOptions = {
|
|||
},
|
||||
defaultColor: false,
|
||||
wrap: true,
|
||||
transformers: [shikiRewriteTypelinks],
|
||||
transformers: [shikiRewriteTypelinks, shikiCopyButton],
|
||||
},
|
||||
],
|
||||
// FIXME: incompatible types between unified/Plugin and Astro/RehypePlugin
|
||||
|
|
@ -206,7 +255,7 @@ async function getMarkdownProcessor(): Promise<MarkdownProcessor> {
|
|||
return globalMarkdownProcessor;
|
||||
}
|
||||
|
||||
export async function processMarkdown(
|
||||
async function processMarkdown(
|
||||
version: string,
|
||||
markdown: string
|
||||
): Promise<string> {
|
||||
|
|
@ -217,3 +266,5 @@ export async function processMarkdown(
|
|||
currentVersion = "NOVERSION";
|
||||
return r;
|
||||
}
|
||||
|
||||
export { markdownConfig, processMarkdown };
|
||||
|
|
|
|||
120
src/config/io/types.d.ts
vendored
120
src/config/io/types.d.ts
vendored
|
|
@ -1,120 +0,0 @@
|
|||
//# FIXME: fuseConfig.ts
|
||||
// --
|
||||
|
||||
// generateSearchLists.ts
|
||||
interface SearchLists {
|
||||
slug: string;
|
||||
link: string;
|
||||
summary: string;
|
||||
}
|
||||
// --
|
||||
|
||||
// generateTypeData.ts
|
||||
interface QuickshellBase {
|
||||
type: string;
|
||||
module: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface QuickshellInstance {
|
||||
name?: string;
|
||||
type: {
|
||||
gadget?: QuickshellGadget;
|
||||
type: string;
|
||||
module: string;
|
||||
name: string;
|
||||
of?: QuickshellBase;
|
||||
};
|
||||
details?: string;
|
||||
flags?: string[];
|
||||
}
|
||||
|
||||
interface QuickshellGadget {
|
||||
[key: string]: QuickshellInstance;
|
||||
}
|
||||
|
||||
interface QuickshellProps {
|
||||
[key: string]: QuickshellInstance;
|
||||
}
|
||||
|
||||
interface QuickshellFunction {
|
||||
ret: QuickshellInstance;
|
||||
name: string;
|
||||
id: string;
|
||||
details: string;
|
||||
params: QuickshellInstance[];
|
||||
}
|
||||
|
||||
interface QuickshellSignal {
|
||||
[key: string]: {
|
||||
name: string;
|
||||
details: string;
|
||||
params: QuickshellInstance[];
|
||||
};
|
||||
}
|
||||
|
||||
interface QuickshellVariant {
|
||||
[key: string]: {
|
||||
name?: string;
|
||||
details: string;
|
||||
params?: QuickshellInstance[];
|
||||
};
|
||||
}
|
||||
|
||||
interface TypeData {
|
||||
name: string;
|
||||
description: string;
|
||||
details: string;
|
||||
flags?: string[];
|
||||
contains?: string[];
|
||||
super?: QuickshellBase;
|
||||
properties?: QuickshellProps;
|
||||
functions?: QuickshellFunction[];
|
||||
signals?: QuickshellSignal;
|
||||
variants?: QuickshellVariant;
|
||||
subtypes?: QuickshellData[];
|
||||
}
|
||||
|
||||
interface ModuleData {
|
||||
name: string;
|
||||
description: string;
|
||||
details: string;
|
||||
types: TypeData[];
|
||||
}
|
||||
|
||||
interface VersionData {
|
||||
name: string;
|
||||
changelog?: string;
|
||||
modules: ModuleData[];
|
||||
}
|
||||
|
||||
interface VersionsData {
|
||||
default: string;
|
||||
versions: VersionData[];
|
||||
}
|
||||
// --
|
||||
|
||||
// helpers.ts
|
||||
interface QMLTypeLinkObject {
|
||||
type: string;
|
||||
module?: string;
|
||||
name?: string;
|
||||
mtype?: string;
|
||||
mname?: string;
|
||||
}
|
||||
// --
|
||||
|
||||
export type {
|
||||
QuickshellBase,
|
||||
QuickshellInstance,
|
||||
QuickshellGadget,
|
||||
QuickshellProps,
|
||||
QuickshellFunction,
|
||||
QuickshellSignal,
|
||||
QuickshellVariant,
|
||||
TypeData,
|
||||
ModuleData,
|
||||
VersionData,
|
||||
VersionsData,
|
||||
QMLTypeLinkObject,
|
||||
};
|
||||
|
|
@ -21,3 +21,4 @@ const { title, description } = Astro.props;
|
|||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,16 +15,18 @@ interface Props {
|
|||
title: string;
|
||||
description: string;
|
||||
headings?: ConfigHeading[];
|
||||
type?: TypeData
|
||||
type?: TypeData;
|
||||
}
|
||||
|
||||
const { title, description, headings, type } = Astro.props;
|
||||
let url = Astro.url.pathname.split("/").filter(s => s !== "");
|
||||
|
||||
const breadcrumbs = [{
|
||||
text: "custom",
|
||||
href: "/",
|
||||
}];
|
||||
const breadcrumbs = [
|
||||
{
|
||||
text: "custom",
|
||||
href: "/",
|
||||
},
|
||||
];
|
||||
|
||||
let linkPath = "";
|
||||
if (url[0] === "docs") {
|
||||
|
|
@ -90,4 +92,33 @@ for (const segment of url) {
|
|||
<Footer/>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script>
|
||||
// FIXME: need to make this work properly, or fold into the markdown processor
|
||||
let headings = document.getElementsByClassName("heading")
|
||||
if (headings.length > 0) {
|
||||
for (const heading of headings) {
|
||||
let button = heading.querySelector("h2")
|
||||
if (button) {
|
||||
button.onclick = () => {
|
||||
let link = window.location.href.split("#")[0];
|
||||
link += `#${button.textContent?.trimEnd().replaceAll(" ", "-").toLowerCase()}`;
|
||||
window.location.href = link
|
||||
navigator.clipboard.writeText(link);
|
||||
heading.classList.toggle("copied")
|
||||
setTimeout(() => heading.classList.remove("copied"), 1000);
|
||||
}
|
||||
}
|
||||
let spanButton = heading.querySelector("span")
|
||||
if (spanButton) {
|
||||
spanButton.onclick = () => {
|
||||
let link = window.location.href.split("#")[0];
|
||||
link += `#${spanButton.textContent?.trim().replaceAll(" ", "-").toLowerCase()}`;
|
||||
window.location.href = link
|
||||
navigator.clipboard.writeText(link);
|
||||
spanButton.classList.toggle("copied")
|
||||
setTimeout(() => heading.classList.remove("copied"), 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@ export interface Props {
|
|||
frontmatter: {
|
||||
title: string;
|
||||
description?: string;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const { headings, frontmatter: { title, description } } = Astro.props;
|
||||
const {
|
||||
headings,
|
||||
frontmatter: { title, description },
|
||||
} = Astro.props;
|
||||
---
|
||||
<GuideLayout title={title} description={description ?? ""} headings={headings}>
|
||||
<slot/>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pre {
|
|||
overflow: hidden;
|
||||
text-wrap: wrap;
|
||||
|
||||
& > button {
|
||||
& .copy-button {
|
||||
all: unset;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
|
|
@ -45,6 +45,7 @@ pre {
|
|||
background-color: hsl(var(--blue) 85% 35% / 0.1);
|
||||
cursor: pointer;
|
||||
transition: color 0.25s;
|
||||
z-index: 10;
|
||||
|
||||
&:hover {
|
||||
color: hsl(var(--blue) 100% 75%);
|
||||
|
|
|
|||
|
|
@ -3736,7 +3736,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hastscript@npm:^9.0.0":
|
||||
"hastscript@npm:^9.0.0, hastscript@npm:^9.0.1":
|
||||
version: 9.0.1
|
||||
resolution: "hastscript@npm:9.0.1"
|
||||
dependencies:
|
||||
|
|
@ -5557,6 +5557,7 @@ __metadata:
|
|||
astro-breadcrumbs: "npm:^3.3.1"
|
||||
astro-icon: "npm:^1.1.5"
|
||||
hast-util-from-html: "npm:^2.0.3"
|
||||
hastscript: "npm:^9.0.1"
|
||||
jsonc-parser: "npm:^3.3.1"
|
||||
pagefind: "npm:^1.4.0"
|
||||
rehype: "npm:^13.0.2"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue