refs INC-36
fixes https://github.com/TryGhost/Ghost/issues/19796
- The tiers-only paywall was incorrectly rendering "Free". Example:
"This post is for subscribers of the Free, Silver and Gold tiers only"
- Steps to reproduce the issue:
1. Create a post with public visibility, publish it
2. Then swap the visibility to specific tiers. The default selects all
paid tiers. Leave it like that
3. Update the post. The paywall show Free, even though it should be
showing only the paid tiers
- This fix filters out the "free" tier when visibility is set to tiers,
before updating a Post or a Page. The fix includes bulk updates from the
list of Posts and Pages (right-click on a Post/Page > Change Access).
refs INC-36
fixes https://github.com/TryGhost/Ghost/issues/19796
- The tiers-only paywall was incorrectly rendering "Free". Example:
"This post is for subscribers of the Free, Silver and Gold tiers only"
- Steps to reproduce the issue:
1. Create a post with public visibility, publish it
2. Then swap the visibility to specific tiers. The default selects all
paid tiers. Leave it like that
3. Update the post. The paywall show Free, even though it should be
showing only the paid tiers
- This fix filters out the "free" tier when visibility is set to tiers,
before updating a Post or a Page. The fix includes bulk updates from the
list of Posts and Pages (right-click on a Post/Page > Change Access).
no ref
- The 'Get help' button was only adding margin on the left when accessed
through account management even though it is also shown on the
unsubscribe page accessed via link.
no issue
Bumps `Comments-UI` app version that contains an improvement to data loading:
- within the comments block we only use Admin auth to show moderation options on each displayed comment but we were always pre-emptively loading the `admin-auth` frame and making the associated Admin API user request. That loading has now been deferred until at least one comment has been displayed cutting down unnecessary requests on each post view
no issue
Bumps `Comments-UI` app version that contains an improvement to data loading:
- within the comments block we only use Admin auth to show moderation options on each displayed comment but we were always pre-emptively loading the `admin-auth` frame and making the associated Admin API user request. That loading has now been deferred until at least one comment has been displayed cutting down unnecessary requests on each post view
closes ENG-627
We were using `cheerio` to parse+modify+serialize our rendered HTML to modify links for member attribution. Cheerio's serializer has a [long-standing issue](https://github.com/cheeriojs/cheerio/issues/720) (that we've [had to deal with before](https://github.com/TryGhost/SDK/issues/124)) where it replaces single-quote attributes with double-quote attributes. That was resulting in broken rendering when content used single-quotes such as in HTML cards that have JSON data inside a `data-` attribute or otherwise used single-quotes to avoid escaping double-quotes in an attribute value.
- swapped the implementation that uses `cheerio` for one that uses `html5parser` to tokenize the html string, from there we can loop over the tokens and replace the href attribute values in the original string without touching any other part of the content. Avoids a full parse+serialize process which is both more costly and can result unexpected content changes due to serializer opinions.
- fixes the quote change bug
- uses tokenization directly to avoid cost of building a full AST
- updated Content API Posts snapshot
- one of our fixtures has a missing closing tag which we're no longer "fixing" with a full parse+serialize step in the link replacer (keeps modified src closer to original and better matches behaviour elsewhere in the app / without member-attribution applied)
- the link replacer no longer converts `attr=""` to `attr` (these are equivalent in the HTML spec so no change in behaviour other than preserving the original source html)
- added a benchmark test file comparing the two implementations because the link replacer runs on render so it's used in a hot path
- new implementation has a 3x performance improvement
- the separate files with the old/new implementations have been cleaned up but I've left the benchmark test file in place for future reference
Benchmark results comparing implementations:
```
❯ node test/benchmark.js
LinkReplacer
├─ cheerio: 5.03K /s ±2.20%
├─ html5parser: 16.5K /s ±0.43%
Completed benchmark in 0.9976526670455933s
┌─────────────┬─────────┬────────────┬─────────┬───────┐
│ (index) │ percent │ iterations │ current │ max │
├─────────────┼─────────┼────────────┼─────────┼───────┤
│ cheerio │ '' │ '5.03K/s' │ 5037 │ 5037 │
│ html5parser │ '' │ '16.5K/s' │ 16534 │ 16534 │
└─────────────┴─────────┴────────────┴─────────┴───────┘
```
no refs
- Tests run locally (US TZ) often always failed because the dates are
pushed to the en-GB locale. The test now forces the same TZ onto the
compared to date.
refs https://linear.app/tryghost/issue/ENG-677
- Portal was completely missing tests for `UnsubscribePage`
- `UnsubscribePage` is unique for Portal in that it needs to be able to
handle logged in and not-logged-in member state/interactions
- Various parts of Portal don't use a shared `GhostApi` instance, making
mocking all functionality impossible
- `UnsubscribePage` was updated to use `onAction` to bring it in line
with other Portal interactions while logged in
- Added checks for UI components for more precision in tests checking subscriptions within the UI
---------
Co-authored-by: Ronald Langeveld <hi@ronaldlangeveld.com>
no issue
- defers loading of `admin-auth` frame and it's API request until we are displaying some comments
- defers the frame load and API request until the comments box is scrolled into view
- eliminates the requests altogether for posts that have no comments
closes ENG-711
When an Admin is authenticated in Comments-UI we only add moderation options to the displayed comments so we don't need to pre-emptively load the `admin-auth` iframe and make the `/ghost/api/admin/users/me/` request until some comments are actually visible.
- used `state.comments.length` property to defer rendering of the admin auth frame until comments have been fetched (after box is scrolled into view) and the count is > 0
refs https://linear.app/tryghost/issue/ENG-712/
I don't think we ever need to respond with a 500 here, if the verify call
fails, we know that the token is unauthorized for use.
refs https://ghost.slack.com/archives/CTH5NDJMS/p1709230854358779
- Customer reported that some code they injected via the Code Injection
crashed the Preview in Ghost Settings.
- This wraps the function where the crash took place (according to
Sentry) in a try/catch to attempt to handle it gracefully.
- Added an additional Sentry log to better understand the situation
should it happen again.
refs. https://linear.app/tryghost/issue/DES-122/bookmark-card-issues
This PR addresses the following content card related problems:
1. The design of the following cards are more self-contained so it makes
more sense to use `px` for their font-sizes and spacings so it looks the
same regardless of the theme. Of course themes still can override these
values.
Updated cards to use `px` for font sizing:
- audio
- bookmark
- file
- product
2. So far header and signup cards had been using `rem` for font-sizes
and some sizing. This commit updates these to use `em` instead so that
it's consistent with all other cards.
3. The favicon sometimes is not available for bookmark cards. This PR also
fixes that by providing a default favicon for these cases.
no issue
Bumps `Comments-UI` app version that contains a few changes:
- comments data is now lazy-loaded with API requests being deferred until the comments block is scrolled into view, saving up-front visitor data usage as well as reducing server-load for page views where the comments are never seen
- comments data is now fetched from `/members/api/comments/{post_id}/` rather than using the post_id in the `filter` param to enable cache bucketing and cache invalidation
- `created_at` timestamp has been dropped from the initial comments data request so the results can be cached, on pagination requests the timestamp has been improved to use the created_at data from the response so it remains consistent and can also be cached
- `order` param has been dropped from API requests as the API has been updated to include our default ordering
refs https://linear.app/tryghost/issue/ENG-677
- UnsubscribePage is intended to be able to be used without logging in
to Portal. The app context (member state) was not synchronized when
logged in, causing conflicts in the client data vs. database.
- Now when a logged in member is found, the member object is manually
updated to reflect the API response(s).
no issue
- switches post browse requests to`/members/api/comments/post/:post_id/` to enable better cache bucketing
and invalidation
- removes `order` param from browse and replies requests
closes ENG-681
There's no need to provide an `order` param with every request in Comments-UI if the API has default ordering that matches our requirements. The order param makes logs more noisy/harder to read than they need to be so we want to get rid of it.
- modified comments API input serializer to add a default order param to the browse and replies endpoints when none is provided
- removed order param from the requests that Comments-UI makes
refs https://linear.app/tryghost/issue/ENG-676/
We want to make sure that we're not serving stale liked counts for
comments, which means we need to cache bust when they're liked/unliked
Unfortuantely this means we need to fetch the comment from the db so
that we have access to the post id.
refs https://linear.app/tryghost/issue/ENG-676/
This is the meat of the change and actually causes the cache to be
invalidated on adds and edits to the comments endpoints.
It doesn't currently include the liked/unliked actions at the moment
as we don't have easy access to the post id from those endpoints.
refs https://linear.app/tryghost/issue/ENG-676/
Now we have the case that there is no filter param, the simple string
approach fails. Instead we build up a URLSearchParams object which
makes it easier to handle conditional params & stringify it at the end.
refs https://linear.app/tryghost/issue/ENG-676/
This is pretty simple as we can reuse the existing browse method
on the CommentsController, but we need to add support for the post_id
option to the endpoint, for it to be added to the frame.
We also need to update the browse method to enforce the post_id on the
NQL filter. I initially tried this with string concatenation, but ran
into way too many bugs, so we're using a mongo transformer instead.