`escape` from `pretty-text/sanitizer` is a re-export of the same
function defined in `discourse-common`. Updating the import paths
across the codebase to use the `discourse-common` import path.
`escape` is a rather simple function that can be accomplished with
a regular expression in `discourse-common`.
On the other hand, the remaining parts in `pretty-text/sanitizer`
has a lot of code, PLUS it depend on the rather heavy "xss" NPM
library.
Currently, most of the consumers of `pretty-text/sanitizer` are of
the `{ escape }` varient. This is resolved by this PR.
The remaining usages are either:
1. via/through `PrettyText` which is essentially gated behind
loading the markdown-it bundle, OR
2. via `sanitize` from `discourse/lib/text`
I believe we may ultimately be able to move all the usages to behind
the markdown-it bundle (or, equivilantly, set up another lazy bundle
for `sanitize`) and be able to shed the sanitization code and the
"xss" library from the initial page load.
`discourse/lib/text` also defines a `sanitizeAsync` which is gated
behind loading the markdown-it bundle.
Looking through the usages of `sanitize`, I believe most of these
can be safely switched to use `sanitizeAsync`, in that they are
already in an asynchrnous path that handles a server response. Most
of them are actually rendering a piece of server-generated HTML
message as flash message, so I am not sure there really is value in
sanitizing (we should be able to trust our own server?), but in any
case, code-wise, they should already be able to absorb the async
just fine.
I am not sure if `sanitize` and `sanitizeAsync` are actually API
compatible – they both take `options` but I think those `options` do
pretty different things. This is somethign for another person to
investigate down the road in another PR.
According to `all-the-plugins`, `discourse-graphviz` also import
from this location, so perhaps we should PR to update. That being
said, it doesn't really hurt anything to keep the alias around for
a while.
This started out as a seemingly benign refactor to replace the
`require` for `withPluginApi` to an actual import. However, it
broke the test in seemingly random places.
It turns out that in serveral places, we are calling `isTesting()`
in module scope and assigning the result to a constant. For example
we do that in the composer service to disable checking drafts when
testing.
This is problematic because `isTesting` doesn't really set until
the `discourse-bootstrap` initializer is run, and so any modules
that are evaluated before then will have locked in the wrong value
for `isTesting()`.
If we are going to use and treat `isTesting()` like a constant then
we will have to make sure we set it sufficiently early before any
code-loading happens.
Previously, the `user-tips` service included a couple of calls to `next()`. These were introduced to work around errors like
```
You attempted to update `availableTips` on `<UserTips:ember659>`, but it had already been used previously in the same computation
```
These errors come from the fact that various `<UserTip>` components are rendering at slightly different times in the runloop and stepping on each other. Normally this doesn't happen in Ember, but the implementation details of our 'Widget' system and its 'RenderGlimmer' helper mean that RenderGlimmer components are rendered later than normal Ember components. Using `next()` avoids the problem because it means that all the updates are scheduled together in the following runloop interation.
However, the use of `next()` can create some subtle timing issues, which have been evident in the recent flakiness of some qunit tests. This commit makes a few changes to improve the situation:
1. Use a TrackedMap to provide fine-grained `shouldRender()` reactivity for each user-tip id. That means that different user tips will not be trying to update the same piece of tracked state (previously the entire `availableTips` array was `@tracked`, and was completely re-assigned every time a new `<UserTip>` was rendered
2. Avoid reassigning any tracked state unless the value has actually changed
3. Remove the `next()` workarounds
- Introduces a `deepFreeze` helper to block any mutations to the current-user fixture
- Add `cloneJSON` to any places which were previously causing mutations
Currently, the UI section that contains the title+category+tags of a topic list item (the mobile version) has only one and very generic CSS class, `.right`. Plugins and themes that need to target this section for styling would have to use awkward/very specific CSS selectors in order to avoid incorrectly styling other elements that happen to have the same generic CSS class.
This commit adds an additional class `.topic-item-metadata` to the section to allow easier and more maintainable styling for it.
See https://github.com/discourse/discourse-clickable-topic/pull/4 for a theme that will benefit from this change.
Normally, modules defined under `blah/index` can be imported as `blah`. This is also true of Ember resolver lookups - `<MyComponent />` should resolve to the same as `<MyComponent::Index />`. This was working as expected in Discourse core, but we had not implemented the same in our custom resolver logic for themes/plugins.
This commit implements the `/index` fallback, and adds a test for the behaviour.
This fixes an issue where, on a textarea with a lot of text, the cursor
would jump when adding a new line. See video in PR for a repro.
This is a Chrome bug with scroll anchoring.
Refs: https://bugs.chromium.org/p/chromium/issues/detail?id=997266
The fix here disables `overflow-anchor` on the composer textarea. There
should be no side effects to this change, as scroll anchoring is likely
not needed for the composer textarea element.
The 'create topic' entry in the dropdown was incorrectly using the 'reply as new topic' description. This fixes the logic to use a separate locale key for the description.
This commit does a couple of things:
1. Add a new plugin outlet, `above-topic-list-item`, to the `topic-list-item` component
2. Pass the topic in question as an outlet argument for the (existing) `above-latest-topic-list-item` outlet in the `latest-topic-list-item` component.
For the admin plugin list we want to be able to link to
a meta topic for plugins, but we have no standard way to
do this at the moment. This adds support for meta_topic_id
alongside other plugin metadata like authors, URL etc,
that gets built into a Meta topic URL in the serializer.
Some time ago, we introduced the `cookAsync` instead of the existing
`cook` function, and planned to migrate everything to it. Then after
migrating, we wanted to raname the function to simply `cook`.
I've checked Core and plugins, and currently we call `cookAsync` everywhere,
there are no calls to the `cook` function anymore. So we're good
to proceed with this refactoring.
This PR makes the first step by making current cookAsync and cook functions
do the same thing. Effectively now the `cook` function becomes an alias
for the `cookAsync` function.
This PR is a first step towards private groups. It redesigns settings/members area of a channel and also drops the "about" page which is now mixed into settings.
This commit is also:
- introducing chat-form, a small DSL to create forms, ideally I would want something in core for this
- introducing a DToggleSwitch page object component to simplify testing toggles
- migrating various components to gjs
Why this change?
Back in May 17 2023 along with the release of Discourse 3.1, we announced
on meta that the legacy hamburger dropdown navigation menu is
deprecated and will be dropped in Discourse 3.2. This is the link to the announcement
on meta: https://meta.discourse.org/t/removing-the-legacy-hamburger-navigation-menu-option/265274
## What does this change do?
This change removes the `legacy` option from the `navigation_menu` site
setting and migrates existing sites on the `legacy` option to the
`header dropdown` option.
All references to the `legacy` option in code and tests have been
removed as well.
Currently, if you set an integer site setting in the admin interface and include thousands separators, you will silently configure the wrong value.
This PR replaces TextField inputs for integer site settings with NumberField. It also cleans the numeric input of any non-digits in the backend in case any separators make it through.
The custom html elements we were using for bootstraping were causing Embroider to end the `<head>` tag and immediately start `<body>`. As a result most of `<meta>` tags ended up in the `<body>`.
That mean (among possibly other issues) that the app did not have CSRF token set properly on launch (in the development env)
Why this change?
Previously just using the `addToolbarPopupMenuOptionsCallback` plugin
API itself was insufficient because it required the return object to
include an `action` key which only accepted a name of the action
function as a string. This was highly problematic because the action
function had to be defined on the `composer` service which means using
the `modifyClass` API to add the action function. This made the API
awkward to use leading to poor developer experiencec.
What does this change do?
This commit introduces a couple of improvemnts to the API.
1. First the API has been renamed to `addComposerToolbarPopupMenuOption` because
the API no longer accepts a callback function which was quite
redundant. Instead, it now accepts an Object. The
`addToolbarPopupMenuOptionsCallback` API function is deprecated and
will be dropped in Discourse 3.3. Note that passing the API a
function is still supported but will be dropped when the `addToolbarPopupMenuOptionsCallback`
is removed.
2. The `action` key in the Object passed to the function can now be a
function and is passed the `toolbarEvent` object when called.
3. The `condition` on key in the Object passed to the function can now be a
function and is passed the `composer` service when called.
It's a special case widget - its constructor has different contructor arguments:
```js
export default class PostCooked {
constructor(attrs, decoratorHelper, currentUser) {
...
```
vs
```js
export default class Widget {
constructor(attrs, register, opts) {
...
```