anchor.diff:          return false;
         });
   
  -  Parser<List<Inline>> _linkOrImage(bool isLink) =>
  -      new Parser<List<Inline>>((String s, Position pos) {
  -        ParseResult testRes = char('[').run(s, pos);
  -        if (!testRes.isSuccess) {
  -          return testRes;
  -        }
  -
  -        // Try inline
  -        ParseResult labelRes = (isLink ? linkText : imageText).run(s, pos);
  +  static final Parser _linkOrImageTestParser = char('[');
  +  static final Parser _linkOrImageRefParser =
  +      (blankline | whitespaceChar).maybe > linkLabel;
  +  Parser<List<Inline>> _linkOrImage(bool isLink) {
  +    Parser labelParser = isLink ? linkText : imageText;
  +    return new Parser<List<Inline>>((String s, Position pos) {
  +      ParseResult testRes = _linkOrImageTestParser.run(s, pos);
  +      if (!testRes.isSuccess) {
  +        return testRes;
  +      }
  +
  +      // Try inline
  +      ParseResult labelRes = labelParser.run(s, pos);
  +      if (!labelRes.isSuccess) {
  +        return labelRes;
  +      }
  +      if (isLink && labelRes.value.contains(new RegExp(r"^\s*$"))) {
  +        return fail.run(s, pos);
  +      }
  +      Inlines linkInlines = inlines.parse(labelRes.value, tabStop: tabStop);
  +      if (isLink && _isContainsLink(linkInlines)) {
  +        List<Inline> resValue = [new Str('[')];
  +        resValue.addAll(linkInlines);
  +        resValue.add(new Str(']'));
  +        return labelRes.copy(value: resValue);
  +      }
  +      ParseResult destRes = linkInline.run(s, labelRes.position);
  +      if (destRes.isSuccess) {
  +        // Links inside link content are not allowed
  +        if (isLink) {
  +          return destRes.copy(
  +              value: [new InlineLink(linkInlines, destRes.value)]);
  +        } else {
  +          return destRes.copy(
  +              value: [new InlineImage(linkInlines, destRes.value)]);
  +        }
  +      }
  +
  +      // Try reference link
  +      ParseResult refRes = _linkOrImageRefParser.run(s, labelRes.position);
  +      if (refRes.isSuccess) {
  +        String reference = refRes.value == "" ? labelRes.value : refRes.value;
  +        String normalizedReference = _normalizeReference(reference);
  +        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, target)]);
  +          } else {
  +            return refRes.copy(
  +                value: [new ReferenceImage(reference, linkInlines, target)]);
  +          }
  +        }
  +      } else {
  +        // Try again from beginning because reference couldn't contain brackets
  +        labelRes = linkLabel.run(s, pos);
           if (!labelRes.isSuccess) {
             return labelRes;
           }
  -        if (isLink && labelRes.value.contains(new RegExp(r"^\s*$"))) {
  -          return fail.run(s, pos);
  -        }
  -        Inlines linkInlines = inlines.parse(labelRes.value, tabStop: tabStop);
  -        if (isLink && _isContainsLink(linkInlines)) {
  -          List<Inline> resValue = [new Str('[')];
  -          resValue.addAll(linkInlines);
  -          resValue.add(new Str(']'));
  -          return labelRes.copy(value: resValue);
  -        }
  -        ParseResult destRes = linkInline.run(s, labelRes.position);
  -        if (destRes.isSuccess) {
  -          // Links inside link content are not allowed
  +        String normalizedReference = _normalizeReference(labelRes.value);
  +        Target target = _references[normalizedReference];
  +        if (target == null) {
  +          target = _options.linkResolver(normalizedReference, labelRes.value);
  +        }
  +        if (target != null) {
             if (isLink) {
  -            return destRes.copy(
  -                value: [new InlineLink(linkInlines, destRes.value)]);
  +            return labelRes.copy(value:
  +                [new ReferenceLink(labelRes.value, linkInlines, target)]);
             } else {
  -            return destRes.copy(
  -                value: [new InlineImage(linkInlines, destRes.value)]);
  -          }
  -        }
  -
  -        // Try reference link
  -        ParseResult refRes = ((blankline | whitespaceChar).maybe > linkLabel)
  -            .run(s, labelRes.position);
  -        if (refRes.isSuccess) {
  -          String reference = refRes.value == "" ? labelRes.value : refRes.value;
  -          String normalizedReference = _normalizeReference(reference);
  -          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, target)]);
  -            } else {
  -              return refRes.copy(
  -                  value: [new ReferenceImage(reference, linkInlines, target)]);
  -            }
  -          }
  -        } else {
  -          // Try again from beginning because reference couldn't contain brackets
  -          labelRes = linkLabel.run(s, pos);
  -          if (!labelRes.isSuccess) {
  -            return labelRes;
  -          }
  -          String normalizedReference = _normalizeReference(labelRes.value);
  -          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, target)]);
  -            } else {
  -              return labelRes.copy(value:
  -                  [new ReferenceImage(labelRes.value, linkInlines, target)]);
  -            }
  -          }
  -        }
  -
  -        return fail.run(s, pos);
  -      });
  +            return labelRes.copy(value:
  +                [new ReferenceImage(labelRes.value, linkInlines, target)]);
  +          }
  +        }
  +      }
  +
  +      return fail.run(s, pos);
  +    });
  +  }
   
     Parser<List<Inline>> get image => char('!') > _linkOrImage(false);
     Parser<List<Inline>> get link => _linkOrImage(true);
   
  -  List<String> allowedSchemes = <String>[
  +  // TODO test benchmark
  +  static final Set<String> allowedSchemes = new Set<String>.from(<String>[
       "coap",
       "doi",
       "javascript",
  
positive.code:     "xfire",
      "xri",
      "ymsgr"
    ];
  
    RegExp autolinkEmailRegExp = new RegExp(
        r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}"
        r"[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");
  
    Parser<List<Inline>> get autolink =>
        new Parser<List<Inline>>((String s, Position pos) {
          ParseResult res = (char('<') >
              pred((String char) =>
                      char.codeUnitAt(0) > 0x20 && char != "<" && char != ">")
                  .manyUntil(char('>'))).run(s, pos);
          if (!res.isSuccess) {
            return res;
          }
          String contents = res.value.join();
          int colon = contents.indexOf(":");
          if (colon >= 1) {
            String schema = contents.substring(0, colon).toLowerCase();
            if (allowedSchemes.contains(schema)) {
              return res.copy(value: [new Autolink(contents)]);
            }
          }
  
          if (contents.contains(autolinkEmailRegExp)) {
            return res.copy(value: [new Autolink.email(contents)]);
          }
  
          return fail.run(s, pos);
        });
  
    //
    // raw html
    //
  
    Parser get rawInlineHtml => choice([
          htmlOpenTag,
          htmlCloseTag,
          htmlCompleteComment,
  
negative.code: 
    Map<String, Target> _references;
  
    Set<String> _inlineDelimiters;
    Set<String> _strSpecialChars;
    Set<String> _intrawordDelimiters;
  
    CommonMarkParser(this._options, [this._references]) {
      _inlineDelimiters = new Set<String>.from(["_", "*"]);
      _strSpecialChars = new Set<String>.from(
          [" ", "*", "_", "`", "!", "[", "]", "&", "<", "\\"]);
      _intrawordDelimiters = new Set<String>.from(["*"]);
      if (_options.smartPunctuation) {
        _inlineDelimiters.addAll(["'", "\""]);
        _strSpecialChars.addAll(["'", "\"", ".", "-"]);
      }
      if (_options.strikeout || _options.subscript) {
        _inlineDelimiters.add("~");
        _strSpecialChars.add("~");
        _intrawordDelimiters.add("~");
      }
      if (_options.superscript) {
        _inlineDelimiters.add('^');
        _strSpecialChars.add('^');
        _intrawordDelimiters.add('^');
      }
    }
  
  