diff --git a/pkgs/markdown/CHANGELOG.md b/pkgs/markdown/CHANGELOG.md index 60a250887..cc4337702 100644 --- a/pkgs/markdown/CHANGELOG.md +++ b/pkgs/markdown/CHANGELOG.md @@ -4,6 +4,7 @@ (https://dart-lang.github.io/tools). * Update `package:web` API references in the example. * Fix performance and correctness of HTML comment parser. +* Optimize indentation processing of fenced code blocks. * Require Dart `^3.4.0`. ## 7.3.0 diff --git a/pkgs/markdown/lib/src/block_syntaxes/fenced_code_block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/fenced_code_block_syntax.dart index cea110665..de695c7a9 100644 --- a/pkgs/markdown/lib/src/block_syntaxes/fenced_code_block_syntax.dart +++ b/pkgs/markdown/lib/src/block_syntaxes/fenced_code_block_syntax.dart @@ -4,6 +4,7 @@ import '../ast.dart'; import '../block_parser.dart'; +import '../charcode.dart' show $space; import '../line.dart'; import '../patterns.dart'; import '../util.dart'; @@ -50,11 +51,6 @@ class FencedCodeBlockSyntax extends BlockSyntax { return Element('pre', [code]); } - String _removeIndentation(String content, int length) { - final text = content.replaceFirst(RegExp('^\\s{0,$length}'), ''); - return content.substring(content.length - text.length); - } - @override List parseChildLines( BlockParser parser, [ @@ -76,7 +72,7 @@ class FencedCodeBlockSyntax extends BlockSyntax { !closingFence.marker.startsWith(openingMarker) || closingFence.hasInfo) { childLines.add( - Line(_removeIndentation(parser.current.content, indent)), + Line(_removeLeadingSpaces(parser.current.content, upTo: indent)), ); parser.advance(); } else { @@ -95,6 +91,24 @@ class FencedCodeBlockSyntax extends BlockSyntax { return childLines; } + + /// Removes the leading spaces (` `) from [content] up the given [upTo] count. + static String _removeLeadingSpaces(String content, {required int upTo}) { + var leadingSpacesCount = 0; + + // Find the index of the first non-space character + // or the first space after the maximum removed specified by 'upTo'. + while (leadingSpacesCount < upTo && leadingSpacesCount < content.length) { + // We can just check for space (` `) since fenced code blocks + // consider spaces before the opening code fence as the + // indentation that should be removed. + if (content.codeUnitAt(leadingSpacesCount) != $space) { + break; + } + leadingSpacesCount += 1; + } + return content.substring(leadingSpacesCount); + } } class _FenceMatch {