Skip to content
55 changes: 20 additions & 35 deletions pkg/app/passage.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,6 @@ func GetReference(doc *html.Node) string {
}



// Helper functions for parsing
func isFormattingTag(tag string) bool {
return tag == "sup" || tag == "i" || tag == "b"
}

func isHeaderTag(tag string) bool {
return tag == "h1" || tag == "h2" || tag == "h3" || tag == "h4"
}

func wrapText(text, tag string) string {
if strings.TrimSpace(text) == "" {
return text
}

if tag == "sup" {
return platform.TelegramSuperscript(strings.Trim(text, " "))
}
if tag == "i" {
return platform.TelegramItalics(text)
}
if tag == "b" || isHeaderTag(tag) {
return platform.TelegramBold(text)
}
return text
}

func ParseNodesForPassage(node *html.Node) string {
var text string
var parts []string
Expand Down Expand Up @@ -104,9 +77,13 @@ func ParseNodesForPassage(node *html.Node) string {
}
break
case "p":
case "i":
parts = append(parts, ParseNodesForPassage(child))
break
case "b":
parts = append(parts, platform.TelegramBold(ParseNodesForPassage(child)))
case "i":
parts = append(parts, platform.TelegramItalics(ParseNodesForPassage(child)))
break
case "br":
parts = append(parts, "\n")
break
Expand All @@ -124,7 +101,7 @@ func ParseNodesForPassage(node *html.Node) string {
}

func GetPassage(ref string, doc *html.Node, version string) string {
filtNodes := utils.FilterTree(passageNode, func(child *html.Node) bool {
filtNodes := utils.FilterTree(doc, func(child *html.Node) bool {
switch tag := child.Data; tag {
case "h1":
fallthrough
Expand All @@ -147,8 +124,10 @@ func GetPassage(ref string, doc *html.Node, version string) string {

var passage strings.Builder

refString := fmt.Sprintf("_%s_ (%s)", ref, version)
passage.WriteString(refString)
if len(ref) > 0 {
refString := fmt.Sprintf("_%s_ (%s)", ref, version)
passage.WriteString(refString)
}

for _, block := range textBlocks {
passage.WriteString("\n")
Expand All @@ -158,19 +137,23 @@ func GetPassage(ref string, doc *html.Node, version string) string {
return passage.String()
}

func ParsePassageFromHtml(rawHtml string) string {
func ParsePassageFromHtml(ref string, rawHtml string, version string) string {
doc, err := html.Parse(strings.NewReader(rawHtml))

if err != nil {
log.Printf("Error parsing html: %v", err)
return rawHtml
}

return strings.TrimSpace(GetPassage(doc))
return strings.TrimSpace(GetPassage(ref, doc, version))
}

func GetBiblePassageFallback(env def.SessionData) def.SessionData {
config := utils.DeserializeUserConfig(env.User.Config)

doc := GetPassageHTML(env.Msg.Message, config.Version)
ref := GetReference(doc)

if doc == nil {
env.Res.Message = "Sorry, I couldn't retrieve that passage. Please check the reference or try again later."
return env
Expand All @@ -180,7 +163,7 @@ func GetBiblePassageFallback(env def.SessionData) def.SessionData {
passageNode, startErr := utils.FindByClass(doc, "passage-text")
if startErr != nil {
log.Printf("Error parsing for passage: %v", startErr)
return ""
return env
}

// Attempt to get the passage
Expand All @@ -199,6 +182,7 @@ func GetBiblePassage(env def.SessionData) def.SessionData {

// If indeed a reference, attempt to query
if len(ref) > 0 {
log.Printf("%s", ref);

// Attempt to retrieve from API
req := QueryRequest{
Expand All @@ -223,7 +207,8 @@ func GetBiblePassage(env def.SessionData) def.SessionData {
}

if len(resp.Verse) > 0 {
env.Res.Message = ParsePassageFromHtml(resp.Verse)
env.Res.Message = ParsePassageFromHtml(ref, resp.Verse, config.Version)
return env
}
}

Expand Down
34 changes: 9 additions & 25 deletions pkg/app/passage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,48 +78,48 @@ func TestGetBiblePassage(t *testing.T) {
func TestParsePassageFromHtml(t *testing.T) {
t.Run("Valid HTML with superscript", func(t *testing.T) {
html := `<p><span><sup>12 </sup>But to all who did receive him, who believed in his name, he gave the right to become children of God,</span></p>`
expected := `¹²But to all who did receive him, who believed in his name, he gave the right to become children of God,`
if got := ParsePassageFromHtml(html); got != expected {
expected := `^12^But to all who did receive him, who believed in his name, he gave the right to become children of God,`
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})

t.Run("HTML with italics", func(t *testing.T) {
html := `<p><i>This is italic.</i></p>`
expected := `_This is italic._`
if got := ParsePassageFromHtml(html); got != expected {
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})

t.Run("HTML with bold", func(t *testing.T) {
html := `<p><b>This is bold.</b></p>`
expected := `*This is bold.*`
if got := ParsePassageFromHtml(html); got != expected {
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})

t.Run("HTML with line breaks", func(t *testing.T) {
html := `<p>Line 1.<br>Line 2.</p>`
expected := "Line 1.\nLine 2."
if got := ParsePassageFromHtml(html); got != expected {
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})

t.Run("Invalid HTML", func(t *testing.T) {
html := `<p>This is malformed HTML`
expected := `This is malformed HTML`
if got := ParsePassageFromHtml(html); got != expected {
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})

t.Run("Nested HTML tags", func(t *testing.T) {
html := `<p><b>This is bold, <i>and this is italic.</i></b></p>`
expected := `*This is bold, *_and this is italic._`
if got := ParsePassageFromHtml(html); got != expected {
expected := `*This is bold, _and this is italic._*`
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})
Expand All @@ -131,23 +131,7 @@ func TestParsePassageFromHtml(t *testing.T) {
// For now, we expect them to be returned raw.
html := `<p>This has special characters: *_. [hello](world)!</p>`
expected := `This has special characters: *_. [hello](world)!`
if got := ParsePassageFromHtml(html); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})

t.Run("Backslash escaping", func(t *testing.T) {
html := `added to you\.`
expected := `added to you\.`
if got := ParsePassageFromHtml(html); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})

t.Run("Dot escaping", func(t *testing.T) {
html := `heaven.`
expected := `heaven.`
if got := ParsePassageFromHtml(html); got != expected {
if got := ParsePassageFromHtml("", html, ""); got != expected {
t.Errorf("ParsePassageFromHtml() = %v, want %v", got, expected)
}
})
Expand Down
Loading