Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions src/MarkdownParser/IViewSupplier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,6 @@ public interface IViewSupplier<T>
/// <returns></returns>
T CreateThematicBreak();

/// <summary>
/// a placeholder for views or other objects
/// </summary>
/// <param name="placeholderName">placeholder string</param>
/// <returns></returns>
T CreatePlaceholder(string placeholderName);

/// <summary>
/// a view that shows fenced code (found in MD blocks starting with ```cs )
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum SegmentIndicator
Strikethrough,
Code,
Link,
LineBreak
LineBreak,
Placeholder
}
}
4 changes: 2 additions & 2 deletions src/MarkdownParser/Models/Segments/LinkSegment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ public class LinkSegment : IndicatorSegment
public string Url { get; }
public string Title { get; }

public LinkSegment(SegmentIndicator indicator, SegmentIndicatorPosition indicatorPosition, string url, string title)
: base(indicator, indicatorPosition)
public LinkSegment(SegmentIndicatorPosition indicatorPosition, string url, string title)
: base(SegmentIndicator.Link, indicatorPosition)
{
Url = url;
Title = title;
Expand Down
24 changes: 24 additions & 0 deletions src/MarkdownParser/Models/Segments/PlaceholderSegment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using MarkdownParser.Models.Segments.Indicators;

namespace MarkdownParser.Models.Segments
{
public class PlaceholderSegment : IndicatorSegment
{
public string Url { get; }
public string Title { get; }

public PlaceholderSegment(string url, string title)
: base(SegmentIndicator.Placeholder, SegmentIndicatorPosition.Start)
{
Url = url;
Title = title;
HasLiteralContent = !string.IsNullOrWhiteSpace(Title)
&& !string.IsNullOrWhiteSpace(Url);
}

public override string ToString()
{
return Title ?? Url ?? string.Empty;
}
}
}
20 changes: 13 additions & 7 deletions src/MarkdownParser/Writer/ViewFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,20 @@ public List<T> FormatSingleBlock(Block markdownBlock)
return _writer.Flush();
}

private Dictionary<string, Reference> ReferenceMap;

private void WriteBlockToView(Block block, ViewWriter<T> writer, bool continueWithNextSibling = true)
{
if (block == null)
var tag = block?.Tag;
if (tag == null)
{
return;
}

switch (block.Tag)
switch (tag)
{
case BlockTag.Document:
ReferenceMap = block.Document.ReferenceMap;
_writer.RegisterReferenceDefinitions(block.Document.ReferenceMap);
WriteBlockToView(block.FirstChild, writer);
break;
Expand Down Expand Up @@ -81,7 +85,8 @@ private void WriteBlockToView(Block block, ViewWriter<T> writer, bool continueWi
writer.StartAndFinalizeHtmlBlock(block.StringContent);
break;
case BlockTag.ReferenceDefinition:
// ignore this tag, because it's handled before so the data can be used during the formatting
// ignore this tag, because it's handled at 'BlockTag.Document' with 'RegisterReferenceDefinitions'
// this way the data is available in time to be used during the formatting
break;
default:
throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block);
Expand All @@ -95,12 +100,13 @@ private void WriteBlockToView(Block block, ViewWriter<T> writer, bool continueWi

private void WriteInlineToView(Inline inline, ViewWriter<T> writer)
{
if (inline == null)
var tag = inline?.Tag;
if (tag == null)
{
return;
}

switch (inline.Tag)
switch (tag)
{
case InlineTag.Code:
writer.AddEmphasis(inline, inline.SourcePosition, inline.SourceLength);
Expand All @@ -111,7 +117,7 @@ private void WriteInlineToView(Inline inline, ViewWriter<T> writer)
writer.AddText(inline.LiteralContent, inline.SourcePosition);
break;
case InlineTag.Link:
writer.AddLink(inline, inline.SourcePosition, inline.SourceLength, inline.TargetUrl, inline.LiteralContent); // check if this works at links
writer.AddLink(inline.SourcePosition, inline.SourceLength, inline.TargetUrl, inline.LiteralContent); // check if this works at links
WriteInlineToView(inline.FirstChild, writer);
break;
case InlineTag.Image:
Expand All @@ -122,7 +128,7 @@ private void WriteInlineToView(Inline inline, ViewWriter<T> writer)
writer.AddEmphasis(inline, inline.SourcePosition, inline.SourceLength);
break;
case InlineTag.Placeholder:
writer.StartAndFinalizePlaceholderBlock(inline.TargetUrl);
writer.AddPlaceholder(inline.SourcePosition, inline.SourceLength, inline.TargetUrl, inline.FirstChild.LiteralContent);
break;
case InlineTag.Strikethrough:
case InlineTag.Emphasis:
Expand Down
15 changes: 7 additions & 8 deletions src/MarkdownParser/Writer/ViewWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,16 @@ public void AddText(string content, int firstCharacterPosition)
GetWorkbenchItem().Add(content, firstCharacterPosition);
}

public void AddLink(Inline inline, int firstCharacterPosition, int length, string url, string urlTitle)
public void AddLink(int firstCharacterPosition, int length, string url, string urlTitle)
{
GetWorkbenchItem().AddLink(firstCharacterPosition, length, url, urlTitle);
}

public void AddPlaceholder(int firstCharacterPosition, int length, string url, string title)
{
GetWorkbenchItem().AddPlaceholder(firstCharacterPosition, length, url, title);
}

public void AddEmphasis(Inline inline, int firstCharacterPosition, int length)
{
SegmentIndicator indicator;
Expand Down Expand Up @@ -308,13 +313,7 @@ public void StartAndFinalizeThematicBreak()
var separator = ViewSupplier.CreateThematicBreak();
StoreView(separator);
}

public void StartAndFinalizePlaceholderBlock(string placeholderName)
{
var placeholderView = ViewSupplier.CreatePlaceholder(placeholderName);
StoreView(placeholderView);
}


private BlockType[] GetAncestorsTreeFromWorkbench(BlockType currentBlockType)
{
var blockTypeTree = new List<BlockType>();
Expand Down
12 changes: 10 additions & 2 deletions src/MarkdownParser/Writer/ViewWriterCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,15 @@ public void AddLink(int firstCharacterPosition, int length, string url, string u

_pendingSegmentIndicators.Add((SegmentIndicator.Link, firstCharacterPosition + length - 1));

var segmentIndicator = new LinkSegment(SegmentIndicator.Link, SegmentIndicatorPosition.Start, url, urlTitle);
var segmentIndicator = new LinkSegment(SegmentIndicatorPosition.Start, url, urlTitle);
_valuesStack.Push((segmentIndicator, _defaultT));
}

public void AddPlaceholder(int firstCharacterPosition, int length, string url, string title)
{
FinalizeSegmentIndicator(firstCharacterPosition);

var segmentIndicator = new PlaceholderSegment(url, title);
_valuesStack.Push((segmentIndicator, _defaultT));
}

Expand Down Expand Up @@ -129,7 +137,7 @@ private void FinalizeSegmentIndicator(int toWritePosition)
switch (pendingIndicator.SegmentIndicator)
{
case SegmentIndicator.Link:
segmentIndicator = new LinkSegment(pendingIndicator.SegmentIndicator, SegmentIndicatorPosition.End, string.Empty, string.Empty);
segmentIndicator = new LinkSegment(SegmentIndicatorPosition.End, string.Empty, string.Empty);
break;
default:
segmentIndicator = new IndicatorSegment(pendingIndicator.SegmentIndicator, SegmentIndicatorPosition.End);
Expand Down
1 change: 1 addition & 0 deletions test/MarkdownParser.Test/MarkdownParser.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<EmbeddedResource Include="Resources\Examples\Sections\paragraphs.md" />
<EmbeddedResource Include="Resources\Examples\Sections\referencedefinitions.md" />
<EmbeddedResource Include="Resources\Examples\TextEmphasis\basic-links.md" />
<EmbeddedResource Include="Resources\Examples\TextEmphasis\basic-placeholders.md" />
<EmbeddedResource Include="Resources\Examples\TextEmphasis\basic-text.md" />
</ItemGroup>

Expand Down
62 changes: 62 additions & 0 deletions test/MarkdownParser.Test/MarkdownParserBlockSegmentsSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,66 @@ public void When_parsing_text_with_links_it_should_output_ordered_segments()
textBlock1!.TextSegments[6].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Link);
textBlock1!.TextSegments[6].As<IndicatorSegment>().IndicatorPosition.Should().Be(SegmentIndicatorPosition.End);
}

[TestMethod]
public void When_parsing_text_with_placeholders_it_should_output_ordered_segments()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------
var markdown = FileReader.ReadFile("TextEmphasis.basic-placeholders.md");

var componentSupplier = new PassThroughComponentSupplier();
var parser = new MarkdownParser<object>(componentSupplier);

//-----------------------------------------------------------------------------------------------------------
// Act
//-----------------------------------------------------------------------------------------------------------
var parseResult = parser.Parse(markdown);

//-----------------------------------------------------------------------------------------------------------
// Assert
//-----------------------------------------------------------------------------------------------------------
parseResult.Count.Should().Be(3);

parseResult[0].Should().BeOfType<TextBlock>();
var textBlock0 = parseResult[0] as TextBlock;
textBlock0!.TextSegments.Length.Should().Be(3);
textBlock0!.TextSegments[0].As<TextSegment>().Text.Should().Be("Use ");
textBlock0!.TextSegments[1].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Placeholder);
textBlock0!.TextSegments[1].As<IndicatorSegment>().IndicatorPosition.Should().Be(SegmentIndicatorPosition.Start);
textBlock0!.TextSegments[1].As<PlaceholderSegment>().Title.Should().Be("placeholder x");
textBlock0!.TextSegments[1].As<PlaceholderSegment>().Url.Should().Be("placeholder x");
textBlock0!.TextSegments[1].As<PlaceholderSegment>().ToString().Should().Be("placeholder x");
textBlock0!.TextSegments[2].As<TextSegment>().Text.Should().Be(" within sentence.");

parseResult[1].Should().BeOfType<TextBlock>();
var textBlock1 = parseResult[1] as TextBlock;
textBlock1!.TextSegments.Length.Should().Be(10);
textBlock1!.TextSegments[0].As<TextSegment>().Text.Should().Be("Paragraphs ");
textBlock1!.TextSegments[1].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Strong);
textBlock1!.TextSegments[1].As<IndicatorSegment>().IndicatorPosition.Should().Be(SegmentIndicatorPosition.Start);
textBlock1!.TextSegments[2].As<TextSegment>().Text.Should().Be("are ");
textBlock1!.TextSegments[3].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Italic);
textBlock1!.TextSegments[3].As<IndicatorSegment>().IndicatorPosition.Should().Be(SegmentIndicatorPosition.Start);
textBlock1!.TextSegments[4].As<TextSegment>().Text.Should().Be("separated ");
textBlock1!.TextSegments[5].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Placeholder);
textBlock1!.TextSegments[5].As<PlaceholderSegment>().Title.Should().Be("placeholder y");
textBlock1!.TextSegments[5].As<PlaceholderSegment>().Url.Should().Be("placeholder y");
textBlock1!.TextSegments[5].As<PlaceholderSegment>().ToString().Should().Be("placeholder y");
textBlock1!.TextSegments[6].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Italic);
textBlock1!.TextSegments[6].As<IndicatorSegment>().IndicatorPosition.Should().Be(SegmentIndicatorPosition.End);
textBlock1!.TextSegments[7].As<TextSegment>().Text.Should().Be(" by");
textBlock1!.TextSegments[8].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Strong);
textBlock1!.TextSegments[8].As<IndicatorSegment>().IndicatorPosition.Should().Be(SegmentIndicatorPosition.End);
textBlock1!.TextSegments[9].As<TextSegment>().Text.Should().Be(" a blank line.");

parseResult[2].Should().BeOfType<TextBlock>();
var textBlock2 = parseResult[2] as TextBlock;
textBlock2!.TextSegments.Length.Should().Be(1);
textBlock2!.TextSegments[0].As<IndicatorSegment>().Indicator.Should().Be(SegmentIndicator.Placeholder);
textBlock2!.TextSegments[0].As<PlaceholderSegment>().Title.Should().Be("placeholder z");
textBlock2!.TextSegments[0].As<PlaceholderSegment>().Url.Should().Be("placeholder z");
textBlock2!.TextSegments[0].As<PlaceholderSegment>().ToString().Should().Be("placeholder z");
}
}
2 changes: 1 addition & 1 deletion test/MarkdownParser.Test/MarkdownParserBlocksSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ public void When_parsing_reference_definitions_it_should_output_correct_ancestor
// Assert
//-----------------------------------------------------------------------------------------------------------
parseResult.Count.Should().Be(1);
parseResult[0].Should().StartWith($"stackview>:+textview:[]{BlockType.Paragraph}");
parseResult[0].Should().StartWith($"textview:[]{BlockType.Paragraph}:Aliquet in luctus in porttitor non quam donec.");
}

[TestMethod]
Expand Down
18 changes: 6 additions & 12 deletions test/MarkdownParser.Test/MarkdownParserSectionsSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,12 @@
// Assert
//-----------------------------------------------------------------------------------------------------------
parseResult.Count.Should().Be(1);
parseResult[0].Should().StartWith("stackview>:+textview");

mockComponentSupplier.MarkdownReferenceDefinitions.Should().HaveCount(2);
parseResult[0].Should().StartWith("textview:Aliquet in luctus in porttitor non quam donec.");
mockComponentSupplier.MarkdownReferenceDefinitions.Should().HaveCount(1);

mockComponentSupplier.MarkdownReferenceDefinitions[0].IsPlaceholder = false;

Check warning on line 213 in test/MarkdownParser.Test/MarkdownParserSectionsSpecs.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.

Check warning on line 213 in test/MarkdownParser.Test/MarkdownParserSectionsSpecs.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.

Check warning on line 213 in test/MarkdownParser.Test/MarkdownParserSectionsSpecs.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.
mockComponentSupplier.MarkdownReferenceDefinitions[0].Label = "LINK";
mockComponentSupplier.MarkdownReferenceDefinitions[0].Title = "title";
mockComponentSupplier.MarkdownReferenceDefinitions[0].Url = "/uri";

mockComponentSupplier.MarkdownReferenceDefinitions[1].IsPlaceholder = false;
mockComponentSupplier.MarkdownReferenceDefinitions[1].Label = "PORTTITOR NON QUAM";
mockComponentSupplier.MarkdownReferenceDefinitions[1].Title = "";
mockComponentSupplier.MarkdownReferenceDefinitions[1].Url = "https://lipsum.com/";
mockComponentSupplier.MarkdownReferenceDefinitions[0].Label = "PORTTITOR NON QUAM";
mockComponentSupplier.MarkdownReferenceDefinitions[0].Title = "lipsum";
mockComponentSupplier.MarkdownReferenceDefinitions[0].Url = "https://lipsum.com/";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,6 @@ public void When_parsing_a_placeholder_it_should_output_a_PlaceHolderView()
// Assert
//-----------------------------------------------------------------------------------------------------------
parseResult.Count.Should().Be(1);
parseResult.First().Should().Be("placeholderview:my-placeholder");
parseResult.First().Should().Be("textview:my-placeholder");
}
}
5 changes: 0 additions & 5 deletions test/MarkdownParser.Test/Mocks/BlockComponentSupplier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@
return "thematicbreakview";
}

public string CreatePlaceholder(string placeholderName)
{
return $"placeholderview:{placeholderName}";
}

public string CreateFencedCodeBlock(TextBlock textBlock, string codeInfo)
{
var content = textBlock.ExtractLiteralContent(Settings.TextualLineBreak);
Expand All @@ -90,7 +85,7 @@
public string CreateReferenceDefinitions()
{
var content = "referencedefinitions>";
foreach (var markdownReferenceDefinition in MarkdownReferenceDefinitions)

Check warning on line 88 in test/MarkdownParser.Test/Mocks/BlockComponentSupplier.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.

Check warning on line 88 in test/MarkdownParser.Test/Mocks/BlockComponentSupplier.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.

Check warning on line 88 in test/MarkdownParser.Test/Mocks/BlockComponentSupplier.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.
{
content += $"|{markdownReferenceDefinition.IsPlaceholder}";
content += $"*{markdownReferenceDefinition.Label}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ public object CreateThematicBreak()
return "ThematicBreak";
}

public object CreatePlaceholder(string placeholderName)
{
return placeholderName;
}

public object CreateFencedCodeBlock(TextBlock textBlock, string codeInfo)
{
return textBlock;
Expand Down
5 changes: 0 additions & 5 deletions test/MarkdownParser.Test/Mocks/StringComponentSupplier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@
return "thematicbreakview";
}

public string CreatePlaceholder(string placeholderName)
{
return $"placeholderview:{placeholderName}";
}

public string CreateFencedCodeBlock(TextBlock textBlock, string codeInfo)
{
var content = textBlock.ExtractLiteralContent(Settings.TextualLineBreak);
Expand All @@ -84,7 +79,7 @@
public string CreateReferenceDefinitions()
{
var content = "referencedefinitions>";
foreach (var markdownReferenceDefinition in MarkdownReferenceDefinitions)

Check warning on line 82 in test/MarkdownParser.Test/Mocks/StringComponentSupplier.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.

Check warning on line 82 in test/MarkdownParser.Test/Mocks/StringComponentSupplier.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.

Check warning on line 82 in test/MarkdownParser.Test/Mocks/StringComponentSupplier.cs

View workflow job for this annotation

GitHub Actions / build-sample-ci

Dereference of a possibly null reference.
{
content += $"|{markdownReferenceDefinition.IsPlaceholder}";
content += $"*{markdownReferenceDefinition.Label}";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[link]: /uri "title"
Aliquet in luctus in [porttitor non quam] donec.

Vestibulum dictum lacinia lacus, at ornare quam consequat ultrices.
Nam quam leo, aliquet in luctus in, [porttitor non quam]. Donec tincidunt augue nisi,
sed pellentesque nisl porttitor vel.

[porttitor non quam]: https://lipsum.com/
[porttitor non quam]: https://lipsum.com/ "lipsum"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Use [placeholder x] within sentence.

Paragraphs **are *separated [placeholder y]* by** a blank line.

[placeholder z]

[placeholder x]: https://lipsum.com/ "lipsum"
[placeholder y]: https://lipsum.com/ "lipsum"
[placeholder z]: https://lipsum.com/ "lipsum"
Loading