Skip to content

Commit

Permalink
Merge pull request #1034 from thephpleague/fix-smart-punct
Browse files Browse the repository at this point in the history
Don't change already-formatted quotation marks
  • Loading branch information
colinodell authored Jul 22, 2024
2 parents b7a7af3 + 1a40b1e commit e8e8a8b
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Updates should follow the [Keep a CHANGELOG](https://keepachangelog.com/) princi

## [Unreleased][unreleased]

### Fixed

- Fixed SmartPunct extension changing already-formatted quotation marks (#1030)

## [2.4.3] - 2024-07-22

### Fixed
Expand Down
28 changes: 10 additions & 18 deletions src/Extension/SmartPunct/QuoteParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,19 @@

final class QuoteParser implements InlineParserInterface
{
/**
* @deprecated This constant is no longer used and will be removed in a future major release
*/
public const DOUBLE_QUOTES = [Quote::DOUBLE_QUOTE, Quote::DOUBLE_QUOTE_OPENER, Quote::DOUBLE_QUOTE_CLOSER];

/**
* @deprecated This constant is no longer used and will be removed in a future major release
*/
public const SINGLE_QUOTES = [Quote::SINGLE_QUOTE, Quote::SINGLE_QUOTE_OPENER, Quote::SINGLE_QUOTE_CLOSER];

public function getMatchDefinition(): InlineParserMatch
{
return InlineParserMatch::oneOf(...[...self::DOUBLE_QUOTES, ...self::SINGLE_QUOTES]);
return InlineParserMatch::oneOf(Quote::SINGLE_QUOTE, Quote::DOUBLE_QUOTE);
}

/**
Expand All @@ -40,8 +47,6 @@ public function parse(InlineParserContext $inlineContext): bool
$char = $inlineContext->getFullMatch();
$cursor = $inlineContext->getCursor();

$normalizedCharacter = $this->getNormalizedQuoteCharacter($char);

$charBefore = $cursor->peek(-1);
if ($charBefore === null) {
$charBefore = "\n";
Expand All @@ -58,28 +63,15 @@ public function parse(InlineParserContext $inlineContext): bool
$canOpen = $leftFlanking && ! $rightFlanking;
$canClose = $rightFlanking;

$node = new Quote($normalizedCharacter, ['delim' => true]);
$node = new Quote($char, ['delim' => true]);
$inlineContext->getContainer()->appendChild($node);

// Add entry to stack to this opener
$inlineContext->getDelimiterStack()->push(new Delimiter($normalizedCharacter, 1, $node, $canOpen, $canClose));
$inlineContext->getDelimiterStack()->push(new Delimiter($char, 1, $node, $canOpen, $canClose));

return true;
}

private function getNormalizedQuoteCharacter(string $character): string
{
if (\in_array($character, self::DOUBLE_QUOTES, true)) {
return Quote::DOUBLE_QUOTE;
}

if (\in_array($character, self::SINGLE_QUOTES, true)) {
return Quote::SINGLE_QUOTE;
}

return $character;
}

/**
* @return bool[]
*/
Expand Down
10 changes: 10 additions & 0 deletions tests/functional/Extension/SmartPunct/SmartPunctFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,15 @@ protected function setUp(): void
public static function dataProvider(): \Generator
{
yield from SpecReader::readFile(__DIR__ . '/../../../../vendor/commonmark/commonmark.js/test/smart_punct.txt');

yield 'Existing formatted quotes should be preserved (issue #1030)' => [
'input' => 'In the middle to late ’90s, it was chaos. "We couldn\'t get out of that rut."',
'output' => "<p>In the middle to late ’90s, it was chaos. “We couldn’t get out of that rut.”</p>\n",
];

yield 'already-formatted quotes are kept as-is' => [
'input' => '"Plain quotes", “normal quotes”, and ”backwards quotes“',
'output' => "<p>“Plain quotes”, “normal quotes”, and ”backwards quotes“</p>\n",
];
}
}

0 comments on commit e8e8a8b

Please sign in to comment.