1<?php
2
3/*
4 * This file is part of the league/commonmark package.
5 *
6 * (c) Colin O'Dell <colinodell@gmail.com>
7 * (c) Rezo Zero / Ambroise Maupate
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13declare(strict_types=1);
14
15namespace League\CommonMark\Extension\Footnote\Parser;
16
17use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
18use League\CommonMark\Inline\Parser\InlineParserInterface;
19use League\CommonMark\InlineParserContext;
20use League\CommonMark\Normalizer\SlugNormalizer;
21use League\CommonMark\Normalizer\TextNormalizerInterface;
22use League\CommonMark\Reference\Reference;
23use League\CommonMark\Util\ConfigurationAwareInterface;
24use League\CommonMark\Util\ConfigurationInterface;
25
26final class AnonymousFootnoteRefParser implements InlineParserInterface, ConfigurationAwareInterface
27{
28    /** @var ConfigurationInterface */
29    private $config;
30
31    /** @var TextNormalizerInterface */
32    private $slugNormalizer;
33
34    public function __construct()
35    {
36        $this->slugNormalizer = new SlugNormalizer();
37    }
38
39    public function getCharacters(): array
40    {
41        return ['^'];
42    }
43
44    public function parse(InlineParserContext $inlineContext): bool
45    {
46        $container = $inlineContext->getContainer();
47        $cursor = $inlineContext->getCursor();
48        $nextChar = $cursor->peek();
49        if ($nextChar !== '[') {
50            return false;
51        }
52        $state = $cursor->saveState();
53
54        $m = $cursor->match('/\^\[[^\n^\]]+\]/');
55        if ($m !== null) {
56            if (\preg_match('#\^\[([^\]]+)\]#', $m, $matches) > 0) {
57                $reference = $this->createReference($matches[1]);
58                $container->appendChild(new FootnoteRef($reference, $matches[1]));
59
60                return true;
61            }
62        }
63
64        $cursor->restoreState($state);
65
66        return false;
67    }
68
69    private function createReference(string $label): Reference
70    {
71        $refLabel = $this->slugNormalizer->normalize($label);
72        $refLabel = \mb_substr($refLabel, 0, 20);
73
74        return new Reference(
75            $refLabel,
76            '#' . $this->config->get('footnote/footnote_id_prefix', 'fn:') . $refLabel,
77            $label
78        );
79    }
80
81    public function setConfiguration(ConfigurationInterface $config): void
82    {
83        $this->config = $config;
84    }
85}
86