| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- // Copyright 2022 Frédéric Guillot. All rights reserved.
- // Use of this source code is governed by the Apache 2.0
- // license that can be found in the LICENSE file.
- package sanitizer
- import (
- "fmt"
- "strconv"
- "strings"
- )
- type ImageCandidate struct {
- ImageURL string
- Descriptor string
- }
- type ImageCandidates []*ImageCandidate
- func (c ImageCandidates) String() string {
- var htmlCandidates []string
- for _, imageCandidate := range c {
- var htmlCandidate string
- if imageCandidate.Descriptor != "" {
- htmlCandidate = fmt.Sprintf(`%s %s`, imageCandidate.ImageURL, imageCandidate.Descriptor)
- } else {
- htmlCandidate = imageCandidate.ImageURL
- }
- htmlCandidates = append(htmlCandidates, htmlCandidate)
- }
- return strings.Join(htmlCandidates, ", ")
- }
- // ParseSrcSetAttribute returns the list of image candidates from the set.
- // https://html.spec.whatwg.org/#parse-a-srcset-attribute
- func ParseSrcSetAttribute(attributeValue string) (imageCandidates ImageCandidates) {
- unparsedCandidates := strings.Split(attributeValue, ", ")
- for _, unparsedCandidate := range unparsedCandidates {
- if candidate, err := parseImageCandidate(unparsedCandidate); err == nil {
- imageCandidates = append(imageCandidates, candidate)
- }
- }
- return imageCandidates
- }
- func parseImageCandidate(input string) (*ImageCandidate, error) {
- input = strings.TrimSpace(input)
- parts := strings.Split(strings.TrimSpace(input), " ")
- nbParts := len(parts)
- if nbParts > 2 || nbParts == 0 {
- return nil, fmt.Errorf(`srcset: invalid number of descriptors`)
- }
- if nbParts == 2 {
- if !isValidWidthOrDensityDescriptor(parts[1]) {
- return nil, fmt.Errorf(`srcset: invalid descriptor`)
- }
- return &ImageCandidate{ImageURL: parts[0], Descriptor: parts[1]}, nil
- }
- return &ImageCandidate{ImageURL: parts[0]}, nil
- }
- func isValidWidthOrDensityDescriptor(value string) bool {
- if value == "" {
- return false
- }
- lastChar := value[len(value)-1:]
- if lastChar != "w" && lastChar != "x" {
- return false
- }
- _, err := strconv.ParseFloat(value[0:len(value)-1], 32)
- return err == nil
- }
|