* 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; } }