Skip to content

Commit fd965cc

Browse files
committed
Allow to build RST content strings
1 parent 5f750ad commit fd965cc

File tree

4 files changed

+143
-3
lines changed

4 files changed

+143
-3
lines changed

src/BuildConfig.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class BuildConfig
3030
private $subdirectoryToBuild;
3131
private $excludedPaths;
3232
private $fileFinder;
33+
// needed to know if we're building an entire directory of RST contents or just a single RST string
34+
private $contentIsString;
35+
// these are the *.fjson files generated by Sphinx and maintained for compatibility reasons
36+
private $generateJsonFiles;
3337

3438
public function __construct()
3539
{
@@ -38,6 +42,8 @@ public function __construct()
3842
$this->symfonyVersion = '4.4';
3943
$this->excludedPaths = [];
4044
$this->imagesPublicPrefix = '';
45+
$this->contentIsString = false;
46+
$this->generateJsonFiles = true;
4147
}
4248

4349
public function createFileFinder(): Finder
@@ -128,6 +134,16 @@ public function getImagesPublicPrefix(): string
128134
return $this->imagesPublicPrefix;
129135
}
130136

137+
public function generateJsonFiles(): bool
138+
{
139+
return $this->generateJsonFiles;
140+
}
141+
142+
public function isContentAString(): bool
143+
{
144+
return $this->contentIsString;
145+
}
146+
131147
public function setSymfonyVersion(string $version): self
132148
{
133149
$this->symfonyVersion = $version;
@@ -219,4 +235,23 @@ public function setExcludedPaths(array $excludedPaths)
219235

220236
$this->excludedPaths = $excludedPaths;
221237
}
238+
239+
/*
240+
* Call this method when you're building a string of RST contents (e.g. the
241+
* contents of a single file) instead of the common case of building an
242+
* entire directory of RST files.
243+
*/
244+
public function setContentIsString(): self
245+
{
246+
$this->contentIsString = true;
247+
248+
return $this;
249+
}
250+
251+
public function disableJsonFileGeneration(): self
252+
{
253+
$this->generateJsonFiles = false;
254+
255+
return $this;
256+
}
222257
}

src/BuildResult.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ class BuildResult
1717
{
1818
private $builder;
1919
private $errors;
20+
// only defined when using build() method
2021
private $jsonResults = [];
22+
// only defined when using buildString() method
23+
private $stringResult = null;
2124

2225
public function __construct(Builder $builder)
2326
{
@@ -45,6 +48,11 @@ public function getErrors(): array
4548
return $this->errors;
4649
}
4750

51+
public function getErrorTrace(): string
52+
{
53+
return implode("\n", $this->errors);
54+
}
55+
4856
public function getMetadata(): Metas
4957
{
5058
return $this->builder->getMetas();
@@ -72,4 +80,18 @@ public function setJsonResults(array $jsonResults): void
7280
{
7381
$this->jsonResults = $jsonResults;
7482
}
83+
84+
/**
85+
* Returns the HTML result of building some string contents
86+
* using the buildString() builder method
87+
*/
88+
public function getStringResult(): ?string
89+
{
90+
return $this->stringResult;
91+
}
92+
93+
public function setStringResult(string $result): void
94+
{
95+
$this->stringResult = $result;
96+
}
7597
}

src/DocBuilder.php

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

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

41-
$metas = $buildResult->getMetadata();
42-
if ($config->getSubdirectoryToBuild()) {
42+
if ($config->isContentAString()) {
43+
$htmlFilePath = $config->getOutputDir().'/index.html';
44+
if (is_file($htmlFilePath)) {
45+
// generated HTML contents are a full HTML page, so we need to
46+
// extract the contents of the <body> tag
47+
$crawler = new Crawler(file_get_contents($htmlFilePath));
48+
$buildResult->setStringResult(trim($crawler->filter('body')->html()));
49+
}
50+
} elseif ($config->getSubdirectoryToBuild()) {
51+
$metas = $buildResult->getMetadata();
4352
$htmlForPdfGenerator = new HtmlForPdfGenerator($metas, $config);
4453
$htmlForPdfGenerator->generateHtmlForPdf();
45-
} else {
54+
} elseif ($config->generateJsonFiles()) {
55+
$metas = $buildResult->getMetadata();
4656
$jsonGenerator = new JsonGenerator($metas, $config);
4757
$buildResult->setJsonResults($jsonGenerator->generateJson($builder->getIndexName()));
4858
}
4959

5060
return $buildResult;
5161
}
62+
63+
public function buildString(string $contents): BuildResult
64+
{
65+
$filesystem = new Filesystem();
66+
$tmpDir = sys_get_temp_dir().'/doc_builder_build_string_'.random_int(1, 100000000);
67+
if ($filesystem->exists($tmpDir)) {
68+
$filesystem->remove($tmpDir);
69+
}
70+
$filesystem->mkdir($tmpDir);
71+
72+
$filesystem->dumpFile($tmpDir.'/index.rst', $contents);
73+
74+
$buildConfig = (new BuildConfig())
75+
->setContentIsString()
76+
->setContentDir($tmpDir)
77+
->setOutputDir($tmpDir.'/output')
78+
->disableBuildCache()
79+
->disableJsonFileGeneration()
80+
;
81+
82+
$buildResult = $this->build($buildConfig);
83+
$filesystem->remove($tmpDir);
84+
85+
return $buildResult;
86+
}
5287
}

tests/IntegrationTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,54 @@ public function parserUnitBlockProvider()
261261
];
262262
}
263263

264+
public function testParseString()
265+
{
266+
$rstString = <<<RST
267+
Lorem ipsum dolor sit amet
268+
==========================
269+
270+
Consectetur adipisicing elit, sed do eiusmod
271+
tempor **incididunt ut** labore et dolore magna aliqua.
272+
273+
* Ut enim ad minim veniam
274+
* Quis nostrud exercitation
275+
* Ullamco laboris nisi ut
276+
277+
`Aliquip ex ea commodo <https://symfony.com>`_ consequat.
278+
Duis aute irure dolor in reprehenderit in voluptate `velit esse`_.
279+
280+
Cillum dolore eu fugiat nulla pariatur
281+
--------------------------------------
282+
283+
Excepteur sint occaecat cupidatat non proident, sunt in
284+
culpa qui *officia deserunt* mollit anim id est laborum.
285+
286+
.. _`velit esse`: https://github.com
287+
RST;
288+
289+
$htmlString = <<<HTML
290+
<div class="section">
291+
<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>
292+
<p>Consectetur adipisicing elit, sed do eiusmod
293+
tempor <strong>incididunt ut</strong> labore et dolore magna aliqua.</p>
294+
<ul>
295+
<li>Ut enim ad minim veniam</li>
296+
<li>Quis nostrud exercitation</li>
297+
<li>Ullamco laboris nisi ut</li>
298+
</ul>
299+
<p><a href="https://symfony.com" class="reference external">Aliquip ex ea commodo</a> consequat.
300+
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>
301+
<div class="section">
302+
<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>
303+
<p>Excepteur sint occaecat cupidatat non proident, sunt in
304+
culpa qui <em>officia deserunt</em> mollit anim id est laborum.</p>
305+
</div>
306+
</div>
307+
HTML;
308+
309+
$this->assertSame($htmlString, (new DocBuilder())->buildString($rstString)->getStringResult());
310+
}
311+
264312
private function createIndenter(): Indenter
265313
{
266314
$indenter = new Indenter();

0 commit comments

Comments
 (0)