diff --git a/lib/widgets/markdown_toolbar.dart b/lib/widgets/markdown_toolbar.dart index 90bb4b77..e54efcad 100644 --- a/lib/widgets/markdown_toolbar.dart +++ b/lib/widgets/markdown_toolbar.dart @@ -85,6 +85,22 @@ class MarkdownToolBar extends StatelessWidget { } } +final _allowedBlockTags = [ + '# ', + '## ', + '### ', + '#### ', + '##### ', + '###### ', + '- ', + '* ', +]; + +final _allowedBlockRegExps = [ + RegExp('- \[[xX ]\] '), + RegExp('\d+\. '), +]; + TextEditingValue modifyCurrentLine( TextEditingValue textEditingValue, String char, @@ -112,35 +128,62 @@ TextEditingValue modifyCurrentLine( lineEndPos = text.length; } + // Check if line already has a block tag + for (var blockTag in _allowedBlockTags) { + if (text.startsWith(blockTag, lineStartPos)) { + var newVal = _removeFromLine(text, cursorPos, lineStartPos, blockTag); + if (blockTag == char) { + return newVal; + } + return modifyCurrentLine(newVal, char); + } + } + + for (var blockTagRegExp in _allowedBlockRegExps) { + var match = blockTagRegExp.matchAsPrefix(text, lineStartPos); + if (match != null) { + var blockTag = match.group(0); + var newVal = _removeFromLine(text, cursorPos, lineStartPos, blockTag); + if (blockTag == char) { + return newVal; + } + return modifyCurrentLine(newVal, char); + } + } + //print('Line Start: $lineStartPos'); //print('Line End: $lineEndPos'); //print('Line: ${text.substring(lineStartPos, lineEndPos)}'); - // Check if already present - if (text.startsWith(char, lineStartPos)) { - //print('Removing `$char`'); - var endOffset = cursorPos; - //print("End Offset: $endOffset"); - if (endOffset > lineStartPos) { - endOffset -= char.length; - //print("End Offset min char: $endOffset"); - } - if (endOffset < lineStartPos) { - endOffset = lineStartPos; - //print("End Offset equal LineStartPos: $endOffset"); - } - return TextEditingValue( - text: text.replaceFirst(char, '', lineStartPos), - selection: TextSelection.collapsed(offset: endOffset), - ); - } - return TextEditingValue( text: text.replaceRange(lineStartPos, lineStartPos, char), selection: TextSelection.collapsed(offset: cursorPos + char.length), ); } +TextEditingValue _removeFromLine( + String text, + int cursorPos, + int lineStartPos, + String char, +) { +//print('Removing `$char`'); + var endOffset = cursorPos; + //print("End Offset: $endOffset"); + if (endOffset > lineStartPos) { + endOffset -= char.length; + //print("End Offset min char: $endOffset"); + } + if (endOffset < lineStartPos) { + endOffset = lineStartPos; + //print("End Offset equal LineStartPos: $endOffset"); + } + return TextEditingValue( + text: text.replaceFirst(char, '', lineStartPos), + selection: TextSelection.collapsed(offset: endOffset), + ); +} + TextEditingValue modifyCurrentWord( TextEditingValue textEditingValue, String char, diff --git a/test/markdown_toolbar_test.dart b/test/markdown_toolbar_test.dart index e71eabf2..58e02d6e 100644 --- a/test/markdown_toolbar_test.dart +++ b/test/markdown_toolbar_test.dart @@ -104,6 +104,26 @@ void main() { ); }); + test("Replaces h1 with h2", () { + _testLine( + before: 'Hi\n# Hello Darkness\nFire', + beforeOffset: 4, + after: 'Hi\n## Hello Darkness\nFire', + afterOffset: 6, + char: '## ', + ); + }); + + test("Replaces h2 with list", () { + _testLine( + before: 'Hi\n## Hello Darkness\nFire', + beforeOffset: 5, + after: 'Hi\n- Hello Darkness\nFire', + afterOffset: 5, + char: '- ', + ); + }); + // // Word based // @@ -252,5 +272,5 @@ void main() { _testPrevWord(text, 0, 0); }); - // Test that clicking on h2 removes h1 and then adds h2 + // Test that if some text is selected then it should be modified }