mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 21:41:26 +08:00
FIX: only allows kbd and not details
This commit is contained in:
@ -201,7 +201,6 @@ module Chat
|
|||||||
upload-protocol
|
upload-protocol
|
||||||
watched-words
|
watched-words
|
||||||
chat-html-inline
|
chat-html-inline
|
||||||
chat-html-block
|
|
||||||
]
|
]
|
||||||
|
|
||||||
MARKDOWN_IT_RULES = %w[
|
MARKDOWN_IT_RULES = %w[
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
// inspired from https://github.com/markdown-it/markdown-it/blob/master/lib/rules_block/html_block.mjs
|
|
||||||
// note that allow lister will run on top of it, so if a tag is allowed here but not on
|
|
||||||
// the allow list, then it won't show up
|
|
||||||
|
|
||||||
const block_names = ["details"];
|
|
||||||
|
|
||||||
const attr_name = "[a-zA-Z_:][a-zA-Z0-9:._-]*";
|
|
||||||
const unquoted = "[^\"'=<>`\\x00-\\x20]+";
|
|
||||||
const single_quoted = "'[^']*'";
|
|
||||||
const double_quoted = '"[^"]*"';
|
|
||||||
const attr_value =
|
|
||||||
"(?:" + unquoted + "|" + single_quoted + "|" + double_quoted + ")";
|
|
||||||
const attribute = "(?:\\s+" + attr_name + "(?:\\s*=\\s*" + attr_value + ")?)";
|
|
||||||
const open_tag = "<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/?>";
|
|
||||||
const close_tag = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>";
|
|
||||||
|
|
||||||
const HTML_OPEN_CLOSE_TAG_RE = new RegExp(
|
|
||||||
"^(?:" + open_tag + "|" + close_tag + ")"
|
|
||||||
);
|
|
||||||
|
|
||||||
// An array of opening and corresponding closing sequences for html tags,
|
|
||||||
// last argument defines whether it can terminate a paragraph or not
|
|
||||||
//
|
|
||||||
const HTML_SEQUENCES = [
|
|
||||||
[
|
|
||||||
/^<(script|pre|style|textarea)(?=(\s|>|$))/i,
|
|
||||||
/<\/(script|pre|style|textarea)>/i,
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
[/^<!--/, /-->/, true],
|
|
||||||
[/^<\?/, /\?>/, true],
|
|
||||||
[/^<![A-Z]/, />/, true],
|
|
||||||
[/^<!\[CDATA\[/, /\]\]>/, true],
|
|
||||||
[
|
|
||||||
new RegExp("^</?(" + block_names.join("|") + ")(?=(\\s|/?>|$))", "i"),
|
|
||||||
/^$/,
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
[new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + "\\s*$"), /^$/, false],
|
|
||||||
];
|
|
||||||
|
|
||||||
function chatHtmlBlock(state, startLine, endLine, silent) {
|
|
||||||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
|
||||||
let max = state.eMarks[startLine];
|
|
||||||
|
|
||||||
// if it's indented more than 3 spaces, it should be a code block
|
|
||||||
if (state.sCount[startLine] - state.blkIndent >= 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state.md.options.html) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.src.charCodeAt(pos) !== 0x3c /* < */) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let lineText = state.src.slice(pos, max);
|
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
for (; i < HTML_SEQUENCES.length; i++) {
|
|
||||||
if (HTML_SEQUENCES[i][0].test(lineText)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i === HTML_SEQUENCES.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (silent) {
|
|
||||||
// true if this sequence can be a terminator, false otherwise
|
|
||||||
return HTML_SEQUENCES[i][2];
|
|
||||||
}
|
|
||||||
|
|
||||||
let nextLine = startLine + 1;
|
|
||||||
|
|
||||||
// If we are here - we detected HTML block.
|
|
||||||
// Let's roll down till block end.
|
|
||||||
if (!HTML_SEQUENCES[i][1].test(lineText)) {
|
|
||||||
for (; nextLine < endLine; nextLine++) {
|
|
||||||
if (state.sCount[nextLine] < state.blkIndent) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
|
||||||
max = state.eMarks[nextLine];
|
|
||||||
lineText = state.src.slice(pos, max);
|
|
||||||
|
|
||||||
if (HTML_SEQUENCES[i][1].test(lineText)) {
|
|
||||||
if (lineText.length !== 0) {
|
|
||||||
nextLine++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.line = nextLine;
|
|
||||||
|
|
||||||
const token = state.push("html_block", "", 0);
|
|
||||||
token.map = [startLine, nextLine];
|
|
||||||
token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setup(helper) {
|
|
||||||
helper.registerPlugin((md) => {
|
|
||||||
if (md.options.discourse.features["chat-html-block"]) {
|
|
||||||
md.block.ruler.push("chat-html-block", chatHtmlBlock);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
14
plugins/chat/spec/lib/chat/chat_pretty_text_spec.rb
Normal file
14
plugins/chat/spec/lib/chat/chat_pretty_text_spec.rb
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
#
|
||||||
|
RSpec.describe Chat::Message do
|
||||||
|
describe ".cook" do
|
||||||
|
it "renders kbd inline tag" do
|
||||||
|
cooked = Chat::Message.cook <<~MD
|
||||||
|
<kbd>Esc</kbd> is pressed
|
||||||
|
MD
|
||||||
|
|
||||||
|
expect(cooked).to include("<p><kbd>Esc</kbd> is pressed</p>")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -97,28 +97,4 @@ RSpec.describe PrettyText do
|
|||||||
"<div class=\"chat-transcript-messages\">\n<p>original message</p></div>",
|
"<div class=\"chat-transcript-messages\">\n<p>original message</p></div>",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "renders kbd inline tag" do
|
|
||||||
cooked = PrettyText.cook <<~MD
|
|
||||||
<kbd>Esc</kbd> is pressed
|
|
||||||
MD
|
|
||||||
|
|
||||||
expect(cooked).to include("<p><kbd>Esc</kbd> is pressed</p>")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "renders details block tag" do
|
|
||||||
cooked = PrettyText.cook <<~MD
|
|
||||||
<details>
|
|
||||||
<summary>Dog</summary>
|
|
||||||
Cat
|
|
||||||
</details>
|
|
||||||
MD
|
|
||||||
|
|
||||||
expect(cooked).to include(<<~HTML.strip)
|
|
||||||
<details>
|
|
||||||
<summary>Dog</summary>
|
|
||||||
Cat
|
|
||||||
</details>
|
|
||||||
HTML
|
|
||||||
end
|
|
||||||
end
|
end
|
Reference in New Issue
Block a user