Skip to content

Commit

Permalink
Add unicode rendering method
Browse files Browse the repository at this point in the history
  • Loading branch information
yuin committed Aug 25, 2020
1 parent aca7fba commit 0faf8bc
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 19 deletions.
16 changes: 12 additions & 4 deletions ast/emoji.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
package ast

import (
"fmt"

"github.com/yuin/goldmark-emoji/definition"
gast "github.com/yuin/goldmark/ast"
)
Expand All @@ -10,12 +12,17 @@ import (
type Emoji struct {
gast.BaseInline

Value *definition.Emoji
ShortName []byte
Value *definition.Emoji
}

// Dump implements Node.Dump.
func (n *Emoji) Dump(source []byte, level int) {
gast.DumpHelper(n, source, level, nil, nil)
m := map[string]string{
"ShortName": string(n.ShortName),
"Value": fmt.Sprintf("%#v", n.Value),
}
gast.DumpHelper(n, source, level, m, nil)
}

// KindEmoji is a NodeKind of the emoji node.
Expand All @@ -27,8 +34,9 @@ func (n *Emoji) Kind() gast.NodeKind {
}

// NewEmoji returns a new Emoji node.
func NewEmoji(value *definition.Emoji) *Emoji {
func NewEmoji(shortName []byte, value *definition.Emoji) *Emoji {
return &Emoji{
Value: value,
ShortName: shortName,
Value: value,
}
}
36 changes: 21 additions & 15 deletions emoji.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ const (
// Entity renders an emoji as an html entity.
Entity RenderingMethod = iota

// Unicode renders an emoji as unicode character.
Unicode

// Twemoji renders an emoji as an img tag with [twemoji](https://github.com/twitter/twemoji).
Twemoji

Expand Down Expand Up @@ -243,12 +246,12 @@ func (s *emojiParser) Parse(parent ast.Node, block text.Reader, pc parser.Contex
return nil
}
block.Advance(i + 1)
name := line[1:i]
emoji, ok := s.Emojis.Get(util.BytesToReadOnlyString(name))
shortName := line[1:i]
emoji, ok := s.Emojis.Get(util.BytesToReadOnlyString(shortName))
if !ok {
return nil
}
return east.NewEmoji(emoji)
return east.NewEmoji(shortName, emoji)
}

type emojiHTMLRenderer struct {
Expand Down Expand Up @@ -284,6 +287,11 @@ func (r *emojiHTMLRenderer) renderEmoji(w util.BufWriter, source []byte, n ast.N
return ast.WalkContinue, nil
}
node := n.(*east.Emoji)
if !node.Value.IsUnicode() && r.Method != Func {
fmt.Fprintf(w, `<span title="%s">:%s:</span>`, util.EscapeHTML(util.StringToReadOnlyBytes(node.Value.Name)), node.ShortName)
return ast.WalkContinue, nil
}

switch r.Method {
case Entity:
for _, r := range node.Value.Unicode {
Expand All @@ -293,20 +301,18 @@ func (r *emojiHTMLRenderer) renderEmoji(w util.BufWriter, source []byte, n ast.N
}
fmt.Fprintf(w, "&#x%x;", r)
}
case Unicode:
fmt.Fprintf(w, "%s", string(node.Value.Unicode))
case Twemoji:
if !node.Value.IsUnicode() {
_, _ = w.WriteString("&#xfffd;")
} else {
s := slash
if !r.XHTML {
s = empty
}
values := []string{}
for _, r := range node.Value.Unicode {
values = append(values, fmt.Sprintf("%x", r))
}
fmt.Fprintf(w, r.TwemojiTemplate, node.Value.Name, strings.Join(values, "-"), s)
s := slash
if !r.XHTML {
s = empty
}
values := []string{}
for _, r := range node.Value.Unicode {
values = append(values, fmt.Sprintf("%x", r))
}
fmt.Fprintf(w, r.TwemojiTemplate, util.EscapeHTML(util.StringToReadOnlyBytes(node.Value.Name)), strings.Join(values, "-"), s)
case Func:
r.RendererFunc(w, source, node, &r.RendererConfig)
}
Expand Down
95 changes: 95 additions & 0 deletions emoji_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,99 @@ func TestOptions(t *testing.T) {
<p><img class="emoji" alt="Fast parrot" src="https://cultofthepartyparrot.com/parrots/hd/fastparrot.gif></p>
`),
}, t)

markdown = goldmark.New(
goldmark.WithExtensions(
New(
WithRenderingMethod(Unicode),
),
),
)

count++
testutil.DoTestCase(markdown, testutil.MarkdownTestCase{
No: count,
Description: "unicode",
Markdown: strings.TrimSpace(`
Lucky :joy:
`),
Expected: strings.TrimSpace(`
<p>Lucky 😂</p>
`),
}, t)

markdown = goldmark.New(
goldmark.WithExtensions(
New(
WithEmojis(
definition.NewEmojis(
definition.NewEmoji("Fast parrot", nil, "fastparrot"),
),
),
WithRenderingMethod(Twemoji),
),
),
)

count++
testutil.DoTestCase(markdown, testutil.MarkdownTestCase{
No: count,
Description: "Non-unicode emoji in twemoji",
Markdown: strings.TrimSpace(`
:fastparrot:
`),
Expected: strings.TrimSpace(`
<p><span title="Fast parrot">:fastparrot:</span></p>
`),
}, t)

markdown = goldmark.New(
goldmark.WithExtensions(
New(
WithEmojis(
definition.NewEmojis(
definition.NewEmoji("Fast parrot", nil, "fastparrot"),
),
),
WithRenderingMethod(Entity),
),
),
)

count++
testutil.DoTestCase(markdown, testutil.MarkdownTestCase{
No: count,
Description: "Non-unicode emoji in entity",
Markdown: strings.TrimSpace(`
:fastparrot:
`),
Expected: strings.TrimSpace(`
<p><span title="Fast parrot">:fastparrot:</span></p>
`),
}, t)

markdown = goldmark.New(
goldmark.WithExtensions(
New(
WithEmojis(
definition.NewEmojis(
definition.NewEmoji("Fast parrot", nil, "fastparrot"),
),
),
WithRenderingMethod(Unicode),
),
),
)

count++
testutil.DoTestCase(markdown, testutil.MarkdownTestCase{
No: count,
Description: "Non-unicode emoji in unicode",
Markdown: strings.TrimSpace(`
:fastparrot:
`),
Expected: strings.TrimSpace(`
<p><span title="Fast parrot">:fastparrot:</span></p>
`),
}, t)
}

0 comments on commit 0faf8bc

Please sign in to comment.