Add category pkg
This supports categories in Write.as / WriteFreely. Ref T809
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// Package category supports post categories
|
||||
package category
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/writeas/slug"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("category doesn't exist")
|
||||
)
|
||||
|
||||
// Category represents a post tag with additional metadata, like a title and slug.
|
||||
type Category struct {
|
||||
ID int64 `json:"-"`
|
||||
Hashtag string `json:"hashtag"`
|
||||
Slug string `json:"slug"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// NewCategory creates a Category you can insert into the database, based on a hashtag. It automatically breaks up the
|
||||
// hashtag by words, based on capitalization, for both the title and a URL-friendly slug.
|
||||
func NewCategory(hashtag string) *Category {
|
||||
title := titleFromHashtag(hashtag)
|
||||
return &Category{
|
||||
Hashtag: hashtag,
|
||||
Slug: slug.Make(title),
|
||||
Title: title,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package category
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// titleFromHashtag generates an all-lowercase title, with spaces inserted based on initial capitalization -- e.g.
|
||||
// "MyWordyTag" becomes "my wordy tag".
|
||||
func titleFromHashtag(hashtag string) string {
|
||||
var t strings.Builder
|
||||
var prev rune
|
||||
for i, c := range hashtag {
|
||||
if unicode.IsUpper(c) {
|
||||
if i > 0 && !unicode.IsUpper(prev) {
|
||||
// Insert space if previous rune wasn't also uppercase (e.g. an abbreviation)
|
||||
t.WriteRune(' ')
|
||||
}
|
||||
t.WriteRune(unicode.ToLower(c))
|
||||
} else {
|
||||
t.WriteRune(c)
|
||||
}
|
||||
prev = c
|
||||
}
|
||||
return t.String()
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package category
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestTitleFromHashtag(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hashtag string
|
||||
expTitle string
|
||||
}{
|
||||
{"proper noun", "Jane", "jane"},
|
||||
{"full name", "JaneDoe", "jane doe"},
|
||||
{"us words", "unitedStates", "united states"},
|
||||
{"usa", "USA", "usa"},
|
||||
{"us monoword", "unitedstates", "unitedstates"},
|
||||
{"100dto", "100DaysToOffload", "100 days to offload"},
|
||||
{"iphone", "iPhone", "iphone"},
|
||||
{"ilike", "iLikeThis", "i like this"},
|
||||
{"abird", "aBird", "a bird"},
|
||||
{"all caps", "URGENT", "urgent"},
|
||||
{"smartphone", "スマートフォン", "スマートフォン"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
res := titleFromHashtag(test.hashtag)
|
||||
if res != test.expTitle {
|
||||
t.Fatalf("#%s: got '%s' expected '%s'", test.hashtag, res, test.expTitle)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,13 @@ require (
|
||||
github.com/gofrs/uuid v3.3.0+incompatible
|
||||
github.com/kylemcc/twitter-text-go v0.0.0-20180726194232-7f582f6736ec
|
||||
github.com/microcosm-cc/bluemonday v1.0.5
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||
github.com/writeas/impart v1.1.1
|
||||
github.com/writeas/openssl-go v1.0.0
|
||||
github.com/writeas/saturday v1.7.1
|
||||
github.com/writeas/slug v1.2.0
|
||||
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 // indirect
|
||||
|
||||
@@ -15,6 +15,8 @@ github.com/kylemcc/twitter-text-go v0.0.0-20180726194232-7f582f6736ec h1:ZXWuspq
|
||||
github.com/kylemcc/twitter-text-go v0.0.0-20180726194232-7f582f6736ec/go.mod h1:voECJzdraJmolzPBgL9Z7ANwXf4oMXaTCsIkdiPpR/g=
|
||||
github.com/microcosm-cc/bluemonday v1.0.5 h1:cF59UCKMmmUgqN1baLvqU/B1ZsMori+duLVTLpgiG3w=
|
||||
github.com/microcosm-cc/bluemonday v1.0.5/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible h1:IIqxTM5Jr7RzhigcL6FkrCNfXkvbR+Nbu1ls48pXYcw=
|
||||
@@ -25,6 +27,8 @@ github.com/writeas/openssl-go v1.0.0 h1:YXM1tDXeYOlTyJjoMlYLQH1xOloUimSR1WMF8kjF
|
||||
github.com/writeas/openssl-go v1.0.0/go.mod h1:WsKeK5jYl0B5y8ggOmtVjbmb+3rEGqSD25TppjJnETA=
|
||||
github.com/writeas/saturday v1.7.1 h1:lYo1EH6CYyrFObQoA9RNWHVlpZA5iYL5Opxo7PYAnZE=
|
||||
github.com/writeas/saturday v1.7.1/go.mod h1:ETE1EK6ogxptJpAgUbcJD0prAtX48bSloie80+tvnzQ=
|
||||
github.com/writeas/slug v1.2.0 h1:EMQ+cwLiOcA6EtFwUgyw3Ge18x9uflUnOnR6bp/J+/g=
|
||||
github.com/writeas/slug v1.2.0/go.mod h1:RE8shOqQP3YhsfsQe0L3RnuejfQ4Mk+JjY5YJQFubfQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0=
|
||||
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
||||
Reference in New Issue
Block a user