landed the email and URL rewriters
This commit is contained in:
+110
-2
@@ -9,8 +9,13 @@
|
|||||||
// The htmlcheck package contains the HTML Checker.
|
// The htmlcheck package contains the HTML Checker.
|
||||||
package htmlcheck
|
package htmlcheck
|
||||||
|
|
||||||
import "net/url"
|
import (
|
||||||
|
"net/mail"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// markupData holds the return from rewriters.
|
||||||
type markupData struct {
|
type markupData struct {
|
||||||
beginMarkup string
|
beginMarkup string
|
||||||
text string
|
text string
|
||||||
@@ -18,14 +23,117 @@ type markupData struct {
|
|||||||
rescan bool
|
rescan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rewriterServices is an interface that provides services to rewriters.
|
||||||
type rewriterServices interface {
|
type rewriterServices interface {
|
||||||
rewriterAttrValue(string) string
|
rewriterAttrValue(string) string
|
||||||
rewriterContextValue(string) any
|
rewriterContextValue(string) any
|
||||||
addExternalRef(url.URL)
|
addExternalRef(*url.URL)
|
||||||
addInternalRef(string)
|
addInternalRef(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rewriter is the interface for components that rewrite source text and place markup around it.
|
||||||
type rewriter interface {
|
type rewriter interface {
|
||||||
Name() string
|
Name() string
|
||||||
Rewrite(string, rewriterServices) *markupData
|
Rewrite(string, rewriterServices) *markupData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emailRewriter is an implementation of Rewriter that recognizes E-mail addresses.
|
||||||
|
type emailRewriter struct{}
|
||||||
|
|
||||||
|
// EmailRewriter is a singleton implementration of rewriter for E-mail addresses.
|
||||||
|
var EmailRewriter = emailRewriter{}
|
||||||
|
|
||||||
|
// Name returns the rewriter's name.
|
||||||
|
func (rw *emailRewriter) Name() string {
|
||||||
|
return "email"
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rewrite rewrites the given string data and adds markup before and after if needed.
|
||||||
|
* Parameters:
|
||||||
|
* data - The data to be rewritten.
|
||||||
|
* svc - Services interface we can use.
|
||||||
|
* Returns:
|
||||||
|
* Pointer to markup data, or nil.
|
||||||
|
*/
|
||||||
|
func (rw *emailRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||||
|
_, err := mail.ParseAddress(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var openA strings.Builder
|
||||||
|
openA.WriteString("<a href=\"mailto:")
|
||||||
|
openA.WriteString(data)
|
||||||
|
openA.WriteString("\"")
|
||||||
|
catenate := svc.rewriterAttrValue("ANCHORTAIL")
|
||||||
|
if catenate != "" {
|
||||||
|
openA.WriteString(" ")
|
||||||
|
openA.WriteString(catenate)
|
||||||
|
}
|
||||||
|
openA.WriteString(">")
|
||||||
|
return &markupData{
|
||||||
|
beginMarkup: openA.String(),
|
||||||
|
text: data,
|
||||||
|
endMarkup: "</a>",
|
||||||
|
rescan: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
// urlRewriter is an implementation of Rewriter that recognizes URLs.
|
||||||
|
type urlRewriter struct{}
|
||||||
|
|
||||||
|
// URLRewriter is a singleton implementration of rewriter for URLs.
|
||||||
|
var URLRewriter = urlRewriter{}
|
||||||
|
|
||||||
|
// Name returns the rewriter's name.
|
||||||
|
func (rw *urlRewriter) Name() string {
|
||||||
|
return "url"
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rewrite rewrites the given string data and adds markup before and after if needed.
|
||||||
|
* Parameters:
|
||||||
|
* data - The data to be rewritten.
|
||||||
|
* svc - Services interface we can use.
|
||||||
|
* Returns:
|
||||||
|
* Pointer to markup data, or nil.
|
||||||
|
*/
|
||||||
|
func (rw *urlRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||||
|
url, err := url.Parse(data)
|
||||||
|
if err != nil {
|
||||||
|
secondChance := ""
|
||||||
|
if strings.HasPrefix(data, "www.") {
|
||||||
|
secondChance = "http://" + data
|
||||||
|
} else if strings.HasPrefix(data, "ftp.") {
|
||||||
|
secondChance = "ftp://" + data
|
||||||
|
} else if strings.HasPrefix(data, "gopher.") {
|
||||||
|
secondChance = "gopher://" + data
|
||||||
|
}
|
||||||
|
if secondChance == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
url, err = url.Parse(secondChance)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if url.Scheme == "http" || url.Scheme == "https" {
|
||||||
|
svc.addExternalRef(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
var openA strings.Builder
|
||||||
|
openA.WriteString("<a href=\"")
|
||||||
|
openA.WriteString(url.String())
|
||||||
|
openA.WriteString("\"")
|
||||||
|
catenate := svc.rewriterAttrValue("ANCHORTAIL")
|
||||||
|
if catenate != "" {
|
||||||
|
openA.WriteString(" ")
|
||||||
|
openA.WriteString(catenate)
|
||||||
|
}
|
||||||
|
openA.WriteString(">")
|
||||||
|
return &markupData{
|
||||||
|
beginMarkup: openA.String(),
|
||||||
|
text: data,
|
||||||
|
endMarkup: "</a>",
|
||||||
|
rescan: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user