"Fossies" - the Fresh Open Source Software Archive

Member "asciidoctor-2.0.10/lib/asciidoctor/rx.rb" (1 Jun 2019, 21849 Bytes) of package /linux/www/asciidoctor-2.0.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "rx.rb": 2.0.8_vs_2.0.9.

    1 module Asciidoctor
    2   # A collection of regular expression constants used by the parser. (For speed, these are not defined in the Rx module,
    3   # but rather directly in the Asciidoctor module).
    4   #
    5   # NOTE The following pattern, which appears frequently, captures the contents between square brackets, ignoring
    6   # escaped closing brackets (closing brackets prefixed with a backslash '\' character)
    7   #
    8   #   Pattern: \[(|#{CC_ALL}*?[^\\])\]
    9   #   Matches: [enclosed text] and [enclosed [text\]], not [enclosed text \\] or [\\] (as these require a trailing space)
   10   module Rx; end
   11 
   12   ## Document header
   13 
   14   # Matches the author info line immediately following the document title.
   15   #
   16   # Examples
   17   #
   18   #   Doc Writer <doc@example.com>
   19   #   Mary_Sue Brontë
   20   #
   21   AuthorInfoLineRx = /^(#{CG_WORD}[#{CC_WORD}\-'.]*)(?: +(#{CG_WORD}[#{CC_WORD}\-'.]*))?(?: +(#{CG_WORD}[#{CC_WORD}\-'.]*))?(?: +<([^>]+)>)?$/
   22 
   23   # Matches the delimiter that separates multiple authors.
   24   #
   25   # Examples
   26   #
   27   #   Doc Writer; Junior Writer
   28   #
   29   AuthorDelimiterRx = /;(?: |$)/
   30 
   31   # Matches the revision info line, which appears immediately following
   32   # the author info line beneath the document title.
   33   #
   34   # Examples
   35   #
   36   #   v1.0
   37   #   2013-01-01
   38   #   v1.0, 2013-01-01: Ring in the new year release
   39   #   1.0, Jan 01, 2013
   40   #
   41   RevisionInfoLineRx = /^(?:[^\d{]*(#{CC_ANY}*?),)? *(?!:)(#{CC_ANY}*?)(?: *(?!^),?: *(#{CC_ANY}*))?$/
   42 
   43   # Matches the title and volnum in the manpage doctype.
   44   #
   45   # Examples
   46   #
   47   #   = asciidoctor(1)
   48   #   = asciidoctor ( 1 )
   49   #
   50   ManpageTitleVolnumRx = /^(#{CC_ANY}+?) *\( *(#{CC_ANY}+?) *\)$/
   51 
   52   # Matches the name and purpose in the manpage doctype.
   53   #
   54   # Examples
   55   #
   56   #   asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
   57   #
   58   ManpageNamePurposeRx = /^(#{CC_ANY}+?) +- +(#{CC_ANY}+)$/
   59 
   60   ## Preprocessor directives
   61 
   62   # Matches a conditional preprocessor directive (e.g., ifdef, ifndef, ifeval and endif).
   63   #
   64   # Examples
   65   #
   66   #   ifdef::basebackend-html[]
   67   #   ifndef::theme[]
   68   #   ifeval::["{asciidoctor-version}" >= "0.1.0"]
   69   #   ifdef::asciidoctor[Asciidoctor!]
   70   #   endif::theme[]
   71   #   endif::basebackend-html[]
   72   #   endif::[]
   73   #
   74   ConditionalDirectiveRx = /^(\\)?(ifdef|ifndef|ifeval|endif)::(\S*?(?:([,+])\S*?)?)\[(#{CC_ANY}+)?\]$/
   75 
   76   # Matches a restricted (read as safe) eval expression.
   77   #
   78   # Examples
   79   #
   80   #   "{asciidoctor-version}" >= "0.1.0"
   81   #
   82   EvalExpressionRx = /^(#{CC_ANY}+?) *([=!><]=|[><]) *(#{CC_ANY}+)$/
   83 
   84   # Matches an include preprocessor directive.
   85   #
   86   # Examples
   87   #
   88   #   include::chapter1.ad[]
   89   #   include::example.txt[lines=1;2;5..10]
   90   #
   91   IncludeDirectiveRx = /^(\\)?include::([^\[][^\[]*)\[(#{CC_ANY}+)?\]$/
   92 
   93   # Matches a trailing tag directive in an include file.
   94   #
   95   # Examples
   96   #
   97   #   // tag::try-catch[]
   98   #   try {
   99   #     someMethod();
  100   #   catch (Exception e) {
  101   #     log(e);
  102   #   }
  103   #   // end::try-catch[]
  104   # NOTE m flag is required for Asciidoctor.js
  105   TagDirectiveRx = /\b(?:tag|(e)nd)::(\S+?)\[\](?=$|[ \r])/m
  106 
  107   ## Attribute entries and references
  108 
  109   # Matches a document attribute entry.
  110   #
  111   # Examples
  112   #
  113   #   :foo: bar
  114   #   :First Name: Dan
  115   #   :sectnums!:
  116   #   :!toc:
  117   #   :long-entry: Attribute value lines ending in ' \' \
  118   #                are joined together as a single value, \
  119   #                collapsing the line breaks and indentation to \
  120   #                a single space.
  121   #
  122   AttributeEntryRx = /^:(!?#{CG_WORD}[^:]*):(?:[ \t]+(#{CC_ANY}*))?$/
  123 
  124   # Matches invalid characters in an attribute name.
  125   InvalidAttributeNameCharsRx = /[^#{CC_WORD}-]/
  126 
  127   # Matches a pass inline macro that surrounds the value of an attribute
  128   # entry once it has been parsed.
  129   #
  130   # Examples
  131   #
  132   #   pass:[text]
  133   #   pass:a[{a} {b} {c}]
  134   #
  135   if RUBY_ENGINE == 'opal'
  136     # NOTE In JavaScript, ^ and $ match the boundaries of the string when the m flag is not set
  137     AttributeEntryPassMacroRx = /^pass:([a-z]+(?:,[a-z-]+)*)?\[(#{CC_ALL}*)\]$/
  138   else
  139     AttributeEntryPassMacroRx = /\Apass:([a-z]+(?:,[a-z-]+)*)?\[(.*)\]\Z/m
  140   end
  141 
  142   # Matches an inline attribute reference.
  143   #
  144   # Examples
  145   #
  146   #   {foobar} or {app_name} or {product-version}
  147   #   {counter:sequence-name:1}
  148   #   {set:foo:bar}
  149   #   {set:name!}
  150   #
  151   AttributeReferenceRx = /(\\)?\{(#{CG_WORD}[#{CC_WORD}-]*|(set|counter2?):#{CC_ANY}+?)(\\)?\}/
  152 
  153   ## Paragraphs and delimited blocks
  154 
  155   # Matches an anchor (i.e., id + optional reference text) on a line above a block.
  156   #
  157   # Examples
  158   #
  159   #   [[idname]]
  160   #   [[idname,Reference Text]]
  161   #
  162   BlockAnchorRx = /^\[\[(?:|([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+))?)\]\]$/
  163 
  164   # Matches an attribute list above a block element.
  165   #
  166   # Examples
  167   #
  168   #   # strictly positional
  169   #   [quote, Adam Smith, Wealth of Nations]
  170   #
  171   #   # name/value pairs
  172   #   [NOTE, caption="Good to know"]
  173   #
  174   #   # as attribute reference
  175   #   [{lead}]
  176   #
  177   BlockAttributeListRx = /^\[(|[#{CC_WORD}.#%{,"']#{CC_ANY}*)\]$/
  178 
  179   # A combined pattern that matches either a block anchor or a block attribute list.
  180   #
  181   # TODO this one gets hit a lot, should be optimized as much as possible
  182   BlockAttributeLineRx = /^\[(?:|[#{CC_WORD}.#%{,"']#{CC_ANY}*|\[(?:|[#{CC_ALPHA}_:][#{CC_WORD}\-:.]*(?:, *#{CC_ANY}+)?)\])\]$/
  183 
  184   # Matches a title above a block.
  185   #
  186   # Examples
  187   #
  188   #   .Title goes here
  189   #
  190   BlockTitleRx = /^\.(\.?[^ \t.]#{CC_ANY}*)$/
  191 
  192   # Matches an admonition label at the start of a paragraph.
  193   #
  194   # Examples
  195   #
  196   #   NOTE: Just a little note.
  197   #   TIP: Don't forget!
  198   #
  199   AdmonitionParagraphRx = /^(#{ADMONITION_STYLES.to_a.join '|'}):[ \t]+/
  200 
  201   # Matches a literal paragraph, which is a line of text preceded by at least one space.
  202   #
  203   # Examples
  204   #
  205   #   <SPACE>Foo
  206   #   <TAB>Foo
  207   LiteralParagraphRx = /^([ \t]+#{CC_ANY}*)$/
  208 
  209   # Matches a comment block.
  210   #
  211   # Examples
  212   #
  213   #   ////
  214   #   This is a block comment.
  215   #   It can span one or more lines.
  216   #   ////
  217   #CommentBlockRx = %r(^/{4,}$)
  218 
  219   # Matches a comment line.
  220   #
  221   # Examples
  222   #
  223   #   // note to author
  224   #
  225   #CommentLineRx = %r(^//(?=[^/]|$))
  226 
  227   ## Section titles
  228 
  229   # Matches an Atx (single-line) section title.
  230   #
  231   # Examples
  232   #
  233   #   == Foo
  234   #   // ^ a level 1 (h2) section title
  235   #
  236   #   == Foo ==
  237   #   // ^ also a level 1 (h2) section title
  238   #
  239   AtxSectionTitleRx = /^(=={0,5})[ \t]+(#{CC_ANY}+?)(?:[ \t]+\1)?$/
  240 
  241   # Matches an extended Atx section title that includes support for the Markdown variant.
  242   ExtAtxSectionTitleRx = /^(=={0,5}|#\#{0,5})[ \t]+(#{CC_ANY}+?)(?:[ \t]+\1)?$/
  243 
  244   # Matches the title only (first line) of an Setext (two-line) section title.
  245   # The title cannot begin with a dot and must have at least one alphanumeric character.
  246   SetextSectionTitleRx = /^((?!\.)#{CC_ANY}*?#{CG_ALNUM}#{CC_ANY}*)$/
  247 
  248   # Matches an anchor (i.e., id + optional reference text) inside a section title.
  249   #
  250   # Examples
  251   #
  252   #   Section Title [[idname]]
  253   #   Section Title [[idname,Reference Text]]
  254   #
  255   InlineSectionAnchorRx = / (\\)?\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+))?\]\]$/
  256 
  257   # Matches invalid ID characters in a section title.
  258   #
  259   # NOTE uppercase chars not included since expression is only run on a lowercase string
  260   InvalidSectionIdCharsRx = /<[^>]+>|&(?:[a-z][a-z]+\d{0,2}|#\d\d\d{0,4}|#x[\da-f][\da-f][\da-f]{0,3});|[^ #{CC_WORD}\-.]+?/
  261 
  262   # Matches an explicit section level style like sect1
  263   #
  264   SectionLevelStyleRx = /^sect\d$/
  265 
  266   ## Lists
  267 
  268   # Detects the start of any list item.
  269   #
  270   # NOTE we only have to check as far as the blank character because we know it means non-whitespace follows.
  271   # IMPORTANT if this regexp does not agree with the regexp for each list type, the parser will hang.
  272   AnyListRx = %r(^(?:[ \t]*(?:-|\*\**|\.\.*|\u2022|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]|(?!//[^/])[ \t]*[^ \t]#{CC_ANY}*?(?::::{0,2}|;;)(?:$|[ \t])|<?\d+>[ \t]))
  273 
  274   # Matches an unordered list item (one level for hyphens, up to 5 levels for asterisks).
  275   #
  276   # Examples
  277   #
  278   #   * Foo
  279   #   - Foo
  280   #
  281   # NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
  282   UnorderedListRx = /^[ \t]*(-|\*\**|\u2022)[ \t]+(#{CC_ANY}*)$/
  283 
  284   # Matches an ordered list item (explicit numbering or up to 5 consecutive dots).
  285   #
  286   # Examples
  287   #
  288   #   . Foo
  289   #   .. Foo
  290   #   1. Foo (arabic, default)
  291   #   a. Foo (loweralpha)
  292   #   A. Foo (upperalpha)
  293   #   i. Foo (lowerroman)
  294   #   I. Foo (upperroman)
  295   #
  296   # NOTE leading space match is not always necessary, but is used for list reader
  297   # NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
  298   OrderedListRx = /^[ \t]*(\.\.*|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]+(#{CC_ANY}*)$/
  299 
  300   # Matches the ordinals for each type of ordered list.
  301   OrderedListMarkerRxMap = {
  302     arabic: /\d+\./,
  303     loweralpha: /[a-z]\./,
  304     lowerroman: /[ivx]+\)/,
  305     upperalpha: /[A-Z]\./,
  306     upperroman: /[IVX]+\)/,
  307     #lowergreek: /[a-z]\]/,
  308   }
  309 
  310   # Matches a description list entry.
  311   #
  312   # Examples
  313   #
  314   #   foo::
  315   #   bar:::
  316   #   baz::::
  317   #   blah;;
  318   #
  319   #   # the term may be followed by a description on the same line...
  320   #
  321   #   foo:: The metasyntactic variable that commonly accompanies 'bar' (see also, <<bar>>).
  322   #
  323   #   # ...or on a separate line, which may optionally be indented
  324   #
  325   #   foo::
  326   #     The metasyntactic variable that commonly accompanies 'bar' (see also, <<bar>>).
  327   #
  328   #   # attribute references may be used in both the term and the description
  329   #
  330   #   {foo-term}:: {foo-desc}
  331   #
  332   # NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
  333   # NOTE must skip line comment when looking for next list item inside list
  334   DescriptionListRx = %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?)(:::{0,2}|;;)(?:$|[ \t]+(#{CC_ANY}*)$))
  335 
  336   # Matches a sibling description list item (excluding the delimiter specified by the key).
  337   # NOTE must skip line comment when looking for sibling list item
  338   DescriptionListSiblingRx = {
  339     '::' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?[^:]|[^ \t:])(::)(?:$|[ \t]+(#{CC_ANY}*)$)),
  340     ':::' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?[^:]|[^ \t:])(:::)(?:$|[ \t]+(#{CC_ANY}*)$)),
  341     '::::' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?[^:]|[^ \t:])(::::)(?:$|[ \t]+(#{CC_ANY}*)$)),
  342     ';;' => %r(^(?!//[^/])[ \t]*([^ \t]#{CC_ANY}*?)(;;)(?:$|[ \t]+(#{CC_ANY}*)$))
  343   }
  344 
  345   # Matches a callout list item.
  346   #
  347   # Examples
  348   #
  349   #   <1> Explanation
  350   #
  351   # or
  352   #
  353   #   <.> Explanation with automatic number
  354   #
  355   # NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
  356   CalloutListRx = /^<(\d+|\.)>[ \t]+(#{CC_ANY}*)$/
  357 
  358   # Matches a callout reference inside literal text.
  359   #
  360   # Examples
  361   #   <1> (optionally prefixed by //, #, -- or ;; line comment chars)
  362   #   <1> <2> (multiple callouts on one line)
  363   #   <!--1--> (for XML-based languages)
  364   #   <.> (auto-numbered)
  365   #
  366   # NOTE extract regexps are applied line-by-line, so we can use $ as end-of-line char
  367   CalloutExtractRx = %r(((?://|#|--|;;) ?)?(\\)?<!?(|--)(\d+|\.)\3>(?=(?: ?\\?<!?\3(?:\d+|\.)\3>)*$))
  368   CalloutExtractRxt = '(\\\\)?<()(\\d+|\\.)>(?=(?: ?\\\\?<(?:\\d+|\\.)>)*$)'
  369   CalloutExtractRxMap = ::Hash.new {|h, k| h[k] = /(#{k.empty? ? '' : "#{::Regexp.escape k} ?"})?#{CalloutExtractRxt}/ }
  370   # NOTE special characters have not been replaced when scanning
  371   CalloutScanRx = /\\?<!?(|--)(\d+|\.)\1>(?=(?: ?\\?<!?\1(?:\d+|\.)\1>)*#{CC_EOL})/
  372   # NOTE special characters have already been replaced when converting to an SGML format
  373   CalloutSourceRx = %r(((?://|#|--|;;) ?)?(\\)?&lt;!?(|--)(\d+|\.)\3&gt;(?=(?: ?\\?&lt;!?\3(?:\d+|\.)\3&gt;)*#{CC_EOL}))
  374   CalloutSourceRxt = "(\\\\)?&lt;()(\\d+|\\.)&gt;(?=(?: ?\\\\?&lt;(?:\\d+|\\.)&gt;)*#{CC_EOL})"
  375   CalloutSourceRxMap = ::Hash.new {|h, k| h[k] = /(#{k.empty? ? '' : "#{::Regexp.escape k} ?"})?#{CalloutSourceRxt}/ }
  376 
  377   # A Hash of regexps for lists used for dynamic access.
  378   ListRxMap = { ulist: UnorderedListRx, olist: OrderedListRx, dlist: DescriptionListRx, colist: CalloutListRx }
  379 
  380   ## Tables
  381 
  382   # Parses the column spec (i.e., colspec) for a table.
  383   #
  384   # Examples
  385   #
  386   #   1*h,2*,^3e
  387   #
  388   ColumnSpecRx = /^(?:(\d+)\*)?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?(\d+%?|~)?([a-z])?$/
  389 
  390   # Parses the start and end of a cell spec (i.e., cellspec) for a table.
  391   #
  392   # Examples
  393   #
  394   #   2.3+<.>m
  395   #
  396   # FIXME use step-wise scan (or treetop) rather than this mega-regexp
  397   CellSpecStartRx = /^[ \t]*(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
  398   CellSpecEndRx = /[ \t]+(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
  399 
  400   # Block macros
  401 
  402   # Matches the custom block macro pattern.
  403   #
  404   # Examples
  405   #
  406   #   gist::123456[]
  407   #
  408   #--
  409   # NOTE we've relaxed the match for target to accomodate the short format (e.g., name::[attrlist])
  410   CustomBlockMacroRx = /^(#{CG_WORD}[#{CC_WORD}-]*)::(|\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
  411 
  412   # Matches an image, video or audio block macro.
  413   #
  414   # Examples
  415   #
  416   #   image::filename.png[Caption]
  417   #   video::http://youtube.com/12345[Cats vs Dogs]
  418   #
  419   BlockMediaMacroRx = /^(image|video|audio)::(\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
  420 
  421   # Matches the TOC block macro.
  422   #
  423   # Examples
  424   #
  425   #   toc::[]
  426   #   toc::[levels=2]
  427   #
  428   BlockTocMacroRx = /^toc::\[(#{CC_ANY}+)?\]$/
  429 
  430   ## Inline macros
  431 
  432   # Matches an anchor (i.e., id + optional reference text) in the flow of text.
  433   #
  434   # Examples
  435   #
  436   #   [[idname]]
  437   #   [[idname,Reference Text]]
  438   #   anchor:idname[]
  439   #   anchor:idname[Reference Text]
  440   #
  441   InlineAnchorRx = /(\\)?(?:\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]|anchor:([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)\[(?:\]|(#{CC_ANY}*?[^\\])\]))/
  442 
  443   # Scans for a non-escaped anchor (i.e., id + optional reference text) in the flow of text.
  444   InlineAnchorScanRx = /(?:^|[^\\\[])\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]|(?:^|[^\\])anchor:([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)\[(?:\]|(#{CC_ANY}*?[^\\])\])/
  445 
  446   # Scans for a leading, non-escaped anchor (i.e., id + optional reference text).
  447   LeadingInlineAnchorRx = /^\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]/
  448 
  449   # Matches a bibliography anchor at the start of the list item text (in a bibliography list).
  450   #
  451   # Examples
  452   #
  453   #   [[[Fowler_1997]]] Fowler M. ...
  454   #
  455   InlineBiblioAnchorRx = /^\[\[\[([#{CC_ALPHA}_:][#{CC_WORD}\-:.]*)(?:, *(#{CC_ANY}+?))?\]\]\]/
  456 
  457   # Matches an inline e-mail address.
  458   #
  459   #   doc.writer@example.com
  460   #
  461   InlineEmailRx = %r(([\\>:/])?#{CG_WORD}(?:&amp;|[#{CC_WORD}\-.%+])*@#{CG_ALNUM}[#{CC_ALNUM}_\-.]*\.[a-zA-Z]{2,5}\b)
  462 
  463   # Matches an inline footnote macro, which is allowed to span multiple lines.
  464   #
  465   # Examples
  466   #   footnote:[text] (not referenceable)
  467   #   footnote:id[text] (referenceable)
  468   #   footnote:id[] (reference)
  469   #   footnoteref:[id,text] (legacy)
  470   #   footnoteref:[id] (legacy)
  471   #
  472   InlineFootnoteMacroRx = /\\?footnote(?:(ref):|:([#{CC_WORD}-]+)?)\[(?:|(#{CC_ALL}*?[^\\]))\]/m
  473 
  474   # Matches an image or icon inline macro.
  475   #
  476   # Examples
  477   #
  478   #   image:filename.png[Alt Text]
  479   #   image:http://example.com/images/filename.png[Alt Text]
  480   #   image:filename.png[More [Alt\] Text] (alt text becomes "More [Alt] Text")
  481   #   icon:github[large]
  482   #
  483   # NOTE be as non-greedy as possible by not allowing newline or left square bracket in target
  484   InlineImageMacroRx = /\\?i(?:mage|con):([^:\s\[](?:[^\n\[]*[^\s\[])?)\[(|#{CC_ALL}*?[^\\])\]/m
  485 
  486   # Matches an indexterm inline macro, which may span multiple lines.
  487   #
  488   # Examples
  489   #
  490   #   indexterm:[Tigers,Big cats]
  491   #   (((Tigers,Big cats)))
  492   #   indexterm2:[Tigers]
  493   #   ((Tigers))
  494   #
  495   InlineIndextermMacroRx = /\\?(?:(indexterm2?):\[(#{CC_ALL}*?[^\\])\]|\(\((#{CC_ALL}+?)\)\)(?!\)))/m
  496 
  497   # Matches either the kbd or btn inline macro.
  498   #
  499   # Examples
  500   #
  501   #   kbd:[F3]
  502   #   kbd:[Ctrl+Shift+T]
  503   #   kbd:[Ctrl+\]]
  504   #   kbd:[Ctrl,T]
  505   #   btn:[Save]
  506   #
  507   InlineKbdBtnMacroRx = /(\\)?(kbd|btn):\[(#{CC_ALL}*?[^\\])\]/m
  508 
  509   # Matches an implicit link and some of the link inline macro.
  510   #
  511   # Examples
  512   #
  513   #   https://github.com
  514   #   https://github.com[GitHub]
  515   #   <https://github.com>
  516   #   link:https://github.com[]
  517   #
  518   # FIXME revisit! the main issue is we need different rules for implicit vs explicit
  519   InlineLinkRx = %r((^|link:|#{CG_BLANK}|&lt;|[>\(\)\[\];])(\\?(?:https?|file|ftp|irc)://[^\s\[\]<]*([^\s.,\[\]<]))(?:\[(|#{CC_ALL}*?[^\\])\])?)m
  520 
  521   # Match a link or e-mail inline macro.
  522   #
  523   # Examples
  524   #
  525   #   link:path[label]
  526   #   mailto:doc.writer@example.com[]
  527   #
  528   # NOTE be as non-greedy as possible by not allowing space or left square bracket in target
  529   InlineLinkMacroRx = /\\?(?:link|(mailto)):(|[^:\s\[][^\s\[]*)\[(|#{CC_ALL}*?[^\\])\]/m
  530 
  531   # Matches the name of a macro.
  532   #
  533   MacroNameRx = /^#{CG_WORD}[#{CC_WORD}-]*$/
  534 
  535   # Matches a stem (and alternatives, asciimath and latexmath) inline macro, which may span multiple lines.
  536   #
  537   # Examples
  538   #
  539   #   stem:[x != 0]
  540   #   asciimath:[x != 0]
  541   #   latexmath:[\sqrt{4} = 2]
  542   #
  543   InlineStemMacroRx = /\\?(stem|(?:latex|ascii)math):([a-z]+(?:,[a-z-]+)*)?\[(#{CC_ALL}*?[^\\])\]/m
  544 
  545   # Matches a menu inline macro.
  546   #
  547   # Examples
  548   #
  549   #   menu:File[Save As...]
  550   #   menu:Edit[]
  551   #   menu:View[Page Style > No Style]
  552   #   menu:View[Page Style, No Style]
  553   #
  554   InlineMenuMacroRx = /\\?menu:(#{CG_WORD}|[#{CC_WORD}&][^\n\[]*[^\s\[])\[ *(?:|(#{CC_ALL}*?[^\\]))?\]/m
  555 
  556   # Matches an implicit menu inline macro.
  557   #
  558   # Examples
  559   #
  560   #   "File > New..."
  561   #
  562   InlineMenuRx = /\\?"([#{CC_WORD}&][^"]*?[ \n]+&gt;[ \n]+[^"]*)"/
  563 
  564   # Matches an inline passthrough, which may span multiple lines.
  565   #
  566   # Examples
  567   #
  568   #   +text+
  569   #   `text` (compat)
  570   #
  571   # NOTE we always capture the attributes so we know when to use compatible (i.e., legacy) behavior
  572   InlinePassRx = {
  573     false => ['+', '`', /(^|[^#{CC_WORD};:])(?:\[([^\]]+)\])?(\\?(\+|`)(\S|\S#{CC_ALL}*?\S)\4)(?!#{CG_WORD})/m],
  574     true  => ['`', nil, /(^|[^`#{CC_WORD}])(?:\[([^\]]+)\])?(\\?(`)([^`\s]|[^`\s]#{CC_ALL}*?\S)\4)(?![`#{CC_WORD}])/m]
  575   }
  576 
  577   # Matches an inline plus passthrough spanning multiple lines, but only when it occurs directly
  578   # inside constrained monospaced formatting in non-compat mode.
  579   #
  580   # Examples
  581   #
  582   #   +text+
  583   #
  584   SinglePlusInlinePassRx = /^(\\)?\+(\S|\S#{CC_ALL}*?\S)\+$/m
  585 
  586   # Matches several variants of the passthrough inline macro, which may span multiple lines.
  587   #
  588   # Examples
  589   #
  590   #   +++text+++
  591   #   $$text$$
  592   #   pass:quotes[text]
  593   #
  594   # NOTE we have to support an empty pass:[] for compatibility with AsciiDoc Python
  595   InlinePassMacroRx = /(?:(?:(\\?)\[([^\]]+)\])?(\\{0,2})(\+\+\+?|\$\$)(#{CC_ALL}*?)\4|(\\?)pass:([a-z]+(?:,[a-z-]+)*)?\[(|#{CC_ALL}*?[^\\])\])/m
  596 
  597   # Matches an xref (i.e., cross-reference) inline macro, which may span multiple lines.
  598   #
  599   # Examples
  600   #
  601   #   <<id,reftext>>
  602   #   xref:id[reftext]
  603   #
  604   # NOTE special characters have already been escaped, hence the entity references
  605   # NOTE { is included in start characters to support target that begins with attribute reference in title content
  606   InlineXrefMacroRx = %r(\\?(?:&lt;&lt;([#{CC_WORD}#/.:{]#{CC_ALL}*?)&gt;&gt;|xref:([#{CC_WORD}#/.:{]#{CC_ALL}*?)\[(?:\]|(#{CC_ALL}*?[^\\])\])))m
  607 
  608   ## Layout
  609 
  610   # Matches a trailing + preceded by at least one space character,
  611   # which forces a hard line break (<br> tag in HTML output).
  612   #
  613   # NOTE AsciiDoc Python allows + to be preceded by TAB; Asciidoctor does not
  614   #
  615   # Examples
  616   #
  617   #   Humpty Dumpty sat on a wall, +
  618   #   Humpty Dumpty had a great fall.
  619   #
  620   if RUBY_ENGINE == 'opal'
  621     # NOTE In JavaScript, ^ and $ only match the start and end of line if the multiline flag is present
  622     HardLineBreakRx = /^(#{CC_ANY}*) \+$/m
  623   else
  624     # NOTE In Ruby, ^ and $ always match start and end of line
  625     HardLineBreakRx = /^(.*) \+$/
  626   end
  627 
  628   # Matches a Markdown horizontal rule.
  629   #
  630   # Examples
  631   #
  632   #   --- or - - -
  633   #   *** or * * *
  634   #   ___ or _ _ _
  635   #
  636   MarkdownThematicBreakRx = /^ {0,3}([-*_])( *)\1\2\1$/
  637 
  638   # Matches an AsciiDoc or Markdown horizontal rule or AsciiDoc page break.
  639   #
  640   # Examples
  641   #
  642   #   ''' (horizontal rule)
  643   #   <<< (page break)
  644   #   --- or - - - (horizontal rule, Markdown)
  645   #   *** or * * * (horizontal rule, Markdown)
  646   #   ___ or _ _ _ (horizontal rule, Markdown)
  647   #
  648   ExtLayoutBreakRx = /^(?:'{3,}|<{3,}|([-*_])( *)\1\2\1)$/
  649 
  650   ## General
  651 
  652   # Matches consecutive blank lines.
  653   #
  654   # Examples
  655   #
  656   #   one
  657   #
  658   #   two
  659   #
  660   BlankLineRx = /\n{2,}/
  661 
  662   # Matches a comma or semi-colon delimiter.
  663   #
  664   # Examples
  665   #
  666   #   one,two
  667   #   three;four
  668   #
  669   #DataDelimiterRx = /[,;]/
  670 
  671   # Matches whitespace (space, tab, newline) escaped by a backslash.
  672   #
  673   # Examples
  674   #
  675   #   three\ blind\ mice
  676   #
  677   EscapedSpaceRx = /\\([ \t\n])/
  678 
  679   # Detects if text is a possible candidate for the replacements substitution.
  680   #
  681   ReplaceableTextRx = /[&']|--|\.\.\.|\([CRT]M?\)/
  682 
  683   # Matches a whitespace delimiter, a sequence of spaces, tabs, and/or newlines.
  684   # Matches the parsing rules of %w strings in Ruby.
  685   #
  686   # Examples
  687   #
  688   #   one two    three   four
  689   #   five  six
  690   #
  691   # TODO change to /(?<!\\)[ \t\n]+/ once lookbehind assertions are implemented in all modern browsers
  692   SpaceDelimiterRx = /([^\\])[ \t\n]+/
  693 
  694   # Matches a + or - modifier in a subs list
  695   #
  696   SubModifierSniffRx = /[+-]/
  697 
  698   # Matches one or more consecutive digits at the end of a line.
  699   #
  700   # Examples
  701   #
  702   #   docbook5
  703   #   html5
  704   #
  705   TrailingDigitsRx = /\d+$/
  706 
  707   # Detects strings that resemble URIs.
  708   #
  709   # Examples
  710   #   http://domain
  711   #   https://domain
  712   #   file:///path
  713   #   data:info
  714   #
  715   #   not c:/sample.adoc or c:\sample.adoc
  716   #
  717   UriSniffRx = %r(^#{CG_ALPHA}[#{CC_ALNUM}.+-]+:/{0,2})
  718 
  719   # Detects XML tags
  720   XmlSanitizeRx = /<[^>]+>/
  721 end