Skip to content

Allow to build RST content strings #109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/BuildConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class BuildConfig
private $subdirectoryToBuild;
private $excludedPaths;
private $fileFinder;
// needed to know if we're building an entire directory of RST contents or just a single RST string
private $contentIsString;
// these are the *.fjson files generated by Sphinx and maintained for compatibility reasons
private $generateJsonFiles;

public function __construct()
{
Expand All @@ -38,6 +42,8 @@ public function __construct()
$this->symfonyVersion = '4.4';
$this->excludedPaths = [];
$this->imagesPublicPrefix = '';
$this->contentIsString = false;
$this->generateJsonFiles = true;
}

public function createFileFinder(): Finder
Expand Down Expand Up @@ -128,6 +134,16 @@ public function getImagesPublicPrefix(): string
return $this->imagesPublicPrefix;
}

public function generateJsonFiles(): bool
{
return $this->generateJsonFiles;
}

public function isContentAString(): bool
{
return $this->contentIsString;
}

public function setSymfonyVersion(string $version): self
{
$this->symfonyVersion = $version;
Expand Down Expand Up @@ -219,4 +235,23 @@ public function setExcludedPaths(array $excludedPaths)

$this->excludedPaths = $excludedPaths;
}

/*
* Call this method when you're building a string of RST contents (e.g. the
* contents of a single file) instead of the common case of building an
* entire directory of RST files.
*/
public function setContentIsString(): self
{
$this->contentIsString = true;

return $this;
}

public function disableJsonFileGeneration(): self
{
$this->generateJsonFiles = false;

return $this;
}
}
22 changes: 22 additions & 0 deletions src/BuildResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ class BuildResult
{
private $builder;
private $errors;
// only defined when using build() method
private $jsonResults = [];
// only defined when using buildString() method
private $stringResult = null;

public function __construct(Builder $builder)
{
Expand Down Expand Up @@ -45,6 +48,11 @@ public function getErrors(): array
return $this->errors;
}

public function getErrorTrace(): string
{
return implode("\n", $this->errors);
}

public function getMetadata(): Metas
{
return $this->builder->getMetas();
Expand Down Expand Up @@ -72,4 +80,18 @@ public function setJsonResults(array $jsonResults): void
{
$this->jsonResults = $jsonResults;
}

/**
* Returns the HTML result of building some string contents
* using the buildString() builder method
*/
public function getStringResult(): ?string
{
return $this->stringResult;
}

public function setStringResult(string $result): void
{
$this->stringResult = $result;
}
}
41 changes: 38 additions & 3 deletions src/DocBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Doctrine\RST\Builder;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\Filesystem\Filesystem;
use SymfonyDocsBuilder\CI\MissingFilesChecker;
use SymfonyDocsBuilder\Generator\HtmlForPdfGenerator;
Expand Down Expand Up @@ -38,15 +39,49 @@ public function build(BuildConfig $config): BuildResult
$filesystem->dumpFile($config->getOutputDir().'/build_errors.txt', implode("\n", $buildResult->getErrors()));
}

$metas = $buildResult->getMetadata();
if ($config->getSubdirectoryToBuild()) {
if ($config->isContentAString()) {
$htmlFilePath = $config->getOutputDir().'/index.html';
if (is_file($htmlFilePath)) {
// generated HTML contents are a full HTML page, so we need to
// extract the contents of the <body> tag
$crawler = new Crawler(file_get_contents($htmlFilePath));
$buildResult->setStringResult(trim($crawler->filter('body')->html()));
}
} elseif ($config->getSubdirectoryToBuild()) {
$metas = $buildResult->getMetadata();
$htmlForPdfGenerator = new HtmlForPdfGenerator($metas, $config);
$htmlForPdfGenerator->generateHtmlForPdf();
} else {
} elseif ($config->generateJsonFiles()) {
$metas = $buildResult->getMetadata();
$jsonGenerator = new JsonGenerator($metas, $config);
$buildResult->setJsonResults($jsonGenerator->generateJson($builder->getIndexName()));
}

return $buildResult;
}

public function buildString(string $contents): BuildResult
{
$filesystem = new Filesystem();
$tmpDir = sys_get_temp_dir().'/doc_builder_build_string_'.random_int(1, 100000000);
if ($filesystem->exists($tmpDir)) {
$filesystem->remove($tmpDir);
}
$filesystem->mkdir($tmpDir);

$filesystem->dumpFile($tmpDir.'/index.rst', $contents);

$buildConfig = (new BuildConfig())
->setContentIsString()
->setContentDir($tmpDir)
->setOutputDir($tmpDir.'/output')
->disableBuildCache()
->disableJsonFileGeneration()
;

$buildResult = $this->build($buildConfig);
$filesystem->remove($tmpDir);

return $buildResult;
}
}
48 changes: 48 additions & 0 deletions tests/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,54 @@ public function parserUnitBlockProvider()
];
}

public function testParseString()
{
$rstString = <<<RST
Lorem ipsum dolor sit amet
==========================

Consectetur adipisicing elit, sed do eiusmod
tempor **incididunt ut** labore et dolore magna aliqua.

* Ut enim ad minim veniam
* Quis nostrud exercitation
* Ullamco laboris nisi ut

`Aliquip ex ea commodo <https://symfony.com>`_ consequat.
Duis aute irure dolor in reprehenderit in voluptate `velit esse`_.

Cillum dolore eu fugiat nulla pariatur
--------------------------------------

Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui *officia deserunt* mollit anim id est laborum.

.. _`velit esse`: https://github.com
RST;

$htmlString = <<<HTML
<div class="section">
<h1 id="lorem-ipsum-dolor-sit-amet"><a class="headerlink" href="#lorem-ipsum-dolor-sit-amet" title="Permalink to this headline">Lorem ipsum dolor sit amet</a></h1>
<p>Consectetur adipisicing elit, sed do eiusmod
tempor <strong>incididunt ut</strong> labore et dolore magna aliqua.</p>
<ul>
<li>Ut enim ad minim veniam</li>
<li>Quis nostrud exercitation</li>
<li>Ullamco laboris nisi ut</li>
</ul>
<p><a href="https://symfony.com" class="reference external">Aliquip ex ea commodo</a> consequat.
Duis aute irure dolor in reprehenderit in voluptate <a href="https://github.com" class="reference external" rel="external noopener noreferrer" target="_blank">velit esse</a>.</p>
<div class="section">
<h2 id="cillum-dolore-eu-fugiat-nulla-pariatur"><a class="headerlink" href="#cillum-dolore-eu-fugiat-nulla-pariatur" title="Permalink to this headline">Cillum dolore eu fugiat nulla pariatur</a></h2>
<p>Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui <em>officia deserunt</em> mollit anim id est laborum.</p>
</div>
</div>
HTML;

$this->assertSame($htmlString, (new DocBuilder())->buildString($rstString)->getStringResult());
}

private function createIndenter(): Indenter
{
$indenter = new Indenter();
Expand Down