]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
parser/metadecoders: Add CSV lazyQuotes option to transform.Unmarshal
authorJoe Mooring <joe.mooring@veriphor.com>
Sat, 13 Jan 2024 18:28:39 +0000 (10:28 -0800)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 16 Jan 2024 08:26:44 +0000 (09:26 +0100)
If true, a quote may appear in an unquoted field and a non-doubled quote
may appear in a quoted field. It defaults to false.

Closes #11884

docs/content/en/functions/transform/Unmarshal.md
parser/metadecoders/decoder.go
tpl/transform/integration_test.go

index 02524509b74f9a046b04edc9302c011709bca54a..e24f763814069ec361685603335f9f95cf005176 100644 (file)
@@ -125,6 +125,9 @@ delimiter
 comment
 : (`string`) The comment character used in the CSV. If set, lines beginning with the comment character without preceding whitespace are ignored.
 
+lazyQuotes
+: (`bool`) If true, a quote may appear in an unquoted field and a non-doubled quote may appear in a quoted field. Default is `false`.
+
 ```go-html-template
 {{ $csv := "a;b;c" | transform.Unmarshal (dict "delimiter" ";") }}
 ```
index 40b3a336cede1d5889ef46a23c5a3a05782327f0..35368e5a531e624cb4de18c65bcfc8300e26946e 100644 (file)
@@ -20,6 +20,7 @@ import (
        "fmt"
        "log"
        "regexp"
+       "strconv"
        "strings"
 
        "github.com/gohugoio/hugo/common/herrors"
@@ -41,6 +42,10 @@ type Decoder struct {
        // Comment, if not 0, is the comment character used in the CSV decoder. Lines beginning with the
        // Comment character without preceding whitespace are ignored.
        Comment rune
+
+       // If true, a quote may appear in an unquoted field and a non-doubled quote
+       // may appear in a quoted field. It defaults to false.
+       LazyQuotes bool
 }
 
 // OptionsKey is used in cache keys.
@@ -48,6 +53,7 @@ func (d Decoder) OptionsKey() string {
        var sb strings.Builder
        sb.WriteRune(d.Delimiter)
        sb.WriteRune(d.Comment)
+       sb.WriteString(strconv.FormatBool(d.LazyQuotes))
        return sb.String()
 }
 
@@ -205,6 +211,7 @@ func (d Decoder) unmarshalCSV(data []byte, v any) error {
        r := csv.NewReader(bytes.NewReader(data))
        r.Comma = d.Delimiter
        r.Comment = d.Comment
+       r.LazyQuotes = d.LazyQuotes
 
        records, err := r.ReadAll()
        if err != nil {
index 3ba65c715114a3b1cac956487e093eadf425ce1b..f035ec71964eea53d27686024e73079bf53512d8 100644 (file)
@@ -107,3 +107,29 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
        _, err := b.BuildE()
        b.Assert(err.Error(), qt.Contains, "error calling highlight: invalid Highlight option: 0")
 }
+
+// Issue #11884
+func TestUnmarshalCSVLazyDecoding(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+disableKinds = ['page','rss','section','sitemap','taxonomy','term']
+-- assets/pets.csv --
+name,description,age
+Spot,a nice dog,3
+Rover,"a big dog",5
+Felix,a "malicious" cat,7
+Bella,"an "evil" cat",9
+Scar,"a "dead cat",11
+-- layouts/index.html --
+{{ $opts := dict "lazyQuotes" true }}
+{{ $data := resources.Get "pets.csv" | transform.Unmarshal $opts }}
+{{ printf "%v" $data | safeHTML }}
+  `
+       b := hugolib.Test(t, files)
+
+       b.AssertFileContent("public/index.html", `
+[[name description age] [Spot a nice dog 3] [Rover a big dog 5] [Felix a "malicious" cat 7] [Bella an "evil" cat 9] [Scar a "dead cat 11]]
+       `)
+}