Skip to content

Commit

Permalink
Normalize strings when they are read from the filesystem, fixes #48
Browse files Browse the repository at this point in the history
This ensures all characters in string are precomposed.
https://blog.golang.org/normalization

* Normalize first

* Change position of normalization

* Add documentation

* Add dependency for text/unicode/norm

* Add tests for composing title strings

* Fix Year and Format
  • Loading branch information
ChristophLabacher authored and mariuswilms committed Jul 25, 2018
1 parent aa62a61 commit 4a68e77
Show file tree
Hide file tree
Showing 37 changed files with 24,700 additions and 4 deletions.
15 changes: 14 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@
[[constraint]]
name = "github.com/gorilla/websocket"
version = "1.2.0"

[[constraint]]
name = "golang.org/x/text"
version = "0.3.0"
8 changes: 6 additions & 2 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"time"

"github.com/fatih/color"
"golang.org/x/text/unicode/norm"
)

var (
Expand Down Expand Up @@ -186,11 +187,14 @@ func (n *Node) Order() uint64 {
}

// The node's computed title with any ordering numbers stripped off, usually for display purposes.
// We normalize the title string to make sure all special characters are represented in their composed form.
// Some filesystems store filenames in decomposed form. Using these directly in the frontend led to visual
// inconsistencies. See: https://blog.golang.org/normalization
func (n *Node) Title() string {
if n.root == n.path {
return filepath.Base(n.root)
return norm.NFC.String(filepath.Base(n.root))
}
return removeOrderNumber(filepath.Base(n.path))
return removeOrderNumber(norm.NFC.String(filepath.Base(n.path)))
}

// Returns the full description of the node.
Expand Down
6 changes: 5 additions & 1 deletion node_doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/russross/blackfriday"
"golang.org/x/net/html"
"golang.org/x/text/unicode/norm"
)

// NodeDoc is a document file.
Expand All @@ -28,8 +29,11 @@ func (d NodeDoc) Order() uint64 {

// Title of the document and computed with any ordering numbers and the
// extension stripped off, usually for display purposes.
// We normalize the title string to make sure all special characters
// are represented in their composed form. For more on this topic see the
// docblock of Node.Title().
func (d NodeDoc) Title() string {
base := filepath.Base(d.path)
base := norm.NFC.String(filepath.Base(d.path))
return removeOrderNumber(strings.TrimSuffix(base, filepath.Ext(base)))
}

Expand Down
35 changes: 35 additions & 0 deletions node_doc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2018 Atelier Disko. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"io/ioutil"
"os"
"path/filepath"
"testing"
)

func TestDocTitlesWithDecomposedFilenames(t *testing.T) {
tmp, _ := ioutil.TempDir("", "tree")
defer os.RemoveAll(tmp)

node0 := filepath.Join(tmp, "foo")
os.Mkdir(node0, 0777)

doc0 := filepath.Join(node0, "01-Cafe\u0301.md")
ioutil.WriteFile(doc0, []byte(""), 0666)

node := &Node{root: tmp, path: filepath.Join(tmp, "foo")}

docs, err := node.Docs()
if err != nil {
t.Errorf("can’t read docs")
}

if docs[0].Title() != "Café" {
t.Errorf("failed to decode file name, got %v", docs[0].Title())
}
}
7 changes: 7 additions & 0 deletions node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,10 @@ func BenchmarkHashCalculation(b *testing.B) {
n.Hash()
}
}

func TestTitlesWithDecomposedFilenames(t *testing.T) {
n := &Node{path: "/bar/Cafe\u0301", root: "/bar"}
if n.Title() != "Café" {
t.Errorf("failed to decode folder name, got %v", n.Title())
}
}
3 changes: 3 additions & 0 deletions vendor/golang.org/x/text/AUTHORS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions vendor/golang.org/x/text/CONTRIBUTORS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions vendor/golang.org/x/text/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions vendor/golang.org/x/text/PATENTS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4a68e77

Please sign in to comment.