Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions i18n/en/code.json
Original file line number Diff line number Diff line change
Expand Up @@ -780,5 +780,29 @@
"Enterprise Features & Licensing": {
"message": "Enterprise Features & Licensing",
"description": "Enterprise Features & Licensing"
},
"Copy Page": {
"message": "Copy Page",
"description": "Copy Page"
},
"Copy page as Markdown for LLMs": {
"message": "Copy page as Markdown for LLMs",
"description": "Copy page as Markdown for LLMs"
},
"View as Markdown": {
"message": "View as Markdown",
"description": "View as Markdown"
},
"View this page as plain text": {
"message": "View this page as plain text",
"description": "View this page as plain text"
},
"Failed to copy markdown": {
"message": "Failed to copy markdown",
"description": "Failed to copy markdown"
},
"Copying...": {
"message": "Copying...",
"description": "Copying..."
}
}
24 changes: 24 additions & 0 deletions i18n/zh/code.json
Original file line number Diff line number Diff line change
Expand Up @@ -804,5 +804,29 @@
"Enterprise Features & Licensing": {
"message": "企业功能与许可",
"description": "Enterprise Features & Licensing"
},
"Copy Page": {
"message": "复制页面",
"description": "Copy Page"
},
"Copy page as Markdown for LLMs": {
"message": "复制为 Markdown 格式,供大语言模型使用",
"description": "Copy page as Markdown for LLMs"
},
"View as Markdown": {
"message": "查看 Markdown 格式",
"description": "View as Markdown"
},
"View this page as plain text": {
"message": "查看纯文本",
"description": "View this page as plain text"
},
"Failed to copy markdown": {
"message": "无法复制 Markdown",
"description": "Failed to copy markdown"
},
"Copying...": {
"message": "正在复制...",
"description": "Copying..."
}
}
117 changes: 117 additions & 0 deletions src/components/CopyPageButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useState, useMemo, useCallback } from "react";
import { Button, Dropdown, Flex, Spin } from "antd";
import styles from "./styles.module.scss";
import DownArrow from "@site/static/icons/down.svg";
import MarkdownSvg from "@site/static/icons/markdown.svg";
import CopySvg from "@site/static/icons/copy.svg";
import CopiedSvg from "@site/static/icons/copied.svg";
import { useDoc } from "@docusaurus/plugin-content-docs/client";
import axios from "axios";
import $t from "@site/src/utils/tools";
// mark
// import TurndownService from "turndown";
// const turndownService = new TurndownService();
// const getPageContentAsHtml = (): string | null => {
// const contentElement = document.querySelector("article");
// return contentElement ? contentElement.innerHTML : null;
// };

// const convertHtmlToMarkdown = (html: string): string => {
// return turndownService.turndown(html);
// };
const CopyDropdownButton: React.FC = () => {
const [loading, setLoading] = useState(false);
const [isCopied, setIsCopied] = useState(false);
const { metadata } = useDoc();
const sourceUrl = useMemo(() => {
return (
metadata?.source?.replace(
"@site",
"https://raw.githubusercontent.com/databendlabs/databend-docs/refs/heads/main"
) || ""
);
}, [metadata]);
const handleCopy = useCallback((url: string) => {
if (!url) return;
setLoading(true);
axios
.get(url)
.then((response) => {
setIsCopied(true);
if (response.status === 200) {
navigator.clipboard.writeText(response.data);
} else {
alert($t("Failed to copy markdown"));
}
})
.finally(() => {
setLoading(false);
setTimeout(() => {
setIsCopied(false);
}, 3000);
});
}, []);
const menu = useMemo(() => {
const items = [
{
key: "copy",
icon: <CopySvg width={16} />,
label: $t("Copy Page"),
description: $t("Copy page as Markdown for LLMs"),
},
{
key: "markdown",
icon: <MarkdownSvg width={18} />,
label: $t("View as Markdown"),
description: $t("View this page as plain text"),
},
];

return {
items: items.map(({ key, icon, label, description }) => ({
key,
label: (
<div>
<div style={{ fontWeight: 500 }}>{label}</div>
<div style={{ fontSize: 12, color: "#888" }}>{description}</div>
</div>
),
icon: <Button icon={icon} />,
})),
onClick: ({ key }: { key: string }) => {
if (key === "copy") handleCopy(sourceUrl);
if (key === "markdown") window.open(sourceUrl, "_blank");
},
};
}, [sourceUrl, handleCopy]);
const renderButtonContent = useMemo(
() => (
<Flex align="center" gap={6}>
{loading ? (
<Spin size="small" />
) : isCopied ? (
<CopiedSvg width={16} />
) : (
<CopySvg width={16} />
)}
<span>{loading ? $t("Copying...") : $t("Copy Page")}</span>
</Flex>
),
[loading, isCopied]
);

return (
<Dropdown.Button
onClick={() => handleCopy(sourceUrl)}
menu={menu}
placement="bottomRight"
icon={<DownArrow width={18} height={"auto"} />}
className={styles.buttonCainter}
trigger={["click"]}
>
{renderButtonContent}
</Dropdown.Button>
);
};

export default CopyDropdownButton;
18 changes: 18 additions & 0 deletions src/components/CopyPageButton/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.buttonCainter {
max-width: 140px;
button {
font-weight: 500;
border: 1px solid var(--color-border) !important;
background-color: var(--color-bg-1) !important;
color: var(--color-text-0) !important;
&:hover {
background-color: var(--color-fill-1) !important;
}
&:last-child {
svg {
position: relative;
top: 2px;
}
}
}
}
1 change: 0 additions & 1 deletion src/css/markdown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@
&:hover {
background-color: var(--bg-hover-copy);
opacity: 1;
color: #fff !important;
}
}
.theme-code-block:hover {
Expand Down
48 changes: 48 additions & 0 deletions src/theme/DocItem/Content/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { type ReactNode } from "react";
import clsx from "clsx";
import { ThemeClassNames } from "@docusaurus/theme-common";
import { useDoc } from "@docusaurus/plugin-content-docs/client";
import Heading from "@theme/Heading";
import MDXContent from "@theme/MDXContent";
import type { Props } from "@theme/DocItem/Content";
import styles from "./styles.module.css";
import CopyPageButton from "@site/src/components/CopyPageButton";

/**
Title can be declared inside md content or declared through
front matter and added manually. To make both cases consistent,
the added title is added under the same div.markdown block
See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120

We render a "synthetic title" if:
- user doesn't ask to hide it with front matter
- the markdown content does not already contain a top-level h1 heading
*/
function useSyntheticTitle(): string | null {
const { metadata, frontMatter, contentTitle } = useDoc();
const shouldRender =
!frontMatter.hide_title && typeof contentTitle === "undefined";
if (!shouldRender) {
return null;
}
return metadata.title;
}

export default function DocItemContent({ children }: Props): ReactNode {
const syntheticTitle = useSyntheticTitle();
return (
<div className={clsx(ThemeClassNames.docs.docMarkdown, "markdown")}>
<section className={styles.headerSection}>
{syntheticTitle ? (
<header>
<Heading as="h1">{syntheticTitle}</Heading>
</header>
) : (
<i />
)}
<CopyPageButton />
</section>
<MDXContent>{children}</MDXContent>
</div>
);
}
15 changes: 15 additions & 0 deletions src/theme/DocItem/Content/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.headerSection {
display: flex;
justify-content: space-between;
align-items: "flex-start";
width: 100%;
padding-right: 12px;
}

@media (max-width: 900px) {
.headerSection {
flex-direction: column-reverse;
align-items: flex-start;
justify-conten: flex-start;
}
}
1 change: 0 additions & 1 deletion src/theme/DocRoot/Layout/Main/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
display: flex;
width: 100%;
}

@media (min-width: 997px) {
.docMainContainer {
flex-grow: 1;
Expand Down
1 change: 1 addition & 0 deletions static/icons/copied.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions static/icons/copy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions static/icons/down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions static/icons/markdown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading