Skip to content

Commit 13133ca

Browse files
committed
Allow resolving links that contain inline syntax.
Fixes dart-lang/markdown#42. [email protected] Review URL: https://codereview.chromium.org//1274753003 .
1 parent 2bcb39e commit 13133ca

File tree

7 files changed

+118
-102
lines changed

7 files changed

+118
-102
lines changed

pkgs/markdown/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.idea
12
.packages
23
.pub
34
packages

pkgs/markdown/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.7.2
2+
3+
* Allow resolving links that contain inline syntax (#42).
4+
15
## 0.7.1+3
26

37
* Updated homepage.

pkgs/markdown/lib/src/html_renderer.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ class HtmlRenderer implements NodeVisitor {
6060
buffer.write('<${element.tag}');
6161

6262
// Sort the keys so that we generate stable output.
63-
// TODO(rnystrom): This assumes keys returns a fresh mutable
64-
// collection.
6563
final attributeNames = element.attributes.keys.toList();
6664
attributeNames.sort((a, b) => a.compareTo(b));
6765
for (final name in attributeNames) {

pkgs/markdown/lib/src/inline_parser.dart

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,10 @@ class LinkSyntax extends TagSyntax {
280280
if (isNullOrEmpty(match[1])) {
281281
if (linkResolver == null) return null;
282282

283-
// Only allow implicit links if the content is just text.
284-
// TODO(rnystrom): Do we want to relax this?
285-
if (state.children.any((child) => child is! Text)) return null;
286-
// If there are multiple children, but they are all text, send the
287-
// combined text to linkResolver.
288-
var textToResolve =
289-
state.children.fold('', (oldVal, child) => oldVal + child.text);
283+
// Treat the contents as unparsed text even if they happen to match. This
284+
// way, we can handle things like [LINK_WITH_UNDERSCORES] as a link and
285+
// not get confused by the emphasis.
286+
var textToResolve = parser.source.substring(state.endPos, parser.pos);
290287

291288
// See if we have a resolver that will generate a link for us.
292289
resolved = true;

pkgs/markdown/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: markdown
2-
version: 0.7.1+3
2+
version: 0.7.2-dev
33
author: Dart Team <[email protected]>
44
description: A library for converting markdown to HTML.
55
homepage: https://github.com/dart-lang/markdown

pkgs/markdown/test/markdown_test.dart

Lines changed: 14 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
/// Unit tests for markdown.
6-
library markdownTests;
6+
library markdown.test.markdown_test;
77

88
import 'package:unittest/unittest.dart';
9+
910
import 'package:markdown/markdown.dart';
1011

12+
import 'utils.dart';
13+
1114
/// Most of these tests are based on observing how showdown behaves:
1215
/// http://softwaremaniacs.org/playground/showdown-highlight/
1316
void main() {
@@ -949,7 +952,8 @@ void main() {
949952
});
950953

951954
group('Resolver', () {
952-
var nyanResolver = (text) => new Text('~=[,,_${text}_,,]:3');
955+
nyanResolver(text) => new Text('~=[,,_${text}_,,]:3');
956+
953957
validate('simple link resolver', '''
954958
resolve [this] thing
955959
''', '''
@@ -960,12 +964,17 @@ void main() {
960964
''', '''
961965
<p>resolve ~=[,,_this_,,]:3 thing</p>
962966
''', imageLinkResolver: nyanResolver);
967+
968+
validate('can resolve link containing inline tags', '''
969+
resolve [*star* _underline_] thing
970+
''', '''
971+
<p>resolve ~=[,,_*star* _underline__,,]:3 thing</p>
972+
''', linkResolver: nyanResolver);
963973
});
964974

965975
group('Custom inline syntax', () {
966-
List<InlineSyntax> nyanSyntax = [
967-
new TextSyntax('nyan', sub: '~=[,,_,,]:3')
968-
];
976+
var nyanSyntax = [new TextSyntax('nyan', sub: '~=[,,_,,]:3')];
977+
969978
validate('simple inline syntax', '''
970979
nyan
971980
''', '''
@@ -1022,90 +1031,3 @@ void main() {
10221031
''', inlineOnly: true);
10231032
});
10241033
}
1025-
1026-
/**
1027-
* Removes eight spaces of leading indentation from a multiline string.
1028-
*
1029-
* Note that this is very sensitive to how the literals are styled. They should
1030-
* be:
1031-
* '''
1032-
* Text starts on own line. Lines up with subsequent lines.
1033-
* Lines are indented exactly 8 characters from the left margin.'''
1034-
*
1035-
* This does nothing if text is only a single line.
1036-
*/
1037-
// TODO(nweiz): Make this auto-detect the indentation level from the first
1038-
// non-whitespace line.
1039-
String cleanUpLiteral(String text) {
1040-
var lines = text.split('\n');
1041-
if (lines.length <= 1) return text;
1042-
1043-
for (var j = 0; j < lines.length; j++) {
1044-
if (lines[j].length > 8) {
1045-
lines[j] = lines[j].substring(8, lines[j].length);
1046-
} else {
1047-
lines[j] = '';
1048-
}
1049-
}
1050-
1051-
return lines.join('\n');
1052-
}
1053-
1054-
void validate(String description, String markdown, String html,
1055-
{List<InlineSyntax> inlineSyntaxes,
1056-
Resolver linkResolver, Resolver imageLinkResolver,
1057-
bool inlineOnly: false}) {
1058-
test(description, () {
1059-
markdown = cleanUpLiteral(markdown);
1060-
html = cleanUpLiteral(html);
1061-
1062-
var result = markdownToHtml(markdown,
1063-
inlineSyntaxes: inlineSyntaxes,
1064-
linkResolver: linkResolver,
1065-
imageLinkResolver: imageLinkResolver,
1066-
inlineOnly: inlineOnly);
1067-
var passed = compareOutput(html, result);
1068-
1069-
if (!passed) {
1070-
// Remove trailing newline.
1071-
html = html.substring(0, html.length - 1);
1072-
1073-
var sb = new StringBuffer();
1074-
sb.writeln('Expected: ${html.replaceAll("\n", "\n ")}');
1075-
sb.writeln(' Actual: ${result.replaceAll("\n", "\n ")}');
1076-
1077-
fail(sb.toString());
1078-
}
1079-
});
1080-
}
1081-
1082-
/// Does a loose comparison of the two strings of HTML. Ignores differences in
1083-
/// newlines and indentation.
1084-
bool compareOutput(String a, String b) {
1085-
int i = 0;
1086-
int j = 0;
1087-
1088-
skipIgnored(String s, int i) {
1089-
// Ignore newlines.
1090-
while ((i < s.length) && (s[i] == '\n')) {
1091-
i++;
1092-
// Ignore indentation.
1093-
while ((i < s.length) && (s[i] == ' ')) i++;
1094-
}
1095-
1096-
return i;
1097-
}
1098-
1099-
while (true) {
1100-
i = skipIgnored(a, i);
1101-
j = skipIgnored(b, j);
1102-
1103-
// If one string runs out of non-ignored strings, the other must too.
1104-
if (i == a.length) return j == b.length;
1105-
if (j == b.length) return i == a.length;
1106-
1107-
if (a[i] != b[j]) return false;
1108-
i++;
1109-
j++;
1110-
}
1111-
}

pkgs/markdown/test/utils.dart

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
library markdown.test.utils;
6+
7+
import 'package:unittest/unittest.dart';
8+
9+
import 'package:markdown/markdown.dart';
10+
11+
/// Removes eight spaces of leading indentation from a multiline string.
12+
///
13+
/// Note that this is very sensitive to how the literals are styled. They should
14+
/// be:
15+
/// '''
16+
/// Text starts on own line. Lines up with subsequent lines.
17+
/// Lines are indented exactly 8 characters from the left margin.'''
18+
///
19+
/// This does nothing if text is only a single line.
20+
// TODO(nweiz): Make this auto-detect the indentation level from the first
21+
// non-whitespace line.
22+
String cleanUpLiteral(String text) {
23+
var lines = text.split('\n');
24+
if (lines.length <= 1) return text;
25+
26+
for (var j = 0; j < lines.length; j++) {
27+
if (lines[j].length > 8) {
28+
lines[j] = lines[j].substring(8, lines[j].length);
29+
} else {
30+
lines[j] = '';
31+
}
32+
}
33+
34+
return lines.join('\n');
35+
}
36+
37+
void validate(String description, String markdown, String html,
38+
{List<InlineSyntax> inlineSyntaxes,
39+
Resolver linkResolver, Resolver imageLinkResolver,
40+
bool inlineOnly: false}) {
41+
test(description, () {
42+
markdown = cleanUpLiteral(markdown);
43+
html = cleanUpLiteral(html);
44+
45+
var result = markdownToHtml(markdown,
46+
inlineSyntaxes: inlineSyntaxes,
47+
linkResolver: linkResolver,
48+
imageLinkResolver: imageLinkResolver,
49+
inlineOnly: inlineOnly);
50+
var passed = compareOutput(html, result);
51+
52+
if (!passed) {
53+
// Remove trailing newline.
54+
html = html.substring(0, html.length - 1);
55+
56+
var sb = new StringBuffer();
57+
sb.writeln('Expected: ${html.replaceAll("\n", "\n ")}');
58+
sb.writeln(' Actual: ${result.replaceAll("\n", "\n ")}');
59+
60+
fail(sb.toString());
61+
}
62+
});
63+
}
64+
65+
/// Does a loose comparison of the two strings of HTML. Ignores differences in
66+
/// newlines and indentation.
67+
bool compareOutput(String a, String b) {
68+
int i = 0;
69+
int j = 0;
70+
71+
skipIgnored(String s, int i) {
72+
// Ignore newlines.
73+
while ((i < s.length) && (s[i] == '\n')) {
74+
i++;
75+
// Ignore indentation.
76+
while ((i < s.length) && (s[i] == ' ')) i++;
77+
}
78+
79+
return i;
80+
}
81+
82+
while (true) {
83+
i = skipIgnored(a, i);
84+
j = skipIgnored(b, j);
85+
86+
// If one string runs out of non-ignored strings, the other must too.
87+
if (i == a.length) return j == b.length;
88+
if (j == b.length) return i == a.length;
89+
90+
if (a[i] != b[j]) return false;
91+
i++;
92+
j++;
93+
}
94+
}

0 commit comments

Comments
 (0)