Implement support for CDATA section

Fixes #165.
This commit is contained in:
Vytautas Šaltenis 2015-12-14 20:23:49 +02:00
parent d18b67ae0a
commit 05a79218ed
2 changed files with 56 additions and 19 deletions

View File

@ -320,6 +320,11 @@ func (p *parser) html(out *bytes.Buffer, data []byte, doRender bool) int {
return size
}
// check for HTML CDATA
if size := p.htmlCDATA(out, data, doRender); size > 0 {
return size
}
// no special case recognized
return 0
}
@ -397,12 +402,10 @@ func (p *parser) html(out *bytes.Buffer, data []byte, doRender bool) int {
return i
}
// HTML comment, lax form
func (p *parser) htmlComment(out *bytes.Buffer, data []byte, doRender bool) int {
i := p.inlineHtmlComment(out, data)
// needs to end with a blank line
if j := p.isEmpty(data[i:]); j > 0 {
size := i + j
func (p *parser) renderHtmlBlock(out *bytes.Buffer, data []byte, start int, doRender bool) int {
// html block needs to end with a blank line
if i := p.isEmpty(data[start:]); i > 0 {
size := start + i
if doRender {
// trim trailing newlines
end := size
@ -416,6 +419,35 @@ func (p *parser) htmlComment(out *bytes.Buffer, data []byte, doRender bool) int
return 0
}
// HTML comment, lax form
func (p *parser) htmlComment(out *bytes.Buffer, data []byte, doRender bool) int {
i := p.inlineHtmlComment(out, data)
return p.renderHtmlBlock(out, data, i, doRender)
}
// HTML CDATA section
func (p *parser) htmlCDATA(out *bytes.Buffer, data []byte, doRender bool) int {
cdataTag := "<![cdata["
cdataTagLen := len(cdataTag)
if len(data) < cdataTagLen+1 {
return 0
}
if !bytes.Equal(bytes.ToLower(data[:cdataTagLen]), []byte(cdataTag)) {
return 0
}
i := cdataTagLen
// scan for an end-of-comment marker, across lines if necessary
for i < len(data) && !(data[i-2] == ']' && data[i-1] == ']' && data[i] == '>') {
i++
}
i++
// no end-of-comment marker
if i >= len(data) {
return 0
}
return p.renderHtmlBlock(out, data, i, doRender)
}
// HR, which is the only self-closing block tag considered
func (p *parser) htmlHr(out *bytes.Buffer, data []byte, doRender bool) int {
if data[0] != '<' || (data[1] != 'h' && data[1] != 'H') || (data[2] != 'r' && data[2] != 'R') {
@ -432,19 +464,7 @@ func (p *parser) htmlHr(out *bytes.Buffer, data []byte, doRender bool) int {
}
if data[i] == '>' {
i++
if j := p.isEmpty(data[i:]); j > 0 {
size := i + j
if doRender {
// trim newlines
end := size
for end > 0 && data[end-1] == '\n' {
end--
}
p.r.BlockHtml(out, data[:end])
}
return size
}
return p.renderHtmlBlock(out, data, i+1, doRender)
}
return 0

View File

@ -1530,3 +1530,20 @@ func TestBlockComments(t *testing.T) {
}
doTestsBlock(t, tests, 0)
}
func TestCDATA(t *testing.T) {
var tests = []string{
"Some text\n\n<![CDATA[foo]]>\n",
"<p>Some text</p>\n\n<![CDATA[foo]]>\n",
"CDATA ]]\n\n<![CDATA[]]]]>\n",
"<p>CDATA ]]</p>\n\n<![CDATA[]]]]>\n",
"CDATA >\n\n<![CDATA[>]]>\n",
"<p>CDATA &gt;</p>\n\n<![CDATA[>]]>\n",
"Lots of text\n\n<![CDATA[lots of te><t\non\nseveral\nlines]]>\n",
"<p>Lots of text</p>\n\n<![CDATA[lots of te><t\non\nseveral\nlines]]>\n",
}
doTestsBlock(t, tests, 0)
}