-
-
Notifications
You must be signed in to change notification settings - Fork 424
feat: generate package docs using @deno/doc
#135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
danielroe
merged 25 commits into
npmx-dev:main
from
devdumpling:dwells-feat-docs-wasm-attempt
Jan 27, 2026
Merged
Changes from 14 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
92ddf1e
feat: prototyping phase for doc gen
devdumpling d87bfcd
cleanup old prototype
devdumpling 3d1221d
fix: polish and cleanup post prototype
devdumpling 5830860
version selector
devdumpling 582fd36
test: add basic e2e and unit tests
devdumpling 6aaf681
fix: some validation issues with markdown rendering and parsing
devdumpling 24017c0
chore: some planning, remove old typedoc ref
devdumpling 6d7a091
fix: type issue with DocsResponse default status
devdumpling c714835
fix: align code link and prefer package docs URL
devdumpling 791dc8f
feat-docs-wasm-attempt
devdumpling ff78f69
fix: use rollupConfig and externals for deno doc module resolution
devdumpling 759dbfc
fix: fence code block regex handles ansi, edge cases, shiki highlight…
devdumpling 6e3cdfc
[autofix.ci] apply automated fixes
autofix-ci[bot] b78ddf0
fix: add translation keys for docs and socket nav links
devdumpling e277a2d
fix: update manifest with upstream
devdumpling ba0ec18
fix: docs link and homepage coexist
devdumpling c06b1b2
chore: move docs api version back to v1 for caching
devdumpling 0299f87
fix: handle invalid urls and errors generating docs
danielroe 58dbc53
fix: some a11y issues
danielroe 11bcd36
Merge origin/main into dwells-feat-docs-wasm-attempt
danielroe 48887f1
Merge remote-tracking branch 'origin/main' into dwells-feat-docs-wasm…
danielroe ed424e1
Merge remote-tracking branch 'origin/main' into dwells-feat-docs-wasm…
danielroe d7aacaa
fix: remove socket link that was incorrectly re-added during merge
danielroe 458ba1a
refactor: extract highlightCodeSync for shared code highlighting
danielroe 722b3bd
chore: remove reexport
danielroe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| @jsr:registry=https://npm.jsr.io |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| <script setup lang="ts"> | ||
| import { onClickOutside } from '@vueuse/core' | ||
| import { compareVersions } from '~/utils/versions' | ||
|
|
||
| const props = defineProps<{ | ||
| packageName: string | ||
| currentVersion: string | ||
| versions: Record<string, unknown> | ||
| distTags: Record<string, string> | ||
| }>() | ||
|
|
||
| const isOpen = ref(false) | ||
| const dropdownRef = ref<HTMLElement>() | ||
|
|
||
| onClickOutside(dropdownRef, () => { | ||
| isOpen.value = false | ||
| }) | ||
|
|
||
| /** Maximum number of versions to show in dropdown */ | ||
| const MAX_VERSIONS = 10 | ||
|
|
||
| /** Get sorted list of recent versions with their tags */ | ||
| const recentVersions = computed(() => { | ||
| const versionList = Object.keys(props.versions) | ||
| .sort((a, b) => compareVersions(b, a)) | ||
| .slice(0, MAX_VERSIONS) | ||
|
|
||
| // Create a map of version -> tags | ||
| const versionTags = new Map<string, string[]>() | ||
| for (const [tag, version] of Object.entries(props.distTags)) { | ||
| const existing = versionTags.get(version) | ||
| if (existing) { | ||
| existing.push(tag) | ||
| } else { | ||
| versionTags.set(version, [tag]) | ||
| } | ||
| } | ||
|
|
||
| return versionList.map(version => ({ | ||
| version, | ||
| tags: versionTags.get(version) ?? [], | ||
| isCurrent: version === props.currentVersion, | ||
| })) | ||
| }) | ||
|
|
||
| const latestVersion = computed(() => props.distTags.latest) | ||
|
|
||
| function getDocsUrl(version: string): string { | ||
| return `/docs/${props.packageName}/v/${version}` | ||
| } | ||
|
|
||
| function handleKeydown(event: KeyboardEvent) { | ||
| if (event.key === 'Escape') { | ||
| isOpen.value = false | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <template> | ||
| <div ref="dropdownRef" class="relative"> | ||
| <button | ||
| type="button" | ||
| aria-haspopup="listbox" | ||
| :aria-expanded="isOpen" | ||
| class="flex items-center gap-1.5 text-fg-subtle font-mono text-sm hover:text-fg transition-colors" | ||
| @click="isOpen = !isOpen" | ||
| @keydown="handleKeydown" | ||
| > | ||
| <span>{{ currentVersion }}</span> | ||
| <span | ||
| v-if="currentVersion === latestVersion" | ||
| class="text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/10 text-emerald-400 font-sans font-medium" | ||
| > | ||
| latest | ||
| </span> | ||
| <span | ||
| class="i-carbon-chevron-down w-3.5 h-3.5 transition-transform duration-200" | ||
| :class="{ 'rotate-180': isOpen }" | ||
| aria-hidden="true" | ||
| /> | ||
| </button> | ||
|
|
||
| <Transition | ||
| enter-active-class="transition duration-150 ease-out" | ||
| enter-from-class="opacity-0 scale-95" | ||
| enter-to-class="opacity-100 scale-100" | ||
| leave-active-class="transition duration-100 ease-in" | ||
| leave-from-class="opacity-100 scale-100" | ||
| leave-to-class="opacity-0 scale-95" | ||
| > | ||
| <div | ||
| v-if="isOpen" | ||
| role="listbox" | ||
| :aria-activedescendant="`version-${currentVersion}`" | ||
| class="absolute top-full left-0 mt-2 min-w-[180px] bg-bg-elevated border border-border rounded-lg shadow-lg z-50 py-1 max-h-[300px] overflow-y-auto" | ||
| @keydown="handleKeydown" | ||
| > | ||
| <NuxtLink | ||
| v-for="{ version, tags, isCurrent } in recentVersions" | ||
| :id="`version-${version}`" | ||
| :key="version" | ||
| :to="getDocsUrl(version)" | ||
| role="option" | ||
| :aria-selected="isCurrent" | ||
| class="flex items-center justify-between gap-3 px-3 py-2 text-sm font-mono hover:bg-bg-muted transition-colors" | ||
| :class="isCurrent ? 'text-fg bg-bg-muted' : 'text-fg-muted'" | ||
| @click="isOpen = false" | ||
| > | ||
| <span class="truncate">{{ version }}</span> | ||
| <span v-if="tags.length > 0" class="flex items-center gap-1 shrink-0"> | ||
| <span | ||
| v-for="tag in tags" | ||
| :key="tag" | ||
| class="text-[10px] px-1.5 py-0.5 rounded font-sans font-medium" | ||
| :class=" | ||
| tag === 'latest' | ||
| ? 'bg-emerald-500/10 text-emerald-400' | ||
| : 'bg-bg-muted text-fg-subtle' | ||
| " | ||
| > | ||
| {{ tag }} | ||
| </span> | ||
| </span> | ||
| </NuxtLink> | ||
|
|
||
| <div | ||
| v-if="Object.keys(versions).length > MAX_VERSIONS" | ||
| class="border-t border-border mt-1 pt-1 px-3 py-2" | ||
| > | ||
| <NuxtLink | ||
| :to="`/${packageName}`" | ||
| class="text-xs text-fg-subtle hover:text-fg transition-colors" | ||
| @click="isOpen = false" | ||
| > | ||
| View all {{ Object.keys(versions).length }} versions | ||
| </NuxtLink> | ||
| </div> | ||
| </div> | ||
| </Transition> | ||
| </div> | ||
| </template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -218,6 +218,30 @@ const homepageUrl = computed(() => { | |
| return homepage | ||
| }) | ||
|
|
||
| // Docs URL: prefer package's homepage (often their docs site), fall back to our API docs | ||
| const docsLink = computed(() => { | ||
| const homepage = displayVersion.value?.homepage | ||
| if (homepage) { | ||
| return { | ||
| href: homepage, | ||
| isExternal: true, | ||
| } | ||
| } | ||
|
|
||
| // Fall back to our generated API docs | ||
| if (displayVersion.value) { | ||
| return { | ||
| to: { | ||
| name: 'docs' as const, | ||
| params: { path: [...pkg.value!.name.split('/'), 'v', displayVersion.value.version] }, | ||
| }, | ||
| isExternal: false, | ||
| } | ||
| } | ||
|
|
||
| return null | ||
| }) | ||
|
|
||
| function normalizeGitUrl(url: string): string { | ||
| return url | ||
| .replace(/^git\+/, '') | ||
|
|
@@ -676,17 +700,7 @@ defineOgImageComponent('Package', { | |
| {{ formatCompactNumber(stars, { decimals: 1 }) }} | ||
| </a> | ||
| </li> | ||
| <li v-if="homepageUrl"> | ||
| <a | ||
| :href="homepageUrl" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| class="link-subtle font-mono text-sm inline-flex items-center gap-1.5" | ||
| > | ||
| <span class="i-carbon-link w-4 h-4" aria-hidden="true" /> | ||
| {{ t('package.links.homepage') }} | ||
| </a> | ||
| </li> | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dropped the homepage url here in favor of the docs link, but as I'm looking back I wonder if maybe we just add both instead? |
||
| <li v-if="displayVersion?.bugs?.url"> | ||
| <a | ||
| :href="displayVersion.bugs.url" | ||
|
|
@@ -726,7 +740,39 @@ defineOgImageComponent('Package', { | |
| {{ t('package.links.jsr') }} | ||
| </a> | ||
| </li> | ||
| <li v-if="displayVersion" class="sm:ml-auto"> | ||
| <li v-if="docsLink"> | ||
| <a | ||
| v-if="docsLink.isExternal" | ||
| :href="docsLink.href" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| class="link-subtle font-mono text-sm inline-flex items-center gap-1.5" | ||
| > | ||
|
devdumpling marked this conversation as resolved.
Outdated
|
||
| <span class="i-carbon-document w-4 h-4" aria-hidden="true" /> | ||
| {{ t('package.links.docs') }} | ||
| </a> | ||
| <NuxtLink | ||
| v-else | ||
| :to="docsLink.to" | ||
| class="link-subtle font-mono text-sm inline-flex items-center gap-1.5" | ||
| > | ||
| <span class="i-carbon-document w-4 h-4" aria-hidden="true" /> | ||
| {{ t('package.links.docs') }} | ||
| </NuxtLink> | ||
| </li> | ||
| <li class="sm:flex-grow"> | ||
| <a | ||
| :href="`https://socket.dev/npm/package/${pkg.name}/overview/${displayVersion?.version ?? 'latest'}`" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| class="link-subtle font-mono text-sm inline-flex items-center gap-1.5" | ||
| > | ||
| <span class="i-simple-icons-socket w-4 h-4" aria-hidden="true" /> | ||
| {{ t('package.links.socket') }} | ||
| </a> | ||
| </li> | ||
|
|
||
| <li v-if="displayVersion"> | ||
| <NuxtLink | ||
| :to="{ | ||
| name: 'code', | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handles the docs specific version toggle.
Might want to align these components eventually (since there's another one we use on the package code page, but this one is specific to the docs page.