**TL;DR:** Refactor autocomplete to use async markdown parsing for code block detection.
Previously, the `inCodeBlock` function in `discourse/app/lib/utilities.js` used regular expressions to determine if a given position in the text was inside a code block. This approach had some limitations and could lead to incorrect behavior in certain edge cases.
This commit refactors `inCodeBlock` to use a more robust algorithm that leverages Discourse's markdown parsing library.
The new approach works as follows:
1. Check if the text contains any code block markers using a regular expression.
If not, return `false` since the cursor can't be in a code block.
1. If potential code blocks exist, find a unique marker character that doesn't appear in the text.
1. Insert the unique marker character into the text at the cursor position.
1. Parse the modified text using Discourse's markdown parser, which converts the markdown into a tree of tokens.
1. Traverse the token tree to find the token that contains the unique marker character.
1. Check if the token's type is one of the types representing code blocks ("code_inline", "code_block", or "fence").
If so, return `true`, indicating that the cursor is inside a code block.
Otherwise, return `false`.
This algorithm provides a more accurate way to determine the cursor's position in relation to code blocks, accounting for the various ways code blocks can be represented in markdown.
To accommodate this change, the autocomplete `triggerRule` option is now an async function.
The autocomplete logic in `composer-editor.js`, `d-editor.js`, and `hashtag-autocomplete.js` has been updated to handle the async nature of `inCodeBlock`.
Additionally, many of the tests have been refactored to handle async behavior. The test helpers now simulate typing and autocomplete selection in a more realistic, step-by-step manner. This should make the tests more robust and reflective of real-world usage.
This is a significant refactor that touches multiple parts of the codebase, but it should lead to more accurate and reliable autocomplete behavior, especially when dealing with code blocks in the editor.
> Written by an 🤖 LLM. Edited by a 🧑💻 human.
Tooltips are generally hard to test, and we noticed that they make tests flaky.
We may not test tooltips in these acceptance tests, since they are already
tested in components/chat-channel-test.js. This PR deletes tooltip-related
assertions and unskips tests that became flaky after adding them.
This fixes the problem reported in
https://meta.discourse.org/t/custom-status-message-in-front-of-by-header-on-scroll/273320.
This problem can be reproduced with any tooltip created using the DTooltip
component or the createDTooltip function.
The problem happens because the trigger for tooltip on mobile is click, and for tooltip
to disappear the user has to click outside the tooltip. This is the default behavior
of tippy.js – the library we use under the hood.
Note that this PR fixes the problem in topics, but not in chat. I'm going to investigate and
address it in chat in a following PR.
To fix it for tooltips created with the createDTooltip function, I had to make a refactoring.
We had a somewhat not ideal solution there, we were leaking an implementation detail
by passing tippy instances to calling sides, so they could then destroy them. With this fix,
I would have to make it more complex, because now we need to also remove onScrool
handlers, and I would need to leak this implementation detail too. So, I firstly refactored
the current solution in 5a4af05 and then added onScroll handlers in fb4aabe.
When refactoring this, I was running locally some temporarily skipped flaky tests. Turned out
they got a bit outdated, so I fixed them. Note that I'm not unskipping them in this commit,
we'll address them separately later.
- Inline mentions on posts
- Inline mentions on chat messages
- The user autocomplete for the composer
- The user autocomplete for chat
- The chat section of the sidebar
- Moves `<ChatMessageInfo />` to `<Chat::Message::Info />`
- Moves `<ChatMessageAvatar />` to `<Chat::Message::Avatar />`
- Moves `<ChatMessageLeftGutter />` to `<Chat::Message::LeftGutter />`, adds tests
- Creates `<Chat::Message::Error />`
- Creates `<Chat::Message::MentionWarning />`, adds tests and a styleguide
- Creates a model for ChatMessageMentionWarning, adds fabricator for it
- Keeps the enter/leave viewport logic inside the `<ChatMessage />` component instead of bubbling it to the channel and thread components
- Adds a scale animation when clicking a reaction
- Creates `chat/later-fn` modifier which accepts a function and a delay. It allows to call a function Xms after a component has been inserted, it's useful for animations.
- Moves css code out of chat-message into relevant files
- Deletes unused code
<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
These spec are flaky only in CI, not locally and not in GitHub actions.
The previous attempt was in 44eabde, but actually the failure happens
a bit earlier. This is another attempt to fix these specs. Quite a lot of
async logic is happening in emulateAutocomplete(), a call to settled()
in the end should help make it more reliable.
These specs were skipped in d6d5eae1. They sometimes failed, and only on CI,
not in GitHub Actions.
I wasn't able to reproduce failures locally, but I expect clicking the send button
in chat composer should be more reliable than emulating pressing <kbd>Enter</kbd>.
This PR adds status to mentions in chat and makes those mentions receive live updates.
There are known unfinished part in this implementation: when posting a message, status on mentions on that message appears immediately, but only if a user used autocomplete when typing the message. If user copy and paste a message with mentions into chat composer, those mentions won't have user status on them.
PRs with fixes for both problems are following soon.
Preparations for this PR that were made previously include:
- DEV: correct a relationship – a chat message may have several mentions 0dcfd7ddec
- DEV: extract the logic for extracting and expanding mentions from ChatNotifier 75b81b6854
- DEV: Always create chat mention records fa543cda06
- DEV: better split create_notification! and send_notifications logic e292c45924
- DEV: more tests for mentions when updating chat messages e7292e1682
- DEV: extract updating status on mentions into a lib function e49d338c21
- DEV: Create and update chat message mentions earlier 35a414bb38
- DEV: Create a chat_mention record when self mentioning 2703f2311a
- DEV: When deleting a chat message, do not delete mention records f4fde4e49b