malcommac/SwiftRichString
π©βπ¨ Elegant Attributed String composition in Swift sauce
Stale β last commit 3y ago
worst of 4 axeslast commit was 3y ago; top contributor handles 94% of recent commitsβ¦
Has a license, tests, and CI β clean foundation to fork and modify.
Documented and popular β useful reference codebase to read through.
last commit was 3y ago; no CI workflows detected
- β4 active contributors
- βMIT licensed
- βTests present
Show 4 more βShow less
- β Stale β last commit 3y ago
- β Small team β 4 contributors active in recent commits
- β Single-maintainer risk β top contributor 94% of recent commits
- β No CI workflows detected
What would change the summary?
- βUse as dependency Mixed β Healthy if: 1 commit in the last 365 days; diversify commit ownership (top <90%)
- βDeploy as-is Mixed β Healthy if: 1 commit in the last 180 days
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README β live-updates from the latest cached analysis.
[](https://repopilot.app/r/malcommac/swiftrichstring)Paste at the top of your README.md β renders inline like a shields.io badge.
βΈPreview social card (1200Γ630)
This card auto-renders when someone shares https://repopilot.app/r/malcommac/swiftrichstring on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: malcommac/SwiftRichString
Generated by RepoPilot Β· 2026-05-10 Β· Source
π€Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale β STOP and ask the user to regenerate it before proceeding. - Treat the AI Β· unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/malcommac/SwiftRichString shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything β but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
π―Verdict
WAIT β Stale β last commit 3y ago
- 4 active contributors
- MIT licensed
- Tests present
- β Stale β last commit 3y ago
- β Small team β 4 contributors active in recent commits
- β Single-maintainer risk β top contributor 94% of recent commits
- β No CI workflows detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
β Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live malcommac/SwiftRichString
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale β regenerate it at
repopilot.app/r/malcommac/SwiftRichString.
What it runs against: a local clone of malcommac/SwiftRichString β the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in malcommac/SwiftRichString | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit β€ 1057 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of malcommac/SwiftRichString. If you don't
# have one yet, run these first:
#
# git clone https://github.com/malcommac/SwiftRichString.git
# cd SwiftRichString
#
# Then paste this script. Every check is read-only β no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of malcommac/SwiftRichString and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "malcommac/SwiftRichString(\\.git)?\\b" \\
&& ok "origin remote is malcommac/SwiftRichString" \\
|| miss "origin remote is not malcommac/SwiftRichString (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift β was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "Sources/SwiftRichString/SwiftRichString.h" \\
&& ok "Sources/SwiftRichString/SwiftRichString.h" \\
|| miss "missing critical file: Sources/SwiftRichString/SwiftRichString.h"
test -f "Sources/SwiftRichString/Style.swift" \\
&& ok "Sources/SwiftRichString/Style.swift" \\
|| miss "missing critical file: Sources/SwiftRichString/Style.swift"
test -f "Sources/SwiftRichString/AttributedString+Extensions.swift" \\
&& ok "Sources/SwiftRichString/AttributedString+Extensions.swift" \\
|| miss "missing critical file: Sources/SwiftRichString/AttributedString+Extensions.swift"
test -f "Sources/SwiftRichString/XMLParser.swift" \\
&& ok "Sources/SwiftRichString/XMLParser.swift" \\
|| miss "missing critical file: Sources/SwiftRichString/XMLParser.swift"
test -f "Sources/SwiftRichString/RichString.swift" \\
&& ok "Sources/SwiftRichString/RichString.swift" \\
|| miss "missing critical file: Sources/SwiftRichString/RichString.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1057 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1027d)"
else
miss "last commit was $days_since_last days ago β artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) β safe to trust"
else
echo "artifact has $fail stale claim(s) β regenerate at https://repopilot.app/r/malcommac/SwiftRichString"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
β‘TL;DR
SwiftRichString is a lightweight Swift library that simplifies creating and composing attributed strings (rich text with fonts, colors, underlines, etc.) across iOS, macOS, tvOS, and watchOS. It provides declarative style composition, XML/HTML tag-based string rendering, local/remote image embedding, and Interface Builder integrationβall without external dependencies. Single-package Swift library: Core styling logic lives in the main Sources/ directory (not visible in file list but inferred from .swiftpm/ config). Three platform-specific example apps (DemoApp/, ExampleMac/, ExampleTvOS/) demonstrate functionality. Tests configured via Configs/SwiftRichStringTests.plist. Documentation assets and Ruby build config suggest CI/release automation.
π₯Who it's for
iOS/macOS/tvOS developers who need to style text programmatically without wrestling with NSAttributedString APIs directly. Specifically: app developers building dynamic UIs with reusable text styles, teams managing consistent typography across platforms, and those integrating styled text in XIB/Storyboard layouts.
π±Maturity & risk
This is an actively maintained, production-ready library. The codebase is substantial (198K lines of Swift), spans multiple example apps (DemoApp, ExampleMac, ExampleTvOS), and includes a test configuration (Configs/SwiftRichStringTests.plist). No signs of abandonment; the Swift Package Manager integration (.swiftpm/) and Swift 5+ syntax indicate modern, current development.
Low risk: zero external dependencies and a single-file dependency footprint. Main risks are single-maintainer (malcommac) and the need to verify recent commit history to confirm active maintenance. The library's scope is narrow and stable (attributed string styling), limiting breaking-change surface area.
Active areas of work
Not visible from file list alone, but CHANGELOG.md and CONTRIBUTING.md indicate active maintenance. The presence of Swift Package Manager workspace (.swiftpm/xcode/) and multiple example targets suggests ongoing cross-platform testing and refinement.
πGet running
Clone and open in Xcode: git clone https://github.com/malcommac/SwiftRichString.git && cd SwiftRichString && open .swiftpm/xcode/package.xcworkspace. Or build via Swift Package Manager: swift build. Run DemoApp target in Xcode for immediate visual feedback.
Daily commands:
Open .swiftpm/xcode/package.xcworkspace in Xcode β select DemoApp target β Cmd+R. Or run tests: select SwiftRichStringTests target β Cmd+U. For macOS example: select ExampleMac target. No external build steps or server startup required.
πΊοΈMap of the codebase
Sources/SwiftRichString/SwiftRichString.hβ Main header file defining the public API and framework interfaceSources/SwiftRichString/Style.swiftβ Core Style class for defining reusable text styling rules; central to the library's value propositionSources/SwiftRichString/AttributedString+Extensions.swiftβ Primary extension adding convenient methods for attributed string composition and manipulationSources/SwiftRichString/XMLParser.swiftβ Parser for tag-based (XML/HTML) string rendering; critical feature for complex text layoutSources/SwiftRichString/RichString.swiftβ Main builder and composer for attributed strings; implements function builder pattern for declarative syntaxPackage.swiftβ SPM package manifest defining platform support, dependencies, and module structureDemoApp/ViewController.swiftβ Primary demo showcasing library usage patterns and API examples
π§©Components & responsibilities
- Style (UIFont, UIColor, NSParagraphStyle, NSShadow) β Encapsulates all text attributes (font, color, paragraph, shadow, transform) for a named style
- Failure mode: Invalid attribute combinations (e.
π οΈHow to make changes
Add a new reusable text style
- In your app setup or constants file, create a new Style instance with desired attributes (font, color, paragraph style, etc.) (
Sources/SwiftRichString/Style.swift) - Add the style to a StyleGroup for easy access and reuse across the app (
Sources/SwiftRichString/StyleGroup.swift) - Apply to any NSAttributedString via
.set(style:range:)extension method (Sources/SwiftRichString/AttributedString+Extensions.swift)
Render tagged (XML/HTML) strings with custom styles
- Define styles for each custom tag you want to support (
Sources/SwiftRichString/TagStyle.swift) - Create a StyleGroup or tag dictionary mapping tag names to TagStyle instances (
Sources/SwiftRichString/StyleGroup.swift) - Call
NSAttributedString(html:styles:)or similar method passing your XML/HTML string and styles (Sources/SwiftRichString/XMLParser.swift)
Embed images (local or remote) in attributed strings
- Create an ImageStyle defining size, offset, and scaling behavior (
Sources/SwiftRichString/ImageStyle.swift) - Use the
attachment()method to embed local images or define remote image tags in XML strings (Sources/SwiftRichString/AttributedString+Extensions.swift) - For remote images, the RemoteImageLoader handles async fetch and caching automatically (
Sources/SwiftRichString/RemoteImageLoader.swift)
Use Dynamic Type to scale fonts with system settings
- When defining a Style, use DynamicType to wrap font sizes instead of fixed sizes (
Sources/SwiftRichString/DynamicType.swift) - DynamicType scales fonts proportionally when user changes accessibility text size (
Sources/SwiftRichString/Style.swift) - Apply style to UILabel or UITextView; scaling happens automatically on system events (
Sources/SwiftRichString/AttributedString+Extensions.swift)
π§Why these technologies
- Swift 5 with function builders β Enables declarative, fluent syntax for composing rich strings; matches modern Swift conventions
- NSAttributedString & NSMutableAttributedString β Native iOS/macOS/tvOS/watchOS text styling API; no external dependencies needed
- XMLParser (Foundation) β Native, lightweight tag parsing without third-party XML libraries; sufficient for tag-based rendering
- Interface Builder (IBDesignable/IBInspectable) β Integrates with Xcode visual editor for real-time design preview and no-code style application
- Swift Package Manager β Modern dependency management; supports iOS, macOS, tvOS, watchOS across multiple platforms
βοΈTrade-offs already made
-
No external dependencies (pure Foundation)
- Why: Keeps library lightweight and eliminates version conflicts; users can embed without Cocoapods/SPM friction
- Consequence: Limited to Foundation's NSAttributedString API; custom features (e.g., advanced layout) must be built in-house
-
XML parser instead of full HTML parser
- Why: Reduces code size; serves 90% of use case (tag-based styling) without HTML spec compliance overhead
- Consequence: Does not handle malformed HTML or complex HTML5 features; users must provide well-formed XML tags
-
Style-first (declarative) approach over runtime manipulation
- Why: Encourages reuse and consistency; easier to manage typography across app
- Consequence: Requires upfront style definition; dynamic per-instance styling is more verbose
-
Async remote image loading with in-memory cache
- Why: Provides good UX for inline images without heavy persistence layer
- Consequence: Cache is in-memory only; images lost on app restart; no disk persistence for offline scenarios
π«Non-goals (don't propose these)
- Real-time collaborative editing or undo/redo stacks
- Full HTML5 or Markdown parser compliance
- Persistent image caching to disk
- Server-side text rendering or PDF generation
- Third-party authentication or network requests beyond image loading
- Support for languages without left-to-right text layout
πͺ€Traps & gotchas
No external dependencies documentedβverify this holds if adding features. XML/HTML parsing is custom (not using Foundation's XMLParser by default, likely)βchanges here require careful testing across platforms. Dynamic Type support is explicit (mentioned in README) but may not work identically on watchOS; test on actual devices. Interface Builder integration (mentioned in features) requires XIB/Storyboard setup that isn't obvious from code; check DemoApp storyboards for examples.
ποΈArchitecture
πRelated repos
jdemeyer/AttributedStringβ Alternative attributed string builder for Swift; useful comparison for design decisions around API ergonomicskishikawakatsumi/StringStylizerβ Similar library for fluent attributed string composition; competitive reference for feature parityAlamofire/Alamofireβ Ecosystem companion for iOS devs; often used alongside rich text libraries for image downloads (SwiftRichString supports remote images)realm/realm-swiftβ Common data persistence layer in apps using SwiftRichString for UI rendering of stored textapple/swift-markdownβ Apple's official Markdown parsing framework; relevant for understanding how tag-based rendering compares to standards-based text markup
πͺPR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for core Style and AttributedString classes
The repo has example apps (DemoApp, ExampleMac, ExampleTvOS) but no visible test files in the structure. Given that SwiftRichString is a styling/composition library, it needs robust tests for Style initialization, merging, application to strings, and edge cases like null values, conflicting attributes, and platform-specific rendering differences across iOS/macOS/tvOS/watchOS.
- [ ] Create Tests/ directory structure mirroring Sources/ layout
- [ ] Add StyleTests.swift covering Style creation, copying, merging, and attribute application
- [ ] Add AttributedStringTests.swift for tag parsing, style composition, and rendering on different platforms
- [ ] Add tests for XML/HTML tag parsing edge cases mentioned in README features
- [ ] Add platform-specific tests using #if os(iOS) guards for Dynamic Type and platform differences
Add GitHub Actions CI/CD workflow for multi-platform Swift testing
The .github/FUNDING.yml file exists but there's no visible .github/workflows/ directory for automated testing. SwiftRichString supports iOS, macOS, tvOS, and watchOS - this requires a matrix-based GitHub Actions workflow to test all platforms on every PR, preventing regressions across different OS targets.
- [ ] Create .github/workflows/swift-tests.yml with matrix strategy for [iOS, macOS, tvOS]
- [ ] Configure xcode-select and scheme building using swift build and xcodebuild
- [ ] Add separate job for Swift Package Manager (swift test) validation
- [ ] Include code coverage reporting and upload to Codecov
- [ ] Add linting step using swiftlint if config exists, or create .swiftlint.yml
Complete and organize API documentation with DocC and inline code examples
The README is truncated mid-feature and lacks API documentation links. SwiftRichString's strength is elegant syntax for styling - this needs comprehensive DocC documentation with code examples for: Style initialization patterns, tag-based rendering syntax, remote image handling, and Dynamic Type integration. Documentation_Assests/ suggests there are examples to formalize.
- [ ] Create Documentation.docc/ structure with articles covering Style creation and composition
- [ ] Add code examples in source files using /// documentation comments for Style, AttributedString, and XML tag rendering classes
- [ ] Document the tag syntax with examples (tags used in DemoApp/ViewController.swift)
- [ ] Create a docpage for platform-specific features (iOS Dynamic Type, tvOS constraints, watchOS limitations)
- [ ] Generate and validate DocC output locally using swift build --product SwiftRichString
πΏGood first issues
- Add comprehensive unit tests for StyleXML tag parsing edge cases (nested tags, malformed XML, unknown tag attributes)βexisting test structure is in Configs/SwiftRichStringTests.plist but coverage likely incomplete.
- Create Swift Markdown documentation snippets (.md files) for each major class (Style, StyleXML, StyleRegEx) to match the inline README examplesβhelps new users navigate code faster.
- Extend ExampleTvOS/ViewController.swift with tvOS-specific styling examples (larger fonts for 10-foot UI, focus-based text highlighting) to showcase platform-specific capabilities mentioned in tagline.
βTop contributors
Click to expand
Top contributors
- @malcommac β 94 commits
- @stefanomondino β 3 commits
- @danqing β 2 commits
- @RolandasRazma β 1 commits
πRecent commits
Click to expand
Recent commits
e0b72d5β Updated logo (malcommac)7a10e77β Merge tag '3.7.2' into develop (malcommac)9bf4b5aβ Merge branch 'release/3.7.2' (malcommac)d031892β Bump to 3.7.2 (malcommac)38a4b3cβ fix #118: Fix for NSTextAttachment (malcommac)d2fd671β Merge branch 'release/3.7.1' (malcommac)ec8dd4eβ Merge tag '3.7.1' into develop (malcommac)9d6a455β Bump to 3.7.1 (malcommac)3cafb3bβ #104 Fixed an issue with escaping function of the strings (malcommac)4c9122fβ Merge branch 'release/3.7.0' (malcommac)
πSecurity observations
SwiftRichString appears to be a well-structured Swift library with low security risk. The codebase shows no critical vulnerabilities based on the available file structure analysis. As a UI/text-styling library with no apparent network operations, database access, or cryptographic operations, the attack surface is minimal. Main recommendations focus on dependency management, documentation of security practices, and ensuring example applications follow security best practices. The library itself does not appear to handle sensitive data or perform operations that would introduce common OWASP vulnerabilities. Regular dependency audits and security policy documentation would further strengthen the security posture.
- Low Β· Missing Package.swift Dependency Lock File β
Package.swift (not provided). The Package.swift file content was not provided in the analysis. Without visibility into the specific versions of dependencies, it's difficult to verify if known vulnerable versions of dependencies are being used. Fix: Ensure Package.swift is present and pins specific versions of all dependencies. Consider using Package.resolved for lock file management. Regularly audit dependencies for known vulnerabilities using tools likeswift package update --dry-runand security scanners. - Low Β· Example Applications with Minimal Security Configuration β
DemoApp/Info.plist, ExampleMac/Info.plist, ExampleTvOS/Info.plist, ExampleWatchOS Extension/Info.plist. Multiple example applications (DemoApp, ExampleMac, ExampleTvOS, ExampleWatchOS Extension) are present with Info.plist files. These example apps may have minimal security configurations and could serve as templates for insecure implementations if developers copy patterns from them. Fix: Review and harden example application configurations. Add security best practices documentation. Include comments in Info.plist files about required security settings (e.g., NSAllowsArbitraryLoads should be false, implement proper entitlements). - Low Β· No Visible Security Policy Documentation β
Repository root. No SECURITY.md or security policy file is evident in the repository structure. This makes it unclear how security vulnerabilities should be reported by researchers. Fix: Create a SECURITY.md file with vulnerability disclosure guidelines, responsible disclosure process, and contact information for security reports. Reference it in README.md.
LLM-derived; treat as a starting point, not a security audit.
πWhere to read next
- Open issues β current backlog
- Recent PRs β what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals β see the live page for receipts. Re-run on a new commit to refresh.