| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// Maintains the internal state needed to parse inline span elements in | 5 /// Maintains the internal state needed to parse inline span elements in |
| 6 /// markdown. | 6 /// markdown. |
| 7 class InlineParser { | 7 class InlineParser { |
| 8 static List<InlineSyntax> get syntaxes { | 8 static List<InlineSyntax> get syntaxes { |
| 9 // Lazy initialize. | 9 // Lazy initialize. |
| 10 if (_syntaxes == null) { | 10 if (_syntaxes == null) { |
| 11 _syntaxes = <InlineSyntax>[ | 11 _syntaxes = <InlineSyntax>[ |
| 12 new AutolinkSyntax(), | 12 new AutolinkSyntax(), |
| 13 new LinkSyntax(), | 13 new LinkSyntax(), |
| 14 // "*" surrounded by spaces is left alone. | 14 // "*" surrounded by spaces is left alone. |
| 15 new TextSyntax(@' \* '), | 15 new TextSyntax(r' \* '), |
| 16 // "_" surrounded by spaces is left alone. | 16 // "_" surrounded by spaces is left alone. |
| 17 new TextSyntax(@' _ '), | 17 new TextSyntax(r' _ '), |
| 18 // Leave already-encoded HTML entities alone. Ensures we don't turn | 18 // Leave already-encoded HTML entities alone. Ensures we don't turn |
| 19 // "&" into "&amp;" | 19 // "&" into "&amp;" |
| 20 new TextSyntax(@'&[#a-zA-Z0-9]*;'), | 20 new TextSyntax(r'&[#a-zA-Z0-9]*;'), |
| 21 // Encode "&". | 21 // Encode "&". |
| 22 new TextSyntax(@'&', sub: '&'), | 22 new TextSyntax(r'&', sub: '&'), |
| 23 // Encode "<". (Why not encode ">" too? Gruber is toying with us.) | 23 // Encode "<". (Why not encode ">" too? Gruber is toying with us.) |
| 24 new TextSyntax(@'<', sub: '<'), | 24 new TextSyntax(r'<', sub: '<'), |
| 25 // Parse "**strong**" tags. | 25 // Parse "**strong**" tags. |
| 26 new TagSyntax(@'\*\*', tag: 'strong'), | 26 new TagSyntax(r'\*\*', tag: 'strong'), |
| 27 // Parse "__strong__" tags. | 27 // Parse "__strong__" tags. |
| 28 new TagSyntax(@'__', tag: 'strong'), | 28 new TagSyntax(r'__', tag: 'strong'), |
| 29 // Parse "*emphasis*" tags. | 29 // Parse "*emphasis*" tags. |
| 30 new TagSyntax(@'\*', tag: 'em'), | 30 new TagSyntax(r'\*', tag: 'em'), |
| 31 // Parse "_emphasis_" tags. | 31 // Parse "_emphasis_" tags. |
| 32 // TODO(rnystrom): Underscores in the middle of a word should not be | 32 // TODO(rnystrom): Underscores in the middle of a word should not be |
| 33 // parsed as emphasis like_in_this. | 33 // parsed as emphasis like_in_this. |
| 34 new TagSyntax(@'_', tag: 'em'), | 34 new TagSyntax(r'_', tag: 'em'), |
| 35 // Parse inline code within double backticks: "``code``". | 35 // Parse inline code within double backticks: "``code``". |
| 36 new CodeSyntax(@'``\s?((?:.|\n)*?)\s?``'), | 36 new CodeSyntax(r'``\s?((?:.|\n)*?)\s?``'), |
| 37 // Parse inline code within backticks: "`code`". | 37 // Parse inline code within backticks: "`code`". |
| 38 new CodeSyntax(@'`([^`]*)`') | 38 new CodeSyntax(r'`([^`]*)`') |
| 39 ]; | 39 ]; |
| 40 } | 40 } |
| 41 | 41 |
| 42 return _syntaxes; | 42 return _syntaxes; |
| 43 } | 43 } |
| 44 | 44 |
| 45 static List<InlineSyntax> _syntaxes; | 45 static List<InlineSyntax> _syntaxes; |
| 46 | 46 |
| 47 /// The string of markdown being parsed. | 47 /// The string of markdown being parsed. |
| 48 final String source; | 48 final String source; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 175 |
| 176 // Insert the substitution. | 176 // Insert the substitution. |
| 177 parser.addNode(new Text(substitute)); | 177 parser.addNode(new Text(substitute)); |
| 178 return true; | 178 return true; |
| 179 } | 179 } |
| 180 } | 180 } |
| 181 | 181 |
| 182 /// Matches autolinks like `<http://foo.com>`. | 182 /// Matches autolinks like `<http://foo.com>`. |
| 183 class AutolinkSyntax extends InlineSyntax { | 183 class AutolinkSyntax extends InlineSyntax { |
| 184 AutolinkSyntax() | 184 AutolinkSyntax() |
| 185 : super(@'<((http|https|ftp)://[^>]*)>'); | 185 : super(r'<((http|https|ftp)://[^>]*)>'); |
| 186 // TODO(rnystrom): Make case insensitive. | 186 // TODO(rnystrom): Make case insensitive. |
| 187 | 187 |
| 188 bool onMatch(InlineParser parser, Match match) { | 188 bool onMatch(InlineParser parser, Match match) { |
| 189 final url = match[1]; | 189 final url = match[1]; |
| 190 | 190 |
| 191 final anchor = new Element.text('a', escapeHtml(url)); | 191 final anchor = new Element.text('a', escapeHtml(url)); |
| 192 anchor.attributes['href'] = url; | 192 anchor.attributes['href'] = url; |
| 193 parser.addNode(anchor); | 193 parser.addNode(anchor); |
| 194 | 194 |
| 195 return true; | 195 return true; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 219 return true; | 219 return true; |
| 220 } | 220 } |
| 221 } | 221 } |
| 222 | 222 |
| 223 /// Matches inline links like `[blah] [id]` and `[blah] (url)`. | 223 /// Matches inline links like `[blah] [id]` and `[blah] (url)`. |
| 224 class LinkSyntax extends TagSyntax { | 224 class LinkSyntax extends TagSyntax { |
| 225 /// The regex for the end of a link needs to handle both reference style and | 225 /// The regex for the end of a link needs to handle both reference style and |
| 226 /// inline styles as well as optional titles for inline links. To make that | 226 /// inline styles as well as optional titles for inline links. To make that |
| 227 /// a bit more palatable, this breaks it into pieces. | 227 /// a bit more palatable, this breaks it into pieces. |
| 228 static get linkPattern { | 228 static get linkPattern { |
| 229 final refLink = @'\s?\[([^\]]*)\]'; // "[id]" reflink id. | 229 final refLink = r'\s?\[([^\]]*)\]'; // "[id]" reflink id. |
| 230 final title = @'(?:[ ]*"([^"]+)"|)'; // Optional title in quotes. | 230 final title = r'(?:[ ]*"([^"]+)"|)'; // Optional title in quotes. |
| 231 final inlineLink = '\\s?\\(([^ )]+)$title\\)'; // "(url "title")" link. | 231 final inlineLink = '\\s?\\(([^ )]+)$title\\)'; // "(url "title")" link. |
| 232 return '\](?:($refLink|$inlineLink)|)'; | 232 return '\](?:($refLink|$inlineLink)|)'; |
| 233 | 233 |
| 234 // The groups matched by this are: | 234 // The groups matched by this are: |
| 235 // 1: Will be non-empty if it's either a ref or inline link. Will be empty | 235 // 1: Will be non-empty if it's either a ref or inline link. Will be empty |
| 236 // if it's just a bare pair of square brackets with nothing after them. | 236 // if it's just a bare pair of square brackets with nothing after them. |
| 237 // 2: Contains the id inside [] for a reference-style link. | 237 // 2: Contains the id inside [] for a reference-style link. |
| 238 // 3: Contains the URL for an inline link. | 238 // 3: Contains the URL for an inline link. |
| 239 // 4: Contains the title, if present, for an inline link. | 239 // 4: Contains the title, if present, for an inline link. |
| 240 } | 240 } |
| 241 | 241 |
| 242 LinkSyntax() | 242 LinkSyntax() |
| 243 : super(@'\[', end: linkPattern); | 243 : super(r'\[', end: linkPattern); |
| 244 | 244 |
| 245 bool onMatchEnd(InlineParser parser, Match match, TagState state) { | 245 bool onMatchEnd(InlineParser parser, Match match, TagState state) { |
| 246 var url; | 246 var url; |
| 247 var title; | 247 var title; |
| 248 | 248 |
| 249 // If we didn't match refLink or inlineLink, then it means there was | 249 // If we didn't match refLink or inlineLink, then it means there was |
| 250 // nothing after the first square bracket, so it isn't a normal markdown | 250 // nothing after the first square bracket, so it isn't a normal markdown |
| 251 // link at all. Instead, we allow users of the library to specify a special | 251 // link at all. Instead, we allow users of the library to specify a special |
| 252 // resolver function ([setImplicitLinkResolver]) that may choose to handle | 252 // resolver function ([setImplicitLinkResolver]) that may choose to handle |
| 253 // this. Otherwise, it's just treated as plain text. | 253 // this. Otherwise, it's just treated as plain text. |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 parser.consume(endMatch[0].length); | 387 parser.consume(endMatch[0].length); |
| 388 } else { | 388 } else { |
| 389 // Didn't close correctly so revert to text. | 389 // Didn't close correctly so revert to text. |
| 390 parser.start = startPos; | 390 parser.start = startPos; |
| 391 parser.advanceBy(endMatch[0].length); | 391 parser.advanceBy(endMatch[0].length); |
| 392 } | 392 } |
| 393 | 393 |
| 394 return null; | 394 return null; |
| 395 } | 395 } |
| 396 } | 396 } |
| OLD | NEW |