22 from pygments.util import get_bool_opt, ClassNotFound |
22 from pygments.util import get_bool_opt, ClassNotFound |
23 |
23 |
24 __all__ = ['BBCodeLexer', 'MoinWikiLexer', 'RstLexer', 'TexLexer', 'GroffLexer', |
24 __all__ = ['BBCodeLexer', 'MoinWikiLexer', 'RstLexer', 'TexLexer', 'GroffLexer', |
25 'MozPreprocHashLexer', 'MozPreprocPercentLexer', |
25 'MozPreprocHashLexer', 'MozPreprocPercentLexer', |
26 'MozPreprocXulLexer', 'MozPreprocJavascriptLexer', |
26 'MozPreprocXulLexer', 'MozPreprocJavascriptLexer', |
27 'MozPreprocCssLexer'] |
27 'MozPreprocCssLexer', 'MarkdownLexer'] |
28 |
28 |
29 |
29 |
30 class BBCodeLexer(RegexLexer): |
30 class BBCodeLexer(RegexLexer): |
31 """ |
31 """ |
32 A lexer that highlights BBCode(-like) syntax. |
32 A lexer that highlights BBCode(-like) syntax. |
498 |
498 |
499 def __init__(self, **options): |
499 def __init__(self, **options): |
500 super(MozPreprocCssLexer, self).__init__( |
500 super(MozPreprocCssLexer, self).__init__( |
501 CssLexer, MozPreprocPercentLexer, **options) |
501 CssLexer, MozPreprocPercentLexer, **options) |
502 |
502 |
|
503 |
|
504 class MarkdownLexer(RegexLexer): |
|
505 """ |
|
506 For `Markdown <https://help.github.com/categories/writing-on-github/>`_ markup. |
|
507 |
|
508 .. versionadded:: 2.2 |
|
509 """ |
|
510 name = 'markdown' |
|
511 aliases = ['md'] |
|
512 filenames = ['*.md'] |
|
513 mimetypes = ["text/x-markdown"] |
|
514 flags = re.MULTILINE |
|
515 |
|
516 def _handle_codeblock(self, match): |
|
517 """ |
|
518 match args: 1:backticks, 2:lang_name, 3:newline, 4:code, 5:backticks |
|
519 """ |
|
520 from pygments.lexers import get_lexer_by_name |
|
521 |
|
522 # section header |
|
523 yield match.start(1), String , match.group(1) |
|
524 yield match.start(2), String , match.group(2) |
|
525 yield match.start(3), Text , match.group(3) |
|
526 |
|
527 # lookup lexer if wanted and existing |
|
528 lexer = None |
|
529 if self.handlecodeblocks: |
|
530 try: |
|
531 lexer = get_lexer_by_name( match.group(2).strip() ) |
|
532 except ClassNotFound: |
|
533 pass |
|
534 code = match.group(4) |
|
535 |
|
536 # no lexer for this language. handle it like it was a code block |
|
537 if lexer is None: |
|
538 yield match.start(4), String, code |
|
539 return |
|
540 |
|
541 for item in do_insertions([], lexer.get_tokens_unprocessed(code)): |
|
542 yield item |
|
543 |
|
544 yield match.start(5), String , match.group(5) |
|
545 |
|
546 tokens = { |
|
547 'root': [ |
|
548 # heading with pound prefix |
|
549 (r'^(#)([^#].+\n)', bygroups(Generic.Heading, Text)), |
|
550 (r'^(#{2,6})(.+\n)', bygroups(Generic.Subheading, Text)), |
|
551 # task list |
|
552 (r'^(\s*)([*-] )(\[[ xX]\])( .+\n)', |
|
553 bygroups(Text, Keyword, Keyword, using(this, state='inline'))), |
|
554 # bulleted lists |
|
555 (r'^(\s*)([*-])(\s)(.+\n)', |
|
556 bygroups(Text, Keyword, Text, using(this, state='inline'))), |
|
557 # numbered lists |
|
558 (r'^(\s*)([0-9]+\.)( .+\n)', |
|
559 bygroups(Text, Keyword, using(this, state='inline'))), |
|
560 # quote |
|
561 (r'^(\s*>\s)(.+\n)', bygroups(Keyword, Generic.Emph)), |
|
562 # text block |
|
563 (r'^(```\n)([\w\W]*?)(^```$)', bygroups(String, Text, String)), |
|
564 # code block with language |
|
565 (r'^(```)(\w+)(\n)([\w\W]*?)(^```$)', _handle_codeblock), |
|
566 |
|
567 include('inline'), |
|
568 ], |
|
569 'inline': [ |
|
570 # escape |
|
571 (r'\\.', Text), |
|
572 # italics |
|
573 (r'(\s)([*_][^*_]+[*_])(\W|\n)', bygroups(Text, Generic.Emph, Text)), |
|
574 # bold |
|
575 # warning: the following rule eats internal tags. eg. **foo _bar_ baz** bar is not italics |
|
576 (r'(\s)((\*\*|__).*\3)((?=\W|\n))', bygroups(Text, Generic.Strong, None, Text)), |
|
577 # "proper way" (r'(\s)([*_]{2}[^*_]+[*_]{2})((?=\W|\n))', bygroups(Text, Generic.Strong, Text)), |
|
578 # strikethrough |
|
579 (r'(\s)(~~[^~]+~~)((?=\W|\n))', bygroups(Text, Generic.Deleted, Text)), |
|
580 # inline code |
|
581 (r'`[^`]+`', String.Backtick), |
|
582 # mentions and topics (twitter and github stuff) |
|
583 (r'[@#][\w/:]+', Name.Entity), |
|
584 # (image?) links eg:  |
|
585 (r'(!?\[)([^]]+)(\])(\()([^)]+)(\))', bygroups(Text, Name.Tag, Text, Text, Name.Attribute, Text)), |
|
586 |
|
587 # general text, must come last! |
|
588 (r'[^\\\s]+', Text), |
|
589 (r'.', Text), |
|
590 ], |
|
591 } |
|
592 |
|
593 def __init__(self, **options): |
|
594 self.handlecodeblocks = get_bool_opt(options, 'handlecodeblocks', True) |
|
595 RegexLexer.__init__(self, **options) |