Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue when rendering multi-line list items #7

Merged
merged 10 commits into from
Aug 1, 2023
14 changes: 14 additions & 0 deletions src/Renderer/Block/ListBlockRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer): s
$content = $childRenderer->renderNodes($node->children());
$content = explode("\n", $content);

$content = array_map(fn ($item) => $this->replaceInternalLineBreakCharacter($item), $content);

if ($listData->type === ListBlock::TYPE_BULLET) {
$content = array_map(fn ($item) => "- {$item}", $content);
}
Expand All @@ -42,4 +44,16 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer): s

return implode("\n", $content) . "\n";
}

/**
* Replace custom line break character with _native_ line breaks.
* Whitespace is added so that other Markdown clients correctly
* render the list and its line breaks.
* @param string $content
* @return string
*/
private function replaceInternalLineBreakCharacter(string $content): string
{
return str_replace(ListItemRenderer::INLINE_LINE_BREAK, " \n ", $content);
}
}
11 changes: 11 additions & 0 deletions src/Renderer/Block/ListItemRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

final class ListItemRenderer implements \League\CommonMark\Renderer\NodeRendererInterface
{
public const INLINE_LINE_BREAK = '_COMMONMARK_MARKDOWN_RENDERER_LINE_BREAK_';

/**
* @param ListItem $node
*
Expand All @@ -24,6 +26,15 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer): s
ListItem::assertInstanceOf($node);

$contents = $childRenderer->renderNodes($node->children());

// If the ListItem contains a line break, replace the line break with a custom string.
// The custom line break string is being replaced with a _native_ line break again, when
// being rendered in a ListBlock.
// This workaround is required to support multi-line list items.
if (str_contains($contents, "\n")) {
$contents = str_replace("\n", self::INLINE_LINE_BREAK, $contents);
}

if (str_starts_with($contents, '<') && ! $this->startsTaskListItem($node)) {
$contents = "\n" . $contents;
}
Expand Down
20 changes: 19 additions & 1 deletion tests/Renderer/MarkdownRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,29 @@ public function it_renders_ast_to_markdown(): void
public function it_parses_and_renders_kitchen_sink(): void
{
$contentKitchenSink = file_get_contents(__DIR__ . '/../stubs/kitchen-sink.md');
$contentKitchenSinkExpected = file_get_contents(__DIR__ . '/../stubs/kitchen-sink-expected.md');

$document = $this->parser->parse($contentKitchenSink);

$result = $this->renderer->renderDocument($document)->getContent();

$this->assertEquals($contentKitchenSink, $result);
$this->assertEquals($contentKitchenSinkExpected, $result);
}

#[Test]
public function it_parses_kitchen_sink_and_parsing_the_result_again_returns_the_same_result(): void
{
$contentKitchenSink = file_get_contents(__DIR__ . '/../stubs/kitchen-sink.md');
$contentKitchenSinkExpected = file_get_contents(__DIR__ . '/../stubs/kitchen-sink-expected.md');

$document = $this->parser->parse($contentKitchenSink);

$result = $this->renderer->renderDocument($document)->getContent();
$this->assertEquals($contentKitchenSinkExpected, $result);

// Take the result and parse it again
$document = $this->parser->parse($result);
$result = $this->renderer->renderDocument($document)->getContent();
$this->assertEquals($contentKitchenSinkExpected, $result);
}
}
27 changes: 27 additions & 0 deletions tests/stubs/kitchen-sink-expected.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Changelog

All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Curiosities

- This is a list item which is followed by an indented content on the next line
which is part of the same list item
- This is a list item which contains multiple paragraphs
This is the second paragraph.
This is the third paragraph.
- This is a list item with multiple paragraphs, but without trailing whitespace in the original document at the end
This is the second paragraph.
This is the third paragraph.

## Task List

- [ ] Task 1
- [x] Task 2

## [Unreleased](https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...HEAD)

**This Text is Bold**
*This Text is Italic*

`\Class->getFoo()`
177 changes: 14 additions & 163 deletions tests/stubs/kitchen-sink.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
# Changelog

All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Curiosities

- This is a list item which is followed by an indented content on the next line
which is part of the same list item
- This is a list item which contains multiple paragraphs
This is the second paragraph.
This is the third paragraph.
- This is a list item with multiple paragraphs, but without trailing whitespace in the original document at the end
This is the second paragraph.
This is the third paragraph.

## Task List

Expand All @@ -12,165 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased](https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...HEAD)

## [1.0.0](https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0) - 2017-06-20

### Added

- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
- Version navigation.
- Links to latest released version in previous versions.
- "Why keep a changelog?" section.
- "Who needs a changelog?" section.
- "How do I make a changelog?" section.
- "Frequently Asked Questions" section.
- New "Guiding Principles" sub-section to "How do I make a changelog?".
- Simplified and Traditional Chinese translations from [@tianshuo](https://github.com/tianshuo).
- German translation from [@mpbzh](https://github.com/mpbzh) & [@Art4](https://github.com/Art4).
- Italian translation from [@azkidenz](https://github.com/azkidenz).
- Swedish translation from [@magol](https://github.com/magol).
- Turkish translation from [@karalamalar](https://github.com/karalamalar).
- French translation from [@zapashcanon](https://github.com/zapashcanon).
- Brazilian Portugese translation from [@Webysther](https://github.com/Webysther).
- Polish translation from [@amielucha](https://github.com/amielucha) & [@m-aciek](https://github.com/m-aciek).
- Russian translation from [@aishek](https://github.com/aishek).
- Czech translation from [@h4vry](https://github.com/h4vry).
- Slovak translation from [@jkostolansky](https://github.com/jkostolansky).
- Korean translation from [@pierceh89](https://github.com/pierceh89).
- Croatian translation from [@porx](https://github.com/porx).
- Persian translation from [@Hameds](https://github.com/Hameds).
- Ukrainian translation from [@osadchyi-s](https://github.com/osadchyi-s).

### Changed

- Start using "changelog" over "change log" since it's the common usage.
- Start versioning based on the current English version at 0.3.0 to help
- translation authors keep things up-to-date.
- Rewrite "What makes unicorns cry?" section.
- Rewrite "Ignoring Deprecations" sub-section to clarify the ideal
- scenario.
- Improve "Commit log diffs" sub-section to further argument against
- them.
- Merge "Why can’t people just use a git log diff?" with "Commit log
- diffs"
- Fix typos in Simplified Chinese and Traditional Chinese translations.
- Fix typos in Brazilian Portuguese translation.
- Fix typos in Turkish translation.
- Fix typos in Czech translation.
- Fix typos in Swedish translation.
- Improve phrasing in French translation.
- Fix phrasing and spelling in German translation.

### Removed

- Section about "changelog" vs "CHANGELOG".

## [0.3.0](https://github.com/olivierlacan/keep-a-changelog/compare/v0.2.0...v0.3.0) - 2015-12-03

### Added

- RU translation from [@aishek](https://github.com/aishek).
- pt-BR translation from [@tallesl](https://github.com/tallesl).
- es-ES translation from [@ZeliosAriex](https://github.com/ZeliosAriex).

## [0.2.0](https://github.com/olivierlacan/keep-a-changelog/compare/v0.1.0...v0.2.0) - 2015-10-06

### Changed

- Remove exclusionary mentions of "open source" since this project can
- benefit both "open" and "closed" source projects equally.

## [0.1.0](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.8...v0.1.0) - 2015-10-06

### Added

- Answer "Should you ever rewrite a change log?".

### Changed

- Improve argument against commit logs.
- Start following [SemVer](https://semver.org) properly.

## [0.0.8](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.7...v0.0.8) - 2015-02-17

### Changed

- Update year to match in every README example.
- Reluctantly stop making fun of Brits only, since most of the world
- writes dates in a strange way.

### Fixed

- Fix typos in recent README changes.
- Update outdated unreleased diff link.

## [0.0.7](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.6...v0.0.7) - 2015-02-16

### Added

- Link, and make it obvious that date format is ISO 8601.

### Changed

- Clarified the section on "Is there a standard change log format?".

### Fixed

- Fix Markdown links to tag comparison URL with footnote-style links.

## [0.0.6](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.5...v0.0.6) - 2014-12-12

### Added

- README section on "yanked" releases.

## [0.0.5](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.4...v0.0.5) - 2014-08-09

### Added

- Markdown links to version tags on release headings.
- Unreleased section to gather unreleased changes and encourage note
- keeping prior to releases.

## [0.0.4](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.3...v0.0.4) - 2014-08-09

### Added

- Better explanation of the difference between the file ("CHANGELOG")
- and its function "the change log".

### Changed

- Refer to a "change log" instead of a "CHANGELOG" throughout the site
- to differentiate between the file and the purpose of the file — the
- logging of changes.

### Removed

- Remove empty sections from CHANGELOG, they occupy too much space and
- create too much noise in the file. People will have to assume that the
- missing sections were intentionally left out because they contained no
- notable changes.

## [0.0.3](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.2...v0.0.3) - 2014-08-09

### Added

- "Why should I care?" section mentioning The Changelog podcast.

## [0.0.2](https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.1...v0.0.2) - 2014-07-10

### Added

- Explanation of the recommended reverse chronological release ordering.

## [0.0.1](https://github.com/olivierlacan/keep-a-changelog/releases/tag/v0.0.1) - 2014-05-31

### Added
**This Text is Bold**
*This Text is Italic*

- This CHANGELOG file to hopefully serve as an evolving example of a
- standardized open source project CHANGELOG.
- CNAME file to enable GitHub Pages custom domain
- README now contains answers to common questions about CHANGELOGs
- Good examples and basic guidelines, including proper date formatting.
- Counter-examples: "What makes unicorns cry?"
- `\Class->getFoo()`
`\Class->getFoo()`
Loading