* element) and the body is emitted through the unformatted handler
* rather than plain cdata, so renderers that distinguish the two
* (metadata, indexer, non-XHTML backends) treat it as literal.
*
* The entry pattern's lookahead only verifies three things: an opener,
* at least one body character, and a valid closer. It does NOT enforce
* non-whitespace body edges or a non-whitespace body interior. GFM's
* edge rules are applied in handle() after the body has been extracted:
*
* 1. Line endings become single spaces.
* 2. If the body both starts and ends with a space, and is not
* entirely whitespace, one space is stripped from each end.
*
* This lets the regex stay small while still producing GFM-correct
* output for the tricky cases:
*
* ` ` -> (all-whitespace body, no strip)
* ` a` -> a (asymmetric edge, no strip)
* ` `` ` -> `` (run of 2 inside body, strip)
*
* Runs of two or more backticks on either delimiter are rejected by
* the length-boundary guards (?allowedModes = [];
}
/** @inheritdoc */
public function getSort()
{
return 165;
}
/** The lexer state / mode name. Subclasses override for n≥2. */
protected function getModeName(): string
{
return 'gfm_backtick_single';
}
/**
* Entry pattern. The length-boundary guards (?Lexer->addEntryPattern(
$this->getEntryPattern(),
$mode,
$this->getModeName()
);
}
/** @inheritdoc */
public function postConnect()
{
$this->Lexer->addExitPattern($this->getExitPattern(), $this->getModeName());
}
/** @inheritdoc */
public function handle($match, $state, $pos, Handler $handler)
{
match ($state) {
DOKU_LEXER_ENTER => $handler->addCall('monospace_open', [], $pos),
DOKU_LEXER_EXIT => $handler->addCall('monospace_close', [], $pos),
DOKU_LEXER_UNMATCHED => $handler->addCall(
'unformatted',
[$this->normalizeBody($match)],
$pos
),
default => true,
};
return true;
}
/**
* GFM code-span body normalization: newlines become spaces; if both
* ends are spaces and the body isn't entirely whitespace, strip one
* space from each end.
*/
protected function normalizeBody(string $body): string
{
$body = str_replace(["\r\n", "\r", "\n"], ' ', $body);
if (
strlen($body) >= 2
&& $body[0] === ' '
&& $body[-1] === ' '
&& trim($body) !== ''
) {
$body = substr($body, 1, -1);
}
return $body;
}
}