resources/page: Escape hash sign in permalinks - hugo - [fork] hugo port for 9front
 (HTM) git clone git@git.drkhsh.at/hugo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 4500b0e423a2c58e6e54526d0d02d2924cc774b6
 (DIR) parent 060cce0a910ffd9dc4e92efbe758fc5f187c3145
 (HTM) Author: Soren L. Hansen <sorenisanerd@gmail.com>
       Date:   Thu,  4 Apr 2024 13:31:20 -0700
       
       resources/page: Escape hash sign in permalinks
       
       When creating a link to a file with a `#` in the filename, the link gets
       truncated. This happens because the filename is eventaully passed to
       `url.Parse` which (correctly!) interprets the `#` as fragment separator.
       
       This commit escapes the `#` in the filename before creating the link.
       
       Fixes #4926
       Fixes #8232
       Fixes #12342
       
       Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
       
       Diffstat:
         M resources/page/page_paths.go        |       7 +++++++
         A resources/page/path_integration_te… |      55 +++++++++++++++++++++++++++++++
       
       2 files changed, 62 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/resources/page/page_paths.go b/resources/page/page_paths.go
       @@ -268,6 +268,13 @@ func CreateTargetPaths(d TargetPathDescriptor) (tp TargetPaths) {
                        tp.SubResourceBaseTarget = pb.PathDir()
                        tp.SubResourceBaseLink = pb.LinkDir()
                }
       +
       +        // paths.{URL,Path}Escape rely on url.Parse which
       +        // will consider # a fragment identifier, so it and
       +        // and everything after it will be stripped from
       +        // `link`, so we need to escape it first.
       +        link = strings.ReplaceAll(link, "#", "%23")
       +
                if d.URL != "" {
                        tp.Link = paths.URLEscape(link)
                } else {
 (DIR) diff --git a/resources/page/path_integration_test.go b/resources/page/path_integration_test.go
       @@ -0,0 +1,55 @@
       +// Copyright 2024 The Hugo Authors. All rights reserved.
       +//
       +// Licensed under the Apache License, Version 2.0 (the "License");
       +// you may not use this file except in compliance with the License.
       +// You may obtain a copy of the License at
       +// http://www.apache.org/licenses/LICENSE-2.0
       +//
       +// Unless required by applicable law or agreed to in writing, software
       +// distributed under the License is distributed on an "AS IS" BASIS,
       +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       +// See the License for the specific language governing permissions and
       +// limitations under the License.
       +
       +package page_test
       +
       +import (
       +        "testing"
       +
       +        "github.com/gohugoio/hugo/hugolib"
       +)
       +
       +// Issue 4926
       +// Issue 8232
       +// Issue 12342
       +func TestHashSignInPermalink(t *testing.T) {
       +        t.Parallel()
       +
       +        files := `
       +-- hugo.toml --
       +disableKinds = ['section','rss','sitemap','taxonomy']
       +[permalinks]
       +s1 = '/:section/:slug'
       +-- layouts/_default/list.html --
       +{{ range site.Pages }}{{ .RelPermalink }}|{{ end }}
       +-- layouts/_default/single.html --
       +{{ .Title }}
       +-- content/s1/p1.md --
       +---
       +title: p#1
       +tags: test#tag#
       +---
       +-- content/s2/p#2.md --
       +---
       +title: p#2
       +---
       +`
       +
       +        b := hugolib.Test(t, files)
       +
       +        b.AssertFileExists("public/s1/p#1/index.html", true)
       +        b.AssertFileExists("public/s2/p#2/index.html", true)
       +        b.AssertFileExists("public/tags/test#tag#/index.html", true)
       +
       +        b.AssertFileContentExact("public/index.html", "/|/s1/p%231/|/s2/p%232/|/tags/test%23tag%23/|")
       +}