Skip to content

Refactor repo parsing, add prose heading anchors and go-pkg component#4

Merged
amery merged 3 commits into
mainfrom
pr-amery-code
Apr 3, 2026
Merged

Refactor repo parsing, add prose heading anchors and go-pkg component#4
amery merged 3 commits into
mainfrom
pr-amery-code

Conversation

@amery

@amery amery commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Component and utility improvements for the content layer:

  • Refactor parseRepo into layered helpers with data-driven
    provider config, path sanitisation (., .., empty segments),
    ellipsis shortening for deep paths, and dual prefix support
    (github: and https://github.com/).
  • Prose heading overrides — shared ProseHeading base component
    with hover-visible § anchor glyph (keyboard-accessible via
    focus-visible). prose-h2 and prose-h3 delegate to it.
    Replaces the default Nuxt Content behaviour of wrapping headings
    in anchor links.
  • :go-pkg MDC component — inline link to pkg.go.dev with
    trailing Go icon. Supports module, directory, symbol, and function
    references with configurable label display. Resolution logic in
    app/utils/go-pkg.ts follows the same layered helper pattern as
    parse-repo.ts.

Files

File Change
app/utils/parse-repo.ts Refactored into splitPath, parsePath, makeRepoLabel, makeRepoURL
app/utils/index.ts ProseHeadingProps interface
app/components/content/prose-heading.vue Shared heading base with anchor glyph
app/components/content/prose-h2.vue Thin delegate
app/components/content/prose-h3.vue Thin delegate
app/utils/go-pkg.ts GoPkgProps, GoPkgLink, resolveGoPkg and helpers
app/components/go-pkg.vue Thin rendering shell
AGENTS.md Documentation for GoPkg and ProseHeading

Test plan

  • pnpm precommit passes (generate, lint, typecheck)
  • Dev server renders prose headings with § glyph on hover
  • § glyph visible on keyboard focus (Tab navigation)
  • :go-pkg{mod="darvaza.org/resolver"} renders as linked text with Go icon
  • :go-pkg{mod="..." sym="Resolver" short} renders as Resolver with Go icon
  • :go-pkg{mod="..." func="NewResolver" short} renders as NewResolver() with Go icon
  • Repo labels for 3+ segment paths display with ellipsis
  • parseRepo accepts both github:owner/repo and https://github.com/owner/repo

Summary by CodeRabbit

  • New Features

    • Go package component for creating pkg.go.dev links with support for modules, directories, symbols, and functions
    • Prose heading components (h2, h3) with customizable anchor glyphs that appear on hover for easy sharing
  • Documentation

    • Added comprehensive component documentation and usage guidelines

amery added 3 commits April 3, 2026 14:50
Break the monolithic parseRepo into focused helpers:

- splitPath: match provider prefix or base URL, normalise segments
  (strips empty parts, `.`, and `..`).
- parsePath: extract structured { provider, repo, directory }.
- makeRepoLabel: shorten deep paths with ellipsis
  (e.g. a/b/c/d → a/b/…/d).
- makeRepoURL: table-driven URL composition from provider config.

Provider configuration is now data-driven via a RepoProvider type
and providers record. Currently supports `github:` prefix and
`https://github.com/` base URL forms.

Signed-off-by: Alejandro Mery <amery@apptly.co>
The default Nuxt Content prose components wrap the entire heading
text in an anchor link, making it behave like a navigation element.

Add a shared ProseHeading base component that renders headings as
plain text with a subtle § glyph that appears on hover (and on
keyboard focus) for section permalinks. prose-h2 and prose-h3
delegate to it with a fixed `as` prop. The glyph is customisable
per heading via MDC attributes.

Signed-off-by: Alejandro Mery <amery@apptly.co>
Inline component for linking Go packages, types, and functions
to pkg.go.dev with a trailing Go icon. Supports module, directory,
symbol, and function references with configurable label display.

Resolution logic lives in app/utils/go-pkg.ts — layered helpers
(makeGoPkgURL, makeGoPkgLabel, resolveGoPkg) following the same
pattern as parse-repo.ts. The component is a thin rendering shell.

Signed-off-by: Alejandro Mery <amery@apptly.co>
@amery amery added enhancement New feature or request component UX labels Apr 3, 2026
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
awesome-apptly 30830c3 Commit Preview URL

Branch Preview URL
Apr 03 2026, 03:53 PM

@coderabbitai

coderabbitai Bot commented Apr 3, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1f7abbe1-76fa-4902-a9c7-4d501e018865

📥 Commits

Reviewing files that changed from the base of the PR and between a409692 and 30830c3.

📒 Files selected for processing (8)
  • AGENTS.md
  • app/components/content/prose-h2.vue
  • app/components/content/prose-h3.vue
  • app/components/content/prose-heading.vue
  • app/components/go-pkg.vue
  • app/utils/go-pkg.ts
  • app/utils/index.ts
  • app/utils/parse-repo.ts

📝 Walkthrough

Walkthrough

This PR adds Vue components and TypeScript utilities for handling Go package documentation links and prose headings with optional anchors. New components include GoPkg for generating pkg.go.dev links, ProseHeading as a base for heading overrides, and ProseH2/ProseH3 wrappers. Associated utilities resolve Go package URLs and parse heading properties. The repo parsing utility is also enhanced to support multiple providers.

Changes

Cohort / File(s) Summary
Documentation
AGENTS.md
Added documentation for GoPkg inline component (with module, directory, symbol, function support and label/short options) and ProseHeading base component (with customizable hover anchor glyph) plus formatting guidance.
Go Package Linking
app/components/go-pkg.vue, app/utils/go-pkg.ts
Introduced GoPkg component and resolveGoPkg utility to generate pkg.go.dev links with optional directory, symbol, and function parameters; supports custom labels and short formatting with accessible attributes.
Prose Heading Components
app/components/content/prose-heading.vue, app/components/content/prose-h2.vue, app/components/content/prose-h3.vue
Added generic ProseHeading base component rendering dynamic heading elements with optional hover-visible permalink anchors (defaulting to § glyph); ProseH2 and ProseH3 delegate to the base component with fixed as values.
Utilities & Types
app/utils/index.ts
Exported ProseHeadingProps interface defining optional id and glyph properties for heading customization.
Repository Parsing Enhancement
app/utils/parse-repo.ts
Refactored repo parsing to introduce RepoProvider type, centralized provider configuration with base URLs, added splitPath() and makeRepoLabel()/makeRepoURL() helpers, and generalized URL/label generation beyond hardcoded GitHub handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hop, hop! Fresh anchors bloom,
Go docs now link with style and zoom,
Prose headings wear their glyphs with grace,
Repos find providers in their space,
A garden of components, neat and true!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the three main changes: repo parsing refactor, prose heading anchors, and go-pkg component addition.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr-amery-code

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Refactor repo parsing, add prose heading anchors and go-pkg component

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Refactor parseRepo into layered helpers with data-driven provider config
  - Path sanitisation (., .., empty segments)
  - Ellipsis shortening for deep paths (e.g. a/b/c/da/b/…/d)
  - Dual prefix support (github: and https://github.com/)
• Add prose heading overrides with hover-visible anchor glyph
  - Shared ProseHeading base component with keyboard-accessible § glyph
  - prose-h2 and prose-h3 delegate to base component
• Add :go-pkg MDC component for pkg.go.dev links
  - Supports module, directory, symbol, and function references
  - Configurable label display with trailing Go icon
  - Layered helper pattern matching parse-repo.ts structure
• Update documentation with new component usage examples
Diagram
flowchart LR
  A["parseRepo refactor"] -->|splitPath| B["Normalised parts"]
  B -->|parsePath| C["Provider + repo + dir"]
  C -->|makeRepoLabel| D["Shortened label"]
  C -->|makeRepoURL| E["Full URL"]
  F["GoPkgProps"] -->|resolveGoPkg| G["GoPkgLink"]
  G -->|go-pkg.vue| H["Rendered link + icon"]
  I["ProseHeadingProps"] -->|ProseHeading| J["Heading + glyph"]
  J -->|prose-h2/h3| K["Delegated headings"]
Loading

Grey Divider

File Changes

1. app/utils/parse-repo.ts ✨ Enhancement +78/-13

Refactor parseRepo into layered data-driven helpers

• Refactored monolithic parseRepo into focused layered helpers
• Added splitPath for provider prefix/URL matching and path normalisation
• Added parsePath to extract structured repo information
• Added makeRepoLabel to shorten deep paths with ellipsis
• Added makeRepoURL for table-driven URL composition
• Introduced data-driven RepoProvider type and providers config record
• Now supports both github: prefix and https://github.com/ base URL forms

app/utils/parse-repo.ts


2. app/utils/go-pkg.ts ✨ Enhancement +67/-0

Add Go package linking utilities and interfaces

• New file implementing Go package linking utilities
• Defined GoPkgProps interface for component props (mod, dir, sym, func, short, label)
• Defined GoPkgLink interface for resolved link data
• Implemented makeGoPkgURL to build pkg.go.dev URLs with optional symbols
• Implemented makeGoPkgLabel to compose display labels with configurable formatting
• Exported resolveGoPkg function to resolve all link data from props

app/utils/go-pkg.ts


3. app/utils/index.ts ✨ Enhancement +8/-0

Add ProseHeadingProps interface for headings

• Added ProseHeadingProps interface with id and glyph properties
• Shared interface for prose heading override components

app/utils/index.ts


View more (5)
4. app/components/content/prose-heading.vue ✨ Enhancement +25/-0

Add shared prose heading with anchor glyph

• New shared base component for prose headings with anchor glyph
• Renders dynamic heading element via component :is binding
• Displays hover-visible and keyboard-accessible § anchor glyph
• Glyph appears on hover and focus-visible states
• Customisable glyph via props with Unicode section symbol default

app/components/content/prose-heading.vue


5. app/components/content/prose-h2.vue ✨ Enhancement +14/-0

Add prose-h2 delegate component

• New thin delegate component for h2 headings
• Delegates to ProseHeading with fixed as="h2" prop
• Passes through id and glyph props

app/components/content/prose-h2.vue


6. app/components/content/prose-h3.vue ✨ Enhancement +14/-0

Add prose-h3 delegate component

• New thin delegate component for h3 headings
• Delegates to ProseHeading with fixed as="h3" prop
• Passes through id and glyph props

app/components/content/prose-h3.vue


7. app/components/go-pkg.vue ✨ Enhancement +23/-0

Add go-pkg MDC component for pkg.go.dev

• New MDC component for inline pkg.go.dev links
• Accepts GoPkgProps for module, directory, symbol, and function references
• Renders link with trailing Go icon from @nuxt/icon
• Opens in new tab with proper accessibility attributes
• Computes resolved link data via resolveGoPkg utility

app/components/go-pkg.vue


8. AGENTS.md 📝 Documentation +18/-0

Document GoPkg and ProseHeading components

• Added documentation for GoPkg component with usage examples
• Documented all GoPkg props (mod, dir, sym, func, short, label)
• Added documentation for ProseHeading component and its delegates
• Included usage notes for proper placement in prose

AGENTS.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Apr 3, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. Unimported ProseHeadingProps 🐞 Bug ≡ Correctness
Description
The prose heading override components use ProseHeadingProps in defineProps/withDefaults without
importing it, so TypeScript cannot resolve the type and the build/typecheck will fail.
Code

app/components/content/prose-heading.vue[R3-8]

+const props = withDefaults(defineProps<ProseHeadingProps & {
+  /** HTML heading element to render. */
+  as: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
+}>(), {
+  glyph: '\u00A7',
+});
Evidence
ProseHeadingProps is declared as an exported interface in app/utils/index.ts, but the new prose
heading components reference it without any import, so the identifier is not in module scope.

app/utils/index.ts[4-10]
app/components/content/prose-heading.vue[1-9]
app/components/content/prose-h2.vue[1-4]
app/components/content/prose-h3.vue[1-4]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ProseHeadingProps` is defined in `app/utils/index.ts` but is referenced in multiple `<script setup lang="ts">` blocks without being imported. This will cause TypeScript errors (e.g., `Cannot find name 'ProseHeadingProps'`) during typecheck/build.

## Issue Context
Nuxt auto-import covers runtime values (e.g., `parseRepo`), but TypeScript types still must be in scope unless explicitly declared globally.

## Fix Focus Areas
- app/components/content/prose-heading.vue[1-9]
- app/components/content/prose-h2.vue[1-4]
- app/components/content/prose-h3.vue[1-4]

## Expected fix
Add explicit type imports, e.g.:
- `import type { ProseHeadingProps } from '~/utils'`

Alternatively, inline the prop types in each component if you do not want shared imports.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unimported GoPkgProps 🐞 Bug ≡ Correctness
Description
The new GoPkg component uses GoPkgProps in defineProps without importing it, so TypeScript cannot
resolve the type and the build/typecheck will fail.
Code

app/components/go-pkg.vue[R2-5]

+/** Inline link to pkg.go.dev with a trailing Go icon. */
+const props = defineProps<GoPkgProps>();
+const link = computed(() => resolveGoPkg(props));
+</script>
Evidence
GoPkgProps is declared as an exported interface in app/utils/go-pkg.ts, but
app/components/go-pkg.vue references it without any import, so the identifier is not in module
scope.

app/utils/go-pkg.ts[3-17]
app/components/go-pkg.vue[1-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`GoPkgProps` is defined in `app/utils/go-pkg.ts` but is referenced in `app/components/go-pkg.vue` without being imported. This will cause TypeScript errors during typecheck/build.

## Issue Context
This component is a thin wrapper around `resolveGoPkg`, but the prop type must be in scope for `defineProps<GoPkgProps>()`.

## Fix Focus Areas
- app/components/go-pkg.vue[1-5]

## Expected fix
Add an explicit type import, e.g.:
- `import type { GoPkgProps } from '~/utils/go-pkg'`

(Leaving `resolveGoPkg` as an auto-imported value is fine if Nuxt imports are configured for `~/utils`.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Malformed URLs for tree refs 🐞 Bug ≡ Correctness
Description
When parseRepo is given a full GitHub URL that already contains a ref path like /tree/main/..., it
will treat tree/main/... as a directory and then prepend /tree/HEAD/ again, producing broken
URLs like /tree/HEAD/tree/main/... instead of rejecting or preserving the original.
Code

app/utils/parse-repo.ts[R69-74]

+function makeRepoURL(provider: RepoProvider, repo: string, directory?: string): string {
+  const { baseURL } = providers[provider];
+  return directory ?
+    `${baseURL}${repo}/tree/HEAD/${directory}` :
+    `${baseURL}${repo}`;
+}
Evidence
splitPath accepts both github: and https://github.com/ inputs, but makeRepoURL always rewrites
directories into /tree/HEAD/<directory>. For inputs that already include tree/<branch>/... after
the repo, that segment becomes part of directory and results in duplicated /tree/... in the
final URL.

app/utils/parse-repo.ts[19-40]
app/utils/parse-repo.ts[42-52]
app/utils/parse-repo.ts[69-74]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`parseRepo()` now accepts `https://github.com/...` inputs, but it will generate malformed URLs if the provided URL already includes ref/file routing segments (e.g. `/tree/<branch>/...` or `/blob/<branch>/...`). The current behavior silently produces broken links (e.g. `/tree/HEAD/tree/<branch>/...`).

## Issue Context
The function comment notes that full URLs containing refs are not stripped, but today the implementation *rewrites* such URLs into an incorrect form instead of failing fast or preserving the original URL.

## Fix Focus Areas
- app/utils/parse-repo.ts[19-40]
- app/utils/parse-repo.ts[42-52]
- app/utils/parse-repo.ts[69-74]

## Expected fix options (pick one)
1) **Fail fast**: when matching the `baseURL` form, if `parts[2]` is `tree` or `blob` (or other known ref prefixes), return `undefined` so the repo link is omitted rather than wrong.
2) **Preserve input URL**: when the input matched `baseURL`, return `url: raw` (or `new URL(raw).toString()`) instead of rebuilding via `/tree/HEAD/`.
3) **Strip known ref prefixes**: detect `/tree/<ref>/...` and set `directory` to the remainder, using `<ref>` instead of `HEAD` (or omit ref entirely if you want HEAD semantics).

Any of these avoids silently producing an invalid GitHub link.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@amery amery self-assigned this Apr 3, 2026
Comment thread app/components/content/prose-heading.vue
Comment thread app/components/go-pkg.vue
@amery amery merged commit 37fba9b into main Apr 3, 2026
11 checks passed
@amery amery deleted the pr-amery-code branch April 3, 2026 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component enhancement New feature or request UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant