diff --git a/htmlcheck/rewriter.go b/htmlcheck/rewriter.go
index 92e4956..6d03b7a 100644
--- a/htmlcheck/rewriter.go
+++ b/htmlcheck/rewriter.go
@@ -9,8 +9,13 @@
// The htmlcheck package contains the HTML Checker.
package htmlcheck
-import "net/url"
+import (
+ "net/mail"
+ "net/url"
+ "strings"
+)
+// markupData holds the return from rewriters.
type markupData struct {
beginMarkup string
text string
@@ -18,14 +23,117 @@ type markupData struct {
rescan bool
}
+// rewriterServices is an interface that provides services to rewriters.
type rewriterServices interface {
rewriterAttrValue(string) string
rewriterContextValue(string) any
- addExternalRef(url.URL)
+ addExternalRef(*url.URL)
addInternalRef(string)
}
+// rewriter is the interface for components that rewrite source text and place markup around it.
type rewriter interface {
Name() string
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("")
+ return &markupData{
+ beginMarkup: openA.String(),
+ text: data,
+ endMarkup: "",
+ 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("")
+ return &markupData{
+ beginMarkup: openA.String(),
+ text: data,
+ endMarkup: "",
+ rescan: false,
+ }
+}