Skip to content

refactor(update): render release notes natively, dropping MarkdownUI#21

Merged
BlackHole1 merged 2 commits into
mainfrom
remove-md-ui
Jun 15, 2026
Merged

refactor(update): render release notes natively, dropping MarkdownUI#21
BlackHole1 merged 2 commits into
mainfrom
remove-md-ui

Conversation

@BlackHole1

Copy link
Copy Markdown
Member

Parse the appcast item's Markdown into blocks in LockIMEKit (ReleaseNotes.blocks) — heading, bullet list, paragraphs — and render them with SwiftUI Text, which draws the inline bold/code/links each block carries. This replaces the MarkdownUI / swift-cmark / NetworkImage dependency graph; the arm64 Release binary shrinks 2.2 MB to 1.4 MB. Verified against all 18 published releases: no unsupported constructs, and any block kind outside the generated subset degrades to a readable paragraph.

Layer GitHub's reading conveniences on top: link @username to its profile, and relabel …/pull/N, …/issues/N, …/compare/A...B as #N and the bare ref range, keeping each link target (an email local part or an @ inside inline code is not taken for a mention). The empty-notes fallback is now a localized catalog string covering every SupportedLanguage. The update-lab notes are enriched so make update-test-* visibly exercises the renderer.

Parse the appcast item's Markdown into blocks in LockIMEKit
(ReleaseNotes.blocks) — heading, bullet list, paragraphs — and render them with
SwiftUI Text, which draws the inline bold/code/links each block carries. This
replaces the MarkdownUI / swift-cmark / NetworkImage dependency graph; the arm64
Release binary shrinks 2.2 MB to 1.4 MB. Verified against all 18 published
releases: no unsupported constructs, and any block kind outside the generated
subset degrades to a readable paragraph.

Layer GitHub's reading conveniences on top: link @username to its profile, and
relabel …/pull/N, …/issues/N, …/compare/A...B as #N and the bare ref range,
keeping each link target (an email local part or an @ inside inline code is not
taken for a mention). The empty-notes fallback is now a localized catalog
string covering every SupportedLanguage. The update-lab notes are enriched so
make update-test-* visibly exercises the renderer.
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 49d1e59a-0b92-4014-9b1c-bbb811c7ea5f

📥 Commits

Reviewing files that changed from the base of the PR and between 2f25252 and a65fcf9.

📒 Files selected for processing (2)
  • Sources/LockIME/UI/UpdateWindowView.swift
  • Sources/LockIMEKit/Updates/ReleaseNotes.swift
🚧 Files skipped from review as they are similar to previous changes (2)
  • Sources/LockIME/UI/UpdateWindowView.swift
  • Sources/LockIMEKit/Updates/ReleaseNotes.swift

Summary by CodeRabbit

  • New Features

    • Redesigned release notes display in update windows with custom rendering (headings, lists, and selectable text).
    • Added GitHub-style changelog formatting, including improved handling of mentions and links.
    • Added localized messaging for empty release notes (“No release notes.”).
  • Improvements

    • Update window now trims whitespace and shows a secondary note when no release notes are available.
    • More robust Markdown-to-UI block parsing for common release-note structures.
  • Tests

    • Added comprehensive release-notes parsing coverage.
  • Chores

    • Removed the MarkdownUI dependency for release-notes rendering.

Walkthrough

The PR removes the third-party MarkdownUI library and replaces it with a custom Markdown rendering pipeline. A new ReleaseNotes.blocks(fromMarkdown:) parser in LockIMEKit uses AttributedString to parse Markdown into typed ReleaseNoteBlock values (headings, list items, paragraphs) and applies GitHub-specific post-processing: compacting PR/issue/compare URLs and linkifying @username mentions. A new ReleaseNotesView SwiftUI struct renders these blocks directly. UpdateWindowView is updated to use this view (or show a localized "No release notes." fallback), the old ReleaseNotesTheme extension is deleted, and project.yml swaps the MarkdownUI package for PermissionFlow. The appcast generation in update-lab.sh is also expanded to emit GitHub-style changelog formatting.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required format '(): ' with 'refactor' as type, 'update' as scope, and a clear subject describing the main change.
Description check ✅ Passed The description comprehensively explains the refactoring work, detailing the native parsing implementation, dependency removal, binary size improvements, and GitHub-specific enhancements.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch remove-md-ui

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/LockIME/UI/UpdateWindowView.swift`:
- Around line 62-67: In the release notes conditional block, replace the simple
`.isEmpty` check on `model.releaseNotesMarkdown` with a whitespace-safe check
using `.trimmingCharacters(in: .whitespaces).isEmpty` to properly handle
whitespace-only strings as empty. Additionally, replace the literal string "No
release notes." in the Text view with a localized string obtained through
`state.loc(...)` or the appropriate `AppKitStrings` accessor, ensuring the
localization key is added to `Localizable.xcstrings` for all supported languages
per the coding guidelines for AppKit-hosted surfaces.

In `@Sources/LockIMEKit/Updates/ReleaseNotes.swift`:
- Around line 119-124: The host validation on line 119 uses
hasSuffix("github.com"), which will incorrectly match malicious domains like
"evilgithub.com" and then relabel their URLs to appear as trusted GitHub
references (the "`#N`" format on line 124 or compare text on line 124). Replace
the loose hasSuffix check with a strict equality check for "github.com"
(optionally also allowing "www.github.com") to ensure only actual GitHub URLs
get the shortened label treatment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: adad3ab1-a523-45ae-ac7e-f96575ef9796

📥 Commits

Reviewing files that changed from the base of the PR and between 51e6866 and 2f25252.

📒 Files selected for processing (8)
  • Sources/LockIME/Localizable.xcstrings
  • Sources/LockIME/UI/ReleaseNotesTheme.swift
  • Sources/LockIME/UI/ReleaseNotesView.swift
  • Sources/LockIME/UI/UpdateWindowView.swift
  • Sources/LockIMEKit/Updates/ReleaseNotes.swift
  • Tests/LockIMEKitTests/ReleaseNotesTests.swift
  • project.yml
  • scripts/update-lab/update-lab.sh
💤 Files with no reviewable changes (2)
  • Sources/LockIME/UI/ReleaseNotesTheme.swift
  • project.yml

Comment thread Sources/LockIME/UI/UpdateWindowView.swift Outdated
Comment thread Sources/LockIMEKit/Updates/ReleaseNotes.swift Outdated
Restrict compactGitHubLabel to github.com and its subdomains so a
look-alike host like evilgithub.com cannot have its …/pull/N link
relabeled to a trusted-looking #N while keeping the untrusted target.

Trim the release notes before the empty check so whitespace-only notes
show the fallback instead of a blank section (ReleaseNotes.blocks already
drops to zero blocks for such input).

Signed-off-by: Kevin Cui <bh@bugs.cc>
@BlackHole1 BlackHole1 merged commit f513fd3 into main Jun 15, 2026
3 checks passed
@BlackHole1 BlackHole1 deleted the remove-md-ui branch June 15, 2026 06:52
BlackHole1 added a commit that referenced this pull request Jun 15, 2026
The README never mentioned the config import/export feature shipped in
#18, nor that the app now downloads as a sub-3 MB .dmg. Add both to the
Features list and drop the stale MarkdownUI mention from the
Architecture section (removed in #21). All nine language variants are
updated together to keep the translations in sync.

Signed-off-by: Kevin Cui <bh@bugs.cc>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant