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: many rendering issues #317

Merged
merged 36 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
15690b3
wip
caarlos0 Jul 12, 2024
a4999c1
wip
caarlos0 Jul 15, 2024
72a11e8
wip
caarlos0 Jul 16, 2024
8cb80e7
wip
caarlos0 Jul 16, 2024
23f13a3
fix: autolink
caarlos0 Jul 16, 2024
fb8db4a
fix: escape characters
caarlos0 Jul 16, 2024
7b94cd1
fix: table
caarlos0 Jul 16, 2024
50a0c1a
ci: golangci lint update
caarlos0 Jul 16, 2024
e20c9e6
feat: use x/golden
caarlos0 Jul 16, 2024
3665449
test: #106
caarlos0 Jul 16, 2024
51a0a46
test: #290
caarlos0 Jul 16, 2024
8dee638
test: #312
caarlos0 Jul 16, 2024
3fc0002
test: #257
caarlos0 Jul 16, 2024
5b1bc2a
test: #149
caarlos0 Jul 16, 2024
b6567c6
fix: #239
caarlos0 Jul 16, 2024
82d883e
feat: use lipgloss table
caarlos0 Jul 17, 2024
791a813
fix: codespan is not a block
caarlos0 Jul 17, 2024
041e267
test: #315
caarlos0 Jul 17, 2024
404fd7e
test: #316
caarlos0 Jul 17, 2024
31232f1
fix: #316
caarlos0 Jul 17, 2024
4a5ae52
test: table
caarlos0 Jul 17, 2024
a8b9af7
fix: codespans, tables
caarlos0 Jul 17, 2024
54f5fac
test: table
caarlos0 Jul 17, 2024
4830eb2
test: #117
caarlos0 Jul 17, 2024
f0e8355
test: #60
caarlos0 Jul 17, 2024
bb80234
fix: rm stylewriter
caarlos0 Jul 18, 2024
49bac14
fix: #313
caarlos0 Jul 18, 2024
63dca24
fix: margin
caarlos0 Jul 18, 2024
a4e220d
fix: blocks and word wrap
caarlos0 Jul 18, 2024
ac108c8
fix: build
caarlos0 Jul 18, 2024
33b8894
chore: gitattributes
caarlos0 Jul 18, 2024
9f68010
fix: test opt
caarlos0 Jul 18, 2024
c7ed991
fix: stable lipgloss
caarlos0 Jul 22, 2024
2e84e54
fix: double styles
caarlos0 Jul 22, 2024
cc0a410
fix: tables
caarlos0 Jul 22, 2024
342f07b
fix: tables
caarlos0 Jul 23, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
cmd/
!*.test
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ linters:
- godot
- godox
- goimports
- gomnd
- mnd
- goprintffuncname
- gosec
- misspell
Expand Down
55 changes: 44 additions & 11 deletions ansi/baseelement.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ func renderText(w io.Writer, p termenv.Profile, rules StylePrimitive, s string)
}

out := termenv.String(s)

if rules.Upper != nil && *rules.Upper {
out = termenv.String(strings.ToUpper(s))
}
Expand Down Expand Up @@ -79,35 +78,69 @@ func renderText(w io.Writer, p termenv.Profile, rules StylePrimitive, s string)
_, _ = io.WriteString(w, out.String())
}

func (e *BaseElement) StyleOverrideRender(w io.Writer, ctx RenderContext, style StylePrimitive) error {
bs := ctx.blockStack
st1 := cascadeStylePrimitives(bs.Current().Style.StylePrimitive, style)
st2 := cascadeStylePrimitives(bs.With(e.Style), style)

return e.doRender(w, ctx.options.ColorProfile, st1, st2)
}

func (e *BaseElement) Render(w io.Writer, ctx RenderContext) error {
bs := ctx.blockStack
st1 := bs.Current().Style.StylePrimitive
st2 := bs.With(e.Style)
return e.doRender(w, ctx.options.ColorProfile, st1, st2)
}

renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Prefix)
func (e *BaseElement) doRender(w io.Writer, p termenv.Profile, st1, st2 StylePrimitive) error {
renderText(w, p, st1, e.Prefix)
defer func() {
renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Suffix)
renderText(w, p, st1, e.Suffix)
}()

rules := bs.With(e.Style)
// render unstyled prefix/suffix
renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix)
renderText(w, p, st1, st2.BlockPrefix)
defer func() {
renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockSuffix)
renderText(w, p, st1, st2.BlockSuffix)
}()

// render styled prefix/suffix
renderText(w, ctx.options.ColorProfile, rules, rules.Prefix)
renderText(w, p, st2, st2.Prefix)
defer func() {
renderText(w, ctx.options.ColorProfile, rules, rules.Suffix)
renderText(w, p, st2, st2.Suffix)
}()

s := e.Token
if len(rules.Format) > 0 {
if len(st2.Format) > 0 {
var err error
s, err = formatToken(rules.Format, s)
s, err = formatToken(st2.Format, s)
if err != nil {
return err
}
}
renderText(w, ctx.options.ColorProfile, rules, s)
renderText(w, p, st2, escapeReplacer.Replace(s))
return nil
}

// https://www.markdownguide.org/basic-syntax/#characters-you-can-escape
var escapeReplacer = strings.NewReplacer(
"\\\\", "\\",
"\\`", "`",
"\\*", "*",
"\\_", "_",
"\\{", "{",
"\\}", "}",
"\\[", "[",
"\\]", "]",
"\\<", "<",
"\\>", ">",
"\\(", "(",
"\\)", ")",
"\\#", "#",
"\\+", "+",
"\\-", "-",
"\\.", ".",
"\\!", "!",
"\\|", "|",
)
96 changes: 48 additions & 48 deletions ansi/elements.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ type ElementRenderer interface {
Render(w io.Writer, ctx RenderContext) error
}

type StyleOverriderElementRenderer interface {
StyleOverrideRender(w io.Writer, ctx RenderContext, style StylePrimitive) error
}

// ElementFinisher is called when leaving a markdown node.
type ElementFinisher interface {
Finish(w io.Writer, ctx RenderContext) error
Expand Down Expand Up @@ -176,16 +180,16 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {

case ast.KindEmphasis:
n := node.(*ast.Emphasis)
s := string(n.Text(source))
style := ctx.options.Styles.Emph
if n.Level > 1 {
style = ctx.options.Styles.Strong
var children []ElementRenderer
nn := n.FirstChild()
for nn != nil {
children = append(children, tr.NewElement(nn, source).Renderer)
nn = nn.NextSibling()
}

return Element{
Renderer: &BaseElement{
Token: html.UnescapeString(s),
Style: style,
Renderer: &EmphasisElement{
Level: n.Level,
Children: children,
},
}

Expand Down Expand Up @@ -213,26 +217,45 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {
// Links
case ast.KindLink:
n := node.(*ast.Link)
var children []ElementRenderer
nn := n.FirstChild()
for nn != nil {
children = append(children, tr.NewElement(nn, source).Renderer)
nn = nn.NextSibling()
}
return Element{
Renderer: &LinkElement{
Text: textFromChildren(node, source),
BaseURL: ctx.options.BaseURL,
URL: string(n.Destination),
BaseURL: ctx.options.BaseURL,
URL: string(n.Destination),
Children: children,
},
}
case ast.KindAutoLink:
n := node.(*ast.AutoLink)
u := string(n.URL(source))
label := string(n.Label(source))

var children []ElementRenderer
nn := n.FirstChild()
for nn != nil {
children = append(children, tr.NewElement(nn, source).Renderer)
nn = nn.NextSibling()
}

if len(children) == 0 {
children = append(children, &BaseElement{
Token: u,
})
}

if n.AutoLinkType == ast.AutoLinkEmail && !strings.HasPrefix(strings.ToLower(u), "mailto:") {
u = "mailto:" + u
}

return Element{
Renderer: &LinkElement{
Text: label,
BaseURL: ctx.options.BaseURL,
URL: u,
Children: children,
BaseURL: ctx.options.BaseURL,
URL: u,
},
}

Expand Down Expand Up @@ -302,23 +325,17 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {
}

case astext.KindTableCell:
s := ""
n := node.FirstChild()
for n != nil {
switch t := n.(type) {
case *ast.AutoLink:
s += string(t.Label(source))
default:
s += string(n.Text(source))
}

n = n.NextSibling()
n := node.(*astext.TableCell)
var children []ElementRenderer
nn := n.FirstChild()
for nn != nil {
children = append(children, tr.NewElement(nn, source).Renderer)
nn = nn.NextSibling()
}

return Element{
Renderer: &TableCellElement{
Text: s,
Head: node.Parent().Kind() == astext.KindTableHeader,
Children: children,
Head: node.Parent().Kind() == astext.KindTableHeader,
},
}

Expand Down Expand Up @@ -358,20 +375,21 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {
Newline: true,
}
return Element{
Entering: "\n",
Renderer: e,
Finisher: e,
}

case astext.KindDefinitionTerm:
return Element{
Entering: "\n",
Renderer: &BaseElement{
Style: ctx.options.Styles.DefinitionTerm,
},
}

case astext.KindDefinitionDescription:
return Element{
Exiting: "\n",
Renderer: &BaseElement{
Style: ctx.options.Styles.DefinitionDescription,
},
Expand All @@ -398,21 +416,3 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {
return Element{}
}
}

func textFromChildren(node ast.Node, source []byte) string {
var s string
for c := node.FirstChild(); c != nil; c = c.NextSibling() {
if c.Kind() == ast.KindText {
cn := c.(*ast.Text)
s += string(cn.Segment.Value(source))

if cn.HardLineBreak() || (cn.SoftLineBreak()) {
s += "\n"
}
} else {
s += string(c.Text(source))
}
}

return s
}
44 changes: 44 additions & 0 deletions ansi/emphasis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ansi

import (
"io"
)

// A EmphasisElement is used to render emphasis.
type EmphasisElement struct {
Children []ElementRenderer
Level int
}

func (e *EmphasisElement) Render(w io.Writer, ctx RenderContext) error {
style := ctx.options.Styles.Emph
if e.Level > 1 {
style = ctx.options.Styles.Strong
}

return e.doRender(w, ctx, style)
}

func (e *EmphasisElement) StyleOverrideRender(w io.Writer, ctx RenderContext, style StylePrimitive) error {
base := ctx.options.Styles.Emph
if e.Level > 1 {
base = ctx.options.Styles.Strong
}
return e.doRender(w, ctx, cascadeStylePrimitives(base, style))
}

func (e *EmphasisElement) doRender(w io.Writer, ctx RenderContext, style StylePrimitive) error {
for _, child := range e.Children {
if r, ok := child.(StyleOverriderElementRenderer); ok {
if err := r.StyleOverrideRender(w, ctx, style); err != nil {
return err
}
} else {
if err := child.Render(w, ctx); err != nil {
return err
}
}
}

return nil
}
Loading