]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
markup/goldmark: Add config options for the typographer extension
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 12 Apr 2023 08:15:02 +0000 (10:15 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 12 Apr 2023 12:41:32 +0000 (14:41 +0200)
Note that the config per language part of this will be handled in #10602.

Updates #9772

markup/goldmark/convert.go
markup/goldmark/convert_test.go
markup/goldmark/goldmark_config/config.go
markup/markup_config/config.go
markup/markup_config/config_test.go

index 3c8dbb299c99869d3d430b8f25ff7f693a7416fa..efcfb714255f15138f7b37f57e255a2ba360b9af 100644 (file)
@@ -20,6 +20,7 @@ import (
        "github.com/gohugoio/hugo/identity"
 
        "github.com/gohugoio/hugo/markup/goldmark/codeblocks"
+       "github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
        "github.com/gohugoio/hugo/markup/goldmark/images"
        "github.com/gohugoio/hugo/markup/goldmark/internal/extensions/attributes"
        "github.com/gohugoio/hugo/markup/goldmark/internal/render"
@@ -120,8 +121,11 @@ func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown {
                extensions = append(extensions, extension.TaskList)
        }
 
-       if cfg.Extensions.Typographer {
-               extensions = append(extensions, extension.Typographer)
+       if !cfg.Extensions.Typographer.Disable {
+               t := extension.NewTypographer(
+                       extension.WithTypographicSubstitutions(toTypographicPunctuationMap(cfg.Extensions.Typographer)),
+               )
+               extensions = append(extensions, t)
        }
 
        if cfg.Extensions.DefinitionList {
@@ -278,3 +282,21 @@ func (p *parserContext) TableOfContents() *tableofcontents.Fragments {
        }
        return nil
 }
+
+// Note: It's tempting to put this in the config package, but that doesn't work.
+// TODO(bep) create upstream issue.
+func toTypographicPunctuationMap(t goldmark_config.Typographer) map[extension.TypographicPunctuation][]byte {
+       return map[extension.TypographicPunctuation][]byte{
+               extension.LeftSingleQuote:  []byte(t.LeftSingleQuote),
+               extension.RightSingleQuote: []byte(t.RightSingleQuote),
+               extension.LeftDoubleQuote:  []byte(t.LeftDoubleQuote),
+               extension.RightDoubleQuote: []byte(t.RightDoubleQuote),
+               extension.EnDash:           []byte(t.EnDash),
+               extension.EmDash:           []byte(t.EmDash),
+               extension.Ellipsis:         []byte(t.Ellipsis),
+               extension.LeftAngleQuote:   []byte(t.LeftAngleQuote),
+               extension.RightAngleQuote:  []byte(t.RightAngleQuote),
+               extension.Apostrophe:       []byte(t.Apostrophe),
+       }
+
+}
index 647ffce583ccb831fa0c5f2f5d2c913dd2afcf90..e92c651fc232875de5c9cfa74800f317403ed344 100644 (file)
@@ -499,3 +499,18 @@ LINE5
                c.Assert(result, qt.Contains, "<span class=\"ln\">2</span><span class=\"cl\">LINE2\n</span></span>")
        })
 }
+
+func TestTypographerConfig(t *testing.T) {
+       c := qt.New(t)
+
+       content := `
+A "quote" and 'another quote' and a "quote with a 'nested' quote" and a 'quote with a "nested" quote' and an ellipsis...
+`
+       mconf := markup_config.Default
+       mconf.Goldmark.Extensions.Typographer.LeftDoubleQuote = "&laquo;"
+       mconf.Goldmark.Extensions.Typographer.RightDoubleQuote = "&raquo;"
+       b := convert(c, mconf, content)
+       got := string(b.Bytes())
+
+       c.Assert(got, qt.Contains, "<p>A &laquo;quote&raquo; and &lsquo;another quote&rsquo; and a &laquo;quote with a &rsquo;nested&rsquo; quote&raquo; and a &lsquo;quote with a &laquo;nested&raquo; quote&rsquo; and an ellipsis&hellip;</p>\n")
+}
index ff0b6bbef923076885350b07c70a7f38aeb13640..f35427ac180b5136b1535351fba724b2ed581149 100644 (file)
@@ -23,7 +23,19 @@ const (
 // DefaultConfig holds the default Goldmark configuration.
 var Default = Config{
        Extensions: Extensions{
-               Typographer:     true,
+               Typographer: Typographer{
+                       Disable:          false,
+                       LeftSingleQuote:  "&lsquo;",
+                       RightSingleQuote: "&rsquo;",
+                       LeftDoubleQuote:  "&ldquo;",
+                       RightDoubleQuote: "&rdquo;",
+                       EnDash:           "&ndash;",
+                       EmDash:           "&mdash;",
+                       Ellipsis:         "&hellip;",
+                       LeftAngleQuote:   "&laquo;",
+                       RightAngleQuote:  "&raquo;",
+                       Apostrophe:       "&rsquo;",
+               },
                Footnote:        true,
                DefinitionList:  true,
                Table:           true,
@@ -54,7 +66,7 @@ type Config struct {
 }
 
 type Extensions struct {
-       Typographer    bool
+       Typographer    Typographer
        Footnote       bool
        DefinitionList bool
 
@@ -66,6 +78,33 @@ type Extensions struct {
        TaskList        bool
 }
 
+// Typographer holds typographer configuration.
+type Typographer struct {
+       // Whether to disable typographer.
+       Disable bool
+
+       // Value used for left single quote.
+       LeftSingleQuote string
+       // Value used for right single quote.
+       RightSingleQuote string
+       // Value used for left double quote.
+       LeftDoubleQuote string
+       // Value used for right double quote.
+       RightDoubleQuote string
+       // Value used for en dash.
+       EnDash string
+       // Value used for em dash.
+       EmDash string
+       // Value used for ellipsis.
+       Ellipsis string
+       // Value used for left angle quote.
+       LeftAngleQuote string
+       // Value used for right angle quote.
+       RightAngleQuote string
+       // Value used for apostrophe.
+       Apostrophe string
+}
+
 type Renderer struct {
        // Whether softline breaks should be rendered as '<br>'
        HardWraps bool
index e254ba7a03e3ebec03bd5793dc03312e855ae2de..60446b9bcc6f2096cd76ef459fe843f0620b6081 100644 (file)
@@ -62,15 +62,32 @@ func Decode(cfg config.Provider) (conf Config, err error) {
 
 func normalizeConfig(m map[string]any) {
        v, err := maps.GetNestedParam("goldmark.parser", ".", m)
-       if err != nil {
-               return
+       if err == nil {
+               vm := maps.ToStringMap(v)
+               // Changed from a bool in 0.81.0
+               if vv, found := vm["attribute"]; found {
+                       if vvb, ok := vv.(bool); ok {
+                               vm["attribute"] = goldmark_config.ParserAttribute{
+                                       Title: vvb,
+                               }
+                       }
+               }
        }
-       vm := maps.ToStringMap(v)
-       // Changed from a bool in 0.81.0
-       if vv, found := vm["attribute"]; found {
-               if vvb, ok := vv.(bool); ok {
-                       vm["attribute"] = goldmark_config.ParserAttribute{
-                               Title: vvb,
+
+       // Changed from a bool in 0.112.0.
+       v, err = maps.GetNestedParam("goldmark.extensions", ".", m)
+       if err == nil {
+               vm := maps.ToStringMap(v)
+               const typographerKey = "typographer"
+               if vv, found := vm[typographerKey]; found {
+                       if vvb, ok := vv.(bool); ok {
+                               if !vvb {
+                                       vm[typographerKey] = goldmark_config.Typographer{
+                                               Disable: true,
+                                       }
+                               } else {
+                                       delete(vm, typographerKey)
+                               }
                        }
                }
        }
index a320e6912a6a6b971ec1112642d36e77894a784d..782cedbc978b5d1a908ed7ff30770690f3a75063 100644 (file)
@@ -52,4 +52,38 @@ func TestConfig(t *testing.T) {
                c.Assert(conf.AsciidocExt.Extensions[0], qt.Equals, "asciidoctor-html5s")
        })
 
+       c.Run("Decode legacy typographer", func(c *qt.C) {
+               c.Parallel()
+               v := config.New()
+
+               // typographer was changed from a bool to a struct in 0.112.0.
+               v.Set("markup", map[string]any{
+                       "goldmark": map[string]any{
+                               "extensions": map[string]any{
+                                       "typographer": false,
+                               },
+                       },
+               })
+
+               conf, err := Decode(v)
+
+               c.Assert(err, qt.IsNil)
+               c.Assert(conf.Goldmark.Extensions.Typographer.Disable, qt.Equals, true)
+
+               v.Set("markup", map[string]any{
+                       "goldmark": map[string]any{
+                               "extensions": map[string]any{
+                                       "typographer": true,
+                               },
+                       },
+               })
+
+               conf, err = Decode(v)
+
+               c.Assert(err, qt.IsNil)
+               c.Assert(conf.Goldmark.Extensions.Typographer.Disable, qt.Equals, false)
+               c.Assert(conf.Goldmark.Extensions.Typographer.Ellipsis, qt.Equals, "&hellip;")
+
+       })
+
 }