Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions docs/2.x/extensions/footnotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ Result:
</div>
```

### Inline footnotes

Inline footnotes (or anonymous footnotes) are easier to write, since you don't have to pick an identifier and move down to type the note. They have a slightly different syntax, with the caret placed before the opening square bracket: `^[Note]`. Inline footnotes do not support multiple paragraphs.

Sample Markdown input:

```markdown
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi^[Elit Malesuada Ridiculus] leo risus, porta ac consectetur ac.
```

Result:

```html
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi<sup id="fnref:elit-malesuada-ridic"><a class="footnote-ref" href="#fn:elit-malesuada-ridic" role="doc-noteref">1</a></sup> leo risus, porta ac consectetur ac.
</p>
<div class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li class="footnote" id="fn:elit-malesuada-ridic" role="doc-endnote">
<p>
Elit Malesuada Ridiculus&nbsp;<a class="footnote-backref" rev="footnote" href="#fnref:elit-malesuada-ridic" role="doc-backlink">↩</a>
</p>
</li>
</ol>
</div>
```

## Usage

Configure your `Environment` as usual and simply add the `FootnoteExtension`:
Expand All @@ -74,14 +102,15 @@ use League\CommonMark\MarkdownConverter;
// If you're happy with the defaults, feel free to remove them from this array
$config = [
'footnote' => [
'backref_class' => 'footnote-backref',
'backref_symbol' => '↩',
'container_add_hr' => true,
'container_class' => 'footnotes',
'ref_class' => 'footnote-ref',
'ref_id_prefix' => 'fnref:',
'footnote_class' => 'footnote',
'footnote_id_prefix' => 'fn:',
'backref_class' => 'footnote-backref',
'backref_symbol' => '↩',
'container_add_hr' => true,
'container_class' => 'footnotes',
'enable_inline_footnotes' => true,
'ref_class' => 'footnote-ref',
'ref_id_prefix' => 'fnref:',
'footnote_class' => 'footnote',
'footnote_id_prefix' => 'fn:',
],
];

Expand Down
8 changes: 6 additions & 2 deletions src/Extension/Footnote/FootnoteExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public function configureSchema(ConfigurationBuilderInterface $builder): void
'backref_symbol' => Expect::string('↩'),
'container_add_hr' => Expect::bool(true),
'container_class' => Expect::string('footnotes'),
'enable_inline_footnotes' => Expect::bool(true),
'ref_class' => Expect::string('footnote-ref'),
'ref_id_prefix' => Expect::string('fnref:'),
'footnote_class' => Expect::string('footnote'),
Expand All @@ -53,16 +54,19 @@ public function configureSchema(ConfigurationBuilderInterface $builder): void

public function register(EnvironmentBuilderInterface $environment): void
{
if ($environment->getConfiguration()->get('footnote/enable_inline_footnotes')) {
$environment->addInlineParser(new AnonymousFootnoteRefParser(), 35);
$environment->addEventListener(DocumentParsedEvent::class, [new AnonymousFootnotesListener(), 'onDocumentParsed'], 40);
}

$environment->addBlockStartParser(new FootnoteStartParser(), 51);
$environment->addInlineParser(new AnonymousFootnoteRefParser(), 35);
$environment->addInlineParser(new FootnoteRefParser(), 51);

$environment->addRenderer(FootnoteContainer::class, new FootnoteContainerRenderer());
$environment->addRenderer(Footnote::class, new FootnoteRenderer());
$environment->addRenderer(FootnoteRef::class, new FootnoteRefRenderer());
$environment->addRenderer(FootnoteBackref::class, new FootnoteBackrefRenderer());

$environment->addEventListener(DocumentParsedEvent::class, [new AnonymousFootnotesListener(), 'onDocumentParsed'], 40);
$environment->addEventListener(DocumentParsedEvent::class, [new FixOrphanedFootnotesAndRefsListener(), 'onDocumentParsed'], 30);
$environment->addEventListener(DocumentParsedEvent::class, [new NumberFootnotesListener(), 'onDocumentParsed'], 20);
$environment->addEventListener(DocumentParsedEvent::class, [new GatherFootnotesListener(), 'onDocumentParsed'], 10);
Expand Down
18 changes: 10 additions & 8 deletions tests/functional/Extension/Footnote/FootnoteExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,16 @@ public function testFootnotesWithCustomOptions(string $input, string $expected):
{
$environment = new Environment([
'footnote' => [
'backref_class' => 'custom-backref',
'backref_class' => 'custom-backref',
// Ensure multiple characters are allowed (including multibyte) and special HTML characters are escaped.
'backref_symbol' => '↩ 🦄️ <3 You',
'container_add_hr' => false,
'container_class' => 'custom-notes',
'ref_class' => 'custom-ref',
'ref_id_prefix' => 'fnref:',
'footnote_class' => 'custom-footnote',
'footnote_id_prefix' => 'fn:',
'backref_symbol' => '↩ 🦄️ <3 You',
'container_add_hr' => false,
'container_class' => 'custom-notes',
'enable_inline_footnotes' => false,
'ref_class' => 'custom-ref',
'ref_id_prefix' => 'fnref:',
'footnote_class' => 'custom-footnote',
'footnote_id_prefix' => 'fn:',
],
]);
$environment->addExtension(new CommonMarkCoreExtension());
Expand All @@ -89,6 +90,7 @@ public static function dataProviderForTestFootnotesWithCustomOptions(): \Generat
{
yield ["Here[^note1]\n\n[^note1]: There", '<p>Here<sup id="fnref:note1"><a class="custom-ref" href="#fn:note1" role="doc-noteref">1</a></sup></p>' . "\n" . '<div class="custom-notes" role="doc-endnotes"><ol><li class="custom-footnote" id="fn:note1" role="doc-endnote"><p>There&nbsp;<a class="custom-backref" rev="footnote" href="#fnref:note1" role="doc-backlink">↩ 🦄️ &lt;3 You</a></p></li></ol></div>'];
yield ["_Here_[^note1]\n\n[^note1]: **There**", '<p><em>Here</em><sup id="fnref:note1"><a class="custom-ref" href="#fn:note1" role="doc-noteref">1</a></sup></p>' . "\n" . '<div class="custom-notes" role="doc-endnotes"><ol><li class="custom-footnote" id="fn:note1" role="doc-endnote"><p><strong>There</strong>&nbsp;<a class="custom-backref" rev="footnote" href="#fnref:note1" role="doc-backlink">↩ 🦄️ &lt;3 You</a></p></li></ol></div>'];
yield ['Disabled inline notes^[note1]', '<p>Disabled inline notes^[note1]</p>'];
}

public function testFootnotesWithEmptySymbol(): void
Expand Down