diff options
Diffstat (limited to 'management')
-rw-r--r-- | management/editor/editor.go | 6 | ||||
-rw-r--r-- | management/manager/process.go | 68 |
2 files changed, 72 insertions, 2 deletions
diff --git a/management/editor/editor.go b/management/editor/editor.go index 0acf03e..f49c4e3 100644 --- a/management/editor/editor.go +++ b/management/editor/editor.go @@ -6,8 +6,10 @@ import "bytes" // Editable ensures data is editable type Editable interface { + SetContentID(id int) ContentID() int ContentName() string + SetSlug(slug string) Editor() *Editor MarshalEditor() ([]byte, error) } @@ -23,9 +25,9 @@ type Field struct { View []byte } -// New takes editable content and any number of Field funcs to describe the edit +// Form takes editable content and any number of Field funcs to describe the edit // page for any content struct added by a user -func New(post Editable, fields ...Field) ([]byte, error) { +func Form(post Editable, fields ...Field) ([]byte, error) { editor := post.Editor() editor.ViewBuf = &bytes.Buffer{} diff --git a/management/manager/process.go b/management/manager/process.go new file mode 100644 index 0000000..ddae024 --- /dev/null +++ b/management/manager/process.go @@ -0,0 +1,68 @@ +package manager + +import ( + "regexp" + "strings" + "unicode" + + "github.com/nilslice/cms/management/editor" + "golang.org/x/text/transform" + "golang.org/x/text/unicode/norm" +) + +// Slug returns a URL friendly string from the title of a post item +func Slug(e editor.Editable) (string, error) { + // get the name of the post item + name := e.ContentName() + + // filter out non-alphanumeric character or non-whitespace + slug, err := stringToSlug(name) + if err != nil { + return "", err + } + + return slug, nil +} + +func isMn(r rune) bool { + return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks +} + +// modified version of: https://www.socketloop.com/tutorials/golang-format-strings-to-seo-friendly-url-example +func stringToSlug(s string) (string, error) { + src := []byte(strings.ToLower(s)) + + // convert all spaces to dash + rx := regexp.MustCompile("[[:space:]]") + src = rx.ReplaceAll(src, []byte("-")) + + // remove all blanks such as tab + rx = regexp.MustCompile("[[:blank:]]") + src = rx.ReplaceAll(src, []byte("")) + + rx = regexp.MustCompile("[!/:-@[-`{-~]") + src = rx.ReplaceAll(src, []byte("")) + + rx = regexp.MustCompile("/[^\x20-\x7F]/") + src = rx.ReplaceAll(src, []byte("")) + + rx = regexp.MustCompile("`&(amp;)?#?[a-z0-9]+;`i") + src = rx.ReplaceAll(src, []byte("-")) + + rx = regexp.MustCompile("`&([a-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig|quot|rsquo);`i") + src = rx.ReplaceAll(src, []byte("\\1")) + + rx = regexp.MustCompile("`[^a-z0-9]`i") + src = rx.ReplaceAll(src, []byte("-")) + + rx = regexp.MustCompile("`[-]+`") + src = rx.ReplaceAll(src, []byte("-")) + + t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC) + slug, _, err := transform.String(t, string(src)) + if err != nil { + return "", err + } + + return strings.TrimSpace(slug), nil +} |