This change forces consistency around code font in Discourse once the
new
rich-editor is enabled
- This means all code blocks in Discourse will render with this font
- Additionally the markdown mode composer will render with this font
Additionally we make 3 small adjustments:
1. We disable ligatures which conflict with typographer
2. We add support for custom ligature settings
3. We adjust down font size, cause 14px ends up matching visually with a
16px non monospace font, this change is already in place previously on
posts
Example:

Since 3e4eac0fed05daedcdea50d6275e143469d55eda, the daily
`Jobs::BadgeGrant` scheduled job enqueues one `Jobs::BackfillBadge`
job per enabled badge. This can become problematic on large sites that
have alot of enabled badges as the long running queries executed by each
`Jobs::BackfillBadge` job may end up exhausting all available
database connections in a short span of time. To combat this, we are
limiting the `cluster_concurrency` of the `Jobs::BackfillBadge` job to
`1`.
Some themes make use of the category background color even when using
emojis or icons as the category style.
Therefore we should always allow the color selector to be visible when
editing the category.
Currently when using `register_topic_preloader_associations`, we are
not able to specify a condition that is evaluated at runtime.
This commit allows specifying a condition and also keeps backward
compatibility.
```
register_topic_preloader_associations(:linked_topic) { true }
register_topic_preloader_associations({
first_post: [uploads]
})
```
- adds .d-editor-container--rich-editor-enabled to d-editor-container
- conditionally swaps textarea to monospace when
siteSettings.rich_editor is enabled
We are doing this intentionally on the old composer when the
new rich editor is enabled to further differentiate the two and
to make it clear that markdown is the "source code"
On 1st April 2025, we start showing no icons if the icon name used is a
deprecated one and therefore no longer part of the svg set.
We'll continue showing the messages with the correct icon name to aid
correction of these names.
Console logging will now be done at an error level for such icons.
We retain the behaviour of raising an error for such icons in plugins
from svg_sprite.rb in test environments, but removed this from
icon-library.js as it's harder to test the actual expected behaviour of
returning the original icon now that it's not part of the deprecation
workflow. (sinon.stub doesn't work well here for `isTesting` - the
alternative would be to override the environment.js module with
`proxyquire`) In any case, once we remove the mapping logic, we won't be
raising errors in test environment either for this scenario.
iOS is automatically converting a double-hyphen (--) to an em-dash (–).
It may get in the way when we're trying to create an horizontal rule
with a ---, so this PR adds the "em-dash + hyphen" case to our input
rule regex.
This commit also ensures meta will resize with the textarea to avoid
meta being badly positioned.
I couldn't easily write a test working on all platforms.
Currently when using `register_topic_preloader_associations`, we are not
able to specify a condition that is evaluated at runtime.
This commit allows specifying a condition and also keeps backward
compatibility.
```
register_topic_preloader_associations({
association: :linked_topic, condition: ->(topic) { topic.custom_field.present? }
})
```
Before this fix a click on a d-menu trigger would fire a click on the
parent element, which could have undesired consequences.
This also fixes two things:
- moves float-kit/form-kit css files higher in the chain, so it's easier
to override
- increases the z-index of the notifications-tracking menu content or it
would be behind the timeline control
This property is used for the `isNew` and `isCreated` computed
properties, which are then used in templates. To make that work
correctly, we need to use `.set` or `@tracked`.
This change removes the foreground color category setting to simplify
the category creation and edit process for admins.
Instead we determine the highest contrasting color (either white or
black) based on the background color.
Contrast algorithm is based on:
https://www.w3.org/TR/AERT/#color-contrast
We also implement the value transformer as part of this change, which
allows overriding the category text color.
This commit allows the ProseMirror rich editor to display chat
transcripts copied from chat using the "Copy" button.
The BBCode usually looks something like this:
```
[chat quote="hunter;29856;2025-03-20T07:13:04Z" channel="design gems 🎉" channelId="95"]
haha **ok** _cool_
[/chat]
```
But there are several variations that must be accounted for:
* Single message from single user
* Multiple messages from a single and multiple users
* Messages inside chat threads
The rich transcript extension has to ignore many of the chat transcript
markdown
tokens because they simply aren't necessary -- none of the ProseMirror
nodes need
to be editable. So, we basically recreate the same HTML that the chat
transcript markdown
rule does in the `toDOM()` function. Maybe in future we want to make the
markdown rule
do less and have this HTML creation in one place, but for now we need to
mirror in both files.
---------
Co-authored-by: Renato Atilio <renato@discourse.org>
When a site has the `must_approve_users` setting enabled, new user data is stored on the Reviewable model, including username, email, and any other data that is entered during signup. If the user is rejected, that data is retained, without a clear path to deleting it.
In order to allow data that could be PII to be removed, without breaking Discourse's audit and logging trails, this change scrubs the PII from the relevant `ReviewableUser` and `UserHistory` objects, replacing that data with who scrubbed it, and why.
When passing our ProsemirrorEditor component an initial value,
we were sometimes passing `null`, which causes the error in
the title of this commit. The fix here is to handle `null`
gracefully as string.
We originally found this on the category edit page, since
we have a `<DEditor />` in the form template form for the
category.
The rules are:
- between 1 and 3 emojis: bigger emoji
- more than 3 or any text or node in the same paragraph: regular emoji
This is implemented through a prose mirror plugin, which try to be smart
and recompute only edited paragraphs. Full scan on first load.
---------
Co-authored-by: Renato Atilio <renato@discourse.org>
Some site settings support backfilling if the user specified it. This works fine for singular site settings sent to the SiteSettingsController#update endpoint, but with bulk save we need to support this for a list of settings as well.
This change alters the params format for SiteSetting::Update.
It also moves the backfill logic into the service.
* Prevents tag separators (commas by default) from wrapping separately
by using absolute positioning so they don't impact the width (thus a
comma can't wrap on its own, because a tag can't influence the width)
* Removes some whitespace creating extra space between categories and
tags (to better match desktop)
* Removes a redundant `flex-wrap: wrap` as `.discourse-tags` already
carries this
* Improves vertical alignment of commas (they were too high on mobile,
which is avoided on desktop with baseline alignment in flex)
* Fixes an issue where tag and separator color could be mismatched
because of a too-broad color being applied to all links
Before:

After:

Small alignment and sizing improvements for emojis/icons added to
categories.
We are also fixing the private category locked icon to retain the grey
color.
This aligns the composer with the post when the preview is
hidden.
Once the width gets a bit too narrow it occupies the full width.
[Screen Recording 2025-03-21 at 2.50.50
PM.webm](https://github.com/user-attachments/assets/4a854642-5b20-41fd-a478-7a943dfe0dd4)
The sidebar requires this to get a little magic numbery, but I tried to
anchor to predictable values otherwise.
---------
Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
This change disables the save and undo buttons for site settings while the setting is being saved. This gives some visual indication that saving is underway, and prevents unnecessarily sending more than one request (which will be no-ops anyway.)
This update adds a new value transformer to the `PostTextSelection`
component. This allows for dynamically setting a `preventClose`
property. This is useful to prevent the `onSelectionChange` listener
from firing a toolbar close. In particular, we want to use this in
Discourse AI to prevent the selection change from closing the toolbar
when selecting new text inside the explain popup
(https://github.com/discourse/discourse-ai/pull/1221)