diff --git a/CHANGELOG.md b/CHANGELOG.md index 03f30ca..654aac8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,14 +26,14 @@ All notable changes to this project are documented here. The format follows not over it. The templates may also live in a file beside the deck, named by the deck's frontmatter - and resolved against the deck's own directory, so that a deck and the furniture it - shares travel together. The deck's own templates override the imported ones of the same - name, the way a deck's own theme overrides the shipped one. + with `templates-file:` and resolved against the deck's own directory, so that a deck and + the furniture it shares travel together. The deck's own templates override the imported + ones of the same name, the way a deck's own theme overrides the shipped one. `examples/markdown/16-templates.md` is the deck that shows it: a template defined in the deck, slides that name one, two and three of them, a template imported from - `templates/chrome.md`, and a template of the deck's own of the same name as one the file - holds — the one that is drawn. The company is invented. + `templates/templates.md`, and a template of the deck's own of the same name as one the + file holds — the one that is drawn. The company is invented. - **A whole corporate template, as the files a company has.** A theme, a brand mark and the furniture of a deck are three separate things, and a company that has all three has @@ -42,13 +42,13 @@ All notable changes to this project are documented here. The format follows `examples/markdown/17-corporate-template.md` is a deck that has them: a theme of its own in `examples/markdown/corporate/theme.yml`, a mark in two colours — one for a light page and one for a dark one, with the crosshair knocked out of it rather than painted on it, - so the page shows through it either way — and a chrome file holding the wordmark, the + so the page shows through it either way — and a templates file holding the wordmark, the rule and the footer. **A dark slide and a light one are the same deck, and the furniture on them cannot be the same furniture**: the name is ink on a light page and white on a dark one, so the dark wordmark is the same named style with the colour laid over it. That is the one - thing a chrome file cannot decide for itself, and it is why there are two of them. + thing a templates file cannot decide for itself, and it is why there are two of them. The company is invented, and so is every figure in the deck. @@ -228,20 +228,22 @@ All notable changes to this project are documented here. The format follows struck-through word rather than refused. The arms of the match are the vocabulary now, and an attribute they do not know is refused by name. -- **A chrome file is read with a ceiling.** The chrome file is the one file this library - reads whole, and it is the one a deck names in its frontmatter: a picture is bounded by - the pixels of its raster and a part of a template by the bytes it inflates to, and the - chrome file was bounded by nothing at all. It is read with a ceiling of a megabyte now, and - a file over it is refused with its size and the ceiling in the message. The ceiling is an - argument of `ChromeFile`, so a caller can hold a deck to a smaller one. +- **A templates file is read with a ceiling.** The templates file is the one file this + library reads whole, and it is the one a deck names in its frontmatter: a picture is + bounded by the pixels of its raster and a part of a template by the bytes it inflates to, + and the templates file was bounded by nothing at all. It is read with a ceiling of a + megabyte now, and a file over it is refused with its size and the ceiling in the message. + The ceiling is an argument of `TemplatesFile`, so a caller can hold a deck to a smaller + one. - **A slide carries at most a hundred shapes.** The chrome of a template is read once and drawn on every slide that names it, so the shapes of a template are multiplied by the - slides that draw them: two hundred shapes in a chrome file named by sixty slides is twelve - thousand shapes and ten megabytes of slide XML, and neither factor was bounded. The slide - count is bounded by `PresentationRenderer::MAX_SLIDES`, and `Furniture::MAX_SHAPES` is the - other half of that bound — a slide that carries more than a hundred shapes, the chrome of - a template included, is refused with the number and the ceiling in the message. + slides that draw them: two hundred shapes in a templates file named by sixty slides is + twelve thousand shapes and ten megabytes of slide XML, and neither factor was bounded. + The slide count is bounded by `PresentationRenderer::MAX_SLIDES`, and + `Furniture::MAX_SHAPES` is the other half of that bound — a slide that carries more than + a hundred shapes, the chrome of a template included, is refused with the number and the + ceiling in the message. - **A picture in a template is paid for once.** The chrome of a template is drawn on every slide that names it, and each of those slides had a picture of its own in the package: a diff --git a/README.md b/README.md index 5ce89b2..52e73fb 100644 --- a/README.md +++ b/README.md @@ -1549,19 +1549,19 @@ The page number is furniture, so it is written in a template and drawn on every names it. A slide may write one itself as well, and the number it carries is the number of the slide it is on. -#### The chrome file +#### The templates file A deck may keep its templates in a file beside it and name it in the deck's frontmatter: ```markdown --- theme: ./theme.yml -chrome: ./chrome.md +templates-file: ./templates.md --- ``` -`chrome.md` is a Markdown file of template definitions in the same syntax as a deck, and it is -resolved against the deck's own directory — so a deck and the furniture it shares travel +`templates.md` is a Markdown file of template definitions in the same syntax as a deck, and it +is resolved against the deck's own directory — so a deck and the furniture it shares travel together. A file that is not there is a failure, and so is a file outside the directories the render may read: a path a deck wrote is held to the same scope as a picture in it. @@ -1720,7 +1720,7 @@ slide that names it: | Ceiling | Value | Bounds | | --- | --- | --- | | `Render\Furniture::MAX_SHAPES` | 100 | the shapes one slide may carry, the chrome of a template included | -| `Template\ChromeFile::MAX_BYTES` | one megabyte | the chrome file a deck may name in its frontmatter | +| `Template\TemplatesFile::MAX_BYTES` | one megabyte | the templates file a deck may name in its frontmatter | Both are refused with the number and the ceiling in the message, and the shape count is the other half of the slide count: a hundred shapes on a slide is a hundred shapes on each of the @@ -1997,7 +1997,7 @@ try { ``` ```text -The frontmatter of slide 1 names "transition", which is not a directive. The directives are: title, name, level, layout, theme, author, description, template, chrome. +The frontmatter of slide 1 names "transition", which is not a directive. The directives are: title, name, level, layout, theme, author, description, template, templates-file. ``` Slidev accepts dozens of directives this library does not read, so a deck written for it will diff --git a/examples/README.md b/examples/README.md index f3425f0..b559f50 100644 --- a/examples/README.md +++ b/examples/README.md @@ -20,7 +20,7 @@ quietly. The profile and the scratch script go to the temporary directory, so | `01-kitchen-sink.md` | `01-kitchen-sink.pptx` | Every construct at once: emphasis, `code`, strikethrough, links, nested lists, an ordered list starting at 7, an aligned table with markup in its cells, a two-line quote, code, a rule, and a `::note` becoming a speaker note | | `02-layout-roles.md` | `02-layout-roles.pptx` | Every layout role, one per slide | | `03-themes.md` | three files | The same deck in `default`, `corporate-dark` and `minimal`, changed by nothing but the `theme:` line — so the three can be put side by side and compared. They differ in type scale, margins, rule weight and heading treatment, not only in palette | -| `04-frontmatter.md` | `04-frontmatter.pptx` | Every frontmatter key and what each one does, and a slide drawn with two templates — one the deck defines and one `templates/chrome.md` holds | +| `04-frontmatter.md` | `04-frontmatter.pptx` | Every frontmatter key and what each one does, and a slide drawn with two templates — one the deck defines and one `templates/templates.md` holds | | `05-steps.md` | `05-steps.pptx` | `::click` steps as click animations on one slide, a `:::click` region that is a step of its own, a build-up across two columns, a `::column` written inside a region, a picture held back for its own click, and a `::note` | | `06-tables.md` | `06-tables.pptx` | Table alignment, a bold filled header, widths from content | | `07-images.md` | `07-images.pptx` | A picture fitted to the room left in its column, a WebP converted to PNG, an SVG drawn to PNG, and the three layouts built around one: `image-text`, `image-title` and `image-slide` | @@ -32,7 +32,7 @@ quietly. The profile and the scratch script go to the temporary directory, so | `13-placed-deck.md` | `13-placed-deck.pptx` | A whole business pitch built out of free shapes and nothing else — a dark cover and a dark sign-off, an agenda of numbered circles, a card grid, a hand-built pricing table with zebra rows and a right-aligned column, a four-pillar comparison, a quarterly roadmap with arrows between phases, and translucent decoration over both dark slides. The company is invented | | `14-shadows.md` | `14-shadows.pptx` | Five shadow types on five different kinds of object — a soft shadow straight down, a hard-edged one with no blur at all, a glow with no offset, one cast down and to the right, and one thrown upward at 40% — plus a shadow on a `:::content` block and on a `::image` | | `15-inline-styles.md` | `15-inline-styles.pptx` | A word in a style of the theme inside a box with a colour of its own, the raw form that needs no style of the theme's, an attribute laid over a named style for one property only, the seven attributes this half draws, and the three it refuses — a name the theme does not have, a label holding Markdown, and the `highlight` it cannot write. The company is invented | -| `16-templates.md` | `16-templates.pptx` | The furniture of a deck, written once: a template defined in the deck, a slide that names one, a slide that names two, a slide that names three, a template imported from `templates/chrome.md`, and a template of the deck's own of the same name as one the file holds — the one that is drawn. The company is invented | +| `16-templates.md` | `16-templates.pptx` | The furniture of a deck, written once: a template defined in the deck, a slide that names one, a slide that names two, a slide that names three, a template imported from `templates/templates.md`, and a template of the deck's own of the same name as one the file holds — the one that is drawn. The company is invented | | `17-corporate-template.md` | `17-corporate-template.pptx` | A whole corporate template: a theme of the company's own, a brand mark in two colours — one for a light page and one for a dark one — and the furniture of a deck written once and named by every slide that wants it. Eight slides of the kinds a company deck is made of: a cover, an agenda, a headline, two columns with a chart, a quote, a table, a divider and a closing. The company is invented | ## The deck that is not anybody's business @@ -51,7 +51,7 @@ Rebuilding that deck from another tool is what turned up both defects in [PR #11 the failure it exists to demonstrate, so `build.php` leaves it alone and says which file and why. -`templates/chrome.md` is not a deck either: it is a file of templates, and +`templates/templates.md` is not a deck either: it is a file of templates, and `04-frontmatter.md` and `16-templates.md` are the decks that name it. It is in a directory of its own because every `.md` file beside the decks is one. @@ -152,7 +152,7 @@ A few of these are here because the render is the only honest evidence: of five slides, and two definitions stand between the cover and this slide in the file: a definition is not drawn, it has no number, and it does not count. - **`16`, the third slide.** The band across the head came out of - `templates/chrome.md`, which the deck's frontmatter names, and the deck says + `templates/templates.md`, which the deck's frontmatter names, and the deck says nothing about where it is or how thick it is. Three templates are named on this slide and the chrome of each of them is drawn on it. - **`16`, the fourth slide.** The number is `accent1` at twelve points and reads @@ -163,7 +163,7 @@ A few of these are here because the render is the only honest evidence: - **`17`, the second slide.** One box, three words and three colours is `15`; what is new here is the furniture around them. The wordmark is the company's own mark beside the company's own name, the rule is a hairline under the header, and the footer is the - confidential mark and the page number. All three are templates of `corporate/chrome.md` + confidential mark and the page number. All three are templates of `corporate/templates.md` and every slide that names them is drawn with them. - **`17`, the seventh slide.** The divider is a dark panel with a gold number on it, and the wordmark on it is the light one: the same named style with the colour laid over it, diff --git a/examples/markdown/04-frontmatter.md b/examples/markdown/04-frontmatter.md index 1e6fea4..7bb132b 100644 --- a/examples/markdown/04-frontmatter.md +++ b/examples/markdown/04-frontmatter.md @@ -3,14 +3,14 @@ title: Every frontmatter key description: One slide per key, and what each one reaches. theme: minimal author: markdown-office -chrome: ./templates/chrome.md +templates-file: ./templates/templates.md --- # Every frontmatter key Nine keys: `title`, `name`, `level`, `layout`, `theme`, `author`, `description`, -`template` and `chrome`. A block naming a tenth is a failure that names these -nine, and this slide carries the first four. +`template` and `templates-file`. A block naming a tenth is a failure that names +these nine, and this slide carries the first four. --- name: A title that is not a heading @@ -61,7 +61,7 @@ template: [wordmark, page] --- This slide names two templates. `wordmark` is the one this deck defines below, -and `page` is the one `templates/chrome.md` — the file this deck's frontmatter +and `page` is the one `templates/templates.md` — the file this deck's frontmatter names — holds. A template's frontmatter names the template and nothing else, which is what diff --git a/examples/markdown/16-templates.md b/examples/markdown/16-templates.md index d91ac6b..31de444 100644 --- a/examples/markdown/16-templates.md +++ b/examples/markdown/16-templates.md @@ -1,7 +1,7 @@ --- title: Slide templates theme: minimal -chrome: ./templates/chrome.md +templates-file: ./templates/templates.md description: The furniture of a deck, written once, and the slides that draw it. template: wordmark --- @@ -18,7 +18,7 @@ A deck gets its templates three ways: - a **definition** in the deck, a block whose frontmatter names a template - a **slide** that names a template, or several of them -- a **chrome file** beside the deck, named in the deck's frontmatter +- a **templates file** beside the deck, named in the deck's frontmatter --- template: wordmark @@ -60,7 +60,7 @@ template: [wordmark, band, page] # A template out of a file -The deck's frontmatter names `templates/chrome.md`. +The deck's frontmatter names `templates/templates.md`. That file holds a template called `band`. The band across the head of this slide came out of that file, and this deck says nothing about where it is or how thick it is. @@ -77,7 +77,7 @@ template: [wordmark, page] # The deck's own template wins :::content{left=6.7% top=20% width=86.7% height=70% font-size=17} -`templates/chrome.md` holds a template called `page` too, and it puts a bare number at +`templates/templates.md` holds a template called `page` too, and it puts a bare number at the foot of the slide. This deck defines its own `page` above, and the deck's own one is the one that is drawn: the number is in the theme's `accent1` rather than its `subtle`, at twelve points rather diff --git a/examples/markdown/17-corporate-template.md b/examples/markdown/17-corporate-template.md index 04c3016..5dd2b26 100644 --- a/examples/markdown/17-corporate-template.md +++ b/examples/markdown/17-corporate-template.md @@ -2,7 +2,7 @@ title: Third-quarter review description: A corporate deck built out of the house template. theme: ./corporate/theme.yml -chrome: ./corporate/chrome.md +templates-file: ./corporate/templates.md layout: title template: wordmark --- diff --git a/examples/markdown/corporate/README.md b/examples/markdown/corporate/README.md index 5a7a7ef..c41e0b4 100644 --- a/examples/markdown/corporate/README.md +++ b/examples/markdown/corporate/README.md @@ -12,7 +12,7 @@ decks have, and every part of it is a file you edit. | `theme.yml` | the design — the twelve colour slots, the faces, the type scale and the rhythm | | `layouts.yml` | which layout each of the eight roles gets | | `text-styles.yml` | the named text styles a deck writes words in | -| `chrome.md` | the furniture of a deck: the wordmark, the rule, the footer | +| `templates.md` | the furniture of a deck: the wordmark, the rule, the footer | | `logo.png`, `logo-light.png` | the mark, for a light page and for a dark one | | `make-logo.php` | draws the two marks from the theme's colours | @@ -22,7 +22,7 @@ The deck that uses all of it is `../17-corporate-template.md`. Three things, and each is one file. -**The name.** `chrome.md` holds the wordmark, and the name is in it twice — once in the +**The name.** `templates.md` holds the wordmark, and the name is in it twice — once in the light template and once in the dark one. The dark one is the same named style with the colour laid over it: @@ -45,7 +45,7 @@ the table uses it for the one row that went down. ## The furniture -The chrome file holds four templates, and a slide names the ones it wants: +The templates file holds four templates, and a slide names the ones it wants: ```markdown --- @@ -63,7 +63,7 @@ template: [wordmark, rule, footer] **A dark slide and a light one are the same deck, and the furniture on them cannot be the same furniture** — the name is ink on a light page and white on a dark one. That is what -the second wordmark is for, and it is the one thing a single chrome file cannot decide for +the second wordmark is for, and it is the one thing a single templates file cannot decide for you. The cover and the two dark slides name `wordmark-light` and nothing else; the light slides diff --git a/examples/markdown/corporate/chrome.md b/examples/markdown/corporate/templates.md similarity index 100% rename from examples/markdown/corporate/chrome.md rename to examples/markdown/corporate/templates.md diff --git a/examples/markdown/templates/chrome.md b/examples/markdown/templates/templates.md similarity index 100% rename from examples/markdown/templates/chrome.md rename to examples/markdown/templates/templates.md diff --git a/src/Exception/MalformedChrome.php b/src/Exception/MalformedChrome.php index 188238e..d02fe18 100644 --- a/src/Exception/MalformedChrome.php +++ b/src/Exception/MalformedChrome.php @@ -5,7 +5,11 @@ namespace MarkdownPresentation\Exception; /** - * A template that is not chrome, or a chrome file that is not templates. + * A template that holds the wrong thing. + * + * A template holds chrome — the free shapes it draws — and nothing else, so a body that + * holds ordinary Markdown, a column marker, or nothing at all is a mistake in the template + * rather than in the deck that draws it. * * Kept apart from {@see UnknownTemplate} because the two failures have opposite fixes: a * name nobody has needs a different name, and a body that holds the wrong thing needs a @@ -58,18 +62,6 @@ public static function empty(string $name): self )); } - /** - * A chrome file that holds something other than template definitions. - */ - public static function slide(string $file): self - { - return new self(sprintf( - 'The chrome file "%s" holds a slide that is not a template definition. A chrome file holds definitions: ' - . 'slides whose frontmatter names a template and nothing else.', - $file, - )); - } - /** * A mistake in a template, told with the message the mistake came with. * diff --git a/src/Exception/MalformedTemplatesFile.php b/src/Exception/MalformedTemplatesFile.php new file mode 100644 index 0000000..cddf381 --- /dev/null +++ b/src/Exception/MalformedTemplatesFile.php @@ -0,0 +1,23 @@ + $roots The directories this render may read a chrome file in, + * @param list $roots The directories this render may read a templates file in, * which the message names: the fix is to move the file into * one of them or to have the program rendering the deck allow * where it is. @@ -31,8 +31,8 @@ public static function at(string $path): self public static function outside(string $written, string $found, array $roots): self { return new self(sprintf( - 'The chrome file "%s" is at "%s" rather than one this render may read (%s). Copy it under one of those ' - . 'directories, or give the renderer that directory as one of its additional roots.', + 'The templates file "%s" is at "%s" rather than one this render may read (%s). Copy it under one of ' + . 'those directories, or give the renderer that directory as one of its additional roots.', $written, $found, implode(', ', $roots), @@ -42,8 +42,8 @@ public static function outside(string $written, string $found, array $roots): se public static function aUrl(string $written): self { return new self(sprintf( - 'The chrome file "%s" is a URL rather than a path. A chrome file is a Markdown file beside the deck, and ' - . 'PHP would have handed "phar://" or "http://" to the stream wrapper it names.', + 'The templates file "%s" is a URL rather than a path. A templates file is a Markdown file beside the ' + . 'deck, and PHP would have handed "phar://" or "http://" to the stream wrapper it names.', $written, )); } diff --git a/src/Exception/ChromeTooLarge.php b/src/Exception/TemplatesFileTooLarge.php similarity index 53% rename from src/Exception/ChromeTooLarge.php rename to src/Exception/TemplatesFileTooLarge.php index 1efded7..bbab891 100644 --- a/src/Exception/ChromeTooLarge.php +++ b/src/Exception/TemplatesFileTooLarge.php @@ -5,19 +5,19 @@ namespace MarkdownPresentation\Exception; /** - * A chrome file bigger than the library will read. + * A templates file bigger than the library will read. * - * The ceiling is {@see \MarkdownPresentation\Template\ChromeFile::MAX_BYTES}, and the size + * The ceiling is {@see \MarkdownPresentation\Template\TemplatesFile::MAX_BYTES}, and the size * is in the message because the fix is a number: only the author of the file can say how * much of the furniture belongs in it and how much belongs on the slides. */ -final class ChromeTooLarge extends InvalidInput +final class TemplatesFileTooLarge extends InvalidInput { public static function of(string $file, int $bytes, int $maximum): self { return new self(sprintf( - 'The chrome file "%s" is %d bytes, and a chrome file may be at most %d. Write less of the furniture in ' - . 'it, or write the furniture on the slides themselves.', + 'The templates file "%s" is %d bytes, and a templates file may be at most %d. Write less of the ' + . 'furniture in it, or write the furniture on the slides themselves.', $file, $bytes, $maximum, diff --git a/src/Render/Furniture.php b/src/Render/Furniture.php index ffaaf5b..ccf3421 100644 --- a/src/Render/Furniture.php +++ b/src/Render/Furniture.php @@ -7,16 +7,17 @@ use MarkdownPresentation\Document\Deck; use MarkdownPresentation\Document\DeckParser; use MarkdownPresentation\Document\Slide as SourceSlide; -use MarkdownPresentation\Exception\ChromeNotFound; use MarkdownPresentation\Exception\MalformedChrome; use MarkdownPresentation\Exception\MalformedFrontmatter; +use MarkdownPresentation\Exception\MalformedTemplatesFile; +use MarkdownPresentation\Exception\TemplatesFileNotFound; use MarkdownPresentation\Exception\TooManyShapes; use MarkdownPresentation\Exception\UnknownTemplate; use MarkdownPresentation\Render\Free\FreeShape; use MarkdownPresentation\Render\Free\FreeSlideNumber; -use MarkdownPresentation\Template\ChromeFile; use MarkdownPresentation\Template\Definition; use MarkdownPresentation\Template\Templates; +use MarkdownPresentation\Template\TemplatesFile; use MarkdownPresentation\Theme\Theme; /** @@ -50,27 +51,28 @@ final class Furniture public const MAX_SHAPES = 100; /** - * @param Deck $deck The deck being rendered, which holds the templates it - * defines and the chrome file it names. - * @param ChromeFile $files The reader of the chrome file the deck names. - * @param Chrome $chrome The reader of a template's body. + * @param Deck $deck The deck being rendered, which holds the templates it + * defines and the templates file it names. + * @param TemplatesFile $files The reader of the templates file the deck names. + * @param Chrome $chrome The reader of a template's body. */ public function __construct( private readonly Deck $deck, - private readonly ChromeFile $files, + private readonly TemplatesFile $files, private readonly Chrome $chrome, ) { } /** - * The templates the deck has: its own over the ones a chrome file holds. + * The templates the deck has: its own over the ones a templates file holds. * - * Read before anything is built, so a chrome file that cannot be read fails while there - * is still no file on disk to clean up. + * Read before anything is built, so a templates file that cannot be read fails while + * there is still no file on disk to clean up. * - * @throws ChromeNotFound * @throws MalformedChrome * @throws MalformedFrontmatter + * @throws MalformedTemplatesFile + * @throws TemplatesFileNotFound */ public function templates(): Templates { @@ -203,39 +205,39 @@ private function names(Templates $templates, SourceSlide $slide): array } /** - * The templates a chrome file holds. + * The templates a templates file holds. * * A file beside the deck, named by the deck's frontmatter and resolved against the * deck's own directory, so that a deck and the furniture it shares travel together. * * @return list * - * @throws ChromeNotFound - * @throws MalformedChrome * @throws MalformedFrontmatter + * @throws MalformedTemplatesFile + * @throws TemplatesFileNotFound */ private function imported(): array { - $written = $this->deck->frontmatterValue('chrome'); + $written = $this->deck->frontmatterValue('templates-file'); if ($written === null) { return []; } if (!is_string($written) || trim($written) === '') { - throw MalformedFrontmatter::wrongType(1, 'chrome', 'a path to a file of chrome'); + throw MalformedFrontmatter::wrongType(1, 'templates-file', 'a path to a file of templates'); } $markdown = $this->files->read(trim($written)); - $chrome = (new DeckParser())->parse($markdown); + $templates = (new DeckParser())->parse($markdown); - // A chrome file holds definitions and nothing else: a slide in it is a slide + // A templates file holds definitions and nothing else: a slide in it is a slide // nobody asked for, and one that would be drawn on a deck it was not written for. - if ($chrome->slides() !== []) { - throw MalformedChrome::slide(trim($written)); + if ($templates->slides() !== []) { + throw MalformedTemplatesFile::slide(trim($written)); } - return $chrome->definitions(); + return $templates->definitions(); } /** diff --git a/src/Render/PresentationRenderer.php b/src/Render/PresentationRenderer.php index 6f4bdc4..f56796e 100644 --- a/src/Render/PresentationRenderer.php +++ b/src/Render/PresentationRenderer.php @@ -33,8 +33,8 @@ use MarkdownPresentation\Render\Free\FreeShape; use MarkdownPresentation\Render\Free\FreeSlideNumber; use MarkdownPresentation\Render\Free\FreeText; -use MarkdownPresentation\Template\ChromeFile; use MarkdownPresentation\Template\Templates; +use MarkdownPresentation\Template\TemplatesFile; use MarkdownPresentation\Theme\LayoutRole; use MarkdownPresentation\Theme\LoadedTheme; use MarkdownPresentation\Theme\Theme; @@ -92,10 +92,12 @@ final class PresentationRenderer * the whole of what makes it affordable is that {@see UnknownDirective} names this list * in the failure itself. */ - public const DIRECTIVES = ['title', 'name', 'level', 'layout', 'theme', 'author', 'description', 'template', 'chrome']; + public const DIRECTIVES = [ + 'title', 'name', 'level', 'layout', 'theme', 'author', 'description', 'template', 'templates-file', + ]; /** The keys that describe the deck rather than a slide, and so belong to slide 1's block. */ - public const DECK_DIRECTIVES = ['theme', 'author', 'description', 'chrome']; + public const DECK_DIRECTIVES = ['theme', 'author', 'description', 'templates-file']; /** The theme a deck that names none gets. */ public const DEFAULT_THEME = 'default'; @@ -153,9 +155,9 @@ final class PresentationRenderer private readonly ThemeResolver $themes; /** - * The reader of the chrome file a deck names. + * The reader of the templates file a deck names. */ - private readonly ChromeFile $chromeFiles; + private readonly TemplatesFile $templatesFiles; /** * The reader of a template's body. @@ -229,7 +231,7 @@ public function __construct( $this->files = new PathScope([$this->directory, ...$imageRoots]); $this->overflows = new Overflows($strict); $this->fonts = new FontReport($strict); - $this->chromeFiles = new ChromeFile($this->directory, $this->files); + $this->templatesFiles = new TemplatesFile($this->directory, $this->files); $this->chrome = new Chrome($this->blocks, $this->directory, $this->files); } @@ -332,7 +334,7 @@ public function render(Deck $deck, string $path): string // The templates before the slides are drawn, and the chrome before either: a slide // that names a template that is not there, and a template that cannot be drawn, are // both failures that happen with no file written behind them. - $this->furniture = new Furniture($deck, $this->chromeFiles, $this->chrome); + $this->furniture = new Furniture($deck, $this->templatesFiles, $this->chrome); $this->templates = $this->furniture->templates(); foreach ($deck->slides() as $slide) { diff --git a/src/Template/Templates.php b/src/Template/Templates.php index c559f41..7dbc3fb 100644 --- a/src/Template/Templates.php +++ b/src/Template/Templates.php @@ -11,7 +11,7 @@ * told apart by where they come from: the deck's own templates override the imported ones * of the same name. It is the rule the theme resolver applies by search order — the first * one found under a name is the one that is used — and it is here rather than in the - * resolver because a chrome file is not a theme and is not found by looking through + * resolver because a templates file is not a theme and is not found by looking through * directories: a deck names the one file it wants. */ final class Templates @@ -30,7 +30,7 @@ private function __construct(private readonly array $definitions) * that is left under a name both of them use. * * @param list $local The templates the deck defines. - * @param list $imported The templates a chrome file defines. + * @param list $imported The templates a templates file defines. */ public static function of(array $local, array $imported): self { diff --git a/src/Template/ChromeFile.php b/src/Template/TemplatesFile.php similarity index 73% rename from src/Template/ChromeFile.php rename to src/Template/TemplatesFile.php index b2d6efa..e5f8347 100644 --- a/src/Template/ChromeFile.php +++ b/src/Template/TemplatesFile.php @@ -4,24 +4,24 @@ namespace MarkdownPresentation\Template; -use MarkdownPresentation\Exception\ChromeNotFound; -use MarkdownPresentation\Exception\ChromeTooLarge; +use MarkdownPresentation\Exception\TemplatesFileNotFound; +use MarkdownPresentation\Exception\TemplatesFileTooLarge; use MarkdownPresentation\Filesystem\PathScope; /** - * The chrome file a deck names, read from beside the deck. + * The templates file a deck names, read from beside the deck. * * A path a deck writes, so it is resolved and held to the directories this render may * read — the same rule an image path has to pass, because both are paths a deck wrote and * neither is worth a way out of the directory the deck was given. */ -final class ChromeFile +final class TemplatesFile { /** - * The largest a chrome file may be. + * The largest a templates file may be. * - * A chrome file is the furniture of a deck — a handful of shapes for each of its - * templates — and a megabyte of it is far past any file of chrome. It is the one file + * A templates file is the furniture of a deck — a handful of shapes for each of its + * templates — and a megabyte of it is far past any file of furniture. It is the one file * this library reads whole, so this is what bounds the memory a deck's frontmatter can * ask for. */ @@ -39,21 +39,21 @@ public function __construct( } /** - * The Markdown of the chrome file a deck names. + * The Markdown of the templates file a deck names. * - * @throws ChromeNotFound - * @throws ChromeTooLarge + * @throws TemplatesFileNotFound + * @throws TemplatesFileTooLarge */ public function read(string $written): string { if (PathScope::isUrl($written)) { - throw ChromeNotFound::aUrl($written); + throw TemplatesFileNotFound::aUrl($written); } $joined = str_starts_with($written, '/') ? $written : rtrim($this->directory, '/') . '/' . $written; if (!is_file($joined)) { - throw ChromeNotFound::at($joined); + throw TemplatesFileNotFound::at($joined); } // `realpath()` rather than the path as written, because `..` and a symlink both walk @@ -61,7 +61,7 @@ public function read(string $written): string $resolved = PathScope::canonical($joined); if ($resolved === null || !$this->files->holds($resolved)) { - throw ChromeNotFound::outside($written, $resolved ?? $joined, $this->files->roots()); + throw TemplatesFileNotFound::outside($written, $resolved ?? $joined, $this->files->roots()); } // The read only happens where the file can be read: `file_get_contents()` warns @@ -76,11 +76,11 @@ public function read(string $written): string : false; if ($markdown === false) { - throw ChromeNotFound::at($resolved); + throw TemplatesFileNotFound::at($resolved); } if (strlen($markdown) > $this->maxBytes) { - throw ChromeTooLarge::of($written, $this->size($resolved, strlen($markdown)), $this->maxBytes); + throw TemplatesFileTooLarge::of($written, $this->size($resolved, strlen($markdown)), $this->maxBytes); } return $markdown; diff --git a/tests/Readme/examples-decks.php b/tests/Readme/examples-decks.php index 26f2eac..6aa9a7c 100644 --- a/tests/Readme/examples-decks.php +++ b/tests/Readme/examples-decks.php @@ -686,7 +686,7 @@ function shadowedNames(Pptx $pptx, int $slide = 1): array it('draws the imported template on the slide that names it, and on no other', function () { [$pptx] = builtDeck('16-templates.md'); - // The band is the one piece of furniture that came out of `templates/chrome.md` and + // The band is the one piece of furniture that came out of `templates/templates.md` and // was not overridden, so it is on the slide that names it and nowhere else — and it is // across the head of the slide, which is where the file puts it. foreach (range(1, $pptx->slideCount()) as $slide) { @@ -710,7 +710,7 @@ function shadowedNames(Pptx $pptx, int $slide = 1): array it('draws the furniture of the corporate template on every slide that names it', function () { [$pptx] = builtDeck('17-corporate-template.md'); - // The wordmark, the rule and the footer are three templates of the deck's own chrome + // The wordmark, the rule and the footer are three templates of the deck's own templates // file, and a slide names the ones it wants. The five light slides name all three; the // cover and the two dark slides name the light wordmark and nothing else — a cover has // no page number, and a dark slide has no footer on it. @@ -735,7 +735,7 @@ function shadowedNames(Pptx $pptx, int $slide = 1): array // The name is ink on a light page and white on a dark one, and the two are the same // named style with the colour laid over it — a deck cannot carry one colour on both - // kinds of slide, and a chrome file cannot decide for itself. + // kinds of slide, and a templates file cannot decide for itself. $light = runOfText($pptx, 'Halden Instruments', 2); $dark = runOfText($pptx, 'Halden Instruments', 7); diff --git a/tests/Unit/exceptions.php b/tests/Unit/exceptions.php index 7c13272..2c8dd6c 100644 --- a/tests/Unit/exceptions.php +++ b/tests/Unit/exceptions.php @@ -3,8 +3,6 @@ declare(strict_types=1); use MarkdownPresentation\Document\DeckParser; -use MarkdownPresentation\Exception\ChromeNotFound; -use MarkdownPresentation\Exception\ChromeTooLarge; use MarkdownPresentation\Exception\ContentOverflow; use MarkdownPresentation\Exception\Exception; use MarkdownPresentation\Exception\FencedFrontmatter; @@ -15,9 +13,12 @@ use MarkdownPresentation\Exception\MalformedFrontmatter; use MarkdownPresentation\Exception\MalformedShape; use MarkdownPresentation\Exception\MalformedTemplate; +use MarkdownPresentation\Exception\MalformedTemplatesFile; use MarkdownPresentation\Exception\MalformedTextStyle; use MarkdownPresentation\Exception\MalformedTheme; use MarkdownPresentation\Exception\NothingToConvert; +use MarkdownPresentation\Exception\TemplatesFileNotFound; +use MarkdownPresentation\Exception\TemplatesFileTooLarge; use MarkdownPresentation\Exception\ThemeNotFound; use MarkdownPresentation\Exception\TooManyShapes; use MarkdownPresentation\Exception\TooManySlides; @@ -96,8 +97,6 @@ function reportedExceptions(): array // The base is for everything; the one below it is for the failures a deck author // can fix by naming something else. $authorFixable = [ - ChromeNotFound::class, - ChromeTooLarge::class, ContentOverflow::class, FencedFrontmatter::class, ImageNotFound::class, @@ -105,8 +104,11 @@ function reportedExceptions(): array MalformedFrontmatter::class, MalformedShape::class, MalformedTemplate::class, + MalformedTemplatesFile::class, MalformedTextStyle::class, MalformedTheme::class, + TemplatesFileNotFound::class, + TemplatesFileTooLarge::class, ThemeNotFound::class, TooManyShapes::class, TooManySlides::class, diff --git a/tests/Unit/rendering.php b/tests/Unit/rendering.php index 47369bf..7c81579 100644 --- a/tests/Unit/rendering.php +++ b/tests/Unit/rendering.php @@ -1893,7 +1893,7 @@ function ico(): string ->toThrow( UnknownDirective::class, 'The frontmatter of slide 1 names "transition", which is not a directive. ' - . 'The directives are: title, name, level, layout, theme, author, description, template, chrome.', + . 'The directives are: title, name, level, layout, theme, author, description, template, templates-file.', ); }); diff --git a/tests/Unit/templates.php b/tests/Unit/templates.php index ff7356c..4120afc 100644 --- a/tests/Unit/templates.php +++ b/tests/Unit/templates.php @@ -5,7 +5,6 @@ use MarkdownPresentation\Document\DeckParser; use MarkdownPresentation\Document\Slide; use MarkdownPresentation\Exception\Exception as MarkdownException; -use MarkdownPresentation\Exception\MalformedChrome; use MarkdownPresentation\Exception\MalformedFrontmatter; use MarkdownPresentation\Exception\UnknownFont; use MarkdownPresentation\Exception\UnknownTemplate; @@ -13,7 +12,7 @@ use MarkdownPresentation\Render\PresentationRenderer; use MarkdownPresentation\Tests\Support\Pptx; use MarkdownPresentation\Tests\Support\Scratch; -use MarkdownPresentation\Template\ChromeFile; +use MarkdownPresentation\Template\TemplatesFile; /** * Slide templates: a piece of furniture written once and drawn on every slide that names it. @@ -387,10 +386,10 @@ function templateRenderer(string $markdown, bool $strict = false): PresentationR ->and($file->positionOf('image', 1))->not->toBe($file->positionOf('image', 2)); }); -it('imports the templates of a chrome file beside the deck', function () { - $chrome = Scratch::file('chrome.md', "---\ntemplate: brand\n---\n::line{left=5% top=72.889% width=30% height=0.185%}\n"); +it('imports the templates of a templates file beside the deck', function () { + $templates = Scratch::file('templates.md', "---\ntemplate: brand\n---\n::line{left=5% top=72.889% width=30% height=0.185%}\n"); - $deck = sprintf("---\nchrome: %s\nlayout: blank\n---\n\n---\nlayout: blank\ntemplate: brand\n---\n", $chrome); + $deck = sprintf("---\ntemplates-file: %s\nlayout: blank\n---\n\n---\nlayout: blank\ntemplate: brand\n---\n", $templates); $file = templateDeck($deck); @@ -399,11 +398,11 @@ function templateRenderer(string $markdown, bool $strict = false): PresentationR it('lets the deck\'s own template override an imported one of the same name', function () { // The same rule the theme resolver applies by search order: the deck's own wins. - $chrome = Scratch::file('chrome.md', "---\ntemplate: brand\n---\n::line{left=5% top=72.889% width=30% height=0.185%}\n"); + $templates = Scratch::file('templates.md', "---\ntemplate: brand\n---\n::line{left=5% top=72.889% width=30% height=0.185%}\n"); $deck = sprintf( - "---\nchrome: %s\nlayout: blank\n---\n\n---\ntemplate: brand\n---\n:::content{left=5%% top=5%% width=30%% height=5%%}\nDeck\n:::\n\n---\nlayout: blank\ntemplate: brand\n---\n", - $chrome, + "---\ntemplates-file: %s\nlayout: blank\n---\n\n---\ntemplate: brand\n---\n:::content{left=5%% top=5%% width=30%% height=5%%}\nDeck\n:::\n\n---\nlayout: blank\ntemplate: brand\n---\n", + $templates, ); $file = templateDeck($deck); @@ -411,76 +410,76 @@ function templateRenderer(string $markdown, bool $strict = false): PresentationR expect($file->shapeNames(2))->toBe(['content']); }); -it('refuses a chrome file that is not there', function () { - $deck = "---\nchrome: ./nowhere.md\nlayout: blank\n---\n"; +it('refuses a templates file that is not there', function () { + $deck = "---\ntemplates-file: ./nowhere.md\nlayout: blank\n---\n"; - expect(templateFailure($deck))->toContain('There is no chrome file at'); + expect(templateFailure($deck))->toContain('There is no templates file at'); }); -it('refuses a chrome file that is a URL', function () { - $deck = "---\nchrome: phar://chrome.md\nlayout: blank\n---\n"; +it('refuses a templates file that is a URL', function () { + $deck = "---\ntemplates-file: phar://templates.md\nlayout: blank\n---\n"; expect(templateFailure($deck))->toContain('is a URL rather than a path'); }); -it('refuses a chrome file that is larger than the library will read', function () { - $chrome = Scratch::file('chrome.md', str_repeat('a', ChromeFile::MAX_BYTES + 1)); +it('refuses a templates file that is larger than the library will read', function () { + $templates = Scratch::file('templates.md', str_repeat('a', TemplatesFile::MAX_BYTES + 1)); - $deck = sprintf("---\nchrome: %s\nlayout: blank\n---\n", $chrome); + $deck = sprintf("---\ntemplates-file: %s\nlayout: blank\n---\n", $templates); expect(templateFailure($deck)) ->toContain(sprintf( - 'is %d bytes, and a chrome file may be at most %d', - ChromeFile::MAX_BYTES + 1, - ChromeFile::MAX_BYTES, + 'is %d bytes, and a templates file may be at most %d', + TemplatesFile::MAX_BYTES + 1, + TemplatesFile::MAX_BYTES, )); }); -it('refuses a chrome file this render may not read', function () { - $chrome = Scratch::file('chrome.md', "---\ntemplate: brand\n---\n::line{}\n"); - $outside = sys_get_temp_dir() . '/chrome-' . bin2hex(random_bytes(6)) . '.md'; +it('refuses a templates file this render may not read', function () { + $templates = Scratch::file('templates.md', "---\ntemplate: brand\n---\n::line{}\n"); + $outside = sys_get_temp_dir() . '/templates-' . bin2hex(random_bytes(6)) . '.md'; file_put_contents($outside, "---\ntemplate: brand\n---\n::line{}\n"); - $deck = sprintf("---\nchrome: %s\nlayout: blank\n---\n", $outside); + $deck = sprintf("---\ntemplates-file: %s\nlayout: blank\n---\n", $outside); expect(templateFailure($deck))->toContain('rather than one this render may read'); unlink($outside); }); -it('refuses a chrome file that holds a slide', function () { - $chrome = Scratch::file('chrome.md', "# A slide\n"); +it('refuses a templates file that holds a slide', function () { + $templates = Scratch::file('templates.md', "# A slide\n"); - $deck = sprintf("---\nchrome: %s\nlayout: blank\n---\n", $chrome); + $deck = sprintf("---\ntemplates-file: %s\nlayout: blank\n---\n", $templates); expect(templateFailure($deck))->toContain('holds a slide that is not a template definition'); }); -it('refuses a chrome file it cannot read', function () { +it('refuses a templates file it cannot read', function () { skipWithoutPermissions('The unreadable file'); - $chrome = Scratch::file('chrome.md', "---\ntemplate: brand\n---\n::line{}\n"); + $templates = Scratch::file('templates.md', "---\ntemplate: brand\n---\n::line{}\n"); - chmod($chrome, 0o000); + chmod($templates, 0o000); - $deck = sprintf("---\nchrome: %s\nlayout: blank\n---\n", $chrome); + $deck = sprintf("---\ntemplates-file: %s\nlayout: blank\n---\n", $templates); - expect(templateFailure($deck))->toContain('There is no chrome file at'); + expect(templateFailure($deck))->toContain('There is no templates file at'); }); -it('refuses a chrome file named on a later slide', function () { - $deck = "---\nlayout: blank\n---\n\n---\nchrome: ./chrome.md\n---\n"; +it('refuses a templates file named on a later slide', function () { + $deck = "---\nlayout: blank\n---\n\n---\ntemplates-file: ./templates.md\n---\n"; expect(templateFailure($deck)) - ->toContain('The frontmatter of slide 2 names "chrome", which is a deck directive'); + ->toContain('The frontmatter of slide 2 names "templates-file", which is a deck directive'); }); -it('refuses a chrome file that is not a path', function () { - $deck = "---\nchrome: 42\nlayout: blank\n---\n"; +it('refuses a templates file that is not a path', function () { + $deck = "---\ntemplates-file: 42\nlayout: blank\n---\n"; expect(templateFailure($deck)) - ->toContain('The frontmatter of slide 1 has a "chrome" that is not a path to a file of chrome'); + ->toContain('The frontmatter of slide 1 has a "templates-file" that is not a path to a file of templates'); }); it('refuses a template that is named by something other than a name', function () {