Skip to content

Commit 6eee201

Browse files
committed
feat: add copy readme to markdown button
1 parent 0887a8a commit 6eee201

7 files changed

Lines changed: 42 additions & 9 deletions

File tree

app/pages/package/[[org]]/[name].vue

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,15 @@ const { data: readmeData } = useLazyFetch<ReadmeResponse>(
6262
const version = requestedVersion.value
6363
return version ? `${base}/v/${version}` : base
6464
},
65-
{ default: () => ({ html: '', playgroundLinks: [], toc: [] }) },
65+
{ default: () => ({ html: '', markdown: '', playgroundLinks: [], toc: [] }) },
6666
)
6767
68+
const readmeMarkdown = computed(() => readmeData.value?.markdown ?? '')
69+
const { copied: copiedMarkdown, copy: copyMarkdown } = useClipboard({
70+
source: readmeMarkdown,
71+
copiedDuring: 2000,
72+
})
73+
6874
// Track active TOC item based on scroll position
6975
const tocItems = computed(() => readmeData.value?.toc ?? [])
7076
const { activeId: activeTocId, scrollToHeading } = useActiveTocItem(tocItems)
@@ -1136,12 +1142,33 @@ onKeyStroke(
11361142
</a>
11371143
</h2>
11381144
<ClientOnly>
1139-
<ReadmeTocDropdown
1140-
v-if="readmeData?.toc && readmeData.toc.length > 1"
1141-
:toc="readmeData.toc"
1142-
:active-id="activeTocId"
1143-
:scroll-to-heading="scrollToHeading"
1144-
/>
1145+
<div class="flex items-center gap-2">
1146+
<button
1147+
v-if="readmeData?.markdown"
1148+
type="button"
1149+
class="flex items-center h-8 gap-1.5 px-2 py-2 font-mono text-xs bg-bg-subtle border border-border-subtle border-solid rounded-md transition-colors duration-150 hover:(text-fg border-border-hover) active:scale-95 focus:border-border-hover focus-visible:outline-accent/70 hover:text-fg"
1150+
:class="copiedMarkdown ? 'text-fg' : 'text-fg-muted'"
1151+
:aria-label="
1152+
copiedMarkdown ? $t('common.copied') : $t('package.readme.copy_markdown')
1153+
"
1154+
@click="copyMarkdown()"
1155+
>
1156+
<span
1157+
class="w-3.5 h-3.5"
1158+
:class="copiedMarkdown ? 'i-carbon:checkmark text-accent' : 'i-carbon:document'"
1159+
aria-hidden="true"
1160+
/>
1161+
<span aria-live="polite">{{
1162+
copiedMarkdown ? $t('common.copied') : $t('package.readme.copy_markdown')
1163+
}}</span>
1164+
</button>
1165+
<ReadmeTocDropdown
1166+
v-if="readmeData?.toc && readmeData.toc.length > 1"
1167+
:toc="readmeData.toc"
1168+
:active-id="activeTocId"
1169+
:scroll-to-heading="scrollToHeading"
1170+
/>
1171+
</div>
11451172
</ClientOnly>
11461173
</div>
11471174

i18n/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@
215215
"no_readme": "No README available.",
216216
"view_on_github": "View on GitHub",
217217
"toc_title": "Outline",
218+
"copy_markdown": "Copy markdown",
218219
"callout": {
219220
"note": "Note",
220221
"tip": "Tip",

lunaria/files/en-GB.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@
215215
"no_readme": "No README available.",
216216
"view_on_github": "View on GitHub",
217217
"toc_title": "Outline",
218+
"copy_markdown": "Copy markdown",
218219
"callout": {
219220
"note": "Note",
220221
"tip": "Tip",

lunaria/files/en-US.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@
215215
"no_readme": "No README available.",
216216
"view_on_github": "View on GitHub",
217217
"toc_title": "Outline",
218+
"copy_markdown": "Copy markdown",
218219
"callout": {
219220
"note": "Note",
220221
"tip": "Tip",

server/api/registry/readme/[...pkg].get.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export default defineCachedEventHandler(
107107
}
108108

109109
if (!readmeContent || readmeContent === NPM_MISSING_README_SENTINEL) {
110-
return { html: '', playgroundLinks: [], toc: [] }
110+
return { html: '', markdown: '', playgroundLinks: [], toc: [] }
111111
}
112112

113113
// Parse repository info for resolving relative URLs to GitHub

server/utils/readme.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ export async function renderReadmeHtml(
277277
packageName: string,
278278
repoInfo?: RepositoryInfo,
279279
): Promise<ReadmeResponse> {
280-
if (!content) return { html: '', playgroundLinks: [], toc: [] }
280+
if (!content) return { html: '', markdown: '', playgroundLinks: [], toc: [] }
281281

282282
const shiki = await getShikiHighlighter()
283283
const renderer = new marked.Renderer()
@@ -455,6 +455,7 @@ ${html}
455455

456456
return {
457457
html: convertToEmoji(sanitized),
458+
markdown: content,
458459
playgroundLinks: collectedLinks,
459460
toc,
460461
}

shared/types/readme.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export interface TocItem {
3030
export interface ReadmeResponse {
3131
/** Rendered HTML content */
3232
html: string
33+
/** Raw markdown content */
34+
markdown: string
3335
/** Extracted playground/demo links */
3436
playgroundLinks: PlaygroundLink[]
3537
/** Table of contents extracted from headings */

0 commit comments

Comments
 (0)