feat(markdown): inline [label](url) link parsing in MarkdownInline (M1, @since 1.6.8)#119
Merged
Merged
Conversation
@SInCE 1.6.8) Headline feature for v1.6.8 — closes the CV v2 migration gap where project / education / experience entry titles could not be rendered as hyperlinks. The renderer pipeline already had the output primitive (RichText.link); the inline-markdown adapter that every body / row / entry renderer routes through just didn't recognise the syntax. After this PR it does. Implementation: - MarkdownInline.append(rich, text, baseStyle) gets a pre-pass that scans for [text](url) matches. Each match emits exactly one rich.link(text, url) run. Plain segments between (or surrounding) link matches flow through the existing MarkdownText emphasis pipeline unchanged, so **bold** / *italic* still work as before. - MarkdownInline.plainText(value) strips link syntax in lockstep: [label](url) collapses to just `label`. Callers that need the visible-text projection (ProjectLabel.parse uses this for the project title) keep getting clean output. - One shared LINK_PATTERN regex constant for both paths so the two views agree on what counts as a link. Design notes: - v1 does NOT honour emphasis INSIDE the link label (a `[**bold**](url)` renders as a single link run with the literal asterisks). Outside emphasis works. Recursive parsing inside the label is a v2 candidate; not worth the parser complexity for the typical CV / cover-letter use case. - v1 does NOT support nested brackets `[a [b] c](url)`. Pattern requires no inner brackets. Document authors hit by this can escape with HTML entities or restructure the label. - Empty link text `[](url)` is matched and emits an empty-text link run (downstream rich.link("", url) handles gracefully). Unusual but legal. What's NOT in this PR: - ProjectRenderer / EntryRenderer wiring. They currently call rich.style(...) directly on the title segment instead of routing through MarkdownInline.append, so a [text](url) in a CvRow.label still won't render as a link in the existing layered presets. That's deliberately scoped to Track M3 (a separate focused PR) so this PR stays a pure parser change with japicmp-clean public-API extension. Test plan: - New MarkdownInlineTest (12 tests): * plainText strips link syntax, combines with emphasis strip, leaves bare brackets intact, handles multiple links, handles null safely (5 tests). * append emits exactly one hyperlink run with correct text/uri for [text](url), mixes plain + emphasis + link, preserves ordering of multiple links, leaves bare brackets as literal, keeps **/* emphasis working without links, null/empty no-op, appendTrimmed strips whitespace then parses (7 tests). - ./mvnw verify -pl . -P japicmp - 1049 tests, 0 failures. japicmp vs v1.6.7 baseline: semver PATCH (compatible behaviour extension on existing public methods, no signature change).
This was referenced Jun 1, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Headline feature for the v1.6.8 cycle — closes the CV v2
migration gap where project / education / experience entry titles
could not be rendered as hyperlinks.
The renderer pipeline already had the output primitive
(
RichText.link(text, uri)— used by the CV header's contactlinks since v1.6.0). What was missing was the inline-markdown
adapter that every body / row / entry renderer routes through
recognising the
[label](url)syntax. After this PR it does.Implementation
MarkdownInline.append(rich, text, baseStyle)gets a pre-passthat scans for
[text](url)matches:rich.link(text, url)run.through the existing
MarkdownTextemphasis pipeline unchanged—
**bold**/*italic*/_italic_still work as before.MarkdownInline.plainText(value)is updated in lockstep:[label](url)collapses to justlabel. Callers that needthe visible-text projection (
ProjectLabel.parseuses thisfor the project title) keep getting clean output.
LINK_PATTERNregex constant for both paths so thetwo views agree on what counts as a link.
What this PR does NOT touch
ProjectRenderer/EntryRenderer— they currently callrich.style(...)directly on the title segment instead ofrouting through
MarkdownInline.append, so a[text](url)ina
CvRow.labelstill won't render as a link in the existinglayered presets. That's deliberately scoped to Track M3 (a
separate focused PR) so this PR stays a pure parser change with
japicmp-clean public-API extension.
CvRowrecord shape — no new field, no breaking change.The link information rides inside the existing
labelstring.Design tradeoffs
(
[**bold**](url)renders as a single link run with literalasterisks; outside emphasis works fine). Recursive parsing
inside the label is a v2 candidate.
[a [b] c](url)—the regex requires no inner brackets. Document authors hit
by this can restructure the label.
[](url)is matched and emits an empty-textlink run. Unusual but legal.
Test plan
MarkdownInlineTest(12 tests):plainTextstrips link syntax, combines with emphasis strip,leaves bare brackets intact, handles multiple links, handles
null safely (5 tests).
appendemits exactly one hyperlink run with the correcttext + uri for
[text](url), mixes plain + emphasis + link,preserves ordering of multiple links, leaves bare brackets
as literal, keeps
**/*/_emphasis working withoutlinks, null/empty no-op,
appendTrimmedstrips whitespacethen parses (7 tests).
./mvnw verify -pl . -P japicmp— 1049 tests, 0failures; japicmp vs v1.6.7 baseline:
semver PATCH(compatible behaviour extension on existing public
methods, no signature change).