From 4267e01de9e8a15353015ea4a2a0ac34d73c4ff4 Mon Sep 17 00:00:00 2001 From: Eyal Posener Date: Sat, 23 Mar 2019 16:18:44 +0200 Subject: [PATCH] Add support for url titles --- goreadme.go | 15 +++++++++-- internal/markdown/comment.go | 51 +++++++++++++++++++++++------------- testdata/pkg1/README.md | 8 +++++- testdata/pkg1/pkg1.go | 8 +++++- 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/goreadme.go b/goreadme.go index 5d68b0e..19e261d 100644 --- a/goreadme.go +++ b/goreadme.go @@ -33,8 +33,19 @@ // // * Code block is recognized by indentation. // -// * URLs will just automatically converted to links -// (Added support to local links - prefixed by dot and slash, for example: ./cmd). +// * Inline code is marked with backticks. +// +// * URLs will just automatically converted to links. +// +// Additionally, some extra formatting was added. +// +// * Local paths will be automatically converted to links, for example: ./goreadme.go. +// +// * A url and can have a title, as follows: (goreadme website) https://goreadme.herokuapp.com. +// +// * A local path and can have a title, as follows: (goreadme main file) ./goreamde.go. +// +// * An image can be added: (image/goreadme icon) ./icon.png package goreadme import ( diff --git a/internal/markdown/comment.go b/internal/markdown/comment.go index 43f5fb9..7d10e90 100644 --- a/internal/markdown/comment.go +++ b/internal/markdown/comment.go @@ -27,6 +27,8 @@ const ( // This excludes some rare yet valid urls ending in common punctuation // in order to allow sentences ending in URLs. + // url title (optional) + urlTitle = `(\(([^)]+)\)\W)?` // protocol (required) e.g. http protoPart = `(https?|ftp|file|gopher|mailto|nntp)` // host (required) e.g. www.example.com or [::1]:8080 @@ -40,7 +42,7 @@ const ( localRx = `\.\/[^\s]+` ) -var matchRx = regexp.MustCompile(`(` + urlRx + `)|(` + identRx + `)|(` + localRx + `)`) +var matchRx = regexp.MustCompile(`(` + urlTitle + `((` + urlRx + `)|(` + localRx + `)))|(` + identRx + `)`) // pairedParensPrefixLen returns the length of the longest prefix of s containing paired parentheses. func pairedParensPrefixLen(s string) int { @@ -80,7 +82,6 @@ func emphasize(w io.Writer, line string, words map[string]string, nice bool) { // m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is urlRx) // write text before match - // commentEscape(w, line[0:m[0]], nice) fmt.Fprintf(w, line[0:m[0]]) // adjust match if necessary match := line[m[0]:m[1]] @@ -93,39 +94,53 @@ func emphasize(w io.Writer, line string, words map[string]string, nice bool) { // analyze match url := "" + title := "" + image := false italics := false if words != nil { url, italics = words[match] } + + // If the url ends with a punctuation mark, we will hold it here. + after := make([]byte, 0, 1) + if m[2] >= 0 { + // A url // match against first parenthesized sub-regexp; must be match against urlRx if !italics { // no alternative URL in words list, use match instead url = match + title = match + if m[4] >= 0 { + title = line[m[6]:m[7]] + url = line[m[8]:m[9]] + if strings.HasPrefix(title, "image/") { + title = strings.TrimPrefix(title, "image/") + image = true + } + } } - italics = false // don't italicize URLs - } - if m[12] >= 0 { - // match against first parenthesized sub-regexp; must be match against urlRx - if !italics { - // no alternative URL in words list, use match instead - url = match - } - italics = false // don't italicize URLs - } - // If the url ends with a punctuation mark, we will hold it here. - after := make([]byte, 0, 1) - - // write match - if len(url) > 0 { + // Remove punctuation mark from url/title suffix. switch url[len(url)-1] { case '.', ',', ':', ';', '?', '!': after = append(after, url[len(url)-1]) + if title[len(title)-1] == url[len(url)-1] { + title = title[:len(title)-1] + } url = url[:len(url)-1] } + + italics = false // don't italicize URLs + } + + // write match + if image { + fmt.Fprint(w, "!") + } + if len(url) > 0 { fmt.Fprint(w, "[") - template.HTMLEscape(w, []byte(url)) + template.HTMLEscape(w, []byte(title)) fmt.Fprint(w, "](") } if italics { diff --git a/testdata/pkg1/README.md b/testdata/pkg1/README.md index 6c5008b..71f8260 100644 --- a/testdata/pkg1/README.md +++ b/testdata/pkg1/README.md @@ -12,10 +12,12 @@ cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est la A local link should just start with period and slash: [./internal](./internal), another local is [./internal/file.go](./internal/file.go). A web page link should just be written as is: [https://goreadme.herokuapp.com](https://goreadme.herokuapp.com), and with path: [https://goreadme.herokuapp.com/projects](https://goreadme.herokuapp.com/projects). +A url can also have a [title](http://example.org). +A local path can also have a [title](./pkg.go). #### Another Section Header -Inline code can be defined with backquotes: `prinlnt("hello world")`, or with indentation: +Inline code can be defined with backticks: `prinlnt("hello world")`, or with indentation: ```go func main() { @@ -29,6 +31,10 @@ You could also use lists: 1. List item number 2. 1. List item number 3. +An image: + +![gopher](https://golang.org/doc/gopher/frontpage.png) + ## Sub Packages * [subpkg1](./subpkg1): Package subpkg1 is the first subpackage diff --git a/testdata/pkg1/pkg1.go b/testdata/pkg1/pkg1.go index 719fc61..bd2942a 100644 --- a/testdata/pkg1/pkg1.go +++ b/testdata/pkg1/pkg1.go @@ -10,10 +10,12 @@ // // A local link should just start with period and slash: ./internal, another local is ./internal/file.go. // A web page link should just be written as is: https://goreadme.herokuapp.com, and with path: https://goreadme.herokuapp.com/projects. +// A url can also have a (title) http://example.org. +// A local path can also have a (title) ./pkg.go. // // Another Section Header // -// Inline code can be defined with backquotes: `prinlnt("hello world")`, or with indentation: +// Inline code can be defined with backticks: `prinlnt("hello world")`, or with indentation: // // func main() { // println("hello world") @@ -24,6 +26,10 @@ // 1. List item number 1. // 1. List item number 2. // 1. List item number 3. +// +// An image: +// +// (image/gopher) https://golang.org/doc/gopher/frontpage.png package pkg1 import "fmt"