From 8d537f392fa04fa9f7c3c15b956753cee045608a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Gra=C3=9Fl?= Date: Thu, 5 Nov 2026 23:30:37 +0100 Subject: [PATCH 1/4] A deck read back into Markdown carries no title it never had --- CHANGELOG.md | 33 ++++++++++++++++++++++++ README.md | 9 ++++--- src/Reverse/DeckWriter.php | 36 ++++++++++++++++++++++++-- tests/Unit/dead-code.php | 6 +++++ tests/Unit/reverse.php | 53 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa3f293..e5d7cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,39 @@ All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed + +- **A deck read back into Markdown carries no title it never had.** PHPPresentation gives + every deck the title `Untitled Presentation`, and the frontmatter carried it as though + somebody had written it: a deck without a title came back with one, and drawing that + Markdown again put a title placeholder and the words "Untitled Presentation" on a slide + that never had a title. + + The title in the frontmatter is the deck's own where the deck has one, and the first + slide's title where it has not — the frontmatter is the first slide's, and a `title:` in + it is that slide's title. So a deck whose title is on its slide and nowhere else keeps + it, and a deck with no title at all comes back with no `title:` line. + + It is the first slide's title and not a later one's, the way it is in the other + direction: a `title:` in the first slide's frontmatter is that slide's title and wins + over its own heading. So a deck whose second slide has a title and whose first does not + gains no title. + +- **The slides example says what it needs when the library is not beside it.** The + `mdword` skill bundle carries this half's gallery as `examples/slides/` and ships no + `vendor/`, so `php examples/slides/build.php` died with a PHP fatal error that said + nothing about what was missing. + + It says what the build needs and stops: + + > This build needs the library itself: put a `vendor/autoload.php` in this directory's + > parent, or run `composer install` in the checkout it came from. + + The Word half's build has said this for a while, and the two halves ship side by side in + one bundle, so they fail the same way. + ## [0.4.0] - 2026-11-04 ### Added diff --git a/README.md b/README.md index 43ef442..1ee2def 100644 --- a/README.md +++ b/README.md @@ -2330,7 +2330,7 @@ echo (new PowerPointToMarkdown($path, new Options(mediaDirectory: null)))->conve ```text --- -title: "Untitled Presentation" +title: "One" author: "markdown-office" --- @@ -2340,8 +2340,11 @@ Text. ``` The frontmatter carries what the deck said about itself — its title, its author and its -description — because a deck's own properties are the only thing about it that is not on a -slide. +description. The title is the deck's own where it has one, and the first slide's where it +has not: PHPPresentation gives every deck the title `Untitled Presentation`, and that is +its own default rather than a title somebody wrote. The frontmatter is the first slide's, +and a `title:` in it is that slide's title — so a deck whose title is on its slide and +nowhere else keeps it. What comes back is the text and the structure. What does not is the design: the type sizes, the colours and the geometry live in the theme and the master, and neither travels to a new diff --git a/src/Reverse/DeckWriter.php b/src/Reverse/DeckWriter.php index 1912f86..4a114e4 100644 --- a/src/Reverse/DeckWriter.php +++ b/src/Reverse/DeckWriter.php @@ -28,6 +28,14 @@ final class DeckWriter */ private const INDENT = ' '; + /** + * The title PHPPresentation gives a deck that carries none. + * + * It is the library's own default rather than a title somebody wrote, so a + * deck that carries it says nothing about its title. + */ + private const DEFAULT_TITLE = 'Untitled Presentation'; + public function __construct(private readonly Options $options) { } @@ -49,7 +57,7 @@ public function write(array $slides, DocumentProperties $properties, ?string $th if ($index === 0) { // The deck's own frontmatter is the first slide's, so the first slide's own // settings are written into it rather than beside it. - $frontmatter = $this->frontmatter($properties, $theme, $slide->frontmatter); + $frontmatter = $this->frontmatter($properties, $theme, $slide->frontmatter, $slide->title); if ($frontmatter !== '') { $body = $frontmatter . "\n" . $body; @@ -105,18 +113,25 @@ private function settings(array $settings): string * the theme it was drawn in rather than in the library's own, and the design of a deck is * most of what a deck is. * + * The title is the deck's own where it has one, and the first slide's where it has not: + * the frontmatter is the first slide's, and a `title:` in it is that slide's title, so a + * deck whose title is on its slide and nowhere else would lose it. + * * @param string|null $theme The name of the theme the deck was drawn in, when it is one * a deck can name again. * @param array $own The first slide's own settings, which are * written into the deck's own block with them. + * @param string|null $slideTitle The title of the first slide, which stands in for the + * deck's own title where the properties carry none. */ private function frontmatter( DocumentProperties $properties, ?string $theme = null, array $own = [], + ?string $slideTitle = null, ): string { $values = [ - 'title' => $properties->getTitle(), + 'title' => $this->title($properties, $slideTitle), 'theme' => $theme, 'author' => $properties->getCreator(), 'description' => $properties->getDescription(), @@ -150,6 +165,23 @@ private function frontmatter( return "---\n" . implode("\n", $lines) . "\n---\n"; } + /** + * The title the deck's frontmatter carries, or null where it carries none. + * + * The properties' title is the deck's own, unless it is {@see self::DEFAULT_TITLE}, + * which says nothing about a deck that carries it. + * + * The first slide's title stands in for it then, because the frontmatter is the first + * slide's and a `title:` in it is that slide's title: a deck whose title is on its slide + * and nowhere else would lose it otherwise. + */ + private function title(DocumentProperties $properties, ?string $slideTitle): ?string + { + $title = $properties->getTitle(); + + return $title === self::DEFAULT_TITLE ? $slideTitle : $title; + } + /** * A YAML scalar, quoted so that a colon or a hash in the value is not read * as syntax. diff --git a/tests/Unit/dead-code.php b/tests/Unit/dead-code.php index 5ba6eb5..45fd95b 100644 --- a/tests/Unit/dead-code.php +++ b/tests/Unit/dead-code.php @@ -608,6 +608,12 @@ function pagesWithClaim(string $claim): array // `styles.yml` is about. The phrase is the old claim, and the README has to be able to // say what the halves part at without saying it. 'a theme directory serves one half' => 'a theme directory serves one half', + + // The frontmatter was said to carry what is not on a slide, and the title was one of + // those things — but a deck's title can be on its first slide and nowhere else, and the + // frontmatter is the first slide's. The phrase is the reason the old sentence gave, so + // that no page may argue that the frontmatter holds only what a slide does not. + 'the frontmatter carries only what is not on a slide' => 'the only thing about it that is not on a slide', ]); it('has no decorative dividers in it', function () { diff --git a/tests/Unit/reverse.php b/tests/Unit/reverse.php index db4ef44..f34fb42 100644 --- a/tests/Unit/reverse.php +++ b/tests/Unit/reverse.php @@ -891,6 +891,59 @@ static function (DocumentProperties $properties): void { ->and(converted($path))->toContain('author: "Fabian"'); }); +it('writes no title into the frontmatter of a deck that has none', function () { + // PHPPresentation gives every deck the title "Untitled Presentation", and that is the + // library's own default rather than a title somebody wrote: a deck carrying it says + // nothing about its title. The frontmatter wrote it all the same, and drawing the + // Markdown again added a title to a slide that never had one. + $path = writtenDeck("Text only.\n"); + + expect(converted($path))->not->toContain('title:'); +}); + +it('writes the title of the first slide into the frontmatter of a deck that has none', function () { + // The frontmatter is the first slide's, and a `title:` in it is that slide's title, so + // a deck whose title is on its slide and nowhere else would lose it. + $path = writtenDeck("# One\n\nText.\n"); + + expect(converted($path))->toContain('title: "One"'); +}); + +it('takes the title of the first slide and not the title of a later one', function () { + // The deck's title is the first slide's title, the way it is in the other direction: + // a deck whose second slide has a title and whose first does not gains no title. + $path = writtenDeck("Text only.\n\n---\n\n# Two\n"); + + expect(converted($path))->not->toContain('title:'); +}); + +it('writes the title of the deck into the frontmatter where it has one', function () { + // The deck's own title is the deck's, and the first slide's title is the first + // slide's: the two are told apart here, and the deck's is the one that is written. + $path = deckWithShapes( + static function (AbstractSlide $slide): void { + placeholderShape($slide, 'title', 'What broke'); + }, + static function (DocumentProperties $properties): void { + $properties->setTitle('Harbour lights'); + }, + ); + + expect(converted($path))->toContain('title: "Harbour lights"'); +}); + +it('draws the same slide again when the Markdown it came from is drawn again', function () { + // The round trip has to be a round trip: the Markdown a deck is read back into, drawn + // again, has to be the deck it came from. The title in the frontmatter is the first + // slide's title, and a heading that says the same thing is not drawn a second time. + $first = writtenDeck("# One\n\nText.\n"); + $back = converted($first); + $second = writtenDeck($back); + + expect(slideTexts($second))->toBe(slideTexts($first)) + ->and(converted($second))->toBe($back); +}); + it('refuses a package with more parts than the limit allows', function () { $path = writtenDeck("# One\n"); From 6ad5b77965e9a531a58f1c940323e9fdff4f81f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Gra=C3=9Fl?= Date: Thu, 5 Nov 2026 23:30:37 +0100 Subject: [PATCH 2/4] The slides example says what it needs when the library is not beside it --- examples/build.php | 18 +++++++- tests/Readme/examples-build.php | 81 +++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 tests/Readme/examples-build.php diff --git a/examples/build.php b/examples/build.php index 8b92085..f4dd863 100644 --- a/examples/build.php +++ b/examples/build.php @@ -11,7 +11,23 @@ * examples/out, and a PNG of every slide beside them in examples/out//. */ -require_once __DIR__ . '/../vendor/autoload.php'; +$autoload = __DIR__ . '/../vendor/autoload.php'; + +// The build drives the library's own API, so it needs the library. A copy of this +// directory on its own — the one the `mdword` skill carries, as `examples/slides/` — has +// the sources and the templates but not the library that builds them, and a missing +// `require` would say nothing about that. +if (!is_file($autoload)) { + fwrite( + STDERR, + "This build needs the library itself: put a `vendor/autoload.php` in this directory's parent," + . " or run `composer install` in the checkout it came from.\n", + ); + + exit(1); +} + +require_once $autoload; require_once __DIR__ . '/decks.php'; use MarkdownPresentation\Document\DeckParser; diff --git a/tests/Readme/examples-build.php b/tests/Readme/examples-build.php new file mode 100644 index 0000000..6c6490a --- /dev/null +++ b/tests/Readme/examples-build.php @@ -0,0 +1,81 @@ + ['pipe', 'w'], 2 => ['pipe', 'w']], + $pipes, + ); + + if (!is_resource($process)) { + throw new RuntimeException('The build could not be started.'); + } + + $out = (string) stream_get_contents($pipes[1]); + $errors = (string) stream_get_contents($pipes[2]); + + fclose($pipes[1]); + fclose($pipes[2]); + + return [proc_close($process), $out, $errors, $directory]; +} + +it('says what the slides example needs when the library is not beside it', function () { + [$status, $out, $errors] = slidesBuildWithoutLibrary(); + + expect($status)->toBe(1) + ->and($errors)->toContain( + 'This build needs the library itself: put a `vendor/autoload.php` in this directory\'s parent,' + . ' or run `composer install` in the checkout it came from.', + ) + // On the error output and not on the standard one: a build that says what it needs + // says it where a shell shows it. + ->and($out)->not->toContain('This build needs the library itself') + // And not as a PHP failure either: a warning about a missing file is what the + // build is there to replace. + ->and($errors)->not->toContain('Warning') + ->and($errors)->not->toContain('Fatal error'); +}); + +it('stops the slides example before it builds anything', function () { + [$status, , , $directory] = slidesBuildWithoutLibrary(); + + // The build says what it needs and stops there: nothing is written, and the decks it + // would have built are not built. + expect($status)->toBe(1) + ->and(is_dir($directory . '/examples/out'))->toBeFalse() + ->and(glob($directory . '/examples/*.pptx') ?: [])->toBe([]); +}); From e4fe352a9963a233c9a7132a84a9e4a53caaa5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Gra=C3=9Fl?= Date: Thu, 5 Nov 2026 23:39:29 +0100 Subject: [PATCH 3/4] A deck read back into Markdown carries no author it never had --- CHANGELOG.md | 8 ++++++++ README.md | 4 +++- src/Reverse/DeckWriter.php | 24 +++++++++++++++++++++++- tests/Unit/reverse.php | 24 ++++++++++++++++++++++-- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d7cd6..ed527b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,14 @@ All notable changes to this project are documented here. The format follows over its own heading. So a deck whose second slide has a title and whose first does not gains no title. +- **A deck read back into Markdown carries no author it never had.** PHPPresentation gives + every deck the author `Unknown Creator`, and that is the library's own default rather + than a name somebody wrote: the frontmatter carried it as though somebody had, and the + deck drawn from that Markdown was made by "Unknown Creator". + + The author in the frontmatter is the deck's own, and a deck that carries the default + carries no author, so none is written. + - **The slides example says what it needs when the library is not beside it.** The `mdword` skill bundle carries this half's gallery as `examples/slides/` and ships no `vendor/`, so `php examples/slides/build.php` died with a PHP fatal error that said diff --git a/README.md b/README.md index 1ee2def..068ddad 100644 --- a/README.md +++ b/README.md @@ -2344,7 +2344,9 @@ description. The title is the deck's own where it has one, and the first slide's has not: PHPPresentation gives every deck the title `Untitled Presentation`, and that is its own default rather than a title somebody wrote. The frontmatter is the first slide's, and a `title:` in it is that slide's title — so a deck whose title is on its slide and -nowhere else keeps it. +nowhere else keeps it. The author is the deck's own, and the name PHPPresentation gives a +deck that carries none — `Unknown Creator` — is a name nobody wrote, so a deck carrying it +carries no author. What comes back is the text and the structure. What does not is the design: the type sizes, the colours and the geometry live in the theme and the master, and neither travels to a new diff --git a/src/Reverse/DeckWriter.php b/src/Reverse/DeckWriter.php index 4a114e4..bd43730 100644 --- a/src/Reverse/DeckWriter.php +++ b/src/Reverse/DeckWriter.php @@ -36,6 +36,14 @@ final class DeckWriter */ private const DEFAULT_TITLE = 'Untitled Presentation'; + /** + * The author PHPPresentation gives a deck that carries none. + * + * It is the library's own default rather than a name somebody wrote, so a deck + * that carries it says nothing about its author. + */ + private const DEFAULT_AUTHOR = 'Unknown Creator'; + public function __construct(private readonly Options $options) { } @@ -133,7 +141,7 @@ private function frontmatter( $values = [ 'title' => $this->title($properties, $slideTitle), 'theme' => $theme, - 'author' => $properties->getCreator(), + 'author' => $this->author($properties), 'description' => $properties->getDescription(), ...$own, ]; @@ -182,6 +190,20 @@ private function title(DocumentProperties $properties, ?string $slideTitle): ?st return $title === self::DEFAULT_TITLE ? $slideTitle : $title; } + /** + * The author the deck's frontmatter carries, or null where it carries none. + * + * The properties' author is the deck's own, unless it is {@see self::DEFAULT_AUTHOR}, + * which says nothing about a deck that carries it: an author called "Unknown Creator" + * is a name nobody wrote, and the Markdown would carry it as though they had. + */ + private function author(DocumentProperties $properties): ?string + { + $author = $properties->getCreator(); + + return $author === self::DEFAULT_AUTHOR ? null : $author; + } + /** * A YAML scalar, quoted so that a colon or a hash in the value is not read * as syntax. diff --git a/tests/Unit/reverse.php b/tests/Unit/reverse.php index f34fb42..c8740ab 100644 --- a/tests/Unit/reverse.php +++ b/tests/Unit/reverse.php @@ -932,6 +932,20 @@ static function (DocumentProperties $properties): void { expect(converted($path))->toContain('title: "Harbour lights"'); }); +it('writes no author into the frontmatter of a deck that has none', function () { + // PHPPresentation gives every deck the author "Unknown Creator", and that is the + // library's own default rather than a name somebody wrote: the Markdown carried it + // as though somebody had, and the deck drawn from that Markdown was made by + // "Unknown Creator". + $path = deckWithShapes( + static function (AbstractSlide $slide): void { + placeholderShape($slide, 'title', 'What broke'); + }, + ); + + expect(converted($path))->not->toContain('author:'); +}); + it('draws the same slide again when the Markdown it came from is drawn again', function () { // The round trip has to be a round trip: the Markdown a deck is read back into, drawn // again, has to be the deck it came from. The title in the frontmatter is the first @@ -1576,15 +1590,21 @@ static function (DocumentProperties $properties): void { it('writes nothing for a block that holds nothing', function () { $writer = new DeckWriter(new Options(mediaDirectory: null)); + $properties = new DocumentProperties(); + $properties->setTitle('A deck'); - expect($writer->write([ + $markdown = $writer->write([ new Slide(0, null, [ Block::paragraph([]), Block::list([Block::item([Block::paragraph([])])]), Block::table([]), Block::image(new Image('A dot', '', '')), ]), - ], new DocumentProperties()))->toContain('---'); + ], $properties); + + // The deck's own frontmatter and nothing after it: every block holds nothing, so + // every block writes nothing. + expect(trim(str_replace('---', '', $markdown)))->toBe('title: "A deck"'); }); it('leaves a picture with nothing in it out', function () { From 23770beece7c975a03cafdedc4225dee4b4309ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Gra=C3=9Fl?= Date: Sun, 8 Nov 2026 10:35:41 +0100 Subject: [PATCH 4/4] The comments say less, and say it once The rule for the title was in the frontmatter's docblock and again in the method that decides it, the two defaults each said the same thing twice, and the tests' comments repeated what the names of the tests already say. What is left is what the code cannot say: that PHPPresentation's own defaults are not a title or a name somebody wrote, and that the frontmatter is the first slide's. --- examples/build.php | 7 +++---- src/Reverse/DeckWriter.php | 30 +++++++++++------------------- tests/Readme/examples-build.php | 16 +++++----------- tests/Unit/dead-code.php | 6 ++---- tests/Unit/reverse.php | 28 ++++++++++------------------ 5 files changed, 31 insertions(+), 56 deletions(-) diff --git a/examples/build.php b/examples/build.php index f4dd863..8318f47 100644 --- a/examples/build.php +++ b/examples/build.php @@ -13,10 +13,9 @@ $autoload = __DIR__ . '/../vendor/autoload.php'; -// The build drives the library's own API, so it needs the library. A copy of this -// directory on its own — the one the `mdword` skill carries, as `examples/slides/` — has -// the sources and the templates but not the library that builds them, and a missing -// `require` would say nothing about that. +// The build drives the library's own API, so it needs the library. The `mdword` skill +// carries a copy of this directory as `examples/slides/`, with the sources and the +// templates but not the library, where a missing `require` would say nothing. if (!is_file($autoload)) { fwrite( STDERR, diff --git a/src/Reverse/DeckWriter.php b/src/Reverse/DeckWriter.php index bd43730..b736323 100644 --- a/src/Reverse/DeckWriter.php +++ b/src/Reverse/DeckWriter.php @@ -29,18 +29,14 @@ final class DeckWriter private const INDENT = ' '; /** - * The title PHPPresentation gives a deck that carries none. - * - * It is the library's own default rather than a title somebody wrote, so a - * deck that carries it says nothing about its title. + * The title PHPPresentation gives a deck that carries none: its own default + * rather than a title somebody wrote. */ private const DEFAULT_TITLE = 'Untitled Presentation'; /** - * The author PHPPresentation gives a deck that carries none. - * - * It is the library's own default rather than a name somebody wrote, so a deck - * that carries it says nothing about its author. + * The author PHPPresentation gives a deck that carries none: its own default + * rather than a name somebody wrote. */ private const DEFAULT_AUTHOR = 'Unknown Creator'; @@ -121,9 +117,8 @@ private function settings(array $settings): string * the theme it was drawn in rather than in the library's own, and the design of a deck is * most of what a deck is. * - * The title is the deck's own where it has one, and the first slide's where it has not: - * the frontmatter is the first slide's, and a `title:` in it is that slide's title, so a - * deck whose title is on its slide and nowhere else would lose it. + * The title is the deck's own where it has one and the first slide's where it has + * not, which is what {@see self::title()} decides. * * @param string|null $theme The name of the theme the deck was drawn in, when it is one * a deck can name again. @@ -177,11 +172,9 @@ private function frontmatter( * The title the deck's frontmatter carries, or null where it carries none. * * The properties' title is the deck's own, unless it is {@see self::DEFAULT_TITLE}, - * which says nothing about a deck that carries it. - * - * The first slide's title stands in for it then, because the frontmatter is the first - * slide's and a `title:` in it is that slide's title: a deck whose title is on its slide - * and nowhere else would lose it otherwise. + * which says nothing about a deck that carries it. The first slide's title stands in + * for it then: the frontmatter is the first slide's, and a `title:` in it is that + * slide's title, so a deck whose title is on its slide and nowhere else would lose it. */ private function title(DocumentProperties $properties, ?string $slideTitle): ?string { @@ -193,9 +186,8 @@ private function title(DocumentProperties $properties, ?string $slideTitle): ?st /** * The author the deck's frontmatter carries, or null where it carries none. * - * The properties' author is the deck's own, unless it is {@see self::DEFAULT_AUTHOR}, - * which says nothing about a deck that carries it: an author called "Unknown Creator" - * is a name nobody wrote, and the Markdown would carry it as though they had. + * The properties' author is the deck's own, unless it is {@see self::DEFAULT_AUTHOR}: + * a name nobody wrote, which the Markdown would carry as though somebody had. */ private function author(DocumentProperties $properties): ?string { diff --git a/tests/Readme/examples-build.php b/tests/Readme/examples-build.php index 6c6490a..21a782e 100644 --- a/tests/Readme/examples-build.php +++ b/tests/Readme/examples-build.php @@ -8,11 +8,8 @@ /* * The slides example, run the way the skill bundle runs it. * - * The `mdword` skill bundle carries this half's gallery as `examples/slides/` and ships no - * `vendor/`, so the build has to say what it needs rather than die with a PHP fatal error - * that says nothing about what is missing. The Word half's build says it, and the two - * halves ship side by side in one bundle, so they fail the same way. - * + * The bundle carries this half's gallery as `examples/slides/` and ships no `vendor/`, so + * the build has to say what it needs rather than die with a fatal error that says nothing. * The copy is made into a tree of its own rather than run where it lies, because the * library *is* beside it here: a build that found this repository's `vendor/` would carry * on and build the decks, and the test would be about nothing. @@ -61,11 +58,9 @@ function slidesBuildWithoutLibrary(): array 'This build needs the library itself: put a `vendor/autoload.php` in this directory\'s parent,' . ' or run `composer install` in the checkout it came from.', ) - // On the error output and not on the standard one: a build that says what it needs - // says it where a shell shows it. + // On the error output and not on the standard one, and not as a PHP failure: the + // build is there to replace a warning about a missing file. ->and($out)->not->toContain('This build needs the library itself') - // And not as a PHP failure either: a warning about a missing file is what the - // build is there to replace. ->and($errors)->not->toContain('Warning') ->and($errors)->not->toContain('Fatal error'); }); @@ -73,8 +68,7 @@ function slidesBuildWithoutLibrary(): array it('stops the slides example before it builds anything', function () { [$status, , , $directory] = slidesBuildWithoutLibrary(); - // The build says what it needs and stops there: nothing is written, and the decks it - // would have built are not built. + // The build says what it needs and stops there: nothing is written. expect($status)->toBe(1) ->and(is_dir($directory . '/examples/out'))->toBeFalse() ->and(glob($directory . '/examples/*.pptx') ?: [])->toBe([]); diff --git a/tests/Unit/dead-code.php b/tests/Unit/dead-code.php index 45fd95b..ddc8b39 100644 --- a/tests/Unit/dead-code.php +++ b/tests/Unit/dead-code.php @@ -609,10 +609,8 @@ function pagesWithClaim(string $claim): array // say what the halves part at without saying it. 'a theme directory serves one half' => 'a theme directory serves one half', - // The frontmatter was said to carry what is not on a slide, and the title was one of - // those things — but a deck's title can be on its first slide and nowhere else, and the - // frontmatter is the first slide's. The phrase is the reason the old sentence gave, so - // that no page may argue that the frontmatter holds only what a slide does not. + // The frontmatter was said to carry what is not on a slide, but a deck's title can be + // on its first slide and nowhere else, and the frontmatter is the first slide's. 'the frontmatter carries only what is not on a slide' => 'the only thing about it that is not on a slide', ]); diff --git a/tests/Unit/reverse.php b/tests/Unit/reverse.php index c8740ab..0f74482 100644 --- a/tests/Unit/reverse.php +++ b/tests/Unit/reverse.php @@ -892,34 +892,30 @@ static function (DocumentProperties $properties): void { }); it('writes no title into the frontmatter of a deck that has none', function () { - // PHPPresentation gives every deck the title "Untitled Presentation", and that is the - // library's own default rather than a title somebody wrote: a deck carrying it says - // nothing about its title. The frontmatter wrote it all the same, and drawing the - // Markdown again added a title to a slide that never had one. + // PHPPresentation's own default, not a title somebody wrote: a deck carrying it says + // nothing about its title. $path = writtenDeck("Text only.\n"); expect(converted($path))->not->toContain('title:'); }); it('writes the title of the first slide into the frontmatter of a deck that has none', function () { - // The frontmatter is the first slide's, and a `title:` in it is that slide's title, so - // a deck whose title is on its slide and nowhere else would lose it. + // The frontmatter is the first slide's, and a `title:` in it is that slide's title. $path = writtenDeck("# One\n\nText.\n"); expect(converted($path))->toContain('title: "One"'); }); it('takes the title of the first slide and not the title of a later one', function () { - // The deck's title is the first slide's title, the way it is in the other direction: - // a deck whose second slide has a title and whose first does not gains no title. + // Only the first slide's title stands in: a deck whose second slide has a title and + // whose first does not gains none. $path = writtenDeck("Text only.\n\n---\n\n# Two\n"); expect(converted($path))->not->toContain('title:'); }); it('writes the title of the deck into the frontmatter where it has one', function () { - // The deck's own title is the deck's, and the first slide's title is the first - // slide's: the two are told apart here, and the deck's is the one that is written. + // The deck's own title is the deck's, and it wins over the first slide's. $path = deckWithShapes( static function (AbstractSlide $slide): void { placeholderShape($slide, 'title', 'What broke'); @@ -933,10 +929,8 @@ static function (DocumentProperties $properties): void { }); it('writes no author into the frontmatter of a deck that has none', function () { - // PHPPresentation gives every deck the author "Unknown Creator", and that is the - // library's own default rather than a name somebody wrote: the Markdown carried it - // as though somebody had, and the deck drawn from that Markdown was made by - // "Unknown Creator". + // PHPPresentation's own default, not a name somebody wrote: the Markdown carried it + // as though somebody had. $path = deckWithShapes( static function (AbstractSlide $slide): void { placeholderShape($slide, 'title', 'What broke'); @@ -948,8 +942,7 @@ static function (AbstractSlide $slide): void { it('draws the same slide again when the Markdown it came from is drawn again', function () { // The round trip has to be a round trip: the Markdown a deck is read back into, drawn - // again, has to be the deck it came from. The title in the frontmatter is the first - // slide's title, and a heading that says the same thing is not drawn a second time. + // again, has to be the deck it came from. $first = writtenDeck("# One\n\nText.\n"); $back = converted($first); $second = writtenDeck($back); @@ -1602,8 +1595,7 @@ static function (DocumentProperties $properties): void { ]), ], $properties); - // The deck's own frontmatter and nothing after it: every block holds nothing, so - // every block writes nothing. + // The deck's own frontmatter and nothing after it. expect(trim(str_replace('---', '', $markdown)))->toBe('title: "A deck"'); });