Merge pull request #295 from Ambrevar/v2FactorSmarty

v2: Factor Smartypants to HTML
This commit is contained in:
Vytautas Šaltenis 2016-08-10 23:01:58 +03:00 committed by GitHub
commit 9926922c0b
5 changed files with 61 additions and 93 deletions

View File

@ -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
View File

@ -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 {

View File

@ -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 &ldquo;some&rdquo; quoted &ldquo;text&rdquo;.</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 &laquo;some&raquo; quoted &laquo;text&raquo;.</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 &mdash; bar</p>\n",
"foo --- bar\n",
"<p>foo &mdash;&ndash; 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 &ndash; bar</p>\n",
"foo --- bar\n",
"<p>foo &mdash; 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) {

View File

@ -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

View File

@ -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 {