mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
godoc: peephole optimization for generated HTML
When searching for regular expressions such as ".", there are many consecutive matches. In the generated HTML, combine them instead of generating a new <span> for each adjacent text segment highlighting a match. Massively reduces the size of the generated HTML in those cases. R=r, rsc CC=golang-dev https://golang.org/cl/3971041
This commit is contained in:
parent
6f788e784e
commit
d4bdaf11d9
1 changed files with 48 additions and 12 deletions
|
|
@ -62,12 +62,48 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection,
|
||||||
if lw != nil {
|
if lw != nil {
|
||||||
selections = append(selections, links)
|
selections = append(selections, links)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute the sequence of consecutive segment changes
|
// compute the sequence of consecutive segment changes
|
||||||
changes := newMerger(selections)
|
changes := newMerger(selections)
|
||||||
|
|
||||||
// The i'th bit in bitset indicates that the text
|
// The i'th bit in bitset indicates that the text
|
||||||
// at the current offset is covered by selections[i].
|
// at the current offset is covered by selections[i].
|
||||||
bitset := 0
|
bitset := 0
|
||||||
lastOffs := 0
|
lastOffs := 0
|
||||||
|
|
||||||
|
// Text segments are written in a delayed fashion
|
||||||
|
// such that consecutive segments belonging to the
|
||||||
|
// same selection can be combined (peephole optimization).
|
||||||
|
// last describes the last segment which has not yet been written.
|
||||||
|
var last struct {
|
||||||
|
begin, end int // valid if begin < end
|
||||||
|
bitset int
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush writes the last delayed text segment
|
||||||
|
flush := func() {
|
||||||
|
if last.begin < last.end {
|
||||||
|
sw(w, text[last.begin:last.end], last.bitset)
|
||||||
|
}
|
||||||
|
last.begin = last.end // invalidate last
|
||||||
|
}
|
||||||
|
|
||||||
|
// segment runs the segment [lastOffs, end) with the selection
|
||||||
|
// indicated by bitset through the segment peephole optimizer.
|
||||||
|
segment := func(end int) {
|
||||||
|
if lastOffs < end { // ignore empty segments
|
||||||
|
if last.end != lastOffs || last.bitset != bitset {
|
||||||
|
// the last segment is not adjacent or
|
||||||
|
// differs from the new one
|
||||||
|
flush()
|
||||||
|
// start a new segment
|
||||||
|
last.begin = lastOffs
|
||||||
|
}
|
||||||
|
last.end = end
|
||||||
|
last.bitset = bitset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// get the next segment change
|
// get the next segment change
|
||||||
index, offs, start := changes.next()
|
index, offs, start := changes.next()
|
||||||
|
|
@ -81,14 +117,15 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection,
|
||||||
// we have a link segment change:
|
// we have a link segment change:
|
||||||
// format the previous selection segment, write the
|
// format the previous selection segment, write the
|
||||||
// link tag and start a new selection segment
|
// link tag and start a new selection segment
|
||||||
sw(w, text[lastOffs:offs], bitset)
|
segment(offs)
|
||||||
|
flush()
|
||||||
lastOffs = offs
|
lastOffs = offs
|
||||||
lw(w, offs, start)
|
lw(w, offs, start)
|
||||||
} else {
|
} else {
|
||||||
// we have a selection change:
|
// we have a selection change:
|
||||||
// format the previous selection segment, determine
|
// format the previous selection segment, determine
|
||||||
// the new selection bitset and start a new segment
|
// the new selection bitset and start a new segment
|
||||||
sw(w, text[lastOffs:offs], bitset)
|
segment(offs)
|
||||||
lastOffs = offs
|
lastOffs = offs
|
||||||
mask := 1 << uint(index)
|
mask := 1 << uint(index)
|
||||||
if start {
|
if start {
|
||||||
|
|
@ -98,7 +135,8 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sw(w, text[lastOffs:], bitset)
|
segment(len(text))
|
||||||
|
flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -283,7 +321,6 @@ var endTag = []byte(`</span>`)
|
||||||
|
|
||||||
|
|
||||||
func selectionTag(w io.Writer, text []byte, selections int) {
|
func selectionTag(w io.Writer, text []byte, selections int) {
|
||||||
if len(text) > 0 {
|
|
||||||
if selections < len(startTags) {
|
if selections < len(startTags) {
|
||||||
if tag := startTags[selections]; len(tag) > 0 {
|
if tag := startTags[selections]; len(tag) > 0 {
|
||||||
w.Write(tag)
|
w.Write(tag)
|
||||||
|
|
@ -294,7 +331,6 @@ func selectionTag(w io.Writer, text []byte, selections int) {
|
||||||
}
|
}
|
||||||
template.HTMLEscape(w, text)
|
template.HTMLEscape(w, text)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FormatText HTML-escapes text and returns it wrapped in <pre> tags.
|
// FormatText HTML-escapes text and returns it wrapped in <pre> tags.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue