(value string, newOutput *bytes.Buffer, cond func() bool, fn func(c rune, s int, idx int) int, finalize func())
| 109 | } |
| 110 | |
| 111 | func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func() bool, fn func(c rune, s int, idx int) int, finalize func()) { |
| 112 | vLen := len(value) |
| 113 | var tagStack []string |
| 114 | idx := 0 |
| 115 | |
| 116 | for idx < vLen && !cond() { |
| 117 | c, s := utf8.DecodeRuneInString(value[idx:]) |
| 118 | if c == utf8.RuneError { |
| 119 | idx += s |
| 120 | continue |
| 121 | } |
| 122 | |
| 123 | if c == '<' { |
| 124 | newOutput.WriteRune(c) |
| 125 | idx += s // consume "<" |
| 126 | |
| 127 | if idx+1 < vLen { |
| 128 | if value[idx] == '/' { |
| 129 | // Close tag |
| 130 | |
| 131 | newOutput.WriteString("/") |
| 132 | |
| 133 | tag := "" |
| 134 | idx++ // consume "/" |
| 135 | |
| 136 | for idx < vLen { |
| 137 | c2, size2 := utf8.DecodeRuneInString(value[idx:]) |
| 138 | if c2 == utf8.RuneError { |
| 139 | idx += size2 |
| 140 | continue |
| 141 | } |
| 142 | |
| 143 | // End of tag found |
| 144 | if c2 == '>' { |
| 145 | idx++ // consume ">" |
| 146 | break |
| 147 | } |
| 148 | tag += string(c2) |
| 149 | idx += size2 |
| 150 | } |
| 151 | |
| 152 | if len(tagStack) > 0 { |
| 153 | // Ideally, the close tag is TOP of tag stack |
| 154 | // In malformed HTML, it must not be, so iterate through the stack and remove the tag |
| 155 | for i := len(tagStack) - 1; i >= 0; i-- { |
| 156 | if tagStack[i] == tag { |
| 157 | // Found the tag |
| 158 | tagStack[i] = tagStack[len(tagStack)-1] |
| 159 | tagStack = tagStack[:len(tagStack)-1] |
| 160 | break |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | newOutput.WriteString(tag) |
| 166 | newOutput.WriteString(">") |
| 167 | } else { |
| 168 | // Open tag |
no test coverage detected
searching dependent graphs…