Merge pull request dart-lang/markdown#84 from mehaase/commonmark
Improve dart-lang/markdowndart-lang/markdown#51.
diff --git a/pkgs/markdown/pubspec.yaml b/pkgs/markdown/pubspec.yaml
index 7740d41..dc8a73d 100644
--- a/pkgs/markdown/pubspec.yaml
+++ b/pkgs/markdown/pubspec.yaml
@@ -8,6 +8,7 @@
dev_dependencies:
args: '^0.13.3+1'
collection: ^1.2.0
+ html: '^0.12.2'
path: '^1.3.1'
test: '^0.12.4+1'
yaml: '^2.1.8'
diff --git a/pkgs/markdown/tool/common_mark_stats.dart b/pkgs/markdown/tool/common_mark_stats.dart
index f34ca05..87c8039 100644
--- a/pkgs/markdown/tool/common_mark_stats.dart
+++ b/pkgs/markdown/tool/common_mark_stats.dart
@@ -6,6 +6,7 @@
import 'dart:mirrors';
import 'package:collection/collection.dart';
+import 'package:html/parser.dart' show parseFragment;
import 'package:markdown/markdown.dart';
import 'package:path/path.dart' as p;
@@ -28,12 +29,20 @@
sections.forEach((section, examples) {
for (var e in examples) {
- var output = markdownToHtml(e.markdown);
-
+ var output;
var nestedMap =
scores.putIfAbsent(section, () => new SplayTreeMap<int, bool>());
- nestedMap[e.example] = (output == e.html);
+ try {
+ output = markdownToHtml(e.markdown);
+ } catch (exc) {
+ nestedMap[e.example] = false;
+ continue;
+ }
+
+ var expected = parseFragment(e.html);
+ var actual = parseFragment(output);
+ nestedMap[e.example] = compareHtml(expected.children, actual.children);
}
});
@@ -91,6 +100,60 @@
'– ${pct}% TOTAL');
}
+/// Compare two DOM trees for equality.
+bool compareHtml(List<Element> expectedElements, List<Element> actualElements) {
+ if (expectedElements.length != actualElements.length) {
+ return false;
+ }
+
+ for (var childNum = 0; childNum < expectedElements.length; childNum++) {
+ var expected = expectedElements[childNum];
+ var actual = actualElements[childNum];
+
+ if (expected.runtimeType != actual.runtimeType) {
+ return false;
+ }
+
+ if (expected is Element) {
+ if (expected.localName != actual.localName) {
+ return false;
+ }
+
+ if (expected.attributes.length != actual.attributes.length) {
+ return false;
+ }
+
+ var expectedAttrKeys = expected.attributes.keys.toList();
+ expectedAttrKeys.sort();
+
+ var actualAttrKeys = actual.attributes.keys.toList();
+ actualAttrKeys.sort();
+
+ for (var attrNum = 0; attrNum < actualAttrKeys.length; attrNum++) {
+ var expectedAttrKey = expectedAttrKeys[attrNum];
+ var actualAttrKey = actualAttrKeys[attrNum];
+
+ if (expectedAttrKey != actualAttrKey) {
+ return false;
+ }
+
+ if (expected.attributes[expectedAttrKey] !=
+ actual.attributes.keys[actualAttrKey]) {
+ return false;
+ }
+ }
+ }
+
+ var childrenEqual = compareHtml(expected.children, actual.children);
+
+ if (!childrenEqual) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
Map<String, List<CommonMarkTestCase>> loadCommonMarkSections() {
var testFile = new File(p.join(_currentDir, _commonMarkTests));
var testsJson = testFile.readAsStringSync();