<commit_before>import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:mirrors';

import 'package:args/args.dart';
import 'package:collection/collection.dart';
import 'package:html/dom.dart';
import 'package:html/parser.dart' show parseFragment;
import 'package:markdown/markdown.dart' show markdownToHtml;
import 'package:path/path.dart' as p;

const _commonMarkTests = 'common_mark_tests.json';

// Locate the "test" directory. Use mirrors so that this works with the test
// package, which loads this suite into an isolate.
String get _currentDir => p
    .dirname((reflect(main) as ClosureMirror).function.location.sourceUri.path);

main(List<String> args) async {
  final parser = new ArgParser()
    ..addOption('section',
        help: 'Restrict tests to one section, provided after the option.')
    ..addFlag('raw',
        defaultsTo: false, help: 'raw JSON format', negatable: false)
    ..addFlag('update-files',
        defaultsTo: false,
        help: 'Update stats files in $_currentDir',
        negatable: false)
    ..addFlag('verbose',
        defaultsTo: false, help: 'verbose output', negatable: false)
    ..addFlag('help', defaultsTo: false, negatable: false);

  ArgResults options;

  try {
    options = parser.parse(args);
  } on FormatException catch (e) {
    stderr.writeln(e);
    print(parser.usage);
    exitCode = 64; // unix standard improper usage
    return;
  }

  if (options['help']) {
    print(parser.usage);
    return;
  }

  var specifiedSection = options['section'] as String;
  var raw = options['raw'] as bool;
  var verbose = options['verbose'] as bool;
  var updateFiles = options['update-files'] as bool;

  if (updateFiles && (raw || verbose || (specifiedSection != null))) {
    stderr.writeln('The `update-files` flag must be used by itself');
    print(parser.usage);
    exitCode = 64; // unix standard improper usage
    return;
  }

  var sections = _loadCommonMarkSections();

  var scores = new SplayTreeMap<String, SplayTreeMap<int, bool>>(
      compareAsciiLowerCaseNatural);

  String indent(String s) => s.splitMapJoin('\n', onNonMatch: (n) => '    $n');

  sections.forEach((section, examples) {
    if (specifiedSection != null && section != specifiedSection) {
      return;
    }
    for (var e in examples) {
      var output;
      var nestedMap =
          scores.putIfAbsent(section, () => new SplayTreeMap<int, bool>());

      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);
      if (verbose && !nestedMap[e.example]) {
        print('FAIL: http://spec.commonmark.org/0.25/#example-${e.example}');
        print('input:');
        print(indent(e.markdown));
        print('expected:');
        print(indent(expected.outerHtml));
        print('actual:');
        print(indent(actual.outerHtml));
        print('-----------------------');
      }
    }
  });

  if (raw || updateFiles) {
    await _printRaw(scores, updateFiles);
  }

  if (!raw || updateFiles) {
    await _printFriendly(scores, updateFiles);
  }<commit_msg>Print caught errors in CommonMark script (#108)<commit_after>import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:mirrors';

import 'package:args/args.dart';
import 'package:collection/collection.dart';
import 'package:html/dom.dart';
import 'package:html/parser.dart' show parseFragment;
import 'package:markdown/markdown.dart' show markdownToHtml;
import 'package:path/path.dart' as p;

const _commonMarkTests = 'common_mark_tests.json';

// Locate the "test" directory. Use mirrors so that this works with the test
// package, which loads this suite into an isolate.
String get _currentDir => p
    .dirname((reflect(main) as ClosureMirror).function.location.sourceUri.path);

main(List<String> args) async {
  final parser = new ArgParser()
    ..addOption('section',
        help: 'Restrict tests to one section, provided after the option.')
    ..addFlag('raw',
        defaultsTo: false, help: 'raw JSON format', negatable: false)
    ..addFlag('update-files',
        defaultsTo: false,
        help: 'Update stats files in $_currentDir',
        negatable: false)
    ..addFlag('verbose',
        defaultsTo: false, help: 'verbose output', negatable: false)
    ..addFlag('help', defaultsTo: false, negatable: false);

  ArgResults options;

  try {
    options = parser.parse(args);
  } on FormatException catch (e) {
    stderr.writeln(e);
    print(parser.usage);
    exitCode = 64; // unix standard improper usage
    return;
  }

  if (options['help']) {
    print(parser.usage);
    return;
  }

  var specifiedSection = options['section'] as String;
  var raw = options['raw'] as bool;
  var verbose = options['verbose'] as bool;
  var updateFiles = options['update-files'] as bool;

  if (updateFiles && (raw || verbose || (specifiedSection != null))) {
    stderr.writeln('The `update-files` flag must be used by itself');
    print(parser.usage);
    exitCode = 64; // unix standard improper usage
    return;
  }

  var sections = _loadCommonMarkSections();

  var scores = new SplayTreeMap<String, SplayTreeMap<int, bool>>(
      compareAsciiLowerCaseNatural);

  String indent(String s) => s.splitMapJoin('\n', onNonMatch: (n) => '    $n');

  printVerboseFailure(
      String message, CommonMarkTestCase test, String expected, String actual) {
    if (!verbose) {
      return;
    }

    print('$message: http://spec.commonmark.org/0.25/#example-${test.example}');
    print('input:');
    print(indent(test.markdown));
    print('expected:');
    print(indent(expected));
    print('actual:');
    print(indent(actual));
    print('-----------------------');
  }

  sections.forEach((section, examples) {
    if (specifiedSection != null && section != specifiedSection) {
      return;
    }
    for (var e in examples) {
      var output;
      var nestedMap =
          scores.putIfAbsent(section, () => new SplayTreeMap<int, bool>());
      var expected = parseFragment(e.html);

      try {
        output = markdownToHtml(e.markdown);
      } catch (exc, stackTrace) {
        nestedMap[e.example] = false;
        printVerboseFailure(
            'ERROR', e, expected.outerHtml, 'Thrown: $exc\n$stackTrace');
        continue;
      }

      var actual = parseFragment(output);
      nestedMap[e.example] = compareHtml(expected.children, actual.children);
      if (!nestedMap[e.example]) {
        printVerboseFailure('FAIL', e, expected.outerHtml, actual.outerHtml);
      }
    }
  });

  if (raw || updateFiles) {
    await _printRaw(scores, updateFiles);
  }

  if (!raw || updateFiles) {
    await _printFriendly(scores, updateFiles);
  }
{'fraction_non_alphanumeric': 0.1454361640670133, 'fraction_numerical': 0.002455228191796649, 'mean_word_length': 3.2746913580246915, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2200524', 'n_tokens_mistral': 2142, 'n_tokens_neox': 2064, 'n_words': 534}