Skip to content

Commit

Permalink
Add support for custom link resolver (issue #2).
Browse files Browse the repository at this point in the history
  • Loading branch information
dikmax committed Jun 25, 2015
1 parent 3b4b781 commit 75a3bda
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 9 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,38 @@ void main() {
}
```

Custom reference resolver
-------------------------

Custom reference resolver may be required when parsing document without implicit defined references, for example
Dartdoc.

```dart
/**
* Throws a [StateError] if ...
* similar to [anotherMethod], but ...
*/
```

In that case you could supply parser with resolver, which should provide all missing links.

```dart
String library = "md_proc";
String version = "0.4.0";
Target linkResolver(String normalizedReference, String reference) {
if (reference.startsWith("new ")) {
String className = reference.substring(4);
return new Target("http://www.dartdocs.org/documentation/$library/$version/index.html#$library/$library.$className@id_$className-", null);
} else {
return null;
}
}
CommonMarkParser parser = new CommonMarkParser(new Options(linkResolver: linkResolver));
Document doc = parser.parse('Hello world!\n===');
String res = HtmlWriter.DEFAULT.write(doc);
```

High-level plan for development
===============================

Expand Down
2 changes: 1 addition & 1 deletion lib/md_proc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import 'src/html_writer.dart';
import 'src/markdown_parser.dart';

export 'src/definitions.dart';
export 'src/markdown_parser.dart';
export 'src/html_writer.dart';
export 'src/markdown_parser.dart';
export 'src/markdown_writer.dart';
export 'src/options.dart';

Expand Down
20 changes: 14 additions & 6 deletions lib/src/markdown_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -747,11 +747,15 @@ class CommonMarkParser {
if (refRes.isSuccess) {
String reference = refRes.value == "" ? labelRes.value : refRes.value;
String normalizedReference = _normalizeReference(reference);
if (_references.containsKey(normalizedReference)) {
Target target = _references[normalizedReference];
if (target == null) {
target = _options.linkResolver(normalizedReference, reference);
}
if (target != null) {
if (isLink) {
return refRes.copy(value: [new ReferenceLink(reference, linkInlines, _references[normalizedReference])]);
return refRes.copy(value: [new ReferenceLink(reference, linkInlines, target)]);
} else {
return refRes.copy(value: [new ReferenceImage(reference, linkInlines, _references[normalizedReference])]);
return refRes.copy(value: [new ReferenceImage(reference, linkInlines, target)]);
}
}
} else {
Expand All @@ -761,11 +765,15 @@ class CommonMarkParser {
return labelRes;
}
String normalizedReference = _normalizeReference(labelRes.value);
if (_references.containsKey(normalizedReference)) {
Target target = _references[normalizedReference];
if (target == null) {
target = _options.linkResolver(normalizedReference, labelRes.value);
}
if (target != null) {
if (isLink) {
return labelRes.copy(value: [new ReferenceLink(labelRes.value, linkInlines, _references[normalizedReference])]);
return labelRes.copy(value: [new ReferenceLink(labelRes.value, linkInlines, target)]);
} else {
return labelRes.copy(value: [new ReferenceImage(labelRes.value, linkInlines, _references[normalizedReference])]);
return labelRes.copy(value: [new ReferenceImage(labelRes.value, linkInlines, target)]);
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion lib/src/options.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
library md_proc.options;

import 'definitions.dart';

/**
* Link resolver accepts two references and should return [Target] with correspondent link.
* If link doesn't exists link resolver should return `null`.
*
* CommonMark defines reference as case insensitive. Use [normalizedReference] when you need reference
* normalized according to CommonMark rules, or just [reference] if you want to get reference as it
* written in document.
*/
typedef Target LinkResolver(String normalizedReference, String reference);

/**
* Default resolver doesn't return any link, so be default parser parses only explicitly written references.
*/
Target DEFAULT_LINK_RESOLVER(String normalizedReference, String reference) => null;

class Options {
bool smartPunctuation;
LinkResolver linkResolver;

Options({this.smartPunctuation: false});
Options({
this.smartPunctuation: false,
this.linkResolver: DEFAULT_LINK_RESOLVER
});

static Options DEFAULT = new Options(smartPunctuation: true);
static Options STRICT = new Options();
Expand Down
4 changes: 3 additions & 1 deletion test/library_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:md_proc/src/options.dart';

import 'parser.dart';
import 'service.dart';

import 'reference_resolver.dart';

void main() {
serviceTests();
Expand All @@ -16,4 +16,6 @@ void main() {
fileTest("SmartPunct", "smart_punct.txt", mdToHtmlTest(Options.DEFAULT));
// Markdown to markdown tests
fileTest("md2md", "markdownToMarkdown.txt", mdToMdTest(Options.STRICT));
// Custom resolver
referenceResolverTests();
}
25 changes: 25 additions & 0 deletions test/markdownToMarkdown.txt
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,28 @@ Lists formatting

3. b
.

Links
=====

.
[reference][reference]

[reference]: reference
.
[reference]


[reference]: reference
.

.
[reference][reference][reference]

[reference]: reference
.
[reference][reference]


[reference]: reference
.
67 changes: 67 additions & 0 deletions test/reference_resolver.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
library referenceResolverTest;

import 'package:test/test.dart' as t;

import 'package:md_proc/md_proc.dart';

Target linkResolver(String normalizedReference, String reference) {
if (reference == "reference") {
return new Target(reference, null);
} else {
return null;
}
}


String md1Test = r'''
This is a [reference].
[reference]: reference2
''';

String md1Pattern = r'''
This is a [reference].
[reference]: reference2
''';

String md2Test = r'''
This is a [reference].
''';

String md2Pattern = r'''
This is a [reference].
[reference]: reference
''';

String md3Test = r'''
This is a [link].
''';

String md3Pattern = r'''
This is a [link].
''';

void referenceResolverTests() {
CommonMarkParser parser = new CommonMarkParser(new Options(linkResolver: linkResolver));
CommonMarkParser defaultParser = CommonMarkParser.DEFAULT;

t.group("Custom reference resolver test", () {
t.test("Should leave defined links as is", () {
Document d1 = parser.parse(md1Test);
Document d2 = defaultParser.parse(md1Pattern);
t.expect(d1, t.equals(d2));
});
t.test("May resolve undefined links", () {
Document d1 = parser.parse(md2Test);
Document d2 = defaultParser.parse(md2Pattern);
t.expect(d1, t.equals(d2));
});
t.test("May not resolve undefined links", () {
Document d1 = parser.parse(md3Test);
Document d2 = defaultParser.parse(md3Pattern);
t.expect(d1, t.equals(d2));
});
});
}
1 change: 1 addition & 0 deletions tool/travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dartanalyzer --fatal-warnings \
lib/src/options.dart \
test/parser.dart \
test/service.dart \
test/reference_resolver.dart \
test/library_test.dart

# Run the tests.
Expand Down

0 comments on commit 75a3bda

Please sign in to comment.