updated links formatting in the autogenerated html->text mail body
This commit is contained in:
		
							parent
							
								
									821aae4a62
								
							
						
					
					
						commit
						531a7abec9
					
				| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Bumped the minimum required Go version to 1.21.0 in order to integrate with the builtin `slog` package.
 | 
					- Bumped the minimum required Go version to 1.21.0 in order to integrate with the builtin `slog` package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- removed _requests table in favor of _logs
 | 
					- removed _requests_ table in favor of logs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Renamed:
 | 
					- Renamed:
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Soft-deprecated and renamed `app.Cache()` with `app.Store()`.
 | 
					- Soft-deprecated and renamed `app.Cache()` with `app.Store()`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Updated links formatting in the autogenerated html->text mail body.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## v0.20.0-rc3
 | 
					## v0.20.0-rc3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,16 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var whitespaceRegex = regexp.MustCompile(`\s+`)
 | 
					var whitespaceRegex = regexp.MustCompile(`\s+`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var tagsToSkip = []string{
 | 
				
			||||||
 | 
						"style", "script", "iframe", "applet", "object", "svg", "img",
 | 
				
			||||||
 | 
						"button", "form", "textarea", "input", "select", "option", "template",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var inlineTags = []string{
 | 
				
			||||||
 | 
						"a", "span", "small", "strike", "strong",
 | 
				
			||||||
 | 
						"sub", "sup", "em", "b", "u", "i",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Very rudimentary auto HTML to Text mail body converter.
 | 
					// Very rudimentary auto HTML to Text mail body converter.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Caveats:
 | 
					// Caveats:
 | 
				
			||||||
| 
						 | 
					@ -20,32 +30,24 @@ var whitespaceRegex = regexp.MustCompile(`\s+`)
 | 
				
			||||||
// - Trailing spaces are preserved.
 | 
					// - Trailing spaces are preserved.
 | 
				
			||||||
// - Multiple consequence newlines are collapsed as one unless multiple <br> tags are used.
 | 
					// - Multiple consequence newlines are collapsed as one unless multiple <br> tags are used.
 | 
				
			||||||
func html2Text(htmlDocument string) (string, error) {
 | 
					func html2Text(htmlDocument string) (string, error) {
 | 
				
			||||||
	var builder strings.Builder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	doc, err := html.Parse(strings.NewReader(htmlDocument))
 | 
						doc, err := html.Parse(strings.NewReader(htmlDocument))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tagsToSkip := []string{
 | 
						var builder strings.Builder
 | 
				
			||||||
		"style", "script", "iframe", "applet", "object", "svg", "img",
 | 
					 | 
				
			||||||
		"button", "form", "textarea", "input", "select", "option", "template",
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	inlineTags := []string{
 | 
					 | 
				
			||||||
		"a", "span", "small", "strike", "strong",
 | 
					 | 
				
			||||||
		"sub", "sup", "em", "b", "u", "i",
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var canAddNewLine bool
 | 
						var canAddNewLine bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// see https://pkg.go.dev/golang.org/x/net/html#Parse
 | 
						// see https://pkg.go.dev/golang.org/x/net/html#Parse
 | 
				
			||||||
	var f func(*html.Node)
 | 
						var f func(*html.Node, *strings.Builder)
 | 
				
			||||||
	f = func(n *html.Node) {
 | 
						f = func(n *html.Node, activeBuilder *strings.Builder) {
 | 
				
			||||||
		// start link wrapping for producing "[text](link)" formatted string
 | 
					 | 
				
			||||||
		isLink := n.Type == html.ElementNode && n.Data == "a"
 | 
							isLink := n.Type == html.ElementNode && n.Data == "a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if isLink {
 | 
							if isLink {
 | 
				
			||||||
			builder.WriteString("[")
 | 
								var linkBuilder strings.Builder
 | 
				
			||||||
 | 
								activeBuilder = &linkBuilder
 | 
				
			||||||
 | 
							} else if activeBuilder == nil {
 | 
				
			||||||
 | 
								activeBuilder = &builder
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch n.Type {
 | 
							switch n.Type {
 | 
				
			||||||
| 
						 | 
					@ -58,34 +60,42 @@ func html2Text(htmlDocument string) (string, error) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if txt != "" {
 | 
								if txt != "" {
 | 
				
			||||||
				builder.WriteString(txt)
 | 
									activeBuilder.WriteString(txt)
 | 
				
			||||||
				canAddNewLine = true
 | 
									canAddNewLine = true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case html.ElementNode:
 | 
							case html.ElementNode:
 | 
				
			||||||
			if n.Data == "br" {
 | 
								if n.Data == "br" {
 | 
				
			||||||
				// always write new lines when <br> tag is used
 | 
									// always write new lines when <br> tag is used
 | 
				
			||||||
				builder.WriteString("\r\n")
 | 
									activeBuilder.WriteString("\r\n")
 | 
				
			||||||
				canAddNewLine = false
 | 
									canAddNewLine = false
 | 
				
			||||||
			} else if canAddNewLine && !list.ExistInSlice(n.Data, inlineTags) {
 | 
								} else if canAddNewLine && !list.ExistInSlice(n.Data, inlineTags) {
 | 
				
			||||||
				builder.WriteString("\r\n")
 | 
									activeBuilder.WriteString("\r\n")
 | 
				
			||||||
				canAddNewLine = false
 | 
									canAddNewLine = false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// prefix list items with dash
 | 
								// prefix list items with dash
 | 
				
			||||||
			if n.Data == "li" {
 | 
								if n.Data == "li" {
 | 
				
			||||||
				builder.WriteString("- ")
 | 
									activeBuilder.WriteString("- ")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for c := n.FirstChild; c != nil; c = c.NextSibling {
 | 
							for c := n.FirstChild; c != nil; c = c.NextSibling {
 | 
				
			||||||
			if c.Type != html.ElementNode || !list.ExistInSlice(c.Data, tagsToSkip) {
 | 
								if c.Type != html.ElementNode || !list.ExistInSlice(c.Data, tagsToSkip) {
 | 
				
			||||||
				f(c)
 | 
									f(c, activeBuilder)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// end link wrapping
 | 
							// format links as [label](href)
 | 
				
			||||||
		if isLink {
 | 
							if isLink {
 | 
				
			||||||
 | 
								linkTxt := strings.TrimSpace(activeBuilder.String())
 | 
				
			||||||
 | 
								if linkTxt == "" {
 | 
				
			||||||
 | 
									linkTxt = "LINK"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								builder.WriteString("[")
 | 
				
			||||||
 | 
								builder.WriteString(linkTxt)
 | 
				
			||||||
			builder.WriteString("]")
 | 
								builder.WriteString("]")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// link href attr extraction
 | 
				
			||||||
			for _, a := range n.Attr {
 | 
								for _, a := range n.Attr {
 | 
				
			||||||
				if a.Key == "href" {
 | 
									if a.Key == "href" {
 | 
				
			||||||
					if a.Val != "" {
 | 
										if a.Val != "" {
 | 
				
			||||||
| 
						 | 
					@ -96,10 +106,11 @@ func html2Text(htmlDocument string) (string, error) {
 | 
				
			||||||
					break
 | 
										break
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								activeBuilder.Reset()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	f(doc)
 | 
						f(doc, &builder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return strings.TrimSpace(builder.String()), nil
 | 
						return strings.TrimSpace(builder.String()), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue