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

Phase 1 of #24

Merged
merged 2 commits into from
Jun 17, 2024
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
18 changes: 18 additions & 0 deletions extras/_test/delete.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
1
//- - - - - - - - -//
~~Hi~~ Hello, world!
//- - - - - - - - -//
<p><del>Hi</del> Hello, world!</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//



2
//- - - - - - - - -//
This ~~has a

new paragraph~~.
//- - - - - - - - -//
<p>This ~~has a</p>
<p>new paragraph~~.</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//
35 changes: 7 additions & 28 deletions extras/_test/insert.txt
Original file line number Diff line number Diff line change
@@ -1,43 +1,22 @@
1
//- - - - - - - - -//
++Hi++ Hello, world!
Hello ++,++ world!
//- - - - - - - - -//
<p><ins>Hi</ins> Hello, world!</p>
<p>Hello <ins>,</ins> world!</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

2
//- - - - - - - - -//
This ++has a
This ++expression is stretched over a

new paragraph++.
paragraph++.
//- - - - - - - - -//
<p>This ++has a</p>
<p>new paragraph++.</p>
<p>This ++expression is stretched over a</p>
<p>paragraph++.</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

3
//- - - - - - - - -//
x ++++foo++ bar++
//- - - - - - - - -//
<p>x <ins><ins>foo</ins> bar</ins></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

4
//- - - - - - - - -//
x ++foo ++bar++++
//- - - - - - - - -//
<p>x <ins>foo <ins>bar</ins></ins></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

5
//- - - - - - - - -//
x ++++foo++++
//- - - - - - - - -//
<p>x <ins><ins>foo</ins></ins></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

6
//- - - - - - - - -//
**++test**++

++**test++**
Expand All @@ -46,7 +25,7 @@ x ++++foo++++
<p><ins>**test</ins>**</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

7
4
//- - - - - - - - -//
[++link]()++

Expand Down
23 changes: 1 addition & 22 deletions extras/_test/mark.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,6 @@ new paragraph==.

3
//- - - - - - - - -//
x ====foo== bar==
//- - - - - - - - -//
<p>x <mark><mark>foo</mark> bar</mark></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

4
//- - - - - - - - -//
x ==foo ==bar====
//- - - - - - - - -//
<p>x <mark>foo <mark>bar</mark></mark></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

5
//- - - - - - - - -//
x ====foo====
//- - - - - - - - -//
<p>x <mark><mark>foo</mark></mark></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

6
//- - - - - - - - -//
**==test**==

==**test==**
Expand All @@ -46,7 +25,7 @@ x ====foo====
<p><mark>**test</mark>**</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

7
4
//- - - - - - - - -//
[==link]()==

Expand Down
25 changes: 16 additions & 9 deletions extras/_test/subscript.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,30 @@ x~i~ + x~j~
<p><sub>foo bar</sub></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

7: Mixed subscript and strikethrough
//- - - - - - - - -//
~~x~foobar~~~
//- - - - - - - - -//
<p><del>x<sub>foobar</sub></del></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

8: Tildes in the middle and text before
7: Tildes in the middle and text before
//- - - - - - - - -//
text H~2~O
//- - - - - - - - -//
<p>text H<sub>2</sub>O</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

9: Tildes in the middle and text after
8: Tildes in the middle and text after
//- - - - - - - - -//
H~2~O text
//- - - - - - - - -//
<p>H<sub>2</sub>O text</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

9: Check for a direct conflict with strikethrough
//- - - - - - - - -//
~~foobar~~
//- - - - - - - - -//
<p><del>foobar</del></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

10: Mixed subscript and strikethrough will not work as expected!
//- - - - - - - - -//
~~x~foobar~~~
//- - - - - - - - -//
<p>~~x~foobar~~~</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//
21 changes: 7 additions & 14 deletions extras/_test/superscript.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
1: Surrounded by cares
1: Surrounded by carets
//- - - - - - - - -//
^foo^
//- - - - - - - - -//
Expand All @@ -19,49 +19,42 @@ x^2^ + x^5^
<p>x<sup>2</sup> + x<sup>5</sup></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

4: Escaped care
4: Escaped caret
//- - - - - - - - -//
^foo\^
//- - - - - - - - -//
<p>^foo^</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

5: : Cares surround text with a non-breaking space entity
5: Carets surround text with a non-breaking space entity
//- - - - - - - - -//
^foo&nbsp;bar^
//- - - - - - - - -//
<p><sup>foo bar</sup></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

6: Cares surround text Surround with a non-breaking space (UTF-8)
6: Carets surround text Surround with a non-breaking space (UTF-8)
//- - - - - - - - -//
^foo bar^
//- - - - - - - - -//
<p><sup>foo bar</sup></p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

7: Cares in the middle and text before
7: Carets in the middle and text before
//- - - - - - - - -//
text C^foo^C
//- - - - - - - - -//
<p>text C<sup>foo</sup>C</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

8: Cares in the middle and text after
8: Carets in the middle and text after
//- - - - - - - - -//
C^foo^C text
//- - - - - - - - -//
<p>C<sup>foo</sup>C text</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

9: Wrong markers in LaTeX style notation should be left untouched
//- - - - - - - - -//
x^2 + x^3
//- - - - - - - - -//
<p>x^2 + x^3</p>
//= = = = = = = = = = = = = = = = = = = = = = = =//

10: Footnote markers should be left untouched
9: Footnote markers should be left untouched
//- - - - - - - - -//
text[^1] text[^2]
//- - - - - - - - -//
Expand Down
11 changes: 11 additions & 0 deletions extras/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ var markTag = inlineTag{
RenderPriority: 550,
}

var deleteTag = inlineTag{
TagKind: kindDelete,
Char: '~',
Number: 2,
Html: "del",
WhitespaceAllowed: false,
ParsePriority: 400,
RenderPriority: 400,
}

type inlineTagNode struct {
ast.BaseInline

Expand All @@ -73,6 +83,7 @@ var (
kindSubscript = ast.NewNodeKind("Subscript")
kindInsert = ast.NewNodeKind("Insert")
kindMark = ast.NewNodeKind("Mark")
kindDelete = ast.NewNodeKind("Delete")
)

func (n *inlineTagNode) Kind() ast.NodeKind {
Expand Down
30 changes: 9 additions & 21 deletions extras/inline.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,35 +48,15 @@ func (s *inlineTagParser) Parse(_ ast.Node, block text.Reader, pc parser.Context
before := block.PrecendingCharacter()
line, segment := block.PeekLine()
node := parser.ScanDelimiter(line, before, s.Number, newInlineTagDelimiterProcessor(s.inlineTag))
if node == nil {
if node == nil || node.OriginalLength > 2 || before == rune(s.Char) {
return nil
}
if !s.WhitespaceAllowed && node.CanOpen && hasSpace(line) {
if !(node.CanClose && pc.LastDelimiter() != nil && pc.LastDelimiter().Char == node.Char) {
return nil
}
}
node.Segment = segment.WithStop(segment.Start + node.OriginalLength)
block.Advance(node.OriginalLength)
pc.PushDelimiter(node)
return node
}

// Check if there is an ordinary white space in the line before the next marker
func hasSpace(line []byte) bool {
marker := line[0]
for i := 1; i < len(line); i++ {
c := line[i]
if c == marker {
break
}
if util.IsSpace(c) {
return true
}
}
return false
}

type inlineTagHTMLRenderer struct {
htmlTag string
tagKind ast.NodeKind
Expand Down Expand Up @@ -133,6 +113,7 @@ type Config struct {
Subscript SubscriptConfig
Insert InsertConfig
Mark MarkConfig
Delete DeleteConfig
}

// SuperscriptConfig configures the superscript extension.
Expand All @@ -155,6 +136,10 @@ type MarkConfig struct {
Enable bool
}

type DeleteConfig struct {
Enable bool
}

// New returns a new inline tag extension.

func New(config Config) goldmark.Extender {
Expand Down Expand Up @@ -185,4 +170,7 @@ func (tag *inlineExtension) Extend(md goldmark.Markdown) {
if tag.conf.Mark.Enable {
addTag(markTag)
}
if tag.conf.Delete.Enable {
addTag(deleteTag)
}
}
58 changes: 49 additions & 9 deletions extras/inline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

"github.com/gohugoio/hugo-goldmark-extensions/extras"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/text"

"github.com/yuin/goldmark"
Expand All @@ -17,11 +16,17 @@ func buildGoldmarkWithInlineTag(conf extras.Config) goldmark.Markdown {
}

var (
markdown = goldmark.New()
markdownWithSuperscript = buildGoldmarkWithInlineTag(extras.Config{Superscript: extras.SuperscriptConfig{Enable: true}})
markdownWithSubscript = buildGoldmarkWithInlineTag(extras.Config{Subscript: extras.SubscriptConfig{Enable: true}})
markdownWithInsert = buildGoldmarkWithInlineTag(extras.Config{Insert: extras.InsertConfig{Enable: true}})
markdownWithMark = buildGoldmarkWithInlineTag(extras.Config{Mark: extras.MarkConfig{Enable: true}})
markdown = goldmark.New()
markdownWithSuperscript = buildGoldmarkWithInlineTag(extras.Config{Superscript: extras.SuperscriptConfig{Enable: true}})
markdownWithSubscript = buildGoldmarkWithInlineTag(extras.Config{Subscript: extras.SubscriptConfig{Enable: true}})
markdownWithInsert = buildGoldmarkWithInlineTag(extras.Config{Insert: extras.InsertConfig{Enable: true}})
markdownWithMark = buildGoldmarkWithInlineTag(extras.Config{Mark: extras.MarkConfig{Enable: true}})
markdownWithDelete = buildGoldmarkWithInlineTag(extras.Config{Delete: extras.DeleteConfig{Enable: true}})
markdownWithDeleteAndSubscript = goldmark.New(
goldmark.WithExtensions(
extras.New(extras.Config{Subscript: extras.SubscriptConfig{Enable: true}}),
extras.New(extras.Config{Delete: extras.DeleteConfig{Enable: true}}),
))
)

func TestSuperscript(t *testing.T) {
Expand Down Expand Up @@ -62,9 +67,7 @@ This formula contains one superscript: f(x) = x^2^ .`
}

func TestSubscript(t *testing.T) {
markdown := goldmark.New(
goldmark.WithExtensions(extras.New(extras.Config{Subscript: extras.SubscriptConfig{Enable: true}}), extension.Strikethrough))
testutil.DoTestCaseFile(markdown, "_test/subscript.txt", t, testutil.ParseCliCaseArg()...)
testutil.DoTestCaseFile(markdownWithDeleteAndSubscript, "_test/subscript.txt", t, testutil.ParseCliCaseArg()...)
}

func TestSubscriptDump(t *testing.T) {
Expand Down Expand Up @@ -175,3 +178,40 @@ Add some marked text: ==marked==. Amazing.`
}
})
}

func TestDelete(t *testing.T) {
testutil.DoTestCaseFile(markdownWithDelete, "_test/delete.txt", t, testutil.ParseCliCaseArg()...)
}

func TestDeleteDump(t *testing.T) {
input := "Delete some text: ~~deleted~~. Amazing."
root := markdownWithDelete.Parser().Parse(text.NewReader([]byte(input)))
root.Dump([]byte(input), 0)
}

func BenchmarkWithAndWithoutDelete(b *testing.B) {
const input = `
## Delete text

Delete some text: ~~deleted~~. Amazing.`

b.Run("without delete extension", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
if err := markdown.Convert([]byte(input), &buf); err != nil {
b.Fatal(err)
}
}
})

b.Run("with delete extension", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
if err := markdownWithMark.Convert([]byte(input), &buf); err != nil {
b.Fatal(err)
}
}
})
}