equal
deleted
inserted
replaced
16 import ( |
16 import ( |
17 "bytes" |
17 "bytes" |
18 "html" |
18 "html" |
19 "regexp" |
19 "regexp" |
20 "strings" |
20 "strings" |
21 |
21 "unicode" |
22 "github.com/shurcooL/sanitized_anchor_name" |
|
23 ) |
22 ) |
24 |
23 |
25 const ( |
24 const ( |
26 charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" |
25 charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" |
27 escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" |
26 escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" |
257 for end > 0 && data[end-1] == ' ' { |
256 for end > 0 && data[end-1] == ' ' { |
258 end-- |
257 end-- |
259 } |
258 } |
260 if end > i { |
259 if end > i { |
261 if id == "" && p.extensions&AutoHeadingIDs != 0 { |
260 if id == "" && p.extensions&AutoHeadingIDs != 0 { |
262 id = sanitized_anchor_name.Create(string(data[i:end])) |
261 id = SanitizedAnchorName(string(data[i:end])) |
263 } |
262 } |
264 block := p.addBlock(Heading, data[i:end]) |
263 block := p.addBlock(Heading, data[i:end]) |
265 block.HeadingID = id |
264 block.HeadingID = id |
266 block.Level = level |
265 block.Level = level |
267 } |
266 } |
671 var info string |
670 var info string |
672 beg, marker := isFenceLine(data, &info, "") |
671 beg, marker := isFenceLine(data, &info, "") |
673 if beg == 0 || beg >= len(data) { |
672 if beg == 0 || beg >= len(data) { |
674 return 0 |
673 return 0 |
675 } |
674 } |
|
675 fenceLength := beg - 1 |
676 |
676 |
677 var work bytes.Buffer |
677 var work bytes.Buffer |
678 work.Write([]byte(info)) |
678 work.Write([]byte(info)) |
679 work.WriteByte('\n') |
679 work.WriteByte('\n') |
680 |
680 |
704 } |
704 } |
705 |
705 |
706 if doRender { |
706 if doRender { |
707 block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer |
707 block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer |
708 block.IsFenced = true |
708 block.IsFenced = true |
|
709 block.FenceLength = fenceLength |
709 finalizeCodeBlock(block) |
710 finalizeCodeBlock(block) |
710 } |
711 } |
711 |
712 |
712 return beg |
713 return beg |
713 } |
714 } |
1501 eol-- |
1502 eol-- |
1502 } |
1503 } |
1503 |
1504 |
1504 id := "" |
1505 id := "" |
1505 if p.extensions&AutoHeadingIDs != 0 { |
1506 if p.extensions&AutoHeadingIDs != 0 { |
1506 id = sanitized_anchor_name.Create(string(data[prev:eol])) |
1507 id = SanitizedAnchorName(string(data[prev:eol])) |
1507 } |
1508 } |
1508 |
1509 |
1509 block := p.addBlock(Heading, data[prev:eol]) |
1510 block := p.addBlock(Heading, data[prev:eol]) |
1510 block.Level = level |
1511 block.Level = level |
1511 block.HeadingID = id |
1512 block.HeadingID = id |
1586 for i < len(text) && text[i] != char { |
1587 for i < len(text) && text[i] != char { |
1587 i++ |
1588 i++ |
1588 } |
1589 } |
1589 return i |
1590 return i |
1590 } |
1591 } |
|
1592 |
|
1593 // SanitizedAnchorName returns a sanitized anchor name for the given text. |
|
1594 // |
|
1595 // It implements the algorithm specified in the package comment. |
|
1596 func SanitizedAnchorName(text string) string { |
|
1597 var anchorName []rune |
|
1598 futureDash := false |
|
1599 for _, r := range text { |
|
1600 switch { |
|
1601 case unicode.IsLetter(r) || unicode.IsNumber(r): |
|
1602 if futureDash && len(anchorName) > 0 { |
|
1603 anchorName = append(anchorName, '-') |
|
1604 } |
|
1605 futureDash = false |
|
1606 anchorName = append(anchorName, unicode.ToLower(r)) |
|
1607 default: |
|
1608 futureDash = true |
|
1609 } |
|
1610 } |
|
1611 return string(anchorName) |
|
1612 } |