extractItemMeta collects the token, filename, and size from a large attachment item node. Returns ok=false when the token is missing. Expected structure (see largeAttItemTpl in mail/large_attachment.go): // icon <div
(item *xhtml.Node)
| 159 | // The token comes from the <a data-mail-token=...>. The first non-anchor |
| 160 | // text is the filename; the next text is the size display. |
| 161 | func extractItemMeta(item *xhtml.Node) (token string, meta LargeAttachmentSummary, ok bool) { |
| 162 | var texts []string |
| 163 | var insideAnchor bool |
| 164 | |
| 165 | var walk func(n *xhtml.Node) |
| 166 | walk = func(n *xhtml.Node) { |
| 167 | if n == nil { |
| 168 | return |
| 169 | } |
| 170 | if n.Type == xhtml.ElementNode && n.Data == "a" { |
| 171 | if t := attr(n, LargeAttachmentTokenAttr); t != "" && token == "" { |
| 172 | token = t |
| 173 | } |
| 174 | // Skip collecting the anchor's label (e.g. "Download" / "下载"). |
| 175 | prev := insideAnchor |
| 176 | insideAnchor = true |
| 177 | defer func() { insideAnchor = prev }() |
| 178 | } |
| 179 | if n.Type == xhtml.TextNode && !insideAnchor { |
| 180 | if s := strings.TrimSpace(n.Data); s != "" { |
| 181 | texts = append(texts, s) |
| 182 | } |
| 183 | } |
| 184 | for c := n.FirstChild; c != nil; c = c.NextSibling { |
| 185 | walk(c) |
| 186 | } |
| 187 | } |
| 188 | walk(item) |
| 189 | |
| 190 | if token == "" { |
| 191 | return "", LargeAttachmentSummary{}, false |
| 192 | } |
| 193 | if len(texts) > 0 { |
| 194 | meta.FileName = texts[0] |
| 195 | } |
| 196 | if len(texts) > 1 { |
| 197 | meta.SizeBytes = parseSizeDisplay(texts[1]) |
| 198 | } |
| 199 | return token, meta, true |
| 200 | } |
| 201 | |
| 202 | func attr(n *xhtml.Node, name string) string { |
| 203 | for _, a := range n.Attr { |
no test coverage detected