Пример #1
0
 /**
  * extractHeaderContents returns a HeaderList containing HeaderContent objects.
  *
  * @param \nochso\WriteMe\Document $document
  *
  * @return \nochso\WriteMe\Markdown\HeaderList
  *
  * @todo Refactor this as it mostly duplicates extractHeaders
  */
 public function extractHeaderContents(Document $document)
 {
     $headerList = new HeaderList();
     $lines = Multiline::create($document->getContent());
     $prevLine = null;
     $isFenced = false;
     $currentHeaderContent = null;
     $isNewHeader = false;
     foreach ($lines as $key => $line) {
         if (preg_match('/^```(?!`)/', $line)) {
             $isFenced = !$isFenced;
         }
         if (!$isFenced) {
             $header = $this->extractHeader($line, $prevLine, $key);
             if ($header !== null) {
                 $currentHeaderContent = HeaderContent::fromHeader($header);
                 $headerList->add($currentHeaderContent);
                 $isNewHeader = true;
             }
         }
         // Add content only if it's *after* the header line
         if ($currentHeaderContent !== null && !$isNewHeader) {
             $currentHeaderContent->addContent($line);
         }
         $prevLine = $line;
         $isNewHeader = false;
     }
     return $headerList;
 }
Пример #2
0
 public function format(Diff $diff)
 {
     $messages = new Multiline($diff->getMessages());
     $messages->prefix('#');
     $lines = new Multiline(array_merge($this->header, $messages->toArray()));
     $lines->setEol("\n");
     $inOld = false;
     $i = 0;
     $old = [];
     $diffLines = $diff->getDiffLines();
     foreach ($diffLines as $line) {
         if ($line->isSame()) {
             if ($inOld === false) {
                 $inOld = $i;
             }
         } elseif ($inOld !== false) {
             if ($i - $inOld > 5) {
                 $old[$inOld] = $i - 1;
             }
             $inOld = false;
         }
         ++$i;
     }
     $start = isset($old[0]) ? $old[0] : 0;
     $end = count($diffLines);
     if ($tmp = array_search($end, $old)) {
         $end = $tmp;
     }
     $newChunk = true;
     for ($i = $start; $i < $end; ++$i) {
         if (isset($old[$i])) {
             $lines->add('');
             $newChunk = true;
             $i = $old[$i];
         }
         if ($newChunk) {
             if ($this->showNonDiffLines === true) {
                 $lines->add('@@ @@');
             }
             $newChunk = false;
         }
         if ($diffLines[$i]->isAddition()) {
             $lines->add('+' . $diffLines[$i]->getText());
         } elseif ($diffLines[$i]->isRemoval()) {
             $lines->add('-' . $diffLines[$i]->getText());
         } elseif ($this->showNonDiffLines === true) {
             $lines->add(' ' . $diffLines[$i]->getText());
         }
     }
     $lines->add('');
     return (string) $lines;
 }
Пример #3
0
 /**
  * @return string
  */
 public function getDescription()
 {
     $docBlock = new DocBlock($this->reflectionParameter->getDeclaringFunction()->getDocComment());
     /** @var \phpDocumentor\Reflection\DocBlock\Tag\ParamTag[] $paramTags */
     $paramTags = $docBlock->getTagsByName('param');
     foreach ($paramTags as $paramTag) {
         if ($paramTag->getVariableName() === '$' . $this->reflectionParameter->getName()) {
             $lines = Multiline::create($paramTag->getDescription());
             $lines->apply('ltrim');
             return (string) $lines;
         }
     }
     return '';
 }
Пример #4
0
 /**
  * Extract frontmatter from a raw document and return the remaining document content.
  *
  * @param string $input Raw file content
  *
  * @return string The remaining document content after extracting the frontmatter into this object.
  */
 public function extract($input)
 {
     $this->data = [];
     $lines = Multiline::create($input);
     // Frontmatter is missing: assume everything is content.
     if ($lines->first() !== self::FRONTMATTER_SEPARATOR) {
         return $input;
     }
     $frontmatterEnd = $this->findFrontmatterEndPosition($lines);
     $rawFrontmatter = implode($lines->getEol(), array_slice($lines->toArray(), 1, $frontmatterEnd - 1));
     $this->extractFrontmatter($rawFrontmatter);
     $content = implode($lines->getEol(), array_slice($lines->toArray(), $frontmatterEnd + 1));
     return $content;
 }
Пример #5
0
 public function setSources($sourceBefore, $sourceAfter, $keepOutput = false)
 {
     $this->fileSizeBefore = strlen($sourceBefore);
     $this->lineCountBefore = Multiline::create($sourceBefore)->count();
     $this->fileSizeAfter = strlen($sourceAfter);
     $this->lineCountAfter = Multiline::create($sourceAfter)->count();
     if ($keepOutput) {
         $this->output = $sourceAfter;
     }
     if ($sourceBefore === $sourceAfter) {
         $this->status = self::STATUS_SAME;
     } else {
         $this->status = self::STATUS_CHANGED;
     }
 }
Пример #6
0
 /**
  * `@toc.sub@` collects Markdown headers that are **below** the placeholder and on the same or deeper level.
  * If there's a header above the placeholder, its depth will be used as a minimum depth.
  * If there's no header above the placeholder, the first header after the placeholder will be used for the minimum depth.
  * There is currently no maximum depth for `@toc.sub@`.
  *
  * e.g.
  * ```markdown
  * # ignore me
  *
  * @toc.sub@
  * ## sub 1
  * # ignore me again
  * ```
  * is converted into
  *
  * ```markdown
  * # ignore me
  * - [sub 1](#sub-1)
  * ## sub 1
  * # ignore me again
  * ```
  *
  * @param \nochso\WriteMe\Placeholder\Call $call
  * @param int                              $maxDepth How many levels of headers you'd like to keep.
  *                                                   Defaults to zero, meaning all sub-headers are kept.
  */
 public function tocSub(Call $call, $maxDepth = 0)
 {
     $parser = new Markdown\HeaderParser();
     $headerList = $parser->extractHeaders($call->getDocument());
     $lines = Multiline::create($call->getDocument()->getContent());
     $lineIndex = $lines->getLineIndexByCharacterPosition($call->getStartPositionOfRawCall());
     $headers = $headerList->getHeadersBelowLine($lineIndex);
     if ($maxDepth > 0) {
         $minDepth = $this->getMinimumDepth($headers);
         // Filter headers that are relatively too deep
         $headers = array_filter($headers, function (Markdown\Header $header) use($minDepth, $maxDepth) {
             return $header->getLevel() - $minDepth < $maxDepth;
         });
     }
     $toc = $this->formatTOC($headers);
     $call->replace($toc);
 }
Пример #7
0
    /**
     * @param \Throwable $throwable
     */
    public function exception($throwable)
    {
        if (!$throwable instanceof \Exception && !$throwable instanceof \Throwable) {
            $this->errln($throwable);
            return;
        }
        $template = <<<TAG
<<bold red>>%s<<reset>>
<<red>>%s<<reset>>


TAG;
        $message = $throwable;
        $message = Multiline::create($message)->prefix('    ');
        $string = sprintf($template, get_class($throwable), $message);
        $string = $this->formatter->format($string, $this->stderr->isPosix());
        $this->stderr->fwrite($string);
    }
Пример #8
0
 /**
  * Gets the formatted output for one option.
  *
  * @param \stdClass $option An option structure.
  *
  * @return string
  */
 protected function getHelpOption($option)
 {
     if (!$option->name) {
         // it's an argument
         return '';
     }
     $text = '    ' . $this->getHelpOptionParam($option->name, $option->param, $option->multi);
     if ($option->alias) {
         $text .= ', ' . $this->getHelpOptionParam($option->alias, $option->param, $option->multi);
     }
     $text .= PHP_EOL;
     if (!$option->descr) {
         $option->descr = 'No description.';
     }
     $indent = 8;
     $remaining = 80 - $indent;
     $lines = Multiline::create(wordwrap($option->descr, $remaining, "\n"));
     $lines->prefix(str_repeat(' ', $indent));
     $text .= (string) $lines . PHP_EOL . PHP_EOL;
     return $text;
 }
Пример #9
0
 /**
  * Returns the diff between two arrays or strings as array.
  *
  * Each array element contains two elements:
  *   - [0] => string $token
  *   - [1] => 2|1|0
  *
  * - 2: REMOVED: $token was removed from $from
  * - 1: ADDED: $token was added to $from
  * - 0: OLD: $token is not changed in $to
  *
  * @param array|string             $from
  * @param array|string             $to
  * @param LongestCommonSubsequence $lcs
  *
  * @return array
  */
 public function diffToArray($from, $to, LongestCommonSubsequence $lcs = null)
 {
     $this->messages = [];
     $diff = [];
     $this->addLineEndingWarning($from, $to);
     if (!is_array($from) && !is_string($from)) {
         $from = (string) $from;
     }
     if (!is_array($to) && !is_string($to)) {
         $to = (string) $to;
     }
     if (is_string($from)) {
         $from = Multiline::create($from)->toArray();
     }
     if (is_string($to)) {
         $to = Multiline::create($to)->toArray();
     }
     $start = [];
     $end = [];
     $fromLength = count($from);
     $toLength = count($to);
     $length = min($fromLength, $toLength);
     for ($i = 0; $i < $length; ++$i) {
         if ($from[$i] === $to[$i]) {
             $start[] = $from[$i];
             unset($from[$i], $to[$i]);
         } else {
             break;
         }
     }
     $length -= $i;
     for ($i = 1; $i < $length; ++$i) {
         if ($from[$fromLength - $i] === $to[$toLength - $i]) {
             array_unshift($end, $from[$fromLength - $i]);
             unset($from[$fromLength - $i], $to[$toLength - $i]);
         } else {
             break;
         }
     }
     if ($lcs === null) {
         $lcs = $this->selectLcsImplementation($from, $to);
     }
     $common = $lcs->calculate(array_values($from), array_values($to));
     foreach ($start as $token) {
         $diff[] = [$token, 0];
     }
     reset($from);
     reset($to);
     foreach ($common as $token) {
         while (($fromToken = reset($from)) !== $token) {
             $diff[] = [array_shift($from), 2];
         }
         while (($toToken = reset($to)) !== $token) {
             $diff[] = [array_shift($to), 1];
         }
         $diff[] = [$token, 0];
         array_shift($from);
         array_shift($to);
     }
     while (($token = array_shift($from)) !== null) {
         $diff[] = [$token, 2];
     }
     while (($token = array_shift($to)) !== null) {
         $diff[] = [$token, 1];
     }
     foreach ($end as $token) {
         $diff[] = [$token, 0];
     }
     return $diff;
 }
Пример #10
0
 public function formatClass(ReflectionClass $class)
 {
     $ml = Multiline::create($class->getLocatedSource()->getSource());
     return trim($ml[$class->getStartLine() - 1]);
 }
Пример #11
0
 protected function removeConsecutiveEmptyDocs(Multiline $lines, $consecutive, $lastStartPos, $pos)
 {
     if ($consecutive > 0 && $lastStartPos === $pos - $consecutive - 1 || $consecutive > 1) {
         foreach (range($pos - $consecutive, $pos - 1) as $needle) {
             $lines->remove($needle);
         }
     }
     return 0;
 }
Пример #12
0
 /**
  * @param \nochso\Omni\Multiline $lines
  *
  * @return string
  */
 private function extractTags(Multiline $lines)
 {
     $tags = new Multiline(array_slice($lines->toArray(), $this->position));
     $tags->setEol((string) $lines->getEol());
     return (string) $tags;
 }
Пример #13
0
 public function testGetLineIndexByCharacterPosition()
 {
     $ml = Multiline::create("ü\nbb\nccc");
     $this->assertSame(0, $ml->getLineIndexByCharacterPosition(1));
     $this->assertSame(0, $ml->getLineIndexByCharacterPosition(2), 'Line feeds belong to the line it is ending with');
     $this->assertSame(1, $ml->getLineIndexByCharacterPosition(3));
     $this->assertSame(2, $ml->getLineIndexByCharacterPosition(9));
     $this->assertSame(null, $ml->getLineIndexByCharacterPosition(10), 'Invalid position must return null');
     $this->assertSame(null, $ml->getLineIndexByCharacterPosition(-1), 'Invalid (negative) position return null');
 }