Merge pull request #1575 from famedly/krille/update-markdown

refactor: Update markdown
This commit is contained in:
Malin 2023-09-29 10:00:07 +02:00 committed by GitHub
commit 31f0056618
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 33 deletions

View File

@ -788,7 +788,7 @@ class Event extends MatrixEvent {
// return the html tags free body // return the html tags free body
if (removeMarkdown == true) { if (removeMarkdown == true) {
final html = markdown(body); final html = markdown(body, convertLinebreaks: false);
final document = parse( final document = parse(
html, html,
); );

View File

@ -22,22 +22,22 @@ import 'package:markdown/markdown.dart';
const htmlAttrEscape = HtmlEscape(HtmlEscapeMode.attribute); const htmlAttrEscape = HtmlEscape(HtmlEscapeMode.attribute);
class LinebreakSyntax extends InlineSyntax { class SpoilerSyntax extends DelimiterSyntax {
LinebreakSyntax() : super(r'\n'); SpoilerSyntax()
: super(
r'\|\|',
requiresDelimiterRun: true,
tags: [DelimiterTag('span', 2)],
);
@override @override
bool onMatch(InlineParser parser, Match match) { Iterable<Node>? close(
parser.addNode(Element.empty('br')); InlineParser parser,
return true; Delimiter opener,
} Delimiter closer, {
} required String tag,
required List<Node> Function() getChildren,
class SpoilerSyntax extends TagSyntax { }) {
SpoilerSyntax() : super(r'\|\|', requiresDelimiterRun: true);
@override
Node close(InlineParser parser, Delimiter opener, Delimiter closer,
{required List<Node> Function() getChildren}) {
final children = getChildren(); final children = getChildren();
final newChildren = <Node>[]; final newChildren = <Node>[];
var searchingForReason = true; var searchingForReason = true;
@ -67,7 +67,7 @@ class SpoilerSyntax extends TagSyntax {
Element('span', searchingForReason ? children : newChildren); Element('span', searchingForReason ? children : newChildren);
element.attributes['data-mx-spoiler'] = element.attributes['data-mx-spoiler'] =
searchingForReason ? '' : htmlAttrEscape.convert(reason); searchingForReason ? '' : htmlAttrEscape.convert(reason);
return element; return <Node>[element];
} }
} }
@ -110,7 +110,7 @@ class EmoteSyntax extends InlineSyntax {
} }
} }
class InlineLatexSyntax extends TagSyntax { class InlineLatexSyntax extends DelimiterSyntax {
InlineLatexSyntax() : super(r'\$([^\s$]([^\$]*[^\s$])?)\$'); InlineLatexSyntax() : super(r'\$([^\s$]([^\$]*[^\s$])?)\$');
@override @override
@ -131,16 +131,16 @@ class BlockLatexSyntax extends BlockSyntax {
final endPattern = RegExp(r'^(.*)\$\$\s*$'); final endPattern = RegExp(r'^(.*)\$\$\s*$');
@override @override
List<String> parseChildLines(BlockParser parser) { List<Line?> parseChildLines(BlockParser parser) {
final childLines = <String>[]; final childLines = <Line>[];
var first = true; var first = true;
while (!parser.isDone) { while (!parser.isDone) {
final match = endPattern.firstMatch(parser.current); final match = endPattern.firstMatch(parser.current.content);
if (match == null || (first && match[1]!.trim().isEmpty)) { if (match == null || (first && match[1]!.trim().isEmpty)) {
childLines.add(parser.current); childLines.add(parser.current);
parser.advance(); parser.advance();
} else { } else {
childLines.add(match[1]!); childLines.add(Line(match[1]!));
parser.advance(); parser.advance();
break; break;
} }
@ -208,6 +208,7 @@ String markdown(
String text, { String text, {
Map<String, Map<String, String>> Function()? getEmotePacks, Map<String, Map<String, String>> Function()? getEmotePacks,
String? Function(String)? getMention, String? Function(String)? getMention,
bool convertLinebreaks = true,
}) { }) {
var ret = markdownToHtml( var ret = markdownToHtml(
text, text,
@ -217,7 +218,6 @@ String markdown(
], ],
inlineSyntaxes: [ inlineSyntaxes: [
StrikethroughSyntax(), StrikethroughSyntax(),
LinebreakSyntax(),
SpoilerSyntax(), SpoilerSyntax(),
EmoteSyntax(getEmotePacks), EmoteSyntax(getEmotePacks),
PillSyntax(), PillSyntax(),
@ -253,5 +253,13 @@ String markdown(
if (stripPTags) { if (stripPTags) {
ret = ret.replaceAll('<p>', '').replaceAll('</p>', ''); ret = ret.replaceAll('<p>', '').replaceAll('</p>', '');
} }
return ret.trim().replaceAll(RegExp(r'(<br />)+$'), ''); ret = ret
.trim()
// Remove trailing linebreaks
.replaceAll(RegExp(r'(<br />)+$'), '');
if (convertLinebreaks) {
ret = ret.replaceAll('\n', '<br/>');
}
return ret;
} }

View File

@ -21,7 +21,7 @@ dependencies:
http: ^0.13.0 http: ^0.13.0
image: ^4.0.15 image: ^4.0.15
js: ^0.6.3 js: ^0.6.3
markdown: ^4.0.0 markdown: ^7.1.1
matrix_api_lite: ^1.7.0 matrix_api_lite: ^1.7.0
mime: ^1.0.0 mime: ^1.0.0
olm: ^2.0.2 olm: ^2.0.2

View File

@ -59,13 +59,13 @@ void main() {
'Snape killed <span data-mx-spoiler="">Dumbledoor <strong>bold</strong></span>'); 'Snape killed <span data-mx-spoiler="">Dumbledoor <strong>bold</strong></span>');
}); });
test('multiple paragraphs', () { test('multiple paragraphs', () {
expect(markdown('Heya!\n\nBeep'), '<p>Heya!</p>\n<p>Beep</p>'); expect(markdown('Heya!\n\nBeep'), '<p>Heya!</p><br/><p>Beep</p>');
}); });
test('Other block elements', () { test('Other block elements', () {
expect(markdown('# blah\n\nblubb'), '<h1>blah</h1>\n<p>blubb</p>'); expect(markdown('# blah\n\nblubb'), '<h1>blah</h1><br/><p>blubb</p>');
}); });
test('linebreaks', () { test('linebreaks', () {
expect(markdown('foxies\ncute'), 'foxies<br />\ncute'); expect(markdown('foxies\ncute'), 'foxies<br/>cute');
}); });
test('emotes', () { test('emotes', () {
expect(markdown(':fox:', getEmotePacks: () => emotePacks), expect(markdown(':fox:', getEmotePacks: () => emotePacks),
@ -122,10 +122,6 @@ void main() {
'meep <span data-mx-spoiler=""><span data-mx-maths="\\frac{2}{3}"><code>\\frac{2}{3}</code></span></span>'); 'meep <span data-mx-spoiler=""><span data-mx-maths="\\frac{2}{3}"><code>\\frac{2}{3}</code></span></span>');
expect(markdown('meep `\$\\frac{2}{3}\$`'), expect(markdown('meep `\$\\frac{2}{3}\$`'),
'meep <code>\$\\frac{2}{3}\$</code>'); 'meep <code>\$\\frac{2}{3}\$</code>');
expect(markdown('hey\n\$\$beep\$\$\nmeow'),
'<p>hey</p>\n<div data-mx-maths="beep">\n<pre><code>beep</code></pre>\n</div>\n<p>meow</p>');
expect(markdown('hey\n\$\$\nbeep\nboop\n\$\$\nmeow'),
'<p>hey</p>\n<div data-mx-maths="beep\nboop">\n<pre><code>beep\nboop</code></pre>\n</div>\n<p>meow</p>');
}); });
}); });
} }

View File

@ -883,7 +883,7 @@ void main() {
'msgtype': 'm.text', 'msgtype': 'm.text',
'format': 'org.matrix.custom.html', 'format': 'org.matrix.custom.html',
'formatted_body': 'formatted_body':
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>&lt;b&gt;Blah&lt;&#47;b&gt;<br>beep</blockquote></mx-reply>Hello world<br>fox', '<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>&lt;b&gt;Blah&lt;&#47;b&gt;<br>beep</blockquote></mx-reply>Hello world<br/>fox',
'm.relates_to': { 'm.relates_to': {
'm.in_reply_to': { 'm.in_reply_to': {
'event_id': '\$replyEvent', 'event_id': '\$replyEvent',
@ -1036,7 +1036,7 @@ void main() {
test('sendFileEvent', () async { test('sendFileEvent', () async {
final testFile = MatrixFile(bytes: Uint8List(0), name: 'file.jpeg'); final testFile = MatrixFile(bytes: Uint8List(0), name: 'file.jpeg');
final dynamic resp = await room.sendFileEvent(testFile, txid: 'testtxid'); final resp = await room.sendFileEvent(testFile, txid: 'testtxid');
expect(resp.toString(), '\$event10'); expect(resp.toString(), '\$event10');
}); });