What's on this page
Markdown
Cecil supports Markdown format, but also Markdown Extra.
Cecil also provides extra features to enhance your content, see below.
Attributes
With Markdown Extra you can set an id, class and custom attributes on certain elements using an attribute block.
For instance, put the desired attribute(s) after a heading, a fenced code block, a link or an image at the end of the line inside curly brackets, like this:
## Header {#id .class attribute=value}
Links
You can create a link with the syntax [Text](url), where url can be a path, a relative path to a Markdown file, an external URL, etc.
Example:
[Link to a path](/about/)
[Link to a Markdown file](about.md)
[Link to Cecil website](https://cecil.app)
Link to a page
You can easily create a link to a page with the syntax [Page title](page:page-id).
Example:
[Link to a blog post](page:blog/post-1)
External
By default external links have the following value for rel attribute: noopener noreferrer.
Example:
<a href="<url>" rel="noopener noreferrer">Link to another website</a>
You can change this behavior with pages.body.links.external options.
Embedded links
Cecil can try to turn a link into embedded content by using the {embed} attribute or by setting the global configuration option pages.body.links.embed.enabled to true.
Example:
[CECIL : LE générateur de SITES STATIQUES en PHP](https://www.youtube.com/watch?v=ur8koU0iYvc){embed}
Local video/audio files
Cecil can also create <video> and <audio> HTML elements, based on the file extension (mp4 and webm for video, mp3, ogg and wav for audio, see pages.body.links.embed).
Example:
[Video file](video.mp4){embed controls poster=/images/video-test.png}
[Audio file](song.mp3){embed controls}
Is converted to:
<video src="/video.mp4" controls poster="/images/video-test.png" style="max-width:100%;height:auto;background-color:#d8d8d8;"></video>
<audio src="/song.mp3" controls></audio>
With {embed=false} (or when embedding is disabled), a local video/audio file stays a link, but its URL points to the published file (fingerprinted if assets.fingerprint is enabled).
Images
To add an image, use an exclamation mark (!) followed by an alternative description in brackets ([]), and the path or URL to the image in parentheses (()).
You can optionally add a title in quotation marks.

Lazy loading
Cecil adds the attribute loading="lazy" to each image.
Example:

Is converted to:
<img src="/image.jpg" loading="lazy">
Decoding
Cecil adds the attribute decoding="async" to each image.
Example:

Is converted to:
<img src="/image.jpg" decoding="async">
Resize
Each image in the body can be resized automatically by setting a smaller width than the original one, with the extra attribute {width=X}.
Example:
{width=800}
Is converted to:
<img src="/thumbnails/800/image.jpg" width="800" height="600">
Formats
If the formats option is defined, alternative images are created and added.
Example:

Could be converted to:
<picture>
<source srcset="/image.avif" type="image/avif">
<source srcset="/image.webp" type="image/webp">
<img src="/image.jpg">
</picture>
Responsive
If the responsive option is enabled, then all images in the body will be made responsive automatically.
Example:
{width=800}
will be converted to:
<img src="/thumbnails/800/image.jpg" width="800" height="600"
srcset="/thumbnails/480/image.jpg 480w,
/thumbnails/640/image.jpg 640w,
/thumbnails/768/image.jpg 768w,
/thumbnails/800/image.jpg 800w"
sizes="100vw"
>
The sizes attribute takes the value of the assets.images.responsive.sizes.default configuration option, but it can be changed by creating a new entry named after a class added to the image.
Example:
assets:
images:
responsive:
sizes:
default: 100vw
my_class: "(max-width: 800px) 768px, 1024px"
{.my_class}
CSS class
You can set a default value to the class attribute of each image with the class option.
Caption
The optional title can be used to create a caption (figcaption) automatically by enabling the caption option.
Example:

Is converted to:
<figure>
<img src="/image.jpg" title="Title">
<figcaption>Title</figcaption>
</figure>
Localized image
For translated pages, Cecil first looks for a language-suffixed file when resolving Markdown image paths.
Example:

With a French page (fr), Cecil tries /images/cecil-logo.fr.png first, then falls back to /images/cecil-logo.png.
Dark and mobile variants
If the dark_suffix option is defined (e.g.: .dark), Cecil looks for a dark variant of each image (e.g.: image.dark.jpg alongside image.jpg) and adds it as a <source media="(prefers-color-scheme: dark)"> in a <picture> element.
In the same way, if the mobile_suffix option is defined (e.g.: .mobile), Cecil looks for a mobile variant of each image (e.g.: image.mobile.jpg) and adds it as a <source> with the mobile_media_query media query.
Placeholder
As images are typically heavier and slower resources, and they don’t block rendering, we should attempt to give users something to look at while they wait for the image to arrive.
The placeholder attribute accepts two options:
color: display a colored background (based on image dominant color)lqip: Low-Quality Image Placeholder
Examples:
{placeholder=color}
{placeholder=lqip}
Heading anchors
An anchor link is added at the end of h2 and h3 headings (see the pages.body.anchors option), to link to a heading of a page:
<h2 id="heading">Heading<a class="heading-anchor" href="#heading" aria-hidden="true" tabindex="-1"></a></h2>
The link is empty: the default templates display a # on hover.
Table of contents
You can add a table of contents with the following Markdown syntax:
[toc]
Excerpt
An excerpt can be defined in the body with one of the following HTML comments: <!-- excerpt --> or <!-- break --> (see the pages.body.excerpt option).
Example:
Introduction.
<!-- excerpt -->
Main content.
Then use the excerpt_html filter in your template.
Notes
Create a Note block (info, tip, important, etc.).
Example:
:::tip
**Tip:** This is advice.
:::
Is converted to:
<aside class="note note-tip">
<p>
<strong>Tip:</strong> This is advice.
</p>
</aside>
Other examples:
Nested notes
A note is closed by a line made of at least as many : as its opening line: to nest notes, use a longer fence for the parent note (::::, then ::::: for a third level, etc.).
::::info
Before.
:::tip
**Tip:** This is advice.
:::
After.
::::
A longer fence also lets you show the note syntax in a code block, inside a note.
Templates
A note is rendered with the partials/notes/<type>.html.twig template, if it exists (in the site layouts/, in a theme or built-in), instead of the <aside> element.
Cecil provides templates for the following types, rendered without JavaScript: a theme can style them, override them and add interactivity. Unlike other notes, their root element is a <div class="note note-<type>"> (not an <aside>), as their content is part of the main content.
| Type | Items | Rendering |
|---|---|---|
tabs |
one per #### heading |
stacked panels (<section class="note-tab">) |
code-group |
one per #### heading, or one per code block (titled with its language) |
same as tabs |
steps |
one per #### heading |
ordered list (<ol class="note-steps-list">) |
accordion |
one per #### heading |
<details class="note-accordion-item"> |
cards |
one per list entry (a leading link is the card title), or per #### heading |
list (<ul class="note-cards-list">) |
The examples below are themselves nested notes: a tabs note (with a :::: fence) shows the Markdown source and its rendering.
Tabs
Alternative contents, one per #### heading (e.g.: per operating system).
Markdown
:::tabs
#### macOS and Linux
```bash
brew install cecilapp/tap/cecil
```
#### Windows
```bash
scoop install https://cecil.app/scoop/cecil.json
```
:::
Result
macOS and Linux
brew install cecilapp/tap/cecil
Windows
scoop install https://cecil.app/scoop/cecil.json
Code group
Like tabs, with code blocks only: without heading, each code block is titled with its language.
Markdown
:::code-group
```bash
curl -LO https://cecil.app/cecil.phar
```
```powershell
Invoke-WebRequest https://cecil.app/cecil.phar -OutFile cecil.phar
```
:::
Result
bash
curl -LO https://cecil.app/cecil.phar
powershell
Invoke-WebRequest https://cecil.app/cecil.phar -OutFile cecil.phar
Steps
A numbered procedure, one step per #### heading.
Markdown
:::steps
#### Create a site
```bash
php cecil.phar new:site
```
#### Preview it
```bash
php cecil.phar serve
```
:::
Result
-
Create a site
php cecil.phar new:site -
Preview it
php cecil.phar serve
Accordion
Collapsible items, one per #### heading (e.g.: a FAQ).
Markdown
:::accordion
#### Is PHP required?
No: the standalone binary embeds PHP.
#### Where is the generated site?
In the `_site` directory.
:::
Result
Is PHP required?
No: the standalone binary embeds PHP.
Where is the generated site?
In the _site directory.
Cards
Links to other pages, one card per list entry: a leading link is the card title.
Markdown
:::cards
- [Installation](../getting-started/2-installation.md): download and install Cecil.
- [Configuration](../configuration/index.md): configure your site.
:::
Result
-
download and install Cecil.
-
configure your site.
Custom template
The template receives a note variable:
note.type: note type (e.g.:tabs)note.id: unique ID in the page (e.g.:note-tabs-1)note.content: HTML of the whole notenote.intro: HTML of the content before the first####headingnote.items: list of items, each with:title: title (HTML)heading: heading element (HTML), with itsidattributeid: heading ID, if anylink: leading link element (HTML) of a list entryurl: leading link URL of a list entrylanguage: language of a code blockcontent: content (HTML)
To override the rendering of a note type, create the template in your site (or theme), for example layouts/partials/notes/tip.html.twig:
<div class="callout callout-{{ note.type }}">
{{ note.content|raw }}
</div>
Notes are rendered when Markdown is converted, before pages rendering: a note template has access to the note variable and to translations (in the page language), but not to page or site.
Syntax highlight
Code block syntax highlighting is enabled by default with the pages.body.highlight option.
If needed, you can disable it with:
pages:
body:
highlight: false
Example:
```php echo "Hello world"; ```
Is rendered to:
echo "Hello world";
You can customize the syntax highlighting style by creating your own theme. See the Highlight.js Theme Guide.
You can also use tempest/highlight instead of highlight.js with the pages.body.highlight.engine option. It's faster, but supports fewer languages. It uses hl-* CSS classes: see the tempest/highlight themes.
The language of a code block is added to the data-lang attribute of the <pre> element (e.g.: <pre data-lang="php">): the default templates display it as a label.
Inserted text
Represents a range of text that has been added.
++text++
Is converted to:
<ins>text</ins>