mirror of
https://github.com/russross/blackfriday.git
synced 2024-03-22 13:40:34 +08:00
Factor Smartypants to HTML
Smartypants is HTML-specific. There is no need to run Smartypants from `Render()`. This simplifies extensions built upon the HTML renderer.
This commit is contained in:
parent
37141d5b5a
commit
02da1dfe9d
|
@ -106,7 +106,7 @@ func doLinkTestsInline(t *testing.T, tests []string) {
|
|||
HTMLRendererParameters: params,
|
||||
})
|
||||
doTestsInlineParam(t, transformTests, TestParams{
|
||||
HTMLFlags: CommonHTMLFlags,
|
||||
HTMLFlags: UseXHTML,
|
||||
HTMLRendererParameters: params,
|
||||
})
|
||||
}
|
||||
|
|
57
html.go
57
html.go
|
@ -29,18 +29,23 @@ type HTMLFlags int
|
|||
|
||||
// HTML renderer configuration options.
|
||||
const (
|
||||
HTMLFlagsNone HTMLFlags = 0
|
||||
SkipHTML HTMLFlags = 1 << iota // Skip preformatted HTML blocks
|
||||
SkipStyle // Skip embedded <style> elements
|
||||
SkipImages // Skip embedded images
|
||||
SkipLinks // Skip all links
|
||||
Safelink // Only link to trusted protocols
|
||||
NofollowLinks // Only link with rel="nofollow"
|
||||
NoreferrerLinks // Only link with rel="noreferrer"
|
||||
HrefTargetBlank // Add a blank target
|
||||
CompletePage // Generate a complete HTML page
|
||||
UseXHTML // Generate XHTML output instead of HTML
|
||||
FootnoteReturnLinks // Generate a link at the end of a footnote to return to the source
|
||||
HTMLFlagsNone HTMLFlags = 0
|
||||
SkipHTML HTMLFlags = 1 << iota // Skip preformatted HTML blocks
|
||||
SkipStyle // Skip embedded <style> elements
|
||||
SkipImages // Skip embedded images
|
||||
SkipLinks // Skip all links
|
||||
Safelink // Only link to trusted protocols
|
||||
NofollowLinks // Only link with rel="nofollow"
|
||||
NoreferrerLinks // Only link with rel="noreferrer"
|
||||
HrefTargetBlank // Add a blank target
|
||||
CompletePage // Generate a complete HTML page
|
||||
UseXHTML // Generate XHTML output instead of HTML
|
||||
FootnoteReturnLinks // Generate a link at the end of a footnote to return to the source
|
||||
Smartypants // Enable smart punctuation substitutions
|
||||
SmartypantsFractions // Enable smart fractions (with Smartypants)
|
||||
SmartypantsDashes // Enable smart dashes (with Smartypants)
|
||||
SmartypantsLatexDashes // Enable LaTeX-style dashes (with Smartypants)
|
||||
SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering
|
||||
|
||||
TagName = "[A-Za-z][A-Za-z0-9-]*"
|
||||
AttributeName = "[a-zA-Z_:][a-zA-Z0-9:._-]*"
|
||||
|
@ -102,6 +107,8 @@ type HTMLRenderer struct {
|
|||
|
||||
lastOutputLen int
|
||||
disableTags int
|
||||
|
||||
sr *SPRenderer
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -127,6 +134,8 @@ func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer {
|
|||
|
||||
closeTag: closeTag,
|
||||
headerIDs: make(map[string]int),
|
||||
|
||||
sr: NewSmartypantsRenderer(params.Flags),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,6 +411,10 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt
|
|||
attrs := []string{}
|
||||
switch node.Type {
|
||||
case Text:
|
||||
node.Literal = esc(node.Literal)
|
||||
if r.Flags&Smartypants != 0 {
|
||||
node.Literal = r.sr.Process(node.Literal)
|
||||
}
|
||||
r.out(w, node.Literal)
|
||||
break
|
||||
case Softbreak:
|
||||
|
@ -705,7 +718,7 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt
|
|||
return GoToNext
|
||||
}
|
||||
|
||||
func (r *HTMLRenderer) writeDocumentHeader(w *bytes.Buffer, sr *SPRenderer) {
|
||||
func (r *HTMLRenderer) writeDocumentHeader(w *bytes.Buffer) {
|
||||
if r.Flags&CompletePage == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -721,8 +734,8 @@ func (r *HTMLRenderer) writeDocumentHeader(w *bytes.Buffer, sr *SPRenderer) {
|
|||
}
|
||||
w.WriteString("<head>\n")
|
||||
w.WriteString(" <title>")
|
||||
if r.Extensions&Smartypants != 0 {
|
||||
w.Write(sr.Process([]byte(r.Title)))
|
||||
if r.Flags&Smartypants != 0 {
|
||||
w.Write(r.sr.Process([]byte(r.Title)))
|
||||
} else {
|
||||
w.Write(esc([]byte(r.Title)))
|
||||
}
|
||||
|
@ -817,20 +830,8 @@ func (r *HTMLRenderer) writeDocumentFooter(w *bytes.Buffer) {
|
|||
func (r *HTMLRenderer) Render(ast *Node) []byte {
|
||||
//println("render_Blackfriday")
|
||||
//dump(ast)
|
||||
// Run Smartypants if it's enabled or simply escape text if not
|
||||
sr := NewSmartypantsRenderer(r.Extensions)
|
||||
ast.Walk(func(node *Node, entering bool) WalkStatus {
|
||||
if node.Type == Text {
|
||||
if r.Extensions&Smartypants != 0 {
|
||||
node.Literal = sr.Process(node.Literal)
|
||||
} else {
|
||||
node.Literal = esc(node.Literal)
|
||||
}
|
||||
}
|
||||
return GoToNext
|
||||
})
|
||||
var buff bytes.Buffer
|
||||
r.writeDocumentHeader(&buff, sr)
|
||||
r.writeDocumentHeader(&buff)
|
||||
if r.Extensions&TOC != 0 || r.Extensions&OmitContents != 0 {
|
||||
r.writeTOC(&buff, ast)
|
||||
if r.Extensions&OmitContents != 0 {
|
||||
|
|
|
@ -1012,11 +1012,7 @@ func TestInlineComments(t *testing.T) {
|
|||
"blahblah\n<!--- foo -->\nrhubarb\n",
|
||||
"<p>blahblah\n<!--- foo -->\nrhubarb</p>\n",
|
||||
}
|
||||
doTestsInlineParam(t, tests, TestParams{
|
||||
Options: Options{
|
||||
Extensions: Smartypants | SmartypantsDashes,
|
||||
},
|
||||
})
|
||||
doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsDashes})
|
||||
}
|
||||
|
||||
func TestSmartDoubleQuotes(t *testing.T) {
|
||||
|
@ -1028,11 +1024,7 @@ func TestSmartDoubleQuotes(t *testing.T) {
|
|||
"two pair of \"some\" quoted \"text\".\n",
|
||||
"<p>two pair of “some” quoted “text”.</p>\n"}
|
||||
|
||||
doTestsInlineParam(t, tests, TestParams{
|
||||
Options: Options{
|
||||
Extensions: Smartypants,
|
||||
},
|
||||
})
|
||||
doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants})
|
||||
}
|
||||
|
||||
func TestSmartAngledDoubleQuotes(t *testing.T) {
|
||||
|
@ -1044,11 +1036,7 @@ func TestSmartAngledDoubleQuotes(t *testing.T) {
|
|||
"two pair of \"some\" quoted \"text\".\n",
|
||||
"<p>two pair of «some» quoted «text».</p>\n"}
|
||||
|
||||
doTestsInlineParam(t, tests, TestParams{
|
||||
Options: Options{
|
||||
Extensions: Smartypants | SmartypantsAngledQuotes,
|
||||
},
|
||||
})
|
||||
doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsAngledQuotes})
|
||||
}
|
||||
|
||||
func TestSmartFractions(t *testing.T) {
|
||||
|
@ -1058,11 +1046,7 @@ func TestSmartFractions(t *testing.T) {
|
|||
"1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.\n",
|
||||
"<p>1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.</p>\n"}
|
||||
|
||||
doTestsInlineParam(t, tests, TestParams{
|
||||
Options: Options{
|
||||
Extensions: Smartypants,
|
||||
},
|
||||
})
|
||||
doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants})
|
||||
|
||||
tests = []string{
|
||||
"1/2, 2/3, 81/100 and 1000000/1048576.\n",
|
||||
|
@ -1070,11 +1054,7 @@ func TestSmartFractions(t *testing.T) {
|
|||
"1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.\n",
|
||||
"<p>1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.</p>\n"}
|
||||
|
||||
doTestsInlineParam(t, tests, TestParams{
|
||||
Options: Options{
|
||||
Extensions: Smartypants | SmartypantsFractions,
|
||||
},
|
||||
})
|
||||
doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsFractions})
|
||||
}
|
||||
|
||||
func TestDisableSmartDashes(t *testing.T) {
|
||||
|
@ -1093,7 +1073,7 @@ func TestDisableSmartDashes(t *testing.T) {
|
|||
"<p>foo — bar</p>\n",
|
||||
"foo --- bar\n",
|
||||
"<p>foo —– bar</p>\n",
|
||||
}, TestParams{Options: Options{Extensions: Smartypants | SmartypantsDashes}})
|
||||
}, TestParams{HTMLFlags: Smartypants | SmartypantsDashes})
|
||||
doTestsInlineParam(t, []string{
|
||||
"foo - bar\n",
|
||||
"<p>foo - bar</p>\n",
|
||||
|
@ -1101,11 +1081,7 @@ func TestDisableSmartDashes(t *testing.T) {
|
|||
"<p>foo – bar</p>\n",
|
||||
"foo --- bar\n",
|
||||
"<p>foo — bar</p>\n",
|
||||
}, TestParams{
|
||||
Options: Options{
|
||||
Extensions: Smartypants | SmartypantsLatexDashes | SmartypantsDashes,
|
||||
},
|
||||
})
|
||||
}, TestParams{HTMLFlags: Smartypants | SmartypantsLatexDashes | SmartypantsDashes})
|
||||
doTestsInlineParam(t, []string{
|
||||
"foo - bar\n",
|
||||
"<p>foo - bar</p>\n",
|
||||
|
@ -1113,9 +1089,7 @@ func TestDisableSmartDashes(t *testing.T) {
|
|||
"<p>foo -- bar</p>\n",
|
||||
"foo --- bar\n",
|
||||
"<p>foo --- bar</p>\n",
|
||||
}, TestParams{
|
||||
Options: Options{Extensions: Smartypants | SmartypantsLatexDashes},
|
||||
})
|
||||
}, TestParams{HTMLFlags: Smartypants | SmartypantsLatexDashes})
|
||||
}
|
||||
|
||||
func TestSkipLinks(t *testing.T) {
|
||||
|
|
49
markdown.go
49
markdown.go
|
@ -36,37 +36,32 @@ type Extensions int
|
|||
// These are the supported markdown parsing extensions.
|
||||
// OR these values together to select multiple extensions.
|
||||
const (
|
||||
NoExtensions Extensions = 0
|
||||
NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words
|
||||
Tables // Render tables
|
||||
FencedCode // Render fenced code blocks
|
||||
Autolink // Detect embedded URLs that are not explicitly marked
|
||||
Strikethrough // Strikethrough text using ~~test~~
|
||||
LaxHTMLBlocks // Loosen up HTML block parsing rules
|
||||
SpaceHeaders // Be strict about prefix header rules
|
||||
HardLineBreak // Translate newlines into line breaks
|
||||
TabSizeEight // Expand tabs to eight spaces instead of four
|
||||
Footnotes // Pandoc-style footnotes
|
||||
NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block
|
||||
HeaderIDs // specify header IDs with {#id}
|
||||
Titleblock // Titleblock ala pandoc
|
||||
AutoHeaderIDs // Create the header ID from the text
|
||||
BackslashLineBreak // Translate trailing backslashes into line breaks
|
||||
DefinitionLists // Render definition lists
|
||||
Smartypants // Enable smart punctuation substitutions
|
||||
SmartypantsFractions // Enable smart fractions (with Smartypants)
|
||||
SmartypantsDashes // Enable smart dashes (with Smartypants)
|
||||
SmartypantsLatexDashes // Enable LaTeX-style dashes (with Smartypants)
|
||||
SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering
|
||||
TOC // Generate a table of contents
|
||||
OmitContents // Skip the main contents (for a standalone table of contents)
|
||||
NoExtensions Extensions = 0
|
||||
NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words
|
||||
Tables // Render tables
|
||||
FencedCode // Render fenced code blocks
|
||||
Autolink // Detect embedded URLs that are not explicitly marked
|
||||
Strikethrough // Strikethrough text using ~~test~~
|
||||
LaxHTMLBlocks // Loosen up HTML block parsing rules
|
||||
SpaceHeaders // Be strict about prefix header rules
|
||||
HardLineBreak // Translate newlines into line breaks
|
||||
TabSizeEight // Expand tabs to eight spaces instead of four
|
||||
Footnotes // Pandoc-style footnotes
|
||||
NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block
|
||||
HeaderIDs // specify header IDs with {#id}
|
||||
Titleblock // Titleblock ala pandoc
|
||||
AutoHeaderIDs // Create the header ID from the text
|
||||
BackslashLineBreak // Translate trailing backslashes into line breaks
|
||||
DefinitionLists // Render definition lists
|
||||
TOC // Generate a table of contents
|
||||
OmitContents // Skip the main contents (for a standalone table of contents)
|
||||
|
||||
CommonHTMLFlags HTMLFlags = UseXHTML
|
||||
CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants |
|
||||
SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
|
||||
|
||||
CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode |
|
||||
Autolink | Strikethrough | SpaceHeaders | HeaderIDs |
|
||||
BackslashLineBreak | DefinitionLists | Smartypants |
|
||||
SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
|
||||
BackslashLineBreak | DefinitionLists
|
||||
)
|
||||
|
||||
// DefaultOptions is a convenience variable with all the options that are
|
||||
|
|
|
@ -368,7 +368,7 @@ func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text [
|
|||
type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int
|
||||
|
||||
// NewSmartypantsRenderer constructs a Smartypants renderer object.
|
||||
func NewSmartypantsRenderer(flags Extensions) *SPRenderer {
|
||||
func NewSmartypantsRenderer(flags HTMLFlags) *SPRenderer {
|
||||
var r SPRenderer
|
||||
if flags&SmartypantsAngledQuotes == 0 {
|
||||
r.callbacks['"'] = r.smartDoubleQuote
|
||||
|
@ -403,8 +403,6 @@ func NewSmartypantsRenderer(flags Extensions) *SPRenderer {
|
|||
// Process is the entry point of the Smartypants renderer.
|
||||
func (r *SPRenderer) Process(text []byte) []byte {
|
||||
var buff bytes.Buffer
|
||||
// first do normal entity escaping
|
||||
text = esc(text)
|
||||
mark := 0
|
||||
for i := 0; i < len(text); i++ {
|
||||
if action := r.callbacks[text[i]]; action != nil {
|
||||
|
|
Loading…
Reference in New Issue
Block a user