Skip to content

Commit

Permalink
Strikeout support.
Browse files Browse the repository at this point in the history
  • Loading branch information
dikmax committed Aug 10, 2015
1 parent a74d8b3 commit 61641a9
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 5 deletions.
12 changes: 12 additions & 0 deletions lib/definitions.dart
Expand Up @@ -568,6 +568,18 @@ class Strong extends Inline {
}


class Strikeout extends Inline {
Inlines contents;

Strikeout(this.contents);

String toString() => 'Strikeout $contents';

bool operator== (obj) => obj is Strikeout &&
_iterableEquality.equals(contents, obj.contents);
}


abstract class Link extends Inline {
Inlines label;
Target target;
Expand Down
14 changes: 14 additions & 0 deletions lib/html_writer.dart
Expand Up @@ -179,6 +179,8 @@ class _HtmlBuilder extends StringBuffer {
writeEmph(inline, stripped: stripped);
} else if (inline is Strong) {
writeStrong(inline, stripped: stripped);
} else if (inline is Strikeout) {
writeStrikeout(inline, stripped: stripped);
} else if (inline is Link) {
writeLink(inline, stripped: stripped);
} else if (inline is Image) {
Expand Down Expand Up @@ -241,6 +243,17 @@ class _HtmlBuilder extends StringBuffer {
}


void writeStrikeout(Strikeout strikeout, {bool stripped: false}) {
if (!stripped) {
write('<del>');
}
writeInlines(strikeout.contents, stripped: stripped);
if (!stripped) {
write('</del>');
}
}


void writeSmartQuote(SmartQuote quote, {bool stripped: false}) {
// TODO different quotation styles
if (quote.open && quote.close) {
Expand Down Expand Up @@ -335,6 +348,7 @@ class HtmlWriter {
return builder.toString();
}

static HtmlWriter commonmark = new HtmlWriter(Options.commonmark);
static HtmlWriter strict = new HtmlWriter(Options.strict);
static HtmlWriter defaults = new HtmlWriter(Options.defaults);
}
36 changes: 33 additions & 3 deletions lib/markdown_parser.dart
Expand Up @@ -68,7 +68,21 @@ class CommonMarkParser {

Map<String, Target> _references;

CommonMarkParser(this._options, [this._references]);
String _inlineDelimiters;
String _strSpecialChars;

CommonMarkParser(this._options, [this._references]) {
_inlineDelimiters = "_*";
_strSpecialChars = " *_`![]&<\\";
if (_options.smartPunctuation) {
_inlineDelimiters += "'\"";
_strSpecialChars += "'\".-";
}
if (_options.strikeout) {
_inlineDelimiters += "~";
_strSpecialChars += "~";
}
}

Document parse(String s) {
// TODO separate preprocess option
Expand Down Expand Up @@ -519,8 +533,9 @@ class CommonMarkParser {
static RegExp _isSpace = new RegExp(r'^\s');

static RegExp _isPunctuation = new RegExp("^[\u{2000}-\u{206F}\u{2E00}-\u{2E7F}\\\\'!\"#\\\$%&\\(\\)\\*\\+,\\-\\.\\/:;<=>\\?@\\[\\]\\^_`\\{\\|\\}~]");

Parser get scanDelims => new Parser((String s, Position pos) {
ParseResult testRes = oneOf(_options.smartPunctuation ? "*_'\"" : "*_").lookAhead.run(s, pos);
ParseResult testRes = oneOf(_inlineDelimiters).lookAhead.run(s, pos);
if (!testRes.isSuccess) {
return testRes;
}
Expand All @@ -544,6 +559,10 @@ class CommonMarkParser {
canOpen = canOpen && (!rightFlanking || _isPunctuation.hasMatch(charBefore));
canClose = canClose && (!leftFlanking || _isPunctuation.hasMatch(charAfter));
}
if (c == '~' && numDelims < 2) {
canOpen = false;
canClose = false;
}
return res.copy(value: [numDelims, canOpen, canClose, c]);
});

Expand Down Expand Up @@ -618,6 +637,17 @@ class CommonMarkParser {
inlines.add(inline);
count--;
}
} else if (char == "~") {
if (count & 1 == 1) {
inlines.add(new Str("~"));
count--;
}
while (count > 0) {
inline = new Strikeout(inlines);
inlines = new Inlines();
inlines.add(inline);
count -= 2;
}
} else {
if (count & 1 == 1) {
inline = new Emph(inlines);
Expand Down Expand Up @@ -930,7 +960,6 @@ class CommonMarkParser {
};


String get _strSpecialChars => _options.smartPunctuation ? " *_`'\".-![]&<\\" : " *_`![]&<\\";
Parser get str => (noneOf(_strSpecialChars + "\n").many1 ^ (chars) => _transformString(chars.join())) |
(oneOf(_strSpecialChars) ^ (chars) => _transformString(chars)) |
(char("\n").notFollowedBy(spnl) ^ (_) => [new Str("\n")]);
Expand Down Expand Up @@ -1793,6 +1822,7 @@ class CommonMarkParser {
Parser get document => (block.manyUntil(eof) ^ (res) => new Document(processParsedBlocks(res))) % "document";


static CommonMarkParser commonmark = new CommonMarkParser(Options.commonmark);
static CommonMarkParser defaults = new CommonMarkParser(Options.defaults);
static CommonMarkParser strict = new CommonMarkParser(Options.strict);
}
14 changes: 14 additions & 0 deletions lib/markdown_writer.dart
Expand Up @@ -128,6 +128,10 @@ class _NotCheckedPart extends _InlinePart {
});
}

if (_options.strikeout) {
content = content.replaceAll(new RegExp("~~"), r"\~~");
}

if (!context.isHeader) {
content = content.replaceAllMapped(_notHeaderRegExp1, (Match m) => m.group(1) + r"\" + m.group(2));
content = content.replaceAllMapped(_notHeaderRegExp2, (Match m) => m.group(1) + r"\" + m.group(2));
Expand Down Expand Up @@ -301,6 +305,8 @@ class _InlineRenderer {
}
} else if (inline is SmartQuote) {
writeSmartQuote(inline, context: context);
} else if (inline is Strikeout) {
writeStrikeout(inline, context: context);
} else if (inline is RawInline) {
write(inline.contents);
} else {
Expand Down Expand Up @@ -364,6 +370,13 @@ class _InlineRenderer {
}


void writeStrikeout(Strikeout strikeout, {_EscapeContext context: _EscapeContext.empty}) {
write("~~");
writeInlines(strikeout.contents, context: context);
write("~~");
}


void writeLink(Link link) {
if (link is InlineLink) {
write('[');
Expand Down Expand Up @@ -708,6 +721,7 @@ class MarkdownWriter {
return builder.toString();
}

static const MarkdownWriter commonmark = const MarkdownWriter(Options.commonmark);
static const MarkdownWriter strict = const MarkdownWriter(Options.strict);
static const MarkdownWriter defaults = const MarkdownWriter(Options.defaults);
}
6 changes: 5 additions & 1 deletion lib/options.dart
Expand Up @@ -15,13 +15,17 @@ Target defaultLinkResolver(String normalizedReference, String reference) => null

class Options {
final bool smartPunctuation;
final bool strikeout;
final LinkResolver linkResolver;

const Options({
this.smartPunctuation: false,
this.strikeout: false,
this.linkResolver: defaultLinkResolver
});

static const Options defaults = const Options(smartPunctuation: true);
static const Options commonmark = const Options(smartPunctuation: true);
static const Options defaults = const Options(smartPunctuation: true,
strikeout: true);
static const Options strict = const Options();
}
37 changes: 37 additions & 0 deletions test/data/strikeout.txt
@@ -0,0 +1,37 @@
## Strikeout tests

.
~~Strikeout text~~
.
<p><del>Strikeout text</del></p>
.

.
~~__Strikeout text__~~
.
<p><del><strong>Strikeout text</strong></del></p>
.

.
Ins~~e~~ide w~~a~~ord
.
<p>Ins<del>e</del>ide w<del>a</del>ord</p>
.

.
~\~No strikeout~~
.
<p>~~No strikeout~~</p>
.

.
\~~No strikeout~~
.
<p>~~No strikeout~~</p>
.

.
~No strikeout~
.
<p>~No strikeout~</p>
.
3 changes: 3 additions & 0 deletions test/data/test_data.dart
Expand Up @@ -15,3 +15,6 @@ final Map<String, String> markdownToMarkdown = _$markdownToMarkdownTests;

@EmbedTests('additionalMarkdownToHtml.txt')
final Map<String, String> additionalMarkdownToHtml = _$additionalMarkdownToHtmlTests;

@EmbedTests('strikeout.txt')
final Map<String, String> strikeout = _$strikeoutTests;
28 changes: 27 additions & 1 deletion test/data/test_data.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/library_test.dart
Expand Up @@ -22,6 +22,7 @@ void main() {
tests("Additional", additionalMarkdownToHtml, mdToHtmlTest(Options.strict));
// Additional tests
tests("SmartPunct", smartPunctuation, mdToHtmlTest(Options.defaults));
tests("Strikeout", strikeout, mdToHtmlTest(Options.defaults));
// Markdown to markdown tests
tests("md2md", markdownToMarkdown, mdToMdTest(Options.strict));
// Custom resolver
Expand Down
14 changes: 14 additions & 0 deletions test/service.dart
Expand Up @@ -495,6 +495,20 @@ void serviceTests() {
});
});

t.group('Strikeout', () {
var strikeout = new Strikeout(new Inlines.from([new Str('Strikeout')]));
t.test('toString', () {
t.expect(strikeout.toString(), t.equals('Strikeout [Str "Strikeout"]'));
});
t.test('==', () {
t.expect(strikeout, t.equals(new Strikeout(new Inlines.from([new Str('Strikeout')]))));
});
t.test('!=', () {
t.expect(strikeout, t.isNot(t.equals(new Inlines.from([new Str('Emph')]))));
t.expect(strikeout, t.isNot(t.equals(null)));
});
});

t.group('InlineLink', () {
var link = new InlineLink(new Inlines.from([new Str('Dart')]), new Target('https://www.dartlang.org/', null));
t.test('toString', () {
Expand Down

0 comments on commit 61641a9

Please sign in to comment.