diff --git a/README.md b/README.md index c177f96..563d0c9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,23 @@ + +![](subwrite-logo.png) + + # subwrite -A Ridiculously Personalized Markdown Editor +A Ridiculously Personalized Markdown Editor by Sarah Jamie Lewis. + +## Screenshots ![](subwrite.png) +![](subwrite-spellcheck.png) + +## Features + +- Reorderable Table of Contents / Section View +- Spellchecking / Custom Dictionary +- Inline Image Previews + +## Contributing + +Open an issue or submit a PR! diff --git a/lib/annotation.dart b/lib/annotation.dart index da39752..7cdd341 100644 --- a/lib/annotation.dart +++ b/lib/annotation.dart @@ -7,6 +7,7 @@ enum AnnotationType { error, todo, note, + image, } class LineAnnotation { diff --git a/lib/file.dart b/lib/file.dart index bdb1b5d..09d2bef 100644 --- a/lib/file.dart +++ b/lib/file.dart @@ -44,6 +44,15 @@ class LineFile extends ChangeNotifier { (value) { spellchecker = value; status = "dictionary loaded"; + + status = "spellchecking document"; + updateStatus(0.0); + notifyListeners(); + spellCheckAll().then((value) { + status = "spellchecking complete"; + updateStatus(1.0); + notifyListeners(); + }); notifyListeners(); }, ); @@ -227,6 +236,7 @@ class LineFile extends ChangeNotifier { status = "spellchecking document"; notifyListeners(); updateStatus(0.0); + spellCheckAll().then((value) { status = "spellcheck complete"; notifyListeners(); @@ -259,6 +269,9 @@ class LineFile extends ChangeNotifier { } parse(); + spellcheck(cursor.line - 1).then((value) { + notifyListeners(); + }); return KeyEventResult.handled; } @@ -413,6 +426,12 @@ class LineFile extends ChangeNotifier { dotAll: true, ); + final _imageRegex = RegExp( + r'!\[([^\[]*)\]\((.*)\)', + caseSensitive: false, + dotAll: true, + ); + List
sections = List.empty(growable: true); Future spellcheck(int i) async { @@ -555,6 +574,11 @@ class LineFile extends ChangeNotifier { .add(LineAnnotation(SourceLink(path, lineStart: backingLines[i].lineNumber, colStart: 0, colEnd: line.text.length + 1, lineEnd: i), "markdown", AnnotationType.highlight, "code")); } + var imageMatch = _imageRegex.matchAsPrefix(line.text); + if (imageMatch != null) { + backingLines[i].annotations.add(LineAnnotation(SourceLink(path, lineStart: backingLines[i].lineNumber, lineEnd: i), "markdown", AnnotationType.image, imageMatch.group(2)!)); + } + _boldRegex.allMatches(backingLines[i].text).forEach((match) { backingLines[i] .annotations diff --git a/lib/line_info.dart b/lib/line_info.dart index 95a02dc..b2dab0e 100644 --- a/lib/line_info.dart +++ b/lib/line_info.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'dart:math'; import 'package:flutter/gestures.dart'; @@ -54,6 +55,11 @@ class LineInfo extends ChangeNotifier { sidebarContent.addAll(icons); + LineAnnotation? image; + if (annotations.any((element) => element.annotationType == AnnotationType.image)) { + image = annotations.firstWhere((element) => element.annotationType == AnnotationType.image); + } + return LayoutBuilder( builder: (context, constraints) { var usableSize = (constraints.maxWidth - gutterWidth - rightMargin - leftMargin).floorToDouble(); @@ -79,18 +85,39 @@ class LineInfo extends ChangeNotifier { var idealHeight = (lineHeight * (1.0 + ((text.length * charWidth) / usableSize).floorToDouble())).ceilToDouble(); - var highlightedLineContainer = Container( - padding: EdgeInsets.zero, - margin: EdgeInsets.only(right: rightMargin, top: 0, bottom: 0, left: leftMargin), - decoration: BoxDecoration( - color: backgroundStyle.backgroundColor, - ), - width: usableSize, - height: idealHeight, - child: highlightedLine, - ); + if (cursorStart != null || image == null) { + var highlightedLineContainer = Container( + padding: EdgeInsets.zero, + margin: EdgeInsets.only(right: rightMargin, top: 0, bottom: 0, left: leftMargin), + decoration: BoxDecoration( + color: backgroundStyle.backgroundColor, + ), + width: usableSize, + height: idealHeight, + child: highlightedLine, + ); - stackElements.add(highlightedLineContainer); + stackElements.add(highlightedLineContainer); + } else { + var file = File(image.type); + idealHeight = 250; + var imageContainer = Container( + padding: EdgeInsets.zero, + margin: EdgeInsets.only(right: rightMargin, top: 0, bottom: 0, left: leftMargin), + decoration: BoxDecoration( + color: backgroundStyle.backgroundColor, + ), + width: usableSize, + child: Image.file( + file, + height: idealHeight, + width: usableSize / 2.0, + fit: BoxFit.contain, + filterQuality: FilterQuality.high, + cacheHeight: idealHeight.floor(), + )); + stackElements.add(imageContainer); + } if (cursorStart != null) { var maxCharsBeforeWrapping = (usableSize / charWidth).floorToDouble(); diff --git a/subwrite-spellcheck.png b/subwrite-spellcheck.png new file mode 100644 index 0000000..61683dc Binary files /dev/null and b/subwrite-spellcheck.png differ diff --git a/subwrite.png b/subwrite.png index 8e6d047..8542bae 100644 Binary files a/subwrite.png and b/subwrite.png differ