1<?php
2
3/*
4 * This file is part of the league/commonmark package.
5 *
6 * (c) Colin O'Dell <colinodell@gmail.com>
7 *
8 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
9 *  - (c) John MacFarlane
10 *
11 * Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
12 *  - (c) Atlassian Pty Ltd
13 *
14 * For the full copyright and license information, please view the LICENSE
15 * file that was distributed with this source code.
16 */
17
18namespace League\CommonMark\Delimiter\Processor;
19
20use League\CommonMark\Delimiter\DelimiterInterface;
21use League\CommonMark\Inline\Element\AbstractStringContainer;
22use League\CommonMark\Inline\Element\Emphasis;
23use League\CommonMark\Inline\Element\Strong;
24use League\CommonMark\Util\ConfigurationAwareInterface;
25use League\CommonMark\Util\ConfigurationInterface;
26
27final class EmphasisDelimiterProcessor implements DelimiterProcessorInterface, ConfigurationAwareInterface
28{
29    /** @var string */
30    private $char;
31
32    /** @var ConfigurationInterface|null */
33    private $config;
34
35    /**
36     * @param string $char The emphasis character to use (typically '*' or '_')
37     */
38    public function __construct(string $char)
39    {
40        $this->char = $char;
41    }
42
43    public function getOpeningCharacter(): string
44    {
45        return $this->char;
46    }
47
48    public function getClosingCharacter(): string
49    {
50        return $this->char;
51    }
52
53    public function getMinLength(): int
54    {
55        return 1;
56    }
57
58    public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int
59    {
60        // "Multiple of 3" rule for internal delimiter runs
61        if (($opener->canClose() || $closer->canOpen()) && $closer->getOriginalLength() % 3 !== 0 && ($opener->getOriginalLength() + $closer->getOriginalLength()) % 3 === 0) {
62            return 0;
63        }
64
65        // Calculate actual number of delimiters used from this closer
66        if ($opener->getLength() >= 2 && $closer->getLength() >= 2) {
67            if ($this->enableStrong()) {
68                return 2;
69            }
70
71            return 0;
72        }
73
74        if ($this->enableEm()) {
75            return 1;
76        }
77
78        return 0;
79    }
80
81    public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse)
82    {
83        if ($delimiterUse === 1) {
84            $emphasis = new Emphasis();
85        } elseif ($delimiterUse === 2) {
86            $emphasis = new Strong();
87        } else {
88            return;
89        }
90
91        $next = $opener->next();
92        while ($next !== null && $next !== $closer) {
93            $tmp = $next->next();
94            $emphasis->appendChild($next);
95            $next = $tmp;
96        }
97
98        $opener->insertAfter($emphasis);
99    }
100
101    public function setConfiguration(ConfigurationInterface $configuration)
102    {
103        $this->config = $configuration;
104    }
105
106    private function enableStrong(): bool
107    {
108        if ($this->config === null) {
109            return false;
110        }
111
112        $deprecatedEnableStrong = $this->config->get('enable_strong', ConfigurationInterface::MISSING);
113        if ($deprecatedEnableStrong !== ConfigurationInterface::MISSING) {
114            @\trigger_error('The "enable_strong" configuration option is deprecated in league/commonmark 1.6 and will be replaced with "commonmark > enable_strong" in 2.0', \E_USER_DEPRECATED);
115        } else {
116            $deprecatedEnableStrong = true;
117        }
118
119        return $this->config->get('commonmark/enable_strong', $deprecatedEnableStrong);
120    }
121
122    private function enableEm(): bool
123    {
124        if ($this->config === null) {
125            return false;
126        }
127
128        $deprecatedEnableEm = $this->config->get('enable_em', ConfigurationInterface::MISSING);
129        if ($deprecatedEnableEm !== ConfigurationInterface::MISSING) {
130            @\trigger_error('The "enable_em" configuration option is deprecated in league/commonmark 1.6 and will be replaced with "commonmark > enable_em" in 2.0', \E_USER_DEPRECATED);
131        } else {
132            $deprecatedEnableEm = true;
133        }
134
135        return $this->config->get('commonmark/enable_em', $deprecatedEnableEm);
136    }
137}
138