diff --git a/NeoDB/NeoDB.xcodeproj/project.pbxproj b/NeoDB/NeoDB.xcodeproj/project.pbxproj index 7fe1246..e9742a6 100644 --- a/NeoDB/NeoDB.xcodeproj/project.pbxproj +++ b/NeoDB/NeoDB.xcodeproj/project.pbxproj @@ -7,8 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 2403E7662D2EF7CC00ED4CB5 /* HTML2Markdown in Frameworks */ = {isa = PBXBuildFile; productRef = 2403E7652D2EF7CC00ED4CB5 /* HTML2Markdown */; }; 242688402D2A9E0D00DFAAC1 /* InjectionNext in Frameworks */ = {isa = PBXBuildFile; productRef = 2426883F2D2A9E0D00DFAAC1 /* InjectionNext */; }; 245FD2132D2A817A005B55B3 /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 245FD2122D2A817A005B55B3 /* KeychainSwift */; }; + 249B951D2D2EF5C800FE3D95 /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 249B951C2D2EF5C800FE3D95 /* MarkdownUI */; }; 24D1BE412D2A9F340063B530 /* Inject in Frameworks */ = {isa = PBXBuildFile; productRef = 24D1BE402D2A9F340063B530 /* Inject */; }; /* End PBXBuildFile section */ @@ -73,7 +75,9 @@ files = ( 245FD2132D2A817A005B55B3 /* KeychainSwift in Frameworks */, 242688402D2A9E0D00DFAAC1 /* InjectionNext in Frameworks */, + 2403E7662D2EF7CC00ED4CB5 /* HTML2Markdown in Frameworks */, 24D1BE412D2A9F340063B530 /* Inject in Frameworks */, + 249B951D2D2EF5C800FE3D95 /* MarkdownUI in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -145,6 +149,8 @@ 245FD2122D2A817A005B55B3 /* KeychainSwift */, 2426883F2D2A9E0D00DFAAC1 /* InjectionNext */, 24D1BE402D2A9F340063B530 /* Inject */, + 249B951C2D2EF5C800FE3D95 /* MarkdownUI */, + 2403E7652D2EF7CC00ED4CB5 /* HTML2Markdown */, ); productName = NeoDB; productReference = 24CEACEF2D0DA6200083D4BA /* NeoDB.app */; @@ -232,6 +238,8 @@ 245FD2112D2A817A005B55B3 /* XCRemoteSwiftPackageReference "keychain-swift" */, 2415DF2F2D2A9DCC00DAC07F /* XCRemoteSwiftPackageReference "InjectionNext" */, 24AFFC8E2D2A9F040085A6D0 /* XCRemoteSwiftPackageReference "Inject" */, + 249B95192D2EF5B500FE3D95 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */, + 2403E7622D2EF7AE00ED4CB5 /* XCRemoteSwiftPackageReference "HTML2Markdown" */, ); preferredProjectObjectVersion = 77; productRefGroup = 24CEACF02D0DA6200083D4BA /* Products */; @@ -631,6 +639,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 2403E7622D2EF7AE00ED4CB5 /* XCRemoteSwiftPackageReference "HTML2Markdown" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/divadretlaw/HTML2Markdown"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.0.2; + }; + }; 2415DF2F2D2A9DCC00DAC07F /* XCRemoteSwiftPackageReference "InjectionNext" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/johnno1962/InjectionNext"; @@ -647,6 +663,14 @@ minimumVersion = 24.0.0; }; }; + 249B95192D2EF5B500FE3D95 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/gonzalezreal/swift-markdown-ui"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.4.1; + }; + }; 24AFFC8E2D2A9F040085A6D0 /* XCRemoteSwiftPackageReference "Inject" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/krzysztofzablocki/Inject.git"; @@ -658,6 +682,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 2403E7652D2EF7CC00ED4CB5 /* HTML2Markdown */ = { + isa = XCSwiftPackageProductDependency; + package = 2403E7622D2EF7AE00ED4CB5 /* XCRemoteSwiftPackageReference "HTML2Markdown" */; + productName = HTML2Markdown; + }; 2426883F2D2A9E0D00DFAAC1 /* InjectionNext */ = { isa = XCSwiftPackageProductDependency; package = 2415DF2F2D2A9DCC00DAC07F /* XCRemoteSwiftPackageReference "InjectionNext" */; @@ -668,6 +697,11 @@ package = 245FD2112D2A817A005B55B3 /* XCRemoteSwiftPackageReference "keychain-swift" */; productName = KeychainSwift; }; + 249B951C2D2EF5C800FE3D95 /* MarkdownUI */ = { + isa = XCSwiftPackageProductDependency; + package = 249B95192D2EF5B500FE3D95 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */; + productName = MarkdownUI; + }; 24D1BE402D2A9F340063B530 /* Inject */ = { isa = XCSwiftPackageProductDependency; package = 24AFFC8E2D2A9F040085A6D0 /* XCRemoteSwiftPackageReference "Inject" */; diff --git a/NeoDB/NeoDB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/NeoDB/NeoDB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index de23583..2338c88 100644 --- a/NeoDB/NeoDB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/NeoDB/NeoDB.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "657466b00a4cf16eda52a23bd963af27f6da71d69047ed11c12b2a367c93a6ba", + "originHash" : "3e7121260e0594c3a45cf5123fec5e95f05a024e1d9a426ddcda347f395a2ad2", "pins" : [ + { + "identity" : "html2markdown", + "kind" : "remoteSourceControl", + "location" : "https://github.com/divadretlaw/HTML2Markdown", + "state" : { + "revision" : "fe37711094b261d9fceeaf021143002ba37e563e", + "version" : "3.0.2" + } + }, { "identity" : "inject", "kind" : "remoteSourceControl", @@ -27,6 +36,42 @@ "revision" : "5e1b02b6a9dac2a759a1d5dbc175c86bd192a608", "version" : "24.0.0" } + }, + { + "identity" : "networkimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/NetworkImage", + "state" : { + "revision" : "2849f5323265386e200484b0d0f896e73c3411b9", + "version" : "6.0.1" + } + }, + { + "identity" : "swift-cmark", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-cmark", + "state" : { + "revision" : "3ccff77b2dc5b96b77db3da0d68d28068593fa53", + "version" : "0.5.0" + } + }, + { + "identity" : "swift-markdown-ui", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/swift-markdown-ui", + "state" : { + "revision" : "5f613358148239d0292c0cef674a3c2314737f9e", + "version" : "2.4.1" + } + }, + { + "identity" : "swiftsoup", + "kind" : "remoteSourceControl", + "location" : "https://github.com/scinfu/SwiftSoup.git", + "state" : { + "revision" : "0837db354faf9c9deb710dc597046edaadf5360f", + "version" : "2.7.6" + } } ], "version" : 3 diff --git a/NeoDB/NeoDB/References/Cursor/timeline_local.md b/NeoDB/NeoDB/References/Cursor/timeline_local.md index a12c333..6ecdc5a 100644 --- a/NeoDB/NeoDB/References/Cursor/timeline_local.md +++ b/NeoDB/NeoDB/References/Cursor/timeline_local.md @@ -1,7 +1,7 @@ # Timeline Local-Only Implementation ## Overview -Modified TimelineService to show only local statuses from the instance. +Modified TimelineService to show only local statuses from the instance and properly render HTML content. ## API Reference From Mastodon API documentation: @@ -9,18 +9,46 @@ From Mastodon API documentation: - Parameter: `local=true` to show only local statuses - Default: Shows both local and remote statuses (local=false) +## Content Rendering +Status content comes in HTML format with the following features: +- Links with href attributes +- Mentions with rel attributes +- Emoji ratings (πŸŒ• for filled stars) +- Paragraphs with spacing + +### HTML Example +```html +

ηœ‹ιŽ 甡影名称 πŸŒ•πŸŒ•πŸŒ•πŸŒ•πŸŒ•

+``` + +### Implementation Details +1. Added SwiftDown package for HTML parsing +2. Created custom AttributedString converter +3. Added link handling support +4. Implemented emoji rating display + +## Dependencies +Required SPM packages: +- SwiftDown: HTML and Markdown parsing +- SwiftSoup (optional): Advanced HTML manipulation + ## Implementation Details 1. Added local parameter to URL query 2. Set local=true by default to show only local statuses 3. Improved error logging for better debugging +4. Added HTML content parsing and rendering +5. Implemented link handling and styling ## Design Rationale - Local-only timeline provides more relevant content for NeoDB users - Reduces noise from remote instances - Improves performance by reducing data load - Better content moderation as all content is from the same instance +- Rich text rendering enhances readability and interaction ## Code Changes - Modified getTimeline method in TimelineService - Added local parameter to URLComponents -- Updated documentation \ No newline at end of file +- Added HTML content rendering support +- Updated documentation +- Enhanced StatusView with rich text support \ No newline at end of file diff --git a/NeoDB/NeoDB/References/Packages/HTML2Markdown.md b/NeoDB/NeoDB/References/Packages/HTML2Markdown.md new file mode 100644 index 0000000..d73afbb --- /dev/null +++ b/NeoDB/NeoDB/References/Packages/HTML2Markdown.md @@ -0,0 +1,41 @@ +# HTML2Markdown + +## What is this? + +It's a Swift Package which attempts to convert HTML into Markdown. + +## How do I use it? + +```swift +let html = "

This is a terrible idea.
I must be daft.

" + +do { + let dom = try HTMLParser().parse(html: html) + let markdown = dom.markdownFormatted(options: .unorderedListBullets) + print(markdown) +} catch { + // parsing error +} +``` + +This generates the following markdown string: + +``` +This is a *terrible* idea.\nI must be daft. +``` + +## What is supported? + +* `` and `` for highlighting text +* ordered and unordered lists (`
    ` and `