Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
Emphasis.php
001 <?php
002
003 /**
004 * @package s9e\TextFormatter
005 * @copyright Copyright (c) 2010-2022 The s9e authors
006 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
007 */
008 namespace s9e\TextFormatter\Plugins\Litedown\Parser\Passes;
009
010 class Emphasis extends AbstractPass
011 {
012 /**
013 * @var bool Whether current EM span is being closed by current emphasis mark
014 */
015 protected $closeEm;
016
017 /**
018 * @var bool Whether current EM span is being closed by current emphasis mark
019 */
020 protected $closeStrong;
021
022 /**
023 * @var integer Starting position of the current EM span in the text
024 */
025 protected $emPos;
026
027 /**
028 * @var integer Ending position of the current EM span in the text
029 */
030 protected $emEndPos;
031
032 /**
033 * @var integer Number of emphasis characters unused in current span
034 */
035 protected $remaining;
036
037 /**
038 * @var integer Starting position of the current STRONG span in the text
039 */
040 protected $strongPos;
041
042 /**
043 * @var integer Ending position of the current STRONG span in the text
044 */
045 protected $strongEndPos;
046
047 /**
048 * {@inheritdoc}
049 */
050 public function parse()
051 {
052 $this->parseEmphasisByCharacter('*', '/\\*+/');
053 $this->parseEmphasisByCharacter('_', '/_+/');
054 }
055
056 /**
057 * Adjust the ending position of current EM and STRONG spans
058 *
059 * @return void
060 */
061 protected function adjustEndingPositions()
062 {
063 if ($this->closeEm && $this->closeStrong)
064 {
065 if ($this->emPos < $this->strongPos)
066 {
067 $this->emEndPos += 2;
068 }
069 else
070 {
071 ++$this->strongEndPos;
072 }
073 }
074 }
075
076 /**
077 * Adjust the starting position of current EM and STRONG spans
078 *
079 * If both EM and STRONG are set to start at the same position, we adjust their position
080 * to match the order they are closed. If they start and end at the same position, STRONG
081 * starts before EM to match Markdown's behaviour
082 *
083 * @return void
084 */
085 protected function adjustStartingPositions()
086 {
087 if ($this->emPos >= 0 && $this->emPos === $this->strongPos)
088 {
089 if ($this->closeEm)
090 {
091 $this->emPos += 2;
092 }
093 else
094 {
095 ++$this->strongPos;
096 }
097 }
098 }
099
100 /**
101 * End current valid EM and STRONG spans
102 *
103 * @return void
104 */
105 protected function closeSpans()
106 {
107 if ($this->closeEm)
108 {
109 --$this->remaining;
110 $this->parser->addTagPair('EM', $this->emPos, 1, $this->emEndPos, 1);
111 $this->emPos = -1;
112 }
113 if ($this->closeStrong)
114 {
115 $this->remaining -= 2;
116 $this->parser->addTagPair('STRONG', $this->strongPos, 2, $this->strongEndPos, 2);
117 $this->strongPos = -1;
118 }
119 }
120
121 /**
122 * Parse emphasis and strong applied using given character
123 *
124 * @param string $character Markup character, either * or _
125 * @param string $regexp Regexp used to match the series of emphasis character
126 * @return void
127 */
128 protected function parseEmphasisByCharacter($character, $regexp)
129 {
130 $pos = $this->text->indexOf($character);
131 if ($pos === false)
132 {
133 return;
134 }
135
136 foreach ($this->getEmphasisByBlock($regexp, $pos) as $block)
137 {
138 $this->processEmphasisBlock($block);
139 }
140 }
141
142 /**
143 * Get emphasis markup split by block
144 *
145 * @param string $regexp Regexp used to match emphasis
146 * @param integer $pos Position in the text of the first emphasis character
147 * @return array[] Each array contains a list of [matchPos, matchLen] pairs
148 */
149 protected function getEmphasisByBlock($regexp, $pos)
150 {
151 $block = [];
152 $blocks = [];
153 $breakPos = $this->text->indexOf("\x17", $pos);
154
155 preg_match_all($regexp, $this->text, $matches, PREG_OFFSET_CAPTURE, $pos);
156 foreach ($matches[0] as $m)
157 {
158 $matchPos = $m[1];
159 $matchLen = strlen($m[0]);
160
161 // Test whether we've just passed the limits of a block
162 if ($matchPos > $breakPos)
163 {
164 $blocks[] = $block;
165 $block = [];
166 $breakPos = $this->text->indexOf("\x17", $matchPos);
167 }
168
169 // Test whether we should ignore this markup
170 if (!$this->ignoreEmphasis($matchPos, $matchLen))
171 {
172 $block[] = [$matchPos, $matchLen];
173 }
174 }
175 $blocks[] = $block;
176
177 return $blocks;
178 }
179
180 /**
181 * Test whether emphasis should be ignored at the given position in the text
182 *
183 * @param integer $matchPos Position of the emphasis in the text
184 * @param integer $matchLen Length of the emphasis
185 * @return bool
186 */
187 protected function ignoreEmphasis($matchPos, $matchLen)
188 {
189 // Ignore single underscores between alphanumeric characters
190 return ($this->text->charAt($matchPos) === '_' && $matchLen === 1 && $this->text->isSurroundedByAlnum($matchPos, $matchLen));
191 }
192
193 /**
194 * Open EM and STRONG spans whose content starts at given position
195 *
196 * @param integer $pos
197 * @return void
198 */
199 protected function openSpans($pos)
200 {
201 if ($this->remaining & 1)
202 {
203 $this->emPos = $pos - $this->remaining;
204 }
205 if ($this->remaining & 2)
206 {
207 $this->strongPos = $pos - $this->remaining;
208 }
209 }
210
211 /**
212 * Process a list of emphasis markup strings
213 *
214 * @param array[] $block List of [matchPos, matchLen] pairs
215 * @return void
216 */
217 protected function processEmphasisBlock(array $block)
218 {
219 $this->emPos = -1;
220 $this->strongPos = -1;
221 foreach ($block as list($matchPos, $matchLen))
222 {
223 $this->processEmphasisMatch($matchPos, $matchLen);
224 }
225 }
226
227 /**
228 * Process an emphasis mark
229 *
230 * @param integer $matchPos
231 * @param integer $matchLen
232 * @return void
233 */
234 protected function processEmphasisMatch($matchPos, $matchLen)
235 {
236 $canOpen = !$this->text->isBeforeWhitespace($matchPos + $matchLen - 1);
237 $canClose = !$this->text->isAfterWhitespace($matchPos);
238 $closeLen = ($canClose) ? min($matchLen, 3) : 0;
239
240 $this->closeEm = ($closeLen & 1) && $this->emPos >= 0;
241 $this->closeStrong = ($closeLen & 2) && $this->strongPos >= 0;
242 $this->emEndPos = $matchPos;
243 $this->strongEndPos = $matchPos;
244 $this->remaining = $matchLen;
245
246 $this->adjustStartingPositions();
247 $this->adjustEndingPositions();
248 $this->closeSpans();
249
250 // Adjust the length of unused markup remaining in current match
251 $this->remaining = ($canOpen) ? min($this->remaining, 3) : 0;
252 $this->openSpans($matchPos + $matchLen);
253 }
254 }