mirror of
https://github.com/discourse/discourse.git
synced 2026-08-03 09:53:24 -05:00
DEV: avoid rich editor input rule if preceded by backtick (#35528)
Adds an input rules wrapper to skip applying input rules whenever there's a backtick ` preceding the regex match.
This commit is contained in:
@@ -20,7 +20,7 @@ export function buildInputRules(extensions, params, includeDefault = true) {
|
||||
start: match[1].length,
|
||||
});
|
||||
|
||||
rules.push(
|
||||
const defaultRules = [
|
||||
// TODO(renato) smartQuotes should respect `markdown_typographer_quotation_marks`
|
||||
...smartQuotes,
|
||||
...[
|
||||
@@ -42,8 +42,10 @@ export function buildInputRules(extensions, params, includeDefault = true) {
|
||||
/^(\u2013-|\u2014-|___\s|\*\*\*\s)$/,
|
||||
horizontalRuleHandler,
|
||||
{ inCodeMark: false }
|
||||
)
|
||||
);
|
||||
),
|
||||
];
|
||||
|
||||
rules.push(...defaultRules.map((rule) => processInputRule(rule, params)));
|
||||
}
|
||||
|
||||
rules.push(...extractInputRules(extensions, params));
|
||||
@@ -67,7 +69,11 @@ function processInputRule(inputRule, params) {
|
||||
}
|
||||
|
||||
if (inputRule instanceof InputRule) {
|
||||
return inputRule;
|
||||
return new InputRule(
|
||||
inputRule.match,
|
||||
wrapHandlerWithBacktickCheck(inputRule.handler),
|
||||
inputRule.options
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -77,12 +83,41 @@ function processInputRule(inputRule, params) {
|
||||
// Default to NOT applying input rules when inCodeMark
|
||||
const options = inputRule.options || {};
|
||||
options.inCodeMark ??= options.inCode || false;
|
||||
return new InputRule(inputRule.match, inputRule.handler, options);
|
||||
|
||||
const handler = !options.inCodeMark
|
||||
? wrapHandlerWithBacktickCheck(inputRule.handler)
|
||||
: inputRule.handler;
|
||||
|
||||
return new InputRule(inputRule.match, handler, options);
|
||||
}
|
||||
|
||||
throw new Error("Input rule must have a match regex and a handler function");
|
||||
}
|
||||
|
||||
function hasBacktickBefore(state, pos) {
|
||||
return pos > 0 && state.doc.textBetween(pos - 1, pos, "\n", "\n") === "`";
|
||||
}
|
||||
|
||||
function wrapHandlerWithBacktickCheck(handler) {
|
||||
return (state, match, start, end) => {
|
||||
if (hasBacktickBefore(state, start)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// For two capturing group patterns like (^|\W)(:emoji:) or (^|\W)(@mention),
|
||||
// also check for backtick before the actual content (after the boundary group)
|
||||
if (
|
||||
match[1] &&
|
||||
match[2] &&
|
||||
hasBacktickBefore(state, start + match[1].length)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return handler(state, match, start, end);
|
||||
};
|
||||
}
|
||||
|
||||
function orderedListRule(nodeType) {
|
||||
return wrappingInputRule(
|
||||
/^(\d+)\.\s$/,
|
||||
|
||||
@@ -344,6 +344,18 @@ describe "Composer - ProseMirror editor", type: :system do
|
||||
expect(rich).to have_css("code", text: "not code")
|
||||
expect(rich).to have_no_css("code", text: "and this, not code")
|
||||
end
|
||||
|
||||
it "doesn't apply input rules immediately after a single backtick" do
|
||||
open_composer
|
||||
composer.type_content("`**not bold**\n`:tada:")
|
||||
|
||||
expect(rich).to have_no_css("strong")
|
||||
expect(rich).to have_no_css("img.emoji")
|
||||
|
||||
composer.toggle_rich_editor
|
||||
|
||||
expect(composer).to have_value("\\`\\*\\*not bold\\*\\*\n\n\\`:tada:")
|
||||
end
|
||||
end
|
||||
|
||||
context "with oneboxing" do
|
||||
|
||||
Reference in New Issue
Block a user