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

User friendly blockquote title #538

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
56 changes: 49 additions & 7 deletions renderer/blockquote.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package renderer
import (
"fmt"
"regexp"
"strings"

"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer"
Expand All @@ -12,14 +13,16 @@ import (

type ConfluenceBlockQuoteRenderer struct {
html.Config
LevelMap BlockQuoteLevelMap
LevelMap BlockQuoteLevelMap
BlockQuoteNode ast.Node
}

// NewConfluenceRenderer creates a new instance of the ConfluenceRenderer
func NewConfluenceBlockQuoteRenderer(opts ...html.Option) renderer.NodeRenderer {
return &ConfluenceBlockQuoteRenderer{
Config: html.NewConfig(),
LevelMap: nil,
Config: html.NewConfig(),
LevelMap: nil,
BlockQuoteNode: nil,
}
}

Expand All @@ -39,6 +42,14 @@ const (
None
)

// Define BlockQuoteClassifierType enum
type BlockQuoteClassifierType int

const (
Legacy BlockQuoteClassifierType = iota
GHAlerts
)

func (t BlockQuoteType) String() string {
return []string{"info", "note", "warning", "tip", "none"}[t]
}
Expand Down Expand Up @@ -93,8 +104,10 @@ func (classifier BlockQuoteClassifier) ClassifyingBlockQuote(literal string) Blo
}

// ParseBlockQuoteType parses the first line of a blockquote and returns its type
func ParseBlockQuoteType(node ast.Node, source []byte) BlockQuoteType {
func ParseBlockQuoteType(node ast.Node, source []byte) (BlockQuoteType, BlockQuoteClassifierType, ast.Node) {
var t = None
var ct = Legacy
var context ast.Node = nil
var legacyClassifier = LegacyBlockQuoteClassifier()
var ghAlertsClassifier = GHAlertsBlockQuoteClassifier()

Expand Down Expand Up @@ -126,6 +139,8 @@ func ParseBlockQuoteType(node ast.Node, source []byte) BlockQuoteType {
rightTextNode := rightNode.(*ast.Text)
if string(n.Value(source)) == "[" && string(rightTextNode.Value(source)) == "]" {
t = ghAlertsClassifier.ClassifyingBlockQuote(string(midTextNode.Value(source)))
ct = GHAlerts
context = midNode
}
}
}
Expand All @@ -150,7 +165,27 @@ func ParseBlockQuoteType(node ast.Node, source []byte) BlockQuoteType {
return ast.WalkContinue, nil
})

return t
return t, ct, context
}

// Helper function to update the source in place
func ghaAlertsUpdateSourceInPlace(source []byte, node ast.Node, value string) {
leftNode := node.PreviousSibling().(*ast.Text)
midNode := node.(*ast.Text)
rightNode := node.NextSibling().(*ast.Text)

title := string(midNode.Value(source))
sanitizedTitle := strings.Replace(strings.ToLower(title), "!", "", -1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing this on a character base, can we do it on a word base (i.e. look for the existing ghalerts with a [! in front and ] afterwards and then simply replace what you found?

capitalizedValue := strings.ToUpper(sanitizedTitle[:1]) + sanitizedTitle[1:]
if value != "" {
capitalizedValue = strings.ToUpper(value[:1]) + value[1:]
}

// Modify the source byte slice directly
copy(source[leftNode.Segment.Start:leftNode.Segment.Stop], []byte(" "))
format := fmt.Sprintf("%%-%ds", len(title))
copy(source[midNode.Segment.Start:midNode.Segment.Stop], []byte(fmt.Sprintf(format, capitalizedValue)))
copy(source[rightNode.Segment.Start:rightNode.Segment.Stop], []byte(" "))
}

// GenerateBlockQuoteLevel walks a given node and returns a map of blockquote levels
Expand Down Expand Up @@ -184,17 +219,24 @@ func (r *ConfluenceBlockQuoteRenderer) renderBlockQuote(writer util.BufWriter, s
r.LevelMap = GenerateBlockQuoteLevel(node)
}

quoteType := ParseBlockQuoteType(node, source)
quoteType, classifierType, blockQuoteCtxNode := ParseBlockQuoteType(node, source)
quoteLevel := r.LevelMap.Level(node)

if quoteLevel == 0 && entering && quoteType != None {
r.BlockQuoteNode = node

prefix := fmt.Sprintf("<ac:structured-macro ac:name=\"%s\"><ac:parameter ac:name=\"icon\">true</ac:parameter><ac:rich-text-body>\n", quoteType)
if _, err := writer.Write([]byte(prefix)); err != nil {
return ast.WalkStop, err
}
if classifierType == GHAlerts {
// Using quoteType as value like so: ghaAlertsUpdateSourceInPlace(source, blockQuoteCtxNode, quoteType.String())
// Will result in the blockquote title replaced by the blockquote type
ghaAlertsUpdateSourceInPlace(source, blockQuoteCtxNode, "")
}
return ast.WalkContinue, nil
}
if quoteLevel == 0 && !entering && quoteType != None {
if quoteLevel == 0 && !entering && node == r.BlockQuoteNode {
suffix := "</ac:rich-text-body></ac:structured-macro>\n"
if _, err := writer.Write([]byte(suffix)); err != nil {
return ast.WalkStop, err
Expand Down
10 changes: 5 additions & 5 deletions testdata/quotes-droph1.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,38 +48,38 @@ <h2 id="Simple-Blockquote">Simple Blockquote</h2>
<h2 id="GH-Alerts-Heading">GH Alerts Heading</h2>
<h3 id="Note-Type-Alert-Heading">Note Type Alert Heading</h3>
<ac:structured-macro ac:name="info"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!NOTE]</p>
<p> Note </p>
<ul>
<li>Note bullet 1</li>
<li>Note bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Tip-Type-Alert-Heading">Tip Type Alert Heading</h3>
<ac:structured-macro ac:name="tip"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!TIP]</p>
<p> Tip </p>
<ul>
<li>Tip bullet 1</li>
<li>Tip bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Warning-Type-Alert-Heading">Warning Type Alert Heading</h3>
<ac:structured-macro ac:name="note"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!WARNING]</p>
<p> Warning </p>
<ul>
<li>Warning bullet 1</li>
<li>Warning bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Important/Caution-Type-Alert-Heading">Important/Caution Type Alert Heading</h3>
<ac:structured-macro ac:name="info"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!IMPORTANT]</p>
<p> Important </p>
<ul>
<li>Important bullet 1</li>
<li>Important bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<ac:structured-macro ac:name="warning"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!CAUTION]</p>
<p> Caution </p>
<ul>
<li>Important bullet 1</li>
<li>Important bullet 2</li>
Expand Down
10 changes: 5 additions & 5 deletions testdata/quotes-stripnewlines.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,38 @@ <h2 id="Simple-Blockquote">Simple Blockquote</h2>
<h2 id="GH-Alerts-Heading">GH Alerts Heading</h2>
<h3 id="Note-Type-Alert-Heading">Note Type Alert Heading</h3>
<ac:structured-macro ac:name="info"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!NOTE]</p>
<p> Note </p>
<ul>
<li>Note bullet 1</li>
<li>Note bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Tip-Type-Alert-Heading">Tip Type Alert Heading</h3>
<ac:structured-macro ac:name="tip"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!TIP]</p>
<p> Tip </p>
<ul>
<li>Tip bullet 1</li>
<li>Tip bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Warning-Type-Alert-Heading">Warning Type Alert Heading</h3>
<ac:structured-macro ac:name="note"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!WARNING]</p>
<p> Warning </p>
<ul>
<li>Warning bullet 1</li>
<li>Warning bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Important/Caution-Type-Alert-Heading">Important/Caution Type Alert Heading</h3>
<ac:structured-macro ac:name="info"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!IMPORTANT]</p>
<p> Important </p>
<ul>
<li>Important bullet 1</li>
<li>Important bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<ac:structured-macro ac:name="warning"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!CAUTION]</p>
<p> Caution </p>
<ul>
<li>Important bullet 1</li>
<li>Important bullet 2</li>
Expand Down
10 changes: 5 additions & 5 deletions testdata/quotes.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,38 +49,38 @@ <h2 id="Simple-Blockquote">Simple Blockquote</h2>
<h2 id="GH-Alerts-Heading">GH Alerts Heading</h2>
<h3 id="Note-Type-Alert-Heading">Note Type Alert Heading</h3>
<ac:structured-macro ac:name="info"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!NOTE]</p>
<p> Note </p>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove the leading and trailing whitespaces on this?

<ul>
<li>Note bullet 1</li>
<li>Note bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Tip-Type-Alert-Heading">Tip Type Alert Heading</h3>
<ac:structured-macro ac:name="tip"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!TIP]</p>
<p> Tip </p>
<ul>
<li>Tip bullet 1</li>
<li>Tip bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Warning-Type-Alert-Heading">Warning Type Alert Heading</h3>
<ac:structured-macro ac:name="note"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!WARNING]</p>
<p> Warning </p>
<ul>
<li>Warning bullet 1</li>
<li>Warning bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<h3 id="Important/Caution-Type-Alert-Heading">Important/Caution Type Alert Heading</h3>
<ac:structured-macro ac:name="info"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!IMPORTANT]</p>
<p> Important </p>
<ul>
<li>Important bullet 1</li>
<li>Important bullet 2</li>
</ul>
</ac:rich-text-body></ac:structured-macro>
<ac:structured-macro ac:name="warning"><ac:parameter ac:name="icon">true</ac:parameter><ac:rich-text-body>
<p>[!CAUTION]</p>
<p> Caution </p>
<ul>
<li>Important bullet 1</li>
<li>Important bullet 2</li>
Expand Down
Loading