updated streamline-setup v2

This commit is contained in:
2025-01-15 08:53:49 -08:00
committed by alec.turner
parent a2ce9248f0
commit 4b569f81b0
20228 changed files with 2932048 additions and 63204 deletions
@@ -15,6 +15,7 @@ namespace League\CommonMark\Parser\Block;
use League\CommonMark\Node\Block\AbstractBlock;
use League\CommonMark\Node\Block\Document;
use League\CommonMark\Node\Block\Paragraph;
use League\CommonMark\Parser\Cursor;
use League\CommonMark\Reference\ReferenceMapInterface;
@@ -50,4 +51,30 @@ final class DocumentBlockParser extends AbstractBlockContinueParser
{
return BlockContinue::at($cursor);
}
public function closeBlock(): void
{
$this->removeLinkReferenceDefinitions();
}
private function removeLinkReferenceDefinitions(): void
{
$emptyNodes = [];
$walker = $this->document->walker();
while ($event = $walker->next()) {
$node = $event->getNode();
// TODO for v3: It would be great if we could find an alternate way to identify such paragraphs.
// Unfortunately, we can't simply check for empty paragraphs here because inlines haven't been processed yet,
// meaning all paragraphs will appear blank here, and we don't have a way to check the status of the reference parser
// which is attached to the (already-closed) paragraph parser.
if ($event->isEntering() && $node instanceof Paragraph && $node->onlyContainsLinkReferenceDefinitions) {
$emptyNodes[] = $node;
}
}
foreach ($emptyNodes as $node) {
$node->detach();
}
}
}
@@ -59,9 +59,7 @@ final class ParagraphParser extends AbstractBlockContinueParser implements Block
public function closeBlock(): void
{
if ($this->referenceParser->hasReferences() && $this->referenceParser->getParagraphContent() === '') {
$this->block->detach();
}
$this->block->onlyContainsLinkReferenceDefinitions = $this->referenceParser->hasReferences() && $this->referenceParser->getParagraphContent() === '';
}
public function parseInlines(InlineParserEngineInterface $inlineParser): void
@@ -322,20 +322,21 @@ class Cursor
*/
public function advanceToNextNonSpaceOrNewline(): int
{
$remainder = $this->getRemainder();
$currentCharacter = $this->getCurrentCharacter();
// Optimization: Avoid the regex if we know there are no spaces or newlines
if ($remainder === '' || ($remainder[0] !== ' ' && $remainder[0] !== "\n")) {
if ($currentCharacter !== ' ' && $currentCharacter !== "\n") {
$this->previousPosition = $this->currentPosition;
return 0;
}
$matches = [];
\preg_match('/^ *(?:\n *)?/', $remainder, $matches, \PREG_OFFSET_CAPTURE);
\preg_match('/^ *(?:\n *)?/', $this->getRemainder(), $matches, \PREG_OFFSET_CAPTURE);
// [0][0] contains the matched text
// [0][1] contains the index of that match
\assert(isset($matches[0]));
$increment = $matches[0][1] + \strlen($matches[0][0]);
$this->advanceBy($increment);
@@ -42,12 +42,12 @@ final class InlineParserContext
*/
private array $matches;
public function __construct(Cursor $contents, AbstractBlock $container, ReferenceMapInterface $referenceMap)
public function __construct(Cursor $contents, AbstractBlock $container, ReferenceMapInterface $referenceMap, int $maxDelimitersPerLine = PHP_INT_MAX)
{
$this->referenceMap = $referenceMap;
$this->container = $container;
$this->cursor = $contents;
$this->delimiterStack = new DelimiterStack();
$this->delimiterStack = new DelimiterStack($maxDelimitersPerLine);
}
public function getContainer(): AbstractBlock
@@ -59,7 +59,7 @@ final class InlineParserEngine implements InlineParserEngineInterface
$contents = \trim($contents);
$cursor = new Cursor($contents);
$inlineParserContext = new InlineParserContext($cursor, $block, $this->referenceMap);
$inlineParserContext = new InlineParserContext($cursor, $block, $this->referenceMap, $this->environment->getConfiguration()->get('max_delimiters_per_line'));
// Have all parsers look at the line to determine what they might want to parse and what positions they exist at
foreach ($this->matchParsers($contents) as $matchPosition => $parsers) {
@@ -32,6 +32,7 @@ use League\CommonMark\Parser\Block\BlockStart;
use League\CommonMark\Parser\Block\BlockStartParserInterface;
use League\CommonMark\Parser\Block\DocumentBlockParser;
use League\CommonMark\Parser\Block\ParagraphParser;
use League\CommonMark\Reference\MemoryLimitedReferenceMap;
use League\CommonMark\Reference\ReferenceInterface;
use League\CommonMark\Reference\ReferenceMap;
@@ -102,7 +103,7 @@ final class MarkdownParser implements MarkdownParserInterface
// finalizeAndProcess
$this->closeBlockParsers(\count($this->activeBlockParsers), $this->lineNumber);
$this->processInlines();
$this->processInlines(\strlen($input));
$this->environment->dispatch(new DocumentParsedEvent($documentParser->getBlock()));
@@ -115,6 +116,9 @@ final class MarkdownParser implements MarkdownParserInterface
*/
private function parseLine(string $line): void
{
// replace NUL characters for security
$line = \str_replace("\0", "\u{FFFD}", $line);
$this->cursor = new Cursor($line);
$matches = $this->parseBlockContinuation();
@@ -158,12 +162,13 @@ final class MarkdownParser implements MarkdownParserInterface
$unmatchedBlocks = 0;
}
$oldBlockLineStart = null;
if ($blockStart->isReplaceActiveBlockParser()) {
$this->prepareActiveBlockParserForReplacement();
$oldBlockLineStart = $this->prepareActiveBlockParserForReplacement();
}
foreach ($blockStart->getBlockParsers() as $newBlockParser) {
$blockParser = $this->addChild($newBlockParser);
$blockParser = $this->addChild($newBlockParser, $oldBlockLineStart);
$tryBlockStarts = $newBlockParser->isContainer();
}
}
@@ -176,7 +181,7 @@ final class MarkdownParser implements MarkdownParserInterface
} else {
// finalize any blocks not matched
if ($unmatchedBlocks > 0) {
$this->closeBlockParsers($unmatchedBlocks, $this->lineNumber);
$this->closeBlockParsers($unmatchedBlocks, $this->lineNumber - 1);
}
if (! $blockParser->isContainer()) {
@@ -262,9 +267,9 @@ final class MarkdownParser implements MarkdownParserInterface
/**
* Walk through a block & children recursively, parsing string content into inline content where appropriate.
*/
private function processInlines(): void
private function processInlines(int $inputSize): void
{
$p = new InlineParserEngine($this->environment, $this->referenceMap);
$p = new InlineParserEngine($this->environment, new MemoryLimitedReferenceMap($this->referenceMap, $inputSize));
foreach ($this->closedBlockParsers as $blockParser) {
$blockParser->parseInlines($p);
@@ -275,12 +280,12 @@ final class MarkdownParser implements MarkdownParserInterface
* Add block of type tag as a child of the tip. If the tip can't accept children, close and finalize it and try
* its parent, and so on til we find a block that can accept children.
*/
private function addChild(BlockContinueParserInterface $blockParser): BlockContinueParserInterface
private function addChild(BlockContinueParserInterface $blockParser, ?int $startLineNumber = null): BlockContinueParserInterface
{
$blockParser->getBlock()->setStartLine($this->lineNumber);
$blockParser->getBlock()->setStartLine($startLineNumber ?? $this->lineNumber);
while (! $this->getActiveBlockParser()->canContain($blockParser->getBlock())) {
$this->closeBlockParsers(1, $this->lineNumber - 1);
$this->closeBlockParsers(1, ($startLineNumber ?? $this->lineNumber) - 1);
}
$this->getActiveBlockParser()->getBlock()->appendChild($blockParser->getBlock());
@@ -307,7 +312,10 @@ final class MarkdownParser implements MarkdownParserInterface
return $popped;
}
private function prepareActiveBlockParserForReplacement(): void
/**
* @return int|null The line number where the old block started
*/
private function prepareActiveBlockParserForReplacement(): ?int
{
// Note that we don't want to parse inlines or finalize this block, as it's getting replaced.
$old = $this->deactivateBlockParser();
@@ -317,6 +325,8 @@ final class MarkdownParser implements MarkdownParserInterface
}
$old->getBlock()->detach();
return $old->getBlock()->getStartLine();
}
/**