-
Notifications
You must be signed in to change notification settings - Fork 14
Render full inbound Articles with rich text and inline images #109
base: main
Are you sure you want to change the base?
Conversation
Support abbr, del, pre, blockquote, code, strong, b, em, i, ul, ol, li and h1 to h5 tags in remote statuses.
- Increase font weight of headers and bold text - Increase blockquote's contrast - Avoid some extra margins
This creates a new column in the `statuses` table which keeps track of activity_pub_type, so in the case of a Note it will be blank (the default) and it will be a string "Article" if the received remote object is an AP Article. There is now a bunch of special case code in the formatters and sanitizers to handle Articles differently, as well as on the clientside.
|
This is actually a lot simpler of a change than I thought it'd be. Although we might want to merge glitch-soc's markdown formatting before this, to make sure the styles are merged properly. |
|
Currently looking into why the tests are failing. For now, here's a list of which tests they are, where they're located, and a summary of why they failed. The errors seem to be the same across all three ruby versions. Long ordered list of failing tests./spec/controllers/api/salmon_controller_spec.rb:21 # Api::SalmonController POST #update with valid post data contains XML in the request body ./spec/controllers/api/salmon_controller_spec.rb:25 # Api::SalmonController POST #update with valid post data returns http success ./spec/controllers/api/salmon_controller_spec.rb:29 # Api::SalmonController POST #update with valid post data creates remote account ./spec/controllers/api/salmon_controller_spec.rb:33 # Api::SalmonController POST #update with valid post data creates status ./spec/controllers/api/salmon_controller_spec.rb:37 # Api::SalmonController POST #update with valid post data creates mention for target account ./spec/controllers/api/subscriptions_controller_spec.rb:60 # Api::SubscriptionsController POST #update returns http success ./spec/controllers/api/subscriptions_controller_spec.rb:64 # Api::SubscriptionsController POST #update creates statuses for feed ./spec/controllers/api/v1/accounts/statuses_controller_spec.rb:15 # Api::V1::Accounts::StatusesController GET #index returns http success ./spec/controllers/api/v1/accounts/statuses_controller_spec.rb:35 # Api::V1::Accounts::StatusesController GET #index with exclude replies returns http success ./spec/controllers/api/v1/accounts/statuses_controller_spec.rb:47 # Api::V1::Accounts::StatusesController GET #index with only pinned returns http success ./spec/controllers/api/v1/conversations_controller_spec.rb:21 # Api::V1::ConversationsController GET #index returns http success ./spec/controllers/api/v1/conversations_controller_spec.rb:26 # Api::V1::ConversationsController GET #index returns pagination headers ./spec/controllers/api/v1/conversations_controller_spec.rb:31 # Api::V1::ConversationsController GET #index returns conversations ./spec/controllers/api/v1/favourites_controller_spec.rb:52 # Api::V1::FavouritesController GET #index with token with read scope and valid resource owner shows favourites owned by the user ./spec/controllers/api/v1/favourites_controller_spec.rb:61 # Api::V1::FavouritesController GET #index with token with read scope and valid resource owner adds pagination headers if necessary ./spec/controllers/api/v1/notifications_controller_spec.rb:102 # Api::V1::NotificationsController GET #index from specified user excludes favourite ./spec/controllers/api/v1/notifications_controller_spec.rb:106 # Api::V1::NotificationsController GET #index from specified user excludes mention ./spec/controllers/api/v1/notifications_controller_spec.rb:110 # Api::V1::NotificationsController GET #index from specified user excludes reblog ./spec/controllers/api/v1/notifications_controller_spec.rb:114 # Api::V1::NotificationsController GET #index from specified user excludes follow ./spec/controllers/api/v1/notifications_controller_spec.rb:124 # Api::V1::NotificationsController GET #index from nonexistent user returns http success ./spec/controllers/api/v1/notifications_controller_spec.rb:128 # Api::V1::NotificationsController GET #index from nonexistent user excludes favourite ./spec/controllers/api/v1/notifications_controller_spec.rb:132 # Api::V1::NotificationsController GET #index from nonexistent user excludes second favourite ./spec/controllers/api/v1/notifications_controller_spec.rb:136 # Api::V1::NotificationsController GET #index from nonexistent user excludes mention ./spec/controllers/api/v1/notifications_controller_spec.rb:140 # Api::V1::NotificationsController GET #index from nonexistent user excludes reblog ./spec/controllers/api/v1/notifications_controller_spec.rb:144 # Api::V1::NotificationsController GET #index from nonexistent user excludes follow ./spec/controllers/api/v1/notifications_controller_spec.rb:154 # Api::V1::NotificationsController GET #index with excluded mentions returns http success ./spec/controllers/api/v1/notifications_controller_spec.rb:158 # Api::V1::NotificationsController GET #index with excluded mentions includes reblog ./spec/controllers/api/v1/notifications_controller_spec.rb:162 # Api::V1::NotificationsController GET #index with excluded mentions excludes mention ./spec/controllers/api/v1/notifications_controller_spec.rb:166 # Api::V1::NotificationsController GET #index with excluded mentions includes favourite ./spec/controllers/api/v1/notifications_controller_spec.rb:170 # Api::V1::NotificationsController GET #index with excluded mentions includes third favourite ./spec/controllers/api/v1/notifications_controller_spec.rb:174 # Api::V1::NotificationsController GET #index with excluded mentions includes follow ./spec/controllers/api/v1/notifications_controller_spec.rb:68 # Api::V1::NotificationsController GET #index with no options returns http success ./spec/controllers/api/v1/notifications_controller_spec.rb:72 # Api::V1::NotificationsController GET #index with no options includes reblog ./spec/controllers/api/v1/notifications_controller_spec.rb:76 # Api::V1::NotificationsController GET #index with no options includes mention ./spec/controllers/api/v1/notifications_controller_spec.rb:80 # Api::V1::NotificationsController GET #index with no options includes favourite ./spec/controllers/api/v1/notifications_controller_spec.rb:84 # Api::V1::NotificationsController GET #index with no options includes follow ./spec/controllers/api/v1/notifications_controller_spec.rb:94 # Api::V1::NotificationsController GET #index from specified user returns http success ./spec/controllers/api/v1/notifications_controller_spec.rb:98 # Api::V1::NotificationsController GET #index from specified user includes favourite ./spec/controllers/api/v1/statuses_controller_spec.rb:107 # Api::V1::StatusesController without an oauth token with a public status GET #show returns http success ./spec/controllers/api/v1/statuses_controller_spec.rb:118 # Api::V1::StatusesController without an oauth token with a public status GET #context returns http success ./spec/controllers/api/v1/statuses_controller_spec.rb:19 # Api::V1::StatusesController with an oauth token GET #show returns http success ./spec/controllers/api/v1/statuses_controller_spec.rb:33 # Api::V1::StatusesController with an oauth token GET #context returns http success ./spec/controllers/api/v1/statuses_controller_spec.rb:46 # Api::V1::StatusesController with an oauth token POST #create returns http success ./spec/controllers/api/v1/statuses_controller_spec.rb:59 # Api::V1::StatusesController with an oauth token DELETE #destroy returns http success ./spec/controllers/api/v1/statuses_controller_spec.rb:63 # Api::V1::StatusesController with an oauth token DELETE #destroy removes the status ./spec/controllers/api/v1/statuses/favourites_controller_spec.rb:24 # Api::V1::Statuses::FavouritesController with an oauth token POST #create returns http success ./spec/controllers/api/v1/statuses/favourites_controller_spec.rb:28 # Api::V1::Statuses::FavouritesController with an oauth token POST #create updates the favourites count ./spec/controllers/api/v1/statuses/favourites_controller_spec.rb:32 # Api::V1::Statuses::FavouritesController with an oauth token POST #create updates the favourited attribute ./spec/controllers/api/v1/statuses/favourites_controller_spec.rb:36 # Api::V1::Statuses::FavouritesController with an oauth token POST #create return json with updated attributes ./spec/controllers/api/v1/statuses/favourites_controller_spec.rb:53 # Api::V1::Statuses::FavouritesController with an oauth token POST #destroy returns http success ./spec/controllers/api/v1/statuses/favourites_controller_spec.rb:57 # Api::V1::Statuses::FavouritesController with an oauth token POST #destroy updates the favourites count ./spec/controllers/api/v1/statuses/favourites_controller_spec.rb:61 # Api::V1::Statuses::FavouritesController with an oauth token POST #destroy updates the favourited attribute ./spec/controllers/api/v1/statuses/mutes_controller_spec.rb:24 # Api::V1::Statuses::MutesController with an oauth token POST #create returns http success ./spec/controllers/api/v1/statuses/mutes_controller_spec.rb:28 # Api::V1::Statuses::MutesController with an oauth token POST #create creates a conversation mute ./spec/controllers/api/v1/statuses/mutes_controller_spec.rb:41 # Api::V1::Statuses::MutesController with an oauth token POST #destroy returns http success ./spec/controllers/api/v1/statuses/mutes_controller_spec.rb:45 # Api::V1::Statuses::MutesController with an oauth token POST #destroy destroys the conversation mute ./spec/controllers/api/v1/statuses/pins_controller_spec.rb:24 # Api::V1::Statuses::PinsController with an oauth token POST #create returns http success ./spec/controllers/api/v1/statuses/pins_controller_spec.rb:28 # Api::V1::Statuses::PinsController with an oauth token POST #create updates the pinned attribute ./spec/controllers/api/v1/statuses/pins_controller_spec.rb:32 # Api::V1::Statuses::PinsController with an oauth token POST #create return json with updated attributes ./spec/controllers/api/v1/statuses/pins_controller_spec.rb:48 # Api::V1::Statuses::PinsController with an oauth token POST #destroy returns http success ./spec/controllers/api/v1/statuses/pins_controller_spec.rb:52 # Api::V1::Statuses::PinsController with an oauth token POST #destroy updates the pinned attribute ./spec/controllers/api/v1/statuses/reblogs_controller_spec.rb:24 # Api::V1::Statuses::ReblogsController with an oauth token POST #create returns http success ./spec/controllers/api/v1/statuses/reblogs_controller_spec.rb:28 # Api::V1::Statuses::ReblogsController with an oauth token POST #create updates the reblogs count ./spec/controllers/api/v1/statuses/reblogs_controller_spec.rb:32 # Api::V1::Statuses::ReblogsController with an oauth token POST #create updates the reblogged attribute ./spec/controllers/api/v1/statuses/reblogs_controller_spec.rb:36 # Api::V1::Statuses::ReblogsController with an oauth token POST #create return json with updated attributes ./spec/controllers/api/v1/statuses/reblogs_controller_spec.rb:53 # Api::V1::Statuses::ReblogsController with an oauth token POST #destroy returns http success ./spec/controllers/api/v1/statuses/reblogs_controller_spec.rb:57 # Api::V1::Statuses::ReblogsController with an oauth token POST #destroy updates the reblogs count ./spec/controllers/api/v1/statuses/reblogs_controller_spec.rb:61 # Api::V1::Statuses::ReblogsController with an oauth token POST #destroy updates the reblogged attribute ./spec/controllers/api/v1/timelines/home_controller_spec.rb:23 # Api::V1::Timelines::HomeController with a user context GET #show returns http success ./spec/controllers/api/v1/timelines/list_controller_spec.rb:25 # Api::V1::Timelines::ListController with a user context GET #show returns http success ./spec/controllers/api/v1/timelines/public_controller_spec.rb:22 # Api::V1::Timelines::PublicController with a user context GET #show returns http success ./spec/controllers/api/v1/timelines/public_controller_spec.rb:35 # Api::V1::Timelines::PublicController with a user context GET #show with local only returns http success ./spec/controllers/api/v1/timelines/tag_controller_spec.rb:22 # Api::V1::Timelines::TagController with a user context GET #show returns http success ./spec/lib/activitypub/activity/announce_spec.rb:114 # ActivityPub::Activity::Announce#perform when the sender is relayed and the relay is enabled creates a reblog by sender of status ./spec/lib/activitypub/activity/announce_spec.rb:45 # ActivityPub::Activity::Announce#perform when sender is followed by a local account a known status creates a reblog by sender of status ./spec/lib/activitypub/activity/announce_spec.rb:53 # ActivityPub::Activity::Announce#perform when sender is followed by a local account an unknown status creates a reblog by sender of status ./spec/lib/activitypub/activity/announce_spec.rb:72 # ActivityPub::Activity::Announce#perform when sender is followed by a local account self-boost of a previously unknown status with correct attributedTo creates a reblog by sender of status ./spec/lib/activitypub/activity/announce_spec.rb:87 # ActivityPub::Activity::Announce#perform when the status belongs to a local user creates a reblog by sender of status ./spec/lib/activitypub/activity/create_spec.rb:115 # ActivityPub::Activity::Create#perform when fetching private creates status ./spec/lib/activitypub/activity/create_spec.rb:135 # ActivityPub::Activity::Create#perform when fetching limited creates status ./spec/lib/activitypub/activity/create_spec.rb:142 # ActivityPub::Activity::Create#perform when fetching limited creates silent mention ./spec/lib/activitypub/activity/create_spec.rb:164 # ActivityPub::Activity::Create#perform when fetching direct creates status ./spec/lib/activitypub/activity/create_spec.rb:184 # ActivityPub::Activity::Create#perform when fetching as a reply creates status ./spec/lib/activitypub/activity/create_spec.rb:212 # ActivityPub::Activity::Create#perform when fetching with mentions creates status ./spec/lib/activitypub/activity/create_spec.rb:234 # ActivityPub::Activity::Create#perform when fetching with mentions missing href creates status ./spec/lib/activitypub/activity/create_spec.rb:256 # ActivityPub::Activity::Create#perform when fetching with media attachments creates status ./spec/lib/activitypub/activity/create_spec.rb:281 # ActivityPub::Activity::Create#perform when fetching with media attachments with focal points creates status ./spec/lib/activitypub/activity/create_spec.rb:304 # ActivityPub::Activity::Create#perform when fetching with media attachments missing url creates status ./spec/lib/activitypub/activity/create_spec.rb:326 # ActivityPub::Activity::Create#perform when fetching with hashtags creates status ./spec/lib/activitypub/activity/create_spec.rb:349 # ActivityPub::Activity::Create#perform when fetching with hashtags missing name creates status ./spec/lib/activitypub/activity/create_spec.rb:373 # ActivityPub::Activity::Create#perform when fetching with emojis creates status ./spec/lib/activitypub/activity/create_spec.rb:398 # ActivityPub::Activity::Create#perform when fetching with emojis missing name creates status ./spec/lib/activitypub/activity/create_spec.rb:419 # ActivityPub::Activity::Create#perform when fetching with emojis missing icon creates status ./spec/lib/activitypub/activity/create_spec.rb:450 # ActivityPub::Activity::Create#perform when fetching with poll creates status ./spec/lib/activitypub/activity/create_spec.rb:456 # ActivityPub::Activity::Create#perform when fetching with poll creates a poll ./spec/lib/activitypub/activity/create_spec.rb:525 # ActivityPub::Activity::Create#perform when sender is followed by local users creates status ./spec/lib/activitypub/activity/create_spec.rb:54 # ActivityPub::Activity::Create#perform when fetching standalone creates status ./spec/lib/activitypub/activity/create_spec.rb:551 # ActivityPub::Activity::Create#perform when sender replies to local status creates status ./spec/lib/activitypub/activity/create_spec.rb:577 # ActivityPub::Activity::Create#perform when sender targets a local user creates status ./spec/lib/activitypub/activity/create_spec.rb:603 # ActivityPub::Activity::Create#perform when sender cc's a local user creates status ./spec/lib/activitypub/activity/create_spec.rb:61 # ActivityPub::Activity::Create#perform when fetching standalone missing to/cc defaults to direct privacy ./spec/lib/activitypub/activity/create_spec.rb:79 # ActivityPub::Activity::Create#perform when fetching public creates status ./spec/lib/activitypub/activity/create_spec.rb:97 # ActivityPub::Activity::Create#perform when fetching unlisted creates status ./spec/lib/feed_manager_spec.rb:109 # FeedManager#filter? for home feed returns false for status by followee mentioning another account ./spec/lib/feed_manager_spec.rb:115 # FeedManager#filter? for home feed returns true for status by followee mentioning blocked account ./spec/lib/feed_manager_spec.rb:156 # FeedManager#filter? for mentions feed returns true for status that mentions blocked account ./spec/lib/ostatus/atom_serializer_spec.rb:410 # OStatus::AtomSerializer#entry if status is present returns element whose rendered view triggers creation when processed ./spec/services/activitypub/fetch_remote_status_service_spec.rb:33 # ActivityPub::FetchRemoteStatusService#call with Note object creates status ./spec/services/activitypub/fetch_remote_status_service_spec.rb:65 # ActivityPub::FetchRemoteStatusService#call with Video object creates status ./spec/services/batched_remove_status_service_spec.rb:32 # BatchedRemoveStatusService removes statuses from author's home feed ./spec/services/batched_remove_status_service_spec.rb:36 # BatchedRemoveStatusService removes statuses from local follower's home feed ./spec/services/batched_remove_status_service_spec.rb:40 # BatchedRemoveStatusService notifies streaming API of followers ./spec/services/batched_remove_status_service_spec.rb:44 # BatchedRemoveStatusService notifies streaming API of author ./spec/services/batched_remove_status_service_spec.rb:48 # BatchedRemoveStatusService notifies streaming API of public timeline ./spec/services/batched_remove_status_service_spec.rb:52 # BatchedRemoveStatusService sends PuSH update to PuSH subscribers ./spec/services/batched_remove_status_service_spec.rb:58 # BatchedRemoveStatusService sends Salmon slap to previously mentioned users ./spec/services/batched_remove_status_service_spec.rb:65 # BatchedRemoveStatusService sends delete activity to followers ./spec/services/fan_out_on_write_service_spec.rb:21 # FanOutOnWriteService delivers status to home timeline ./spec/services/fan_out_on_write_service_spec.rb:25 # FanOutOnWriteService delivers status to local followers ./spec/services/fan_out_on_write_service_spec.rb:30 # FanOutOnWriteService delivers status to hashtag ./spec/services/fan_out_on_write_service_spec.rb:34 # FanOutOnWriteService delivers status to public timeline ./spec/services/favourite_service_spec.rb:16 # FavouriteService local creates a favourite ./spec/services/fetch_remote_status_service_spec.rb:28 # FetchRemoteStatusService protocol is :activitypub creates status ./spec/services/notify_service_spec.rb:102 # NotifyService reblogs shows reblogs when explicitly enabled ./spec/services/notify_service_spec.rb:107 # NotifyService reblogs shows reblogs when disabled ./spec/services/notify_service_spec.rb:78 # NotifyService for direct messages if recipient is supposed to be following sender if the message chain initiated by recipient and is direct message does notify ./spec/services/notify_service_spec.rb:87 # NotifyService for direct messages if recipient is NOT supposed to be following sender does notify ./spec/services/notify_service_spec.rb:97 # NotifyService reblogs shows reblogs by default ./spec/services/post_status_service_spec.rb:103 # PostStatusService creates a status for the given application ./spec/services/post_status_service_spec.rb:112 # PostStatusService creates a status with a language set ./spec/services/post_status_service_spec.rb:121 # PostStatusService processes mentions ./spec/services/post_status_service_spec.rb:133 # PostStatusService processes hashtags ./spec/services/post_status_service_spec.rb:159 # PostStatusService crawls links ./spec/services/post_status_service_spec.rb:168 # PostStatusService attaches the given media to the created status ./spec/services/post_status_service_spec.rb:16 # PostStatusService creates a new response status ./spec/services/post_status_service_spec.rb:181 # PostStatusService does not attach media from another account to the created status ./spec/services/post_status_service_spec.rb:233 # PostStatusService returns existing status when used twice with idempotency key ./spec/services/post_status_service_spec.rb:53 # PostStatusService creates response to the original status of boost ./spec/services/post_status_service_spec.rb:66 # PostStatusService creates a sensitive status ./spec/services/post_status_service_spec.rb:6 # PostStatusService creates a new status ./spec/services/post_status_service_spec.rb:73 # PostStatusService creates a status with spoiler text ./spec/services/post_status_service_spec.rb:82 # PostStatusService creates a status with empty default spoiler text ./spec/services/post_status_service_spec.rb:89 # PostStatusService creates a status with the given visibility ./spec/services/post_status_service_spec.rb:96 # PostStatusService creates a status with limited visibility for silenced users ./spec/services/reblog_service_spec.rb:20 # ReblogService creates a reblog with appropriate visibility boosting privately reblogs privately ./spec/services/reblog_service_spec.rb:29 # ReblogService creates a reblog with appropriate visibility public reblogs of private toots should remain private reblogs privately ./spec/services/reblog_service_spec.rb:46 # ReblogService OStatus creates a reblog ./spec/services/reblog_service_spec.rb:50 # ReblogService OStatus sends a Salmon slap for a remote reblog ./spec/services/reblog_service_spec.rb:67 # ReblogService ActivityPub creates a reblog ./spec/services/reblog_service_spec.rb:72 # ReblogService ActivityPub after_create_commit :store_uri keeps consistent reblog count ./spec/services/reblog_service_spec.rb:77 # ReblogService ActivityPub distributes to followers ./spec/services/reblog_service_spec.rb:81 # ReblogService ActivityPub sends an announce activity to the author ./spec/services/remove_status_service_spec.rb:27 # RemoveStatusService removes status from author's home feed ./spec/services/remove_status_service_spec.rb:31 # RemoveStatusService removes status from local follower's home feed ./spec/services/remove_status_service_spec.rb:35 # RemoveStatusService sends PuSH update to PuSH subscribers ./spec/services/remove_status_service_spec.rb:41 # RemoveStatusService sends delete activity to followers ./spec/services/remove_status_service_spec.rb:45 # RemoveStatusService sends Salmon slap to previously mentioned users ./spec/services/remove_status_service_spec.rb:52 # RemoveStatusService sends delete activity to rebloggers ./spec/workers/publish_scheduled_status_worker_spec.rb:15 # PublishScheduledStatusWorker perform creates a status ./spec/workers/publish_scheduled_status_worker_spec.rb:19 # PublishScheduledStatusWorker perform removes the scheduled status |
|
@dariusk Hmm, so far the most common factor in all the errors is a missing |
|
Yeah, I have no experience with unit/integration tests in Mastodon. I'll see what I can do. |
…rk into florence-pr/articles
57df8a1 to
5452b7a
Compare
|
@1011X I do have the tests passing, though I have not written new tests for this feature yet. Still, it's a start. |
|
I've added some simple tests to make sure that
I think this is ready for review at this point. |
|
BTW where can I contribute documentation for this? If it's something I can include in this PR I'm happy to do so. Otherwise I can provide docs somewhere else if this gets merged. |
We are still working out the details about documentation, but we had a few others things get in the way this past week when we were supposed to reach a decision. We'll let you know when we got that stuff ready. |
|
So to clarify, this change is ready to merge? |
|
I'm the author of the PR, I thought it was the job of reviewers to
determine whether it's ready to merge.
It is feature complete and tests are provided, if that's what you mean.
…On Wed, Jul 31, 2019, 7:30 AM Clar Fon ***@***.***> wrote:
So to clarify, this change is ready to merge?
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#109?email_source=notifications&email_token=AACBBVSSRV23NFJ47NNPOEDQCGOXRA5CNFSM4HZO4EU2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3HOAEY#issuecomment-516874259>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AACBBVXQNVVE2TKBSNDVBPLQCGOXRANCNFSM4HZO4EUQ>
.
|
|
Yes, sorry, that's what I meant. Also I am in part talking to you and also in part talking to everyone else looking at this PR. 😅 |
|
Should be good to go. |
|
I don't think I'm qualified to review this. Probably better handled by @clarfon. |
|
My only concern is making sure that this and the markdown rendering that glitch-social does play nicely together. Although, I think that it'd be fair to block 0.2.0 on merging that as well as this. We should probably discuss this before merge, though, to double check that this is okay to plan for the next release. In terms of the code, everything is fine to me, although I would also suggest running yarn install
bundle install
yarn build:development
yarn manage:translations |
|
FYI @dariusk I am going to pull these changes into my fork as well :) |
So @mal0ki asked me to make this PR. Here it is!
The idea is to provide a "read article" link similar to "read more" when Florence receives an AP object of
Articletype. So if you subscribe directly to a blog on write.as or similar, you can read the full article, with rich text, in Florence.What it looks like
Here are some preview images. These are running Florence from this PR branch. The "article" posts here come from a test instance of WriteFreely.
How it appears in timelines:
What it looks like when you click to focus an article:
What it looks like with inline images:
You'll notice that link is hard to read but it's just rendering with the default mastodon theme. I'm working on the assumption that it'll be using whatever link theming the user has set.
Tech notes
This is my first time adding a column to a table in Rails. I'm probably doing something wrong in terms of database design. My implementation generally feels a little "hacky" and I'm sure there are more elegant solutions. I'm happy to implement these if someone will suggest to me what they are.
I've made a new
activity_typecolumn in thestatusestable which at the moment says"Article"if the server sees anArticleobject come in, but is otherwise empty. This field is used to then change how the server renders what's in there.A note on images
Inline images for posts are cached locally the moment the object is received by the server, so user IPs aren't exposed when they read an article with images on their client. I use the same mechanism that already exists for creating media attachments.