| // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import '../inline_parser.dart'; | |
| import '../util.dart'; | |
| /// Represents one kind of Markdown tag that can be parsed. | |
| abstract class InlineSyntax { | |
| final RegExp pattern; | |
| /// The first character of [pattern], to be used as an efficient first check | |
| /// that this syntax matches the current parser position. | |
| final int? _startCharacter; | |
| /// Create a new [InlineSyntax] which matches text on [pattern]. | |
| /// | |
| /// If [startCharacter] is passed, it is used as a pre-matching check which | |
| /// is faster than matching against [pattern]. | |
| /// | |
| /// If [caseSensitive] is disabled, then case is ignored when matching | |
| /// the [pattern]. | |
| InlineSyntax(String pattern, {int? startCharacter, bool caseSensitive = true}) | |
| : pattern = RegExp(pattern, multiLine: true, caseSensitive: caseSensitive), | |
| _startCharacter = startCharacter; | |
| /// Tries to match at the parser's current position. | |
| /// | |
| /// The parser's position can be overriden with [startMatchPos]. | |
| /// Returns whether or not the pattern successfully matched. | |
| bool tryMatch(InlineParser parser, [int? startMatchPos]) { | |
| startMatchPos ??= parser.pos; | |
| // Before matching with the regular expression [pattern], which can be | |
| // expensive on some platforms, check if even the first character matches | |
| // this syntax. | |
| if (_startCharacter != null && | |
| parser.source.codeUnitAt(startMatchPos) != _startCharacter) { | |
| return false; | |
| } | |
| final startMatch = pattern.matchAsPrefix(parser.source, startMatchPos); | |
| if (startMatch == null) return false; | |
| // Write any existing plain text up to this point. | |
| parser.writeText(); | |
| if (onMatch(parser, startMatch)) parser.consume(startMatch.match.length); | |
| return true; | |
| } | |
| /// Processes [match], adding nodes to [parser] and possibly advancing | |
| /// [parser]. | |
| /// | |
| /// Returns whether the caller should advance [parser] by `match[0].length`. | |
| bool onMatch(InlineParser parser, Match match); | |
| } |