/** * @param \nochso\WriteMe\Placeholder\Call $call * @param string $templateName 'summary', 'short' or 'full' */ public function api(Call $call, $templateName) { $classes = $this->getClasses($call->getDocument()); $template = new Template(); $template->prepare($classes, $call->getDocument()->getFrontmatter()); $call->replace($template->render($templateName . '.php')); }
/** * @param \nochso\WriteMe\Placeholder\Call $call * * @return \nochso\WriteMe\Markdown\HeaderContent[] */ private function getHeaderContents(Call $call) { $changelogPath = $this->findChangelog($call->getDocument()); $changelog = Document::fromFile($changelogPath); $parser = new HeaderParser(); $headerContentList = $parser->extractHeaderContents($changelog); $maxChanges = $this->options->getValue('changelog.max-changes'); $releaseLevel = $this->options->getValue('changelog.release-level'); $changes = 0; /** @var HeaderContent[] $displayHeaders */ $displayHeaders = []; /** @var HeaderContent $headerContent */ foreach ($headerContentList->getHeaders() as $headerContent) { // This header marks a release if ($headerContent->getLevel() === $releaseLevel) { $changes++; // Stop if we reached the max amount of changes. if ($changes > $maxChanges) { break; } $displayHeaders[] = $headerContent; } // Keep adding sub-HeaderContent if we're within a release if ($changes > 0 && $headerContent->getLevel() > $releaseLevel) { $displayHeaders[] = $headerContent; } } return $displayHeaders; }
public function writemePlaceholderDocs(Call $call) { $classes = []; foreach ($this->placeholders->toArray() as $placeholder) { $classes[get_class($placeholder)] = ReflectionClass::createFromInstance($placeholder); } $template = new TemplateData(); $template->setHeaderStartLevel($this->options->getValue('placeholder-docs.header-depth')); $template->prepare($classes, $this->placeholders); $docs = $template->render('full.php'); $docs = (new Converter())->escape($docs); $call->replace($docs); }
/** * Travis CI build status. * * @param \nochso\WriteMe\Placeholder\Call $call * @param string|null $userRepository User/repository, e.g. `nochso/writeme`. Defaults to `composer.name` * @param string|null $branch Optional branch name. */ public function badgeTravis(Call $call, $userRepository = null, $branch = null) { if ($userRepository === null) { $userRepository = $call->getDocument()->getFrontmatter()->get('composer.name'); } if ($userRepository === null) { return; } $image = sprintf('https://api.travis-ci.org/%s.svg', $userRepository); if ($branch !== null) { $image .= '?branch=' . $branch; } $url = 'https://travis-ci.org/' . $userRepository; $this->image($call, $image, 'Travis CI build status', $url); }
/** * getMethodsForCall by Call method name and priority. * * @param \nochso\WriteMe\Placeholder\Call $call * * @return \nochso\WriteMe\Reflection\Method[] A list of matching methods of this collection. */ public function getMethodsForCall(Call $call) { $name = $call->getDotName(); if (!isset($this->methods[$name])) { $name = Method::WILDCARD_METHOD_NAME; } if (!isset($this->methods[$name])) { return []; } $methods = []; foreach ($this->methods[$name] as $method) { if ($method->hasPriorityOfCall($call)) { $methods[] = $method; } } return $methods; }
/** * `@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); }
/** * @dataProvider tocSubProvider * * @param string $input * @param string $expected */ public function testTocSub($input, $expected) { $document = new Document($input); $toc = new TOC(); $toc->prepare($document); $call = Call::extractFirstCall($document); $toc->tocSub($call); $this->assertSame($expected, $document->getContent()); }
public function testWildcard_WhenFrontmatterIsUnknown_MustNotBeReplaced() { $document = new Document('@foo@'); $frontmatter = new Frontmatter(); $call = Call::extractFirstCall($document); $frontmatter->wildcard($call); $this->assertFalse($call->isReplaced()); $this->assertSame('@foo@', $document->getContent()); }
public function testGetMethodsForCall_SpecificPlaceholdersHavePriorityOverPotentialFrontmatter() { // Frontmatter must not accidentally replace a @toc@ call even though it *theoretically* would be frontmatter. $collection = new PlaceholderCollection([new TOC(), new Frontmatter()]); $document = new Document("---\ntoc: foo\n---\n@toc@"); $call = Call::extractFirstCall($document, Placeholder::PRIORITY_FIRST); $methods = $collection->getMethodsForCall($call); $this->assertCount(0, $methods); $tocCall = Call::extractFirstCall($document, Placeholder::PRIORITY_LAST); $methods = $collection->getMethodsForCall($tocCall); $this->assertCount(1, $methods); $this->assertSame(TOC::class, get_class($methods[0]->getPlaceholder())); }
public function wildcard(Call $call) { $path = $call->getIdentifier(); if ($call->getMethod() !== null) { $path .= '.' . $call->getMethod(); } $value = $call->getDocument()->getFrontmatter()->get($path); if ($value !== null) { $call->replace($value); } }
/** * applyPlaceholdersAtPriority by calling only the placeholders that are relevant at a certain priority. * * @param Document $document The document to modify. * @param int $priority The priority stage to consider. * Placeholders are only called when they've * listed that priority. See * `Placeholder::getCallPriorities()` * @param \nochso\WriteMe\Placeholder\PlaceholderCollection $placeholders */ private function applyPlaceholdersAtPriority(Document $document, $priority, PlaceholderCollection $placeholders) { $offset = 0; $call = Call::extractFirstCall($document, $priority, $offset); while ($call !== null) { $methods = $placeholders->getMethodsForCall($call); $isReplaced = false; foreach ($methods as $method) { $method->call($call); if ($call->isReplaced()) { $isReplaced = true; break; } } if ($isReplaced) { // Anything could have changed in content. Start from the beginning. $offset = 0; } else { // The call was skipped by all placeholders. Ignore it at this priority. $offset = $call->getEndPositionOfRawCall(); } $call = Call::extractFirstCall($document, $priority, $offset); } }
public function testGetEndPositionOfRawCall() { $document = new Document('@test@ @test@'); $call = Call::extractFirstCall($document, Placeholder::PRIORITY_FIRST); $this->assertSame(6, $call->getEndPositionOfRawCall()); $secondCall = Call::extractFirstCall($document, Placeholder::PRIORITY_FIRST, $call->getEndPositionOfRawCall()); $this->assertSame(13, $secondCall->getEndPositionOfRawCall(), 'End position must be absolute and not be influenced by an offset'); }
/** * Call a placeholder method with the Call object and parameters extracted from the raw template call. */ public function call(Call $call) { $callable = [$this->placeholder, $this->method->getShortName()]; $params = array_merge([$call], $call->getParameters()); call_user_func_array($callable, $params); }