Example #1
0
 /**
  * Parse the given content.
  *
  * Any newly created nodes should be pushed to the stack. Any remaining content should be passed to the next parser
  * in the chain.
  *
  * @param Text $content
  * @param Container $target
  * @return void
  */
 public function parseBlock(Text $content, Container $target)
 {
     $content->handle('/
             (
                 (?:                             # We are either at the beginning of the match
                     ^|\\n                        # or at a newline (for multi-line quotes)
                 )
                 (?:
                     [ ]{0,3}\\>[ ]*              # either a blank line
                   |
                     [ ]{0,3}\\>[ ]?[`~]{3,}.*    # or a code fence
                   |
                     [ ]{0,3}\\>                  # or non-blank lines...
                     [ ]*[^\\n\\ ][^\\n]*[ ]*
                     (                           # ...with lazy continuation
                         \\n
                         [ ]{0,3}
                         [^>\\-+*=\\ \\n][^\\n]*
                     )*
                 )
             )+
             $
         /mx', function (Text $content) use($target) {
         // Remove block quote marker plus surrounding whitespace on each line
         $content->replace('/^[ ]{0,3}\\>[ ]?/m', '');
         $blockquote = new Blockquote();
         $target->addChild($blockquote);
         $this->first->parseBlock($content, $blockquote);
     }, function (Text $part) use($target) {
         $this->next->parseBlock($part, $target);
     });
 }
 /**
  * Parse the given content.
  *
  * Any newly created nodes should be pushed to the stack. Any remaining content should be passed to the next parser
  * in the chain.
  *
  * @param Text $content
  * @param Container $target
  * @return void
  */
 public function parseBlock(Text $content, Container $target)
 {
     $content->handle('{
             ^(?:
                 ([ ]{0,3})                  #1 Initial indentation
                 (                           #2 Fence
                     ([`~])                  #3 The fence character (` or ~)
                     \\3{2,}                  #  At least two remaining fence characters
                 )
                 ([^`\\n]*?)?                 #4 Code language [optional]
                 (?:
                     \\n(.*?)                 #5 Code block
                 )?
                 (?:(?<=\\n)([ ]{0,3}\\2\\3*[ ]*)|\\z)  #  Closing fence or end of document
             )$
         }msx', function (Text $whole, Text $whitespace, Text $fence, Text $fenceChar, Text $lang, Text $code = null) use($target) {
         $leading = $whitespace->getLength();
         $code = $code ?: new Text();
         $language = new Text(explode(' ', $lang->trim())[0]);
         $language->decodeEntities();
         // Remove all leading whitespace from content lines
         if ($leading > 0) {
             $code->replace("/^[ ]{0,{$leading}}/m", '');
         }
         $target->addChild(new CodeBlock($code, $language));
     }, function (Text $part) use($target) {
         $this->next->parseBlock($part, $target);
     });
 }
Example #3
0
 /**
  * Parse the given content.
  *
  * Any newly created nodes should be pushed to the stack. Any remaining content should be passed to the next parser
  * in the chain.
  *
  * @param Text $content
  * @param Container $target
  * @return void
  */
 public function parseBlock(Text $content, Container $target)
 {
     $content->handle('{
             (?:                 # Ensure blank line before (or beginning of subject)
                 \\A\\s*\\n?|
                 \\n\\s*\\n
             )
             [ ]{4}              # four leading spaces
             .+
             (?:                 # optionally more spaces
                 (?:             # blank lines in between are okay
                     \\n[ ]*
                 )*
                 \\n
                 [ ]{4}
                 .+
             )*
             $
         }mx', function (Text $code) use($target) {
         // Remove leading blank lines
         $code->replace('/^(\\s*\\n)*/', '');
         // Remove indent
         $code->replace('/^[ ]{1,4}/m', '');
         $code->append("\n");
         $target->addChild(new CodeBlock($code));
     }, function (Text $part) use($target) {
         $this->next->parseBlock($part, $target);
     });
 }
Example #4
0
 /**
  * Parse the given content.
  *
  * Any newly created nodes should be pushed to the stack. Any remaining content should be passed to the next parser
  * in the chain.
  *
  * @param Text $content
  * @param Container $target
  * @return void
  */
 public function parseBlock(Text $content, Container $target)
 {
     $content->handle('/^\\s*$/m', function (Text $line) use($target) {
         $target->addChild(new BlankLine($line));
     }, function (Text $part) use($target) {
         $paragraph = new Paragraph($part);
         $target->addChild($paragraph);
         $this->inlineParser->queue($paragraph->getText(), $paragraph);
     });
 }
Example #5
0
 /**
  * Parse the given content.
  *
  * Any newly created nodes should be pushed to the stack. Any remaining content should be passed to the next parser
  * in the chain.
  *
  * @param Text $content
  * @param Container $target
  * @return void
  */
 public function parseBlock(Text $content, Container $target)
 {
     $content->handle('{
             ^[ ]{0,3}       # Optional leading spaces
             (\\#{1,6})       # $1 = string of #\'s
             (([ ].+?)??)    # $2 = Header text
             ([ ]\\#*[ ]*)?   # optional closing #\'s (not counted)
             $
         }mx', function (Text $whole, Text $marks, Text $content) use($target) {
         $level = $marks->getLength();
         $heading = new Heading($content->trim(), $level);
         $target->addChild($heading);
         $this->inlineParser->queue($heading->getText(), $heading);
     }, function (Text $part) use($target) {
         $this->next->parseBlock($part, $target);
     });
 }
Example #6
0
 /**
  * Parse the given content.
  *
  * Any newly created nodes should be pushed to the stack. Any remaining content should be passed to the next parser
  * in the chain.
  *
  * @param Text $content
  * @param Container $target
  * @return void
  */
 public function parseBlock(Text $content, Container $target)
 {
     $content->handle('{
             ^
             [ ]{0,3}
             ([^>\\-*=\\ \\n].*)
             [ ]*
             \\n
             [ ]{0,3}
             (=+|-+)
             [ ]*
             \\n*
             $
         }mx', function (Text $whole, Text $content, Text $mark) use($target) {
         $level = substr($mark, 0, 1) == '=' ? 1 : 2;
         $heading = new Heading($content->trim(), $level);
         $target->addChild($heading);
         $this->inlineParser->queue($heading->getText(), $heading);
     }, function (Text $part) use($target) {
         $this->next->parseBlock($part, $target);
     });
 }
Example #7
0
 /**
  * Parse the given content.
  *
  * Any newly created nodes should be pushed to the stack. Any remaining content should be passed to the next parser
  * in the chain.
  *
  * @param Text $content
  * @param Container $target
  * @return void
  */
 public function parseBlock(Text $content, Container $target)
 {
     $tags = implode('|', $this->getValidTags());
     $content->handle('{
             ^                        # starts at the beginning or with a newline
             [ ]{0,3}                 # up to 3 leading spaces allowed
             (?:                      # start with one of the following...
                 \\<(?:' . $tags . ')\\s*/?\\>?|    # an opening HTML tag, or
                 \\</(?:' . $tags . ')\\s*\\>|      # a closing HTML tag, or
                 \\<!--(-(?!-)|[^\\-])*?--\\>|  # a HTML comment, or
                 \\<\\?.*?\\?\\>|                # a processing instruction, or
                 \\<![A-Z]+\\s+[^>]+\\>|        # an element type declaration, or
                 \\<!\\[CDATA\\[.*?\\]\\]\\>       # a CDATA section
             )
             .*?                      # match everything until...
             ((?=\\n[ ]*\\n)|\\Z)      # we encounter an empty line or the end
         }imsx', function (Text $content) use($target) {
         $block = new HTMLBlock($content);
         $target->addChild($block);
     }, function (Text $part) use($target) {
         $this->next->parseBlock($part, $target);
     });
 }
Example #8
0
 public function render(Container $root)
 {
     $this->buffer = new Text();
     $root->visit($this);
     return $this->buffer;
 }
Example #9
0
 protected function parseOrderedLists(Text $content, Container $target)
 {
     $content->handle('{
             ^
             ([ ]{0,3})              # $1 - initial indent
             ([0-9]+)([.)])          # $2 - list marker; $3 - punctuation
             (?|
                 ([ ]{1,4})          # $4 - list indent
                 [^ ].*
               |
                 ()                  # ... which can also be empty
             )
             (
                 \\n\\n?
                 \\1[ ]{2}\\4
                 .*
             )*
             (
                 (?:
                     \\n
                     \\1[0-9]+\\3\\4
                     [^ ].*
                   |                     # empty items
                     \\n
                     \\1\\2
                   |                     # Lazy continuation lines
                     \\n
                     [ ]*
                     (?:
                         [^0-9>\\-+*=\\ \\n]
                       |
                         [0-9]+[^.)]
                     )
                     [^\\n]*
                 )
                 (
                     \\n\\n?
                     \\1[ ]{2}\\4
                     .*
                 )*
             )*
             $
         }mx', function (Text $content, Text $i, Text $start, Text $punctuation, Text $indent) use($target) {
         $isTerse = !$content->match('/^[ ]*$/m');
         $lines = explode("\n", $content->getString());
         $start = $start->getString();
         $indentLength = $i->getLength() + $indent->getLength() + 2;
         $list = new ListBlock('ol', $isTerse, $start);
         // Go through all the lines to assemble the list items
         $curItem = substr(array_shift($lines), $indentLength) . "\n";
         foreach ($lines as $line) {
             if (preg_match('/^[0-9]+' . preg_quote($punctuation) . '/', $line)) {
                 $this->addItemToList($curItem, $list);
                 $curItem = substr($line, $indentLength) . "\n";
             } else {
                 $curItem .= $this->unindentLine($line, $indentLength) . "\n";
             }
         }
         $this->addItemToList($curItem, $list);
         $target->addChild($list);
     }, function (Text $part) use($target) {
         $this->next->parseBlock($part, $target);
     });
 }
 protected function handle(Text $content, $mark, Container $target, callable $next)
 {
     $content->handle($this->getPattern($mark), function () use($target) {
         $target->addChild(new HorizontalRule());
     }, $next);
 }
Example #11
0
 public function visit(NodeVisitorInterface $visitor)
 {
     $visitor->enterBlockquote($this);
     parent::visit($visitor);
     $visitor->leaveBlockquote($this);
 }
Example #12
0
 public function visit(NodeVisitorInterface $visitor)
 {
     $visitor->enterListBlock($this);
     parent::visit($visitor);
     $visitor->leaveListBlock($this);
 }