From 1431d17e838ee598dc4514518f53bdb187d27ede Mon Sep 17 00:00:00 2001 From: CodeNameAkshay Date: Fri, 21 May 2021 19:24:00 +0530 Subject: [PATCH 1/5] add strikethrough, code, blockquote, image and more --- lib/format_markdown.dart | 63 +++++++++- lib/markdown_text_input.dart | 222 +++++++++++++++++++++++++---------- pubspec.yaml | 1 + 3 files changed, 221 insertions(+), 65 deletions(-) diff --git a/lib/format_markdown.dart b/lib/format_markdown.dart index 394ba2b..b5c8348 100644 --- a/lib/format_markdown.dart +++ b/lib/format_markdown.dart @@ -3,7 +3,8 @@ class FormatMarkdown { /// Convert [data] part into [ResultMarkdown] from [type]. /// Use [fromIndex] and [toIndex] for converting part of [data] /// [titleSize] is used for markdown titles - static ResultMarkdown convertToMarkdown(MarkdownType type, String data, int fromIndex, int toIndex, + static ResultMarkdown convertToMarkdown( + MarkdownType type, String data, int fromIndex, int toIndex, {int titleSize = 1}) { late String changedData; late int replaceCursorIndex; @@ -17,12 +18,18 @@ class FormatMarkdown { changedData = '_${data.substring(fromIndex, toIndex)}_'; replaceCursorIndex = 1; break; + case MarkdownType.strikethrough: + changedData = '~~${data.substring(fromIndex, toIndex)}~~'; + replaceCursorIndex = 2; + break; case MarkdownType.link: - changedData = '[${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})'; + changedData = + '[${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})'; replaceCursorIndex = 3; break; case MarkdownType.title: - changedData = "${"#" * titleSize} ${data.substring(fromIndex, toIndex)}"; + changedData = + "${"#" * titleSize} ${data.substring(fromIndex, toIndex)}"; replaceCursorIndex = 0; break; case MarkdownType.list: @@ -34,12 +41,38 @@ class FormatMarkdown { }).join(); replaceCursorIndex = 0; break; + case MarkdownType.code: + changedData = '```${data.substring(fromIndex, toIndex)}```'; + replaceCursorIndex = 3; + break; + case MarkdownType.blockquote: + var index = 0; + final splitedData = data.substring(fromIndex, toIndex).split('\n'); + changedData = splitedData.map((value) { + index++; + return index == splitedData.length ? '> $value' : '> $value\n'; + }).join(); + replaceCursorIndex = 0; + break; + case MarkdownType.separator: + changedData = '\n------\n${data.substring(fromIndex, toIndex)}'; + replaceCursorIndex = 0; + break; + case MarkdownType.image: + changedData = + '![${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})'; + replaceCursorIndex = 3; + break; } final cursorIndex = changedData.length; - return ResultMarkdown(data.substring(0, fromIndex) + changedData + data.substring(toIndex, data.length), - cursorIndex, replaceCursorIndex); + return ResultMarkdown( + data.substring(0, fromIndex) + + changedData + + data.substring(toIndex, data.length), + cursorIndex, + replaceCursorIndex); } } @@ -67,6 +100,9 @@ enum MarkdownType { /// For _italic_ text italic, + /// For ~~strikethrough~~ text + strikethrough, + /// For [link](https://flutter.dev) link, @@ -77,5 +113,20 @@ enum MarkdownType { /// * Item 1 /// * Item 2 /// * Item 3 - list + list, + + /// For ```code``` text + code, + + /// For : + /// > Item 1 + /// > Item 2 + /// > Item 3 + blockquote, + + /// For adding ------ + separator, + + /// For ![Alt text](https://picsum.photos/500/500) + image, } diff --git a/lib/markdown_text_input.dart b/lib/markdown_text_input.dart index c256e16..9db72ea 100644 --- a/lib/markdown_text_input.dart +++ b/lib/markdown_text_input.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:markdown_editable_textinput/format_markdown.dart'; +import 'package:expandable/expandable.dart'; /// Widget with markdown buttons class MarkdownTextInput extends StatefulWidget { @@ -23,7 +24,10 @@ class MarkdownTextInput extends StatefulWidget { /// Constructor for [MarkdownTextInput] MarkdownTextInput(this.onTextChanged, this.initialValue, - {this.label = '', this.validators, this.textDirection = TextDirection.ltr, this.maxLines = 10}); + {this.label = '', + this.validators, + this.textDirection = TextDirection.ltr, + this.maxLines = 10}); @override _MarkdownTextInputState createState() => _MarkdownTextInputState(); @@ -31,21 +35,26 @@ class MarkdownTextInput extends StatefulWidget { class _MarkdownTextInputState extends State { final _controller = TextEditingController(); - TextSelection textSelection = const TextSelection(baseOffset: 0, extentOffset: 0); + TextSelection textSelection = + const TextSelection(baseOffset: 0, extentOffset: 0); void onTap(MarkdownType type, {int titleSize = 1}) { final basePosition = textSelection.baseOffset; - var noTextSelected = (textSelection.baseOffset - textSelection.extentOffset) == 0; + var noTextSelected = + (textSelection.baseOffset - textSelection.extentOffset) == 0; - final result = FormatMarkdown.convertToMarkdown( - type, _controller.text, textSelection.baseOffset, textSelection.extentOffset, + final result = FormatMarkdown.convertToMarkdown(type, _controller.text, + textSelection.baseOffset, textSelection.extentOffset, titleSize: titleSize); - _controller.value = _controller.value - .copyWith(text: result.data, selection: TextSelection.collapsed(offset: basePosition + result.cursorIndex)); + _controller.value = _controller.value.copyWith( + text: result.data, + selection: + TextSelection.collapsed(offset: basePosition + result.cursorIndex)); if (noTextSelected) { - _controller.selection = TextSelection.collapsed(offset: _controller.selection.end - result.replaceCursorIndex); + _controller.selection = TextSelection.collapsed( + offset: _controller.selection.end - result.replaceCursorIndex); } } @@ -53,7 +62,8 @@ class _MarkdownTextInputState extends State { void initState() { _controller.text = widget.initialValue; _controller.addListener(() { - if (_controller.selection.baseOffset != -1) textSelection = _controller.selection; + if (_controller.selection.baseOffset != -1) + textSelection = _controller.selection; widget.onTextChanged(_controller.text); }); super.initState(); @@ -84,71 +94,165 @@ class _MarkdownTextInputState extends State { cursorColor: Theme.of(context).primaryColor, textDirection: widget.textDirection, decoration: InputDecoration( - enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).accentColor)), - focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).accentColor)), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: Theme.of(context).accentColor)), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide(color: Theme.of(context).accentColor)), hintText: widget.label, - hintStyle: const TextStyle(color: Color.fromRGBO(63, 61, 86, 0.5)), - contentPadding: const EdgeInsets.symmetric(vertical: 15, horizontal: 10), + hintStyle: + const TextStyle(color: Color.fromRGBO(63, 61, 86, 0.5)), + contentPadding: + const EdgeInsets.symmetric(vertical: 15, horizontal: 10), ), ), - Material( - color: Theme.of(context).cardColor, - borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), - child: Row( - children: [ - InkWell( - key: const Key('bold_button'), - onTap: () => onTap(MarkdownType.bold), - child: const Padding( - padding: EdgeInsets.all(10), - child: Icon( - Icons.format_bold, + SizedBox( + height: 44, + child: Material( + color: Theme.of(context).cardColor, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(10), + bottomRight: Radius.circular(10)), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + InkWell( + key: const Key('bold_button'), + onTap: () => onTap(MarkdownType.bold), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.format_bold, + ), + ), + ), + InkWell( + key: const Key('italic_button'), + onTap: () => onTap(MarkdownType.italic), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.format_italic, + ), + ), + ), + InkWell( + key: const Key('strikethrough_button'), + onTap: () => onTap(MarkdownType.strikethrough), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.format_strikethrough, + ), + ), + ), + InkWell( + key: const Key('code_button'), + onTap: () => onTap(MarkdownType.code), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.code, + ), ), ), - ), - InkWell( - key: const Key('italic_button'), - onTap: () => onTap(MarkdownType.italic), - child: const Padding( - padding: EdgeInsets.all(10), - child: Icon( - Icons.format_italic, + ExpandableNotifier( + child: Expandable( + collapsed: ExpandableButton( + child: const Center( + child: Padding( + padding: EdgeInsets.all(10), + child: Text( + 'H#', + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.w700), + ), + ), + ), + ), + expanded: Container( + color: Colors.white10, + child: Row( + children: [ + for (int i = 1; i <= 6; i++) + InkWell( + key: Key('H${i}_button'), + onTap: () => + onTap(MarkdownType.title, titleSize: i), + child: Padding( + padding: const EdgeInsets.all(10), + child: Text( + 'H$i', + style: TextStyle( + fontSize: (18 - i).toDouble(), + fontWeight: FontWeight.w700), + ), + ), + ), + ExpandableButton( + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.close, + ), + ), + ), + ], + ), + ), + ), + ), + InkWell( + key: const Key('link_button'), + onTap: () => onTap(MarkdownType.link), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.link, + ), + ), + ), + InkWell( + key: const Key('list_button'), + onTap: () => onTap(MarkdownType.list), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.list, + ), ), ), - ), - for (int i = 1; i <= 3; i++) InkWell( - key: Key('H${i}_button'), - onTap: () => onTap(MarkdownType.title, titleSize: i), - child: Padding( - padding: const EdgeInsets.all(10), - child: Text( - 'H$i', - style: TextStyle(fontSize: (18 - i).toDouble(), fontWeight: FontWeight.w700), + key: const Key('quote_button'), + onTap: () => onTap(MarkdownType.blockquote), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.format_quote_rounded, ), ), ), - InkWell( - key: const Key('link_button'), - onTap: () => onTap(MarkdownType.link), - child: const Padding( - padding: EdgeInsets.all(10), - child: Icon( - Icons.link, + InkWell( + key: const Key('separator_button'), + onTap: () => onTap(MarkdownType.separator), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.minimize_rounded, + ), ), ), - ), - InkWell( - key: const Key('list_button'), - onTap: () => onTap(MarkdownType.list), - child: const Padding( - padding: EdgeInsets.all(10), - child: Icon( - Icons.list, + InkWell( + key: const Key('image_button'), + onTap: () => onTap(MarkdownType.image), + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon( + Icons.image_rounded, + ), ), ), - ), - ], + ], + ), ), ) ], diff --git a/pubspec.yaml b/pubspec.yaml index a9b42df..c2c15e4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,6 +11,7 @@ dependencies: flutter: sdk: flutter effective_dart: ^1.3.1 + expandable: ^5.0.1 dev_dependencies: From 1a8f9d173b78173aa947106ca20b5ea7f2dfee01 Mon Sep 17 00:00:00 2001 From: CodeNameAkshay Date: Fri, 21 May 2021 19:24:23 +0530 Subject: [PATCH 2/5] write markdown conversion tests --- test/markdown_conversion_test.dart | 207 +++++++++++++++++++++++++---- 1 file changed, 180 insertions(+), 27 deletions(-) diff --git a/test/markdown_conversion_test.dart b/test/markdown_conversion_test.dart index 56b82c3..7254fde 100644 --- a/test/markdown_conversion_test.dart +++ b/test/markdown_conversion_test.dart @@ -4,80 +4,233 @@ import 'package:markdown_editable_textinput/format_markdown.dart'; void main() { group("test all convertToMarkdown function's cases", () { test('convert to bold', () { - var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.bold, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.bold, testString, from, to); - expect(formattedText.cursorIndex, 9, reason: "dolor length = 5, '**' '**' = 4"); - expect(formattedText.data, 'Lorem ipsum **dolor** sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 9, + reason: "dolor length = 5, '**' '**' = 4"); + expect(formattedText.data, + 'Lorem ipsum **dolor** sit amet, consectetur adipiscing elit.'); }); test('convert to italic', () { - var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.italic, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.italic, testString, from, to); - expect(formattedText.cursorIndex, 7, reason: "dolor length = 5, '_' '_' = 2"); - expect(formattedText.data, 'Lorem ipsum _dolor_ sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 7, + reason: "dolor length = 5, '_' '_' = 2"); + expect(formattedText.data, + 'Lorem ipsum _dolor_ sit amet, consectetur adipiscing elit.'); + }); + + test('convert to strikethrough', () { + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var from = 12; + var to = 17; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.strikethrough, testString, from, to); + + expect(formattedText.cursorIndex, 9, + reason: "dolor length = 5, '~~' '~~' = 4"); + expect(formattedText.data, + 'Lorem ipsum ~~dolor~~ sit amet, consectetur adipiscing elit.'); }); test('convert to H1', () { - var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 1); + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.title, testString, from, to, + titleSize: 1); expect(formattedText.cursorIndex, 7, reason: "dolor length = 5, '# '= 2"); - expect(formattedText.data, 'Lorem ipsum # dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.data, + 'Lorem ipsum # dolor sit amet, consectetur adipiscing elit.'); }); test('convert to H2', () { - var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 2); + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.title, testString, from, to, + titleSize: 2); - expect(formattedText.cursorIndex, 8, reason: "dolor length = 5, '## '= 3"); - expect(formattedText.data, 'Lorem ipsum ## dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 8, + reason: "dolor length = 5, '## '= 3"); + expect(formattedText.data, + 'Lorem ipsum ## dolor sit amet, consectetur adipiscing elit.'); }); test('convert to H3', () { - var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var from = 12; + var to = 17; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.title, testString, from, to, + titleSize: 3); + + expect(formattedText.cursorIndex, 9, + reason: "dolor length = 5, '### '= 4"); + expect(formattedText.data, + 'Lorem ipsum ### dolor sit amet, consectetur adipiscing elit.'); + }); + + test('convert to H4', () { + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var from = 12; + var to = 17; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.title, testString, from, to, + titleSize: 4); + + expect(formattedText.cursorIndex, 10, + reason: "dolor length = 5, '#### '= 5"); + expect(formattedText.data, + 'Lorem ipsum #### dolor sit amet, consectetur adipiscing elit.'); + }); + + test('convert to H5', () { + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var from = 12; + var to = 17; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.title, testString, from, to, + titleSize: 5); + + expect(formattedText.cursorIndex, 11, + reason: "dolor length = 5, '##### '= 6"); + expect(formattedText.data, + 'Lorem ipsum ##### dolor sit amet, consectetur adipiscing elit.'); + }); + + test('convert to H6', () { + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 3); + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.title, testString, from, to, + titleSize: 6); - expect(formattedText.cursorIndex, 9, reason: "dolor length = 5, '### '= 4"); - expect(formattedText.data, 'Lorem ipsum ### dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 12, + reason: "dolor length = 5, '###### '= 7"); + expect(formattedText.data, + 'Lorem ipsum ###### dolor sit amet, consectetur adipiscing elit.'); }); test('convert to List', () { - var testString = 'Lorem ipsum\ndolor sit amet\nconsectetur adipiscing elit.'; + var testString = + 'Lorem ipsum\ndolor sit amet\nconsectetur adipiscing elit.'; var from = 0; var to = testString.length; - var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.list, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.list, testString, from, to); - expect(formattedText.data, '* Lorem ipsum\n* dolor sit amet\n* consectetur adipiscing elit.'); - expect(formattedText.cursorIndex, 61, reason: "testString length = 55, '* * * '= 6"); + expect(formattedText.data, + '* Lorem ipsum\n* dolor sit amet\n* consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 61, + reason: "testString length = 55, '* * * '= 6"); }); test('convert to Link', () { - var testString = 'Lorem ipsum dolor sit amet consectetur adipiscing elit.'; + var testString = + 'Lorem ipsum dolor sit amet consectetur adipiscing elit.'; + var from = 12; + var to = 17; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.link, testString, from, to); + + expect(formattedText.data, + 'Lorem ipsum [dolor](dolor) sit amet consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 14, + reason: "dolor length = 5, '[](dolor)'= 9"); + }); + + test('convert to code', () { + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var from = 12; + var to = 17; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.code, testString, from, to); + + expect(formattedText.cursorIndex, 11, + reason: "dolor length = 5, '```' '```' = 6"); + expect(formattedText.data, + 'Lorem ipsum ```dolor``` sit amet, consectetur adipiscing elit.'); + }); + + test('convert to blockquote', () { + var testString = + 'Lorem ipsum\ndolor sit amet\nconsectetur adipiscing elit.'; + var from = 0; + var to = testString.length; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.blockquote, testString, from, to); + + expect(formattedText.data, + '> Lorem ipsum\n> dolor sit amet\n> consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 61, + reason: "testString length = 55, '> > > '= 6"); + }); + + test('convert to image', () { + var testString = + 'Lorem ipsum dolor sit amet consectetur adipiscing elit.'; + var from = 12; + var to = 17; + + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.image, testString, from, to); + + expect(formattedText.data, + 'Lorem ipsum ![dolor](dolor) sit amet consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 15, + reason: "dolor length = 5, '![](dolor)'= 10"); + }); + + test('convert to separator', () { + var testString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.link, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown( + MarkdownType.separator, testString, from, to); - expect(formattedText.data, 'Lorem ipsum [dolor](dolor) sit amet consectetur adipiscing elit.'); - expect(formattedText.cursorIndex, 14, reason: "dolor length = 5, '[](dolor)'= 9"); + expect(formattedText.cursorIndex, 13, + reason: "dolor length = 5, '\n------\n' = 8"); + expect(formattedText.data, + 'Lorem ipsum \n------\ndolor sit amet, consectetur adipiscing elit.'); }); }); } From f8650aa5daa417ed253a8414155c549585e04b5c Mon Sep 17 00:00:00 2001 From: CodeNameAkshay Date: Fri, 21 May 2021 19:37:26 +0530 Subject: [PATCH 3/5] write markdown text input tests --- lib/markdown_text_input.dart | 1 + test/markdown_text_input_test.dart | 121 ++++++++++++++++++++++------- 2 files changed, 96 insertions(+), 26 deletions(-) diff --git a/lib/markdown_text_input.dart b/lib/markdown_text_input.dart index 9db72ea..51391cf 100644 --- a/lib/markdown_text_input.dart +++ b/lib/markdown_text_input.dart @@ -157,6 +157,7 @@ class _MarkdownTextInputState extends State { ), ExpandableNotifier( child: Expandable( + key: Key('H#_button'), collapsed: ExpandableButton( child: const Center( child: Padding( diff --git a/test/markdown_text_input_test.dart b/test/markdown_text_input_test.dart index fcd6569..7e5a932 100644 --- a/test/markdown_text_input_test.dart +++ b/test/markdown_text_input_test.dart @@ -5,25 +5,43 @@ import 'package:markdown_editable_textinput/markdown_text_input.dart'; void main() { testWidgets('MarkdownTextInput has all buttons', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: Scaffold(body: MarkdownTextInput(print, 'initial value')))); + await tester.pumpWidget(MaterialApp( + home: Scaffold(body: MarkdownTextInput(print, 'initial value')))); final boldKey = const Key('bold_button'); final italicKey = const Key('italic_button'); + final strikethroughKey = const Key('strikethrough_button'); + final hKey = const Key('H#_button'); final h1Key = const Key('H1_button'); final h2Key = const Key('H2_button'); final h3Key = const Key('H3_button'); + final h4Key = const Key('H4_button'); + final h5Key = const Key('H5_button'); + final h6Key = const Key('H6_button'); final linkKey = const Key('link_button'); final listKey = const Key('list_button'); + final quoteKey = const Key('quote_button'); + final separatorKey = const Key('separator_button'); + final imageKey = const Key('image_button'); expect(find.byKey(boldKey), findsOneWidget); expect(find.byKey(italicKey), findsOneWidget); + expect(find.byKey(strikethroughKey), findsOneWidget); + expect(find.byKey(hKey), findsOneWidget); expect(find.byKey(h1Key), findsOneWidget); expect(find.byKey(h2Key), findsOneWidget); expect(find.byKey(h3Key), findsOneWidget); + expect(find.byKey(h4Key), findsOneWidget); + expect(find.byKey(h5Key), findsOneWidget); + expect(find.byKey(h6Key), findsOneWidget); expect(find.byKey(linkKey), findsOneWidget); expect(find.byKey(listKey), findsOneWidget); + expect(find.byKey(quoteKey), findsOneWidget); + expect(find.byKey(separatorKey), findsOneWidget); + expect(find.byKey(imageKey), findsOneWidget); }); - testWidgets('MarkdownTextInput make bold from selection', (WidgetTester tester) async { + testWidgets('MarkdownTextInput make bold from selection', + (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -32,7 +50,8 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('bold_button'); await tester.tap(find.byKey(boldKey)); @@ -40,7 +59,8 @@ void main() { expect(initialValue, '**initial value**'); }); - testWidgets('MarkdownTextInput make italic from selection', (WidgetTester tester) async { + testWidgets('MarkdownTextInput make italic from selection', + (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -49,7 +69,8 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('italic_button'); await tester.tap(find.byKey(boldKey)); @@ -57,7 +78,8 @@ void main() { expect(initialValue, '_initial value_'); }); - testWidgets('MarkdownTextInput make H1 from selection', (WidgetTester tester) async { + testWidgets('MarkdownTextInput make strikethrough from selection', + (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -66,15 +88,17 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); - final boldKey = const Key('H1_button'); + final boldKey = const Key('strikethrough_button'); await tester.tap(find.byKey(boldKey)); - expect(initialValue, '# initial value'); + expect(initialValue, '~~initial value~~'); }); - testWidgets('MarkdownTextInput make H2 from selection', (WidgetTester tester) async { + testWidgets('MarkdownTextInput make code from selection', + (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -83,15 +107,17 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); - final boldKey = const Key('H2_button'); + final boldKey = const Key('code_button'); await tester.tap(find.byKey(boldKey)); - expect(initialValue, '## initial value'); + expect(initialValue, '```initial value```'); }); - testWidgets('MarkdownTextInput make H3 from selection', (WidgetTester tester) async { + testWidgets('MarkdownTextInput make link from selection', + (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -100,16 +126,18 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); - final boldKey = const Key('H3_button'); + final boldKey = const Key('link_button'); await tester.tap(find.byKey(boldKey)); - expect(initialValue, '### initial value'); + expect(initialValue, '[initial value](initial value)'); }); - testWidgets('MarkdownTextInput make link from selection', (WidgetTester tester) async { - var initialValue = 'initial value'; + testWidgets('MarkdownTextInput make list from selection', + (WidgetTester tester) async { + var initialValue = 'initial\nvalue'; await tester.pumpWidget(MaterialApp( home: Scaffold( body: MarkdownTextInput((String value) { @@ -117,15 +145,17 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); - final boldKey = const Key('link_button'); + final boldKey = const Key('list_button'); await tester.tap(find.byKey(boldKey)); - expect(initialValue, '[initial value](initial value)'); + expect(initialValue, '* initial\n* value'); }); - testWidgets('MarkdownTextInput make list from selection', (WidgetTester tester) async { + testWidgets('MarkdownTextInput make blockquote from selection', + (WidgetTester tester) async { var initialValue = 'initial\nvalue'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -134,11 +164,50 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); - final boldKey = const Key('list_button'); + final boldKey = const Key('quote_button'); await tester.tap(find.byKey(boldKey)); - expect(initialValue, '* initial\n* value'); + expect(initialValue, '> initial\n> value'); + }); + + testWidgets('MarkdownTextInput make separator from selection', + (WidgetTester tester) async { + var initialValue = 'initial value'; + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: MarkdownTextInput((String value) { + initialValue = value; + }, initialValue)))); + + final formfield = tester.widget(find.text(initialValue)); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); + + final boldKey = const Key('separator_button'); + await tester.tap(find.byKey(boldKey)); + + expect(initialValue, '\n------\ninitial value'); + }); + + testWidgets('MarkdownTextInput make image link from selection', + (WidgetTester tester) async { + var initialValue = 'initial value'; + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: MarkdownTextInput((String value) { + initialValue = value; + }, initialValue)))); + + final formfield = tester.widget(find.text(initialValue)); + formfield.controller.selection = + TextSelection(baseOffset: 0, extentOffset: initialValue.length); + + final boldKey = const Key('image_button'); + await tester.tap(find.byKey(boldKey)); + + expect(initialValue, '![initial value](initial value)'); }); } From 4eaaca65b7f913841410f46cf39e90c416bfe160 Mon Sep 17 00:00:00 2001 From: CodeNameAkshay Date: Tue, 25 May 2021 14:00:44 +0530 Subject: [PATCH 4/5] fix line length #15 --- lib/format_markdown.dart | 20 +--- lib/markdown_text_input.dart | 53 +++------ test/markdown_conversion_test.dart | 183 ++++++++++------------------- test/markdown_text_input_test.dart | 57 +++------ 4 files changed, 101 insertions(+), 212 deletions(-) diff --git a/lib/format_markdown.dart b/lib/format_markdown.dart index b5c8348..788aa11 100644 --- a/lib/format_markdown.dart +++ b/lib/format_markdown.dart @@ -3,8 +3,7 @@ class FormatMarkdown { /// Convert [data] part into [ResultMarkdown] from [type]. /// Use [fromIndex] and [toIndex] for converting part of [data] /// [titleSize] is used for markdown titles - static ResultMarkdown convertToMarkdown( - MarkdownType type, String data, int fromIndex, int toIndex, + static ResultMarkdown convertToMarkdown(MarkdownType type, String data, int fromIndex, int toIndex, {int titleSize = 1}) { late String changedData; late int replaceCursorIndex; @@ -23,13 +22,11 @@ class FormatMarkdown { replaceCursorIndex = 2; break; case MarkdownType.link: - changedData = - '[${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})'; + changedData = '[${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})'; replaceCursorIndex = 3; break; case MarkdownType.title: - changedData = - "${"#" * titleSize} ${data.substring(fromIndex, toIndex)}"; + changedData = "${"#" * titleSize} ${data.substring(fromIndex, toIndex)}"; replaceCursorIndex = 0; break; case MarkdownType.list: @@ -59,20 +56,15 @@ class FormatMarkdown { replaceCursorIndex = 0; break; case MarkdownType.image: - changedData = - '![${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})'; + changedData = '![${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})'; replaceCursorIndex = 3; break; } final cursorIndex = changedData.length; - return ResultMarkdown( - data.substring(0, fromIndex) + - changedData + - data.substring(toIndex, data.length), - cursorIndex, - replaceCursorIndex); + return ResultMarkdown(data.substring(0, fromIndex) + changedData + data.substring(toIndex, data.length), + cursorIndex, replaceCursorIndex); } } diff --git a/lib/markdown_text_input.dart b/lib/markdown_text_input.dart index 51391cf..48db928 100644 --- a/lib/markdown_text_input.dart +++ b/lib/markdown_text_input.dart @@ -24,10 +24,7 @@ class MarkdownTextInput extends StatefulWidget { /// Constructor for [MarkdownTextInput] MarkdownTextInput(this.onTextChanged, this.initialValue, - {this.label = '', - this.validators, - this.textDirection = TextDirection.ltr, - this.maxLines = 10}); + {this.label = '', this.validators, this.textDirection = TextDirection.ltr, this.maxLines = 10}); @override _MarkdownTextInputState createState() => _MarkdownTextInputState(); @@ -35,26 +32,21 @@ class MarkdownTextInput extends StatefulWidget { class _MarkdownTextInputState extends State { final _controller = TextEditingController(); - TextSelection textSelection = - const TextSelection(baseOffset: 0, extentOffset: 0); + TextSelection textSelection = const TextSelection(baseOffset: 0, extentOffset: 0); void onTap(MarkdownType type, {int titleSize = 1}) { final basePosition = textSelection.baseOffset; - var noTextSelected = - (textSelection.baseOffset - textSelection.extentOffset) == 0; + var noTextSelected = (textSelection.baseOffset - textSelection.extentOffset) == 0; - final result = FormatMarkdown.convertToMarkdown(type, _controller.text, - textSelection.baseOffset, textSelection.extentOffset, + final result = FormatMarkdown.convertToMarkdown( + type, _controller.text, textSelection.baseOffset, textSelection.extentOffset, titleSize: titleSize); - _controller.value = _controller.value.copyWith( - text: result.data, - selection: - TextSelection.collapsed(offset: basePosition + result.cursorIndex)); + _controller.value = _controller.value + .copyWith(text: result.data, selection: TextSelection.collapsed(offset: basePosition + result.cursorIndex)); if (noTextSelected) { - _controller.selection = TextSelection.collapsed( - offset: _controller.selection.end - result.replaceCursorIndex); + _controller.selection = TextSelection.collapsed(offset: _controller.selection.end - result.replaceCursorIndex); } } @@ -62,8 +54,7 @@ class _MarkdownTextInputState extends State { void initState() { _controller.text = widget.initialValue; _controller.addListener(() { - if (_controller.selection.baseOffset != -1) - textSelection = _controller.selection; + if (_controller.selection.baseOffset != -1) textSelection = _controller.selection; widget.onTextChanged(_controller.text); }); super.initState(); @@ -94,24 +85,18 @@ class _MarkdownTextInputState extends State { cursorColor: Theme.of(context).primaryColor, textDirection: widget.textDirection, decoration: InputDecoration( - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Theme.of(context).accentColor)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Theme.of(context).accentColor)), + enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).accentColor)), + focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).accentColor)), hintText: widget.label, - hintStyle: - const TextStyle(color: Color.fromRGBO(63, 61, 86, 0.5)), - contentPadding: - const EdgeInsets.symmetric(vertical: 15, horizontal: 10), + hintStyle: const TextStyle(color: Color.fromRGBO(63, 61, 86, 0.5)), + contentPadding: const EdgeInsets.symmetric(vertical: 15, horizontal: 10), ), ), SizedBox( height: 44, child: Material( color: Theme.of(context).cardColor, - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(10), - bottomRight: Radius.circular(10)), + borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), child: ListView( scrollDirection: Axis.horizontal, children: [ @@ -164,8 +149,7 @@ class _MarkdownTextInputState extends State { padding: EdgeInsets.all(10), child: Text( 'H#', - style: TextStyle( - fontSize: 16, fontWeight: FontWeight.w700), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700), ), ), ), @@ -177,15 +161,12 @@ class _MarkdownTextInputState extends State { for (int i = 1; i <= 6; i++) InkWell( key: Key('H${i}_button'), - onTap: () => - onTap(MarkdownType.title, titleSize: i), + onTap: () => onTap(MarkdownType.title, titleSize: i), child: Padding( padding: const EdgeInsets.all(10), child: Text( 'H$i', - style: TextStyle( - fontSize: (18 - i).toDouble(), - fontWeight: FontWeight.w700), + style: TextStyle(fontSize: (18 - i).toDouble(), fontWeight: FontWeight.w700), ), ), ), diff --git a/test/markdown_conversion_test.dart b/test/markdown_conversion_test.dart index 7254fde..3a5d50f 100644 --- a/test/markdown_conversion_test.dart +++ b/test/markdown_conversion_test.dart @@ -4,233 +4,168 @@ import 'package:markdown_editable_textinput/format_markdown.dart'; void main() { group("test all convertToMarkdown function's cases", () { test('convert to bold', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.bold, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.bold, testString, from, to); - expect(formattedText.cursorIndex, 9, - reason: "dolor length = 5, '**' '**' = 4"); - expect(formattedText.data, - 'Lorem ipsum **dolor** sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 9, reason: "dolor length = 5, '**' '**' = 4"); + expect(formattedText.data, 'Lorem ipsum **dolor** sit amet, consectetur adipiscing elit.'); }); test('convert to italic', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.italic, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.italic, testString, from, to); - expect(formattedText.cursorIndex, 7, - reason: "dolor length = 5, '_' '_' = 2"); - expect(formattedText.data, - 'Lorem ipsum _dolor_ sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 7, reason: "dolor length = 5, '_' '_' = 2"); + expect(formattedText.data, 'Lorem ipsum _dolor_ sit amet, consectetur adipiscing elit.'); }); test('convert to strikethrough', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.strikethrough, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.strikethrough, testString, from, to); - expect(formattedText.cursorIndex, 9, - reason: "dolor length = 5, '~~' '~~' = 4"); - expect(formattedText.data, - 'Lorem ipsum ~~dolor~~ sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 9, reason: "dolor length = 5, '~~' '~~' = 4"); + expect(formattedText.data, 'Lorem ipsum ~~dolor~~ sit amet, consectetur adipiscing elit.'); }); test('convert to H1', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.title, testString, from, to, - titleSize: 1); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 1); expect(formattedText.cursorIndex, 7, reason: "dolor length = 5, '# '= 2"); - expect(formattedText.data, - 'Lorem ipsum # dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.data, 'Lorem ipsum # dolor sit amet, consectetur adipiscing elit.'); }); test('convert to H2', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.title, testString, from, to, - titleSize: 2); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 2); - expect(formattedText.cursorIndex, 8, - reason: "dolor length = 5, '## '= 3"); - expect(formattedText.data, - 'Lorem ipsum ## dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 8, reason: "dolor length = 5, '## '= 3"); + expect(formattedText.data, 'Lorem ipsum ## dolor sit amet, consectetur adipiscing elit.'); }); test('convert to H3', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.title, testString, from, to, - titleSize: 3); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 3); - expect(formattedText.cursorIndex, 9, - reason: "dolor length = 5, '### '= 4"); - expect(formattedText.data, - 'Lorem ipsum ### dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 9, reason: "dolor length = 5, '### '= 4"); + expect(formattedText.data, 'Lorem ipsum ### dolor sit amet, consectetur adipiscing elit.'); }); test('convert to H4', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.title, testString, from, to, - titleSize: 4); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 4); - expect(formattedText.cursorIndex, 10, - reason: "dolor length = 5, '#### '= 5"); - expect(formattedText.data, - 'Lorem ipsum #### dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 10, reason: "dolor length = 5, '#### '= 5"); + expect(formattedText.data, 'Lorem ipsum #### dolor sit amet, consectetur adipiscing elit.'); }); test('convert to H5', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.title, testString, from, to, - titleSize: 5); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 5); - expect(formattedText.cursorIndex, 11, - reason: "dolor length = 5, '##### '= 6"); - expect(formattedText.data, - 'Lorem ipsum ##### dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 11, reason: "dolor length = 5, '##### '= 6"); + expect(formattedText.data, 'Lorem ipsum ##### dolor sit amet, consectetur adipiscing elit.'); }); test('convert to H6', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.title, testString, from, to, - titleSize: 6); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.title, testString, from, to, titleSize: 6); - expect(formattedText.cursorIndex, 12, - reason: "dolor length = 5, '###### '= 7"); - expect(formattedText.data, - 'Lorem ipsum ###### dolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 12, reason: "dolor length = 5, '###### '= 7"); + expect(formattedText.data, 'Lorem ipsum ###### dolor sit amet, consectetur adipiscing elit.'); }); test('convert to List', () { - var testString = - 'Lorem ipsum\ndolor sit amet\nconsectetur adipiscing elit.'; + var testString = 'Lorem ipsum\ndolor sit amet\nconsectetur adipiscing elit.'; var from = 0; var to = testString.length; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.list, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.list, testString, from, to); - expect(formattedText.data, - '* Lorem ipsum\n* dolor sit amet\n* consectetur adipiscing elit.'); - expect(formattedText.cursorIndex, 61, - reason: "testString length = 55, '* * * '= 6"); + expect(formattedText.data, '* Lorem ipsum\n* dolor sit amet\n* consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 61, reason: "testString length = 55, '* * * '= 6"); }); test('convert to Link', () { - var testString = - 'Lorem ipsum dolor sit amet consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.link, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.link, testString, from, to); - expect(formattedText.data, - 'Lorem ipsum [dolor](dolor) sit amet consectetur adipiscing elit.'); - expect(formattedText.cursorIndex, 14, - reason: "dolor length = 5, '[](dolor)'= 9"); + expect(formattedText.data, 'Lorem ipsum [dolor](dolor) sit amet consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 14, reason: "dolor length = 5, '[](dolor)'= 9"); }); test('convert to code', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.code, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.code, testString, from, to); - expect(formattedText.cursorIndex, 11, - reason: "dolor length = 5, '```' '```' = 6"); - expect(formattedText.data, - 'Lorem ipsum ```dolor``` sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 11, reason: "dolor length = 5, '```' '```' = 6"); + expect(formattedText.data, 'Lorem ipsum ```dolor``` sit amet, consectetur adipiscing elit.'); }); test('convert to blockquote', () { - var testString = - 'Lorem ipsum\ndolor sit amet\nconsectetur adipiscing elit.'; + var testString = 'Lorem ipsum\ndolor sit amet\nconsectetur adipiscing elit.'; var from = 0; var to = testString.length; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.blockquote, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.blockquote, testString, from, to); - expect(formattedText.data, - '> Lorem ipsum\n> dolor sit amet\n> consectetur adipiscing elit.'); - expect(formattedText.cursorIndex, 61, - reason: "testString length = 55, '> > > '= 6"); + expect(formattedText.data, '> Lorem ipsum\n> dolor sit amet\n> consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 61, reason: "testString length = 55, '> > > '= 6"); }); test('convert to image', () { - var testString = - 'Lorem ipsum dolor sit amet consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.image, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.image, testString, from, to); - expect(formattedText.data, - 'Lorem ipsum ![dolor](dolor) sit amet consectetur adipiscing elit.'); - expect(formattedText.cursorIndex, 15, - reason: "dolor length = 5, '![](dolor)'= 10"); + expect(formattedText.data, 'Lorem ipsum ![dolor](dolor) sit amet consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 15, reason: "dolor length = 5, '![](dolor)'= 10"); }); test('convert to separator', () { - var testString = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + var testString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; var from = 12; var to = 17; - var formattedText = FormatMarkdown.convertToMarkdown( - MarkdownType.separator, testString, from, to); + var formattedText = FormatMarkdown.convertToMarkdown(MarkdownType.separator, testString, from, to); - expect(formattedText.cursorIndex, 13, - reason: "dolor length = 5, '\n------\n' = 8"); - expect(formattedText.data, - 'Lorem ipsum \n------\ndolor sit amet, consectetur adipiscing elit.'); + expect(formattedText.cursorIndex, 13, reason: "dolor length = 5, '\n------\n' = 8"); + expect(formattedText.data, 'Lorem ipsum \n------\ndolor sit amet, consectetur adipiscing elit.'); }); }); } diff --git a/test/markdown_text_input_test.dart b/test/markdown_text_input_test.dart index 7e5a932..b2f8795 100644 --- a/test/markdown_text_input_test.dart +++ b/test/markdown_text_input_test.dart @@ -5,8 +5,7 @@ import 'package:markdown_editable_textinput/markdown_text_input.dart'; void main() { testWidgets('MarkdownTextInput has all buttons', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp( - home: Scaffold(body: MarkdownTextInput(print, 'initial value')))); + await tester.pumpWidget(MaterialApp(home: Scaffold(body: MarkdownTextInput(print, 'initial value')))); final boldKey = const Key('bold_button'); final italicKey = const Key('italic_button'); final strikethroughKey = const Key('strikethrough_button'); @@ -40,8 +39,7 @@ void main() { expect(find.byKey(imageKey), findsOneWidget); }); - testWidgets('MarkdownTextInput make bold from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make bold from selection', (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -50,8 +48,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('bold_button'); await tester.tap(find.byKey(boldKey)); @@ -59,8 +56,7 @@ void main() { expect(initialValue, '**initial value**'); }); - testWidgets('MarkdownTextInput make italic from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make italic from selection', (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -69,8 +65,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('italic_button'); await tester.tap(find.byKey(boldKey)); @@ -78,8 +73,7 @@ void main() { expect(initialValue, '_initial value_'); }); - testWidgets('MarkdownTextInput make strikethrough from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make strikethrough from selection', (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -88,8 +82,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('strikethrough_button'); await tester.tap(find.byKey(boldKey)); @@ -97,8 +90,7 @@ void main() { expect(initialValue, '~~initial value~~'); }); - testWidgets('MarkdownTextInput make code from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make code from selection', (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -107,8 +99,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('code_button'); await tester.tap(find.byKey(boldKey)); @@ -116,8 +107,7 @@ void main() { expect(initialValue, '```initial value```'); }); - testWidgets('MarkdownTextInput make link from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make link from selection', (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -126,8 +116,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('link_button'); await tester.tap(find.byKey(boldKey)); @@ -135,8 +124,7 @@ void main() { expect(initialValue, '[initial value](initial value)'); }); - testWidgets('MarkdownTextInput make list from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make list from selection', (WidgetTester tester) async { var initialValue = 'initial\nvalue'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -145,8 +133,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('list_button'); await tester.tap(find.byKey(boldKey)); @@ -154,8 +141,7 @@ void main() { expect(initialValue, '* initial\n* value'); }); - testWidgets('MarkdownTextInput make blockquote from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make blockquote from selection', (WidgetTester tester) async { var initialValue = 'initial\nvalue'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -164,8 +150,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('quote_button'); await tester.tap(find.byKey(boldKey)); @@ -173,8 +158,7 @@ void main() { expect(initialValue, '> initial\n> value'); }); - testWidgets('MarkdownTextInput make separator from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make separator from selection', (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -183,8 +167,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('separator_button'); await tester.tap(find.byKey(boldKey)); @@ -192,8 +175,7 @@ void main() { expect(initialValue, '\n------\ninitial value'); }); - testWidgets('MarkdownTextInput make image link from selection', - (WidgetTester tester) async { + testWidgets('MarkdownTextInput make image link from selection', (WidgetTester tester) async { var initialValue = 'initial value'; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -202,8 +184,7 @@ void main() { }, initialValue)))); final formfield = tester.widget(find.text(initialValue)); - formfield.controller.selection = - TextSelection(baseOffset: 0, extentOffset: initialValue.length); + formfield.controller.selection = TextSelection(baseOffset: 0, extentOffset: initialValue.length); final boldKey = const Key('image_button'); await tester.tap(find.byKey(boldKey)); From ca7fb8df24a7693fe988c43601cccea7490c87a5 Mon Sep 17 00:00:00 2001 From: Akshay Maurya Date: Wed, 26 May 2021 19:42:29 +0530 Subject: [PATCH 5/5] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 034f8ce..2a5b00c 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,13 @@ MarkdownEditableTextInput is a TextField Widget that allow you to convert easily what's in the TextField to Markdown. ## Features -- [x] Convert to Bold, Italic, Title (h1,h2,h3), List and Link +- [x] Convert to Bold, Italic, Strikethrough +- [x] Convert to Code, Quote, Links +- [x] Convert to Heading (H1, H2, H3, H4, H5, H6) and Links - [x] Support text direction ## Demo -![](pictures/test_edition.gif) +https://user-images.githubusercontent.com/60510869/119675122-65409f00-be5a-11eb-8cc4-c0f8757030ab.mp4 ## Usage The color of the MarkdownTextInput is defined by the color set in your Theme :