scribe/spec/classes/markup_converter_spec.cr
Edward Loveall 09995cde5c
Overlapping refactor
Example:

* Text: "strong and emphasized only"
* Markups:
  * Strong: 0..10
  * Emphasis: 7..21

First, get all the borders of the markups, including the start (0) and
end (text.size) indexes of the text in order:

```
[0, 7, 10, 21, 26]
```

Then attach markups to each range. Note that the ranges are exclusive;
they don't include the final number:

* 0...7: Strong
* 7...10: Strong, Emphasized
* 10...21: Emphasized
* 21...26: N/A

Bundle each range and it's related markups into a value object
RangeWithMarkup and return the list.

Loop through that list and recursively apply each markup to each
segment of text:

* Apply a `Strong` markup to the text "strong "
* Apply a `Strong` markup to the text "and"
  * Wrap that in an `Emphasis` markup
* Apply an `Emphasis` markup to the text " emphasized"
* Leave the text " only" as is

---

This has the side effect of breaking up the nodes more than they need
to be broken up. For example right now the algorithm creates this HTML:

```
<strong>strong </strong><em><strong>and</strong></em>
```

instead of:

```
<strong>strong <em>and</em></strong>
```

But that's a task for another day.
2021-08-08 15:08:43 -04:00

196 lines
4.9 KiB
Crystal

require "../spec_helper"
include Nodes
describe MarkupConverter do
describe "#convert" do
it "returns just text with no markups" do
markups = [] of PostResponse::Markup
result = MarkupConverter.convert(text: "Hello, world", markups: markups)
result.should eq([Text.new(content: "Hello, world")])
end
it "returns text with multiple markups" do
markups = Array(PostResponse::Markup).from_json <<-JSON
[
{
"title": null,
"type": "STRONG",
"href": null,
"start": 0,
"end": 6,
"rel": null,
"anchorType": null
},
{
"title": null,
"type": "EM",
"href": null,
"start": 11,
"end": 21,
"rel": null,
"anchorType": null
}
]
JSON
result = MarkupConverter.convert(text: "strong and emphasized only", markups: markups)
result.should eq([
Strong.new(children: [Text.new(content: "strong")] of Child),
Text.new(content: " and "),
Emphasis.new(children: [Text.new(content: "emphasized")] of Child),
Text.new(content: " only"),
])
end
it "returns text with a code markup" do
markups = Array(PostResponse::Markup).from_json <<-JSON
[
{
"title": null,
"type": "CODE",
"href": null,
"start": 7,
"end": 11,
"rel": null,
"anchorType": null
}
]
JSON
result = MarkupConverter.convert(text: "inline code", markups: markups)
result.should eq([
Text.new(content: "inline "),
Code.new(children: [Text.new(content: "code")] of Child),
])
end
it "renders an A-LINK markup" do
markups = Array(PostResponse::Markup).from_json <<-JSON
[
{
"title": "",
"type": "A",
"href": "https://example.com",
"start": 7,
"end": 11,
"rel": "",
"anchorType": "LINK"
}
]
JSON
result = MarkupConverter.convert(text: "I am a Link", markups: markups)
result.should eq([
Text.new("I am a "),
Anchor.new(children: [Text.new("Link")] of Child, href: "https://example.com"),
])
end
it "renders an A-USER markup" do
markups = Array(PostResponse::Markup).from_json <<-JSON
[
{
"title": null,
"type": "A",
"href": null,
"userId": "abc123",
"start": 3,
"end": 10,
"rel": null,
"anchorType": "USER"
}
]
JSON
result = MarkupConverter.convert(text: "Hi Dr Nick!", markups: markups)
result.should eq([
Text.new("Hi "),
UserAnchor.new(children: [Text.new("Dr Nick")] of Child, userId: "abc123"),
Text.new("!"),
])
end
it "renders overlapping markups" do
markups = Array(PostResponse::Markup).from_json <<-JSON
[
{
"title": null,
"type": "STRONG",
"href": null,
"userId": null,
"start": 7,
"end": 15,
"rel": null,
"anchorType": null
},
{
"title": null,
"type": "EM",
"href": null,
"userId": null,
"start": 0,
"end": 10,
"rel": null,
"anchorType": null
}
]
JSON
result = MarkupConverter.convert(text: "Italic and bold", markups: markups)
result.should eq([
Emphasis.new(children: [Text.new("Italic ")] of Child),
Emphasis.new(children: [
Strong.new(children: [Text.new("and")] of Child),
] of Child),
Strong.new(children: [Text.new(" bold")] of Child),
])
end
end
describe "#wrap_in_markups" do
it "returns text wrapped in multiple markups" do
markups = Array(PostResponse::Markup).from_json <<-JSON
[
{
"title": null,
"type": "STRONG",
"href": null,
"start": 0,
"end": 17,
"rel": null,
"anchorType": null
},
{
"title": null,
"type": "A",
"href": null,
"userId": "abc123",
"start": 13,
"end": 17,
"rel": null,
"anchorType": "USER"
}
]
JSON
converter = MarkupConverter.new(text: "it's ya boi, jack", markups: markups)
result = converter.wrap_in_markups("jack", markups)
result.should eq([
UserAnchor.new(children: [
Strong.new([
Text.new("jack"),
] of Child),
] of Child, userId: "abc123"),
])
end
end
end