diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 5fd5001..e986402 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -39,7 +39,7 @@ }, "type": "shell", "command": [ - "dart format --fix -l 80 lib test" + "dart format -l 80 lib test" ], "dependsOn": [], "args": [], diff --git a/lib/src/parser.dart b/lib/src/parser.dart index ad97fa3..00bb8a3 100644 --- a/lib/src/parser.dart +++ b/lib/src/parser.dart @@ -453,17 +453,19 @@ List _parseInlineSpans(String text) { for (var i = 0; i < length; i++) { final ch = codes[i]; - // Check for escaped characters - if (ch == esc /* \ */ && i != length - 1) { - final nextChar = codes[i + 1]; - // Check if the next character is an escaped character - if (_escapedChars.length > nextChar && _escapedChars[nextChar] == 1) { - hasExcluded = true; // We have an escaped character - excluded.add(i); // Exclude this character as it is escaped - i++; // skip next char - continue; + // If we are inside a monospace block, we should only look + // for the closing backtick. + if (mask.contains(MD$Style.monospace)) { + if (ch == 96 /* ` */ && i > 0 && codes[i - 1] != esc /* ignore \` */) { + // Found closing backtick + maybePushSpan(i); + mask ^= MD$Style.monospace; + start = i + 1; } + // We continue to the next character, ignoring any other + // special markers. + continue; } // If this character is part of a link or image, skip it @@ -478,6 +480,19 @@ List _parseInlineSpans(String text) { continue; } + // Check for escaped characters + if (ch == esc /* \ */ && i != length - 1) { + final nextChar = codes[i + 1]; + // Check if the next character is an escaped character + if (_escapedChars.length > nextChar && _escapedChars[nextChar] == 1) { + hasExcluded = true; // We have an escaped character + excluded.add(i); // Exclude this character as it is escaped + i++; // skip next char + + continue; + } + } + // If the character is not a special inline marker, continue if (_kind.length > ch && _kind[ch] == 0) continue; diff --git a/test/parser/parser_test.dart b/test/parser/parser_test.dart index 2938687..c6a6ee1 100644 --- a/test/parser/parser_test.dart +++ b/test/parser/parser_test.dart @@ -370,6 +370,47 @@ void main() => group('Parse', () { ); }); + test('Inline code should treat inline code as literal', () { + // A map of markdown syntax to its expected literal representation + // inside a code block. + const List syntaxes = [ + '*italic*', + '_italic_', + '**bold**', + '__underline__', + '~~strike~~', + '==highlight==', + '||spoiler||', + r'\* \_ \`', + '!alt', + '* Item 1', + '# Header', + '---', + '1. Item **1**', + '[Markdown Live Preview](https://markdownlivepreview.com/)', + 'package:flutter_md/flutter_md.dart' + ]; + + final text = syntaxes.map((syntax) => '`$syntax`').join(); + final markdown = markdownDecoder.convert(text); + + expect(markdown.blocks, + allOf(isNotEmpty, hasLength(1), everyElement(isA()))); + + final paragraph = markdown.blocks.first as MD$Paragraph; + final spans = paragraph.spans; + + for (var i = 0; i < syntaxes.length; i++) { + final expectedText = syntaxes.elementAt(i); + + final codeSpan = spans[i]; + expect(codeSpan.text, expectedText); + expect(codeSpan.style, MD$Style.monospace, + reason: + 'Span for "$expectedText" should only have monospace style'); + } + }); + group('Parse escaped characters', () { const escapedCharacterTests = { r'\\': r'\', // Backslash