A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

92 lines
2.1 KiB

  1. /*
  2. * Copyright © 2018-2020 Musing Studio LLC.
  3. *
  4. * This file is part of WriteFreely.
  5. *
  6. * WriteFreely is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License, included
  8. * in the LICENSE file in this source code package.
  9. */
  10. // Package parse assists in the parsing of plain text posts
  11. package parse
  12. import (
  13. "github.com/writeas/web-core/stringmanip"
  14. "regexp"
  15. "strings"
  16. )
  17. var (
  18. titleElementReg = regexp.MustCompile("</?p>")
  19. urlReg = regexp.MustCompile("https?://")
  20. imgReg = regexp.MustCompile(`!\[([^]]+)\]\([^)]+\)`)
  21. )
  22. // PostLede attempts to extract the first thought of the given post, generally
  23. // contained within the first line or sentence of text.
  24. func PostLede(t string, includePunc bool) string {
  25. // Adjust where we truncate if we want to include punctuation
  26. iAdj := 0
  27. if includePunc {
  28. iAdj = 1
  29. }
  30. // Find lede within first line of text
  31. nl := strings.IndexRune(t, '\n')
  32. if nl > -1 {
  33. t = t[:nl]
  34. }
  35. // Strip certain HTML tags
  36. t = titleElementReg.ReplaceAllString(t, "")
  37. // Strip URL protocols
  38. t = urlReg.ReplaceAllString(t, "")
  39. // Strip image URL, leaving only alt text
  40. t = imgReg.ReplaceAllString(t, " $1 ")
  41. // Find lede within first sentence
  42. punc := strings.Index(t, ". ")
  43. if punc > -1 {
  44. t = t[:punc+iAdj]
  45. }
  46. punc = stringmanip.IndexRune(t, '。')
  47. if punc > -1 {
  48. c := []rune(t)
  49. t = string(c[:punc+iAdj])
  50. }
  51. punc = stringmanip.IndexRune(t, '?')
  52. if punc > -1 {
  53. c := []rune(t)
  54. t = string(c[:punc+iAdj])
  55. }
  56. return t
  57. }
  58. // TruncToWord truncates the given text to the provided limit.
  59. func TruncToWord(s string, l int) (string, bool) {
  60. truncated := false
  61. c := []rune(s)
  62. if len(c) > l {
  63. truncated = true
  64. s = string(c[:l])
  65. spaceIdx := strings.LastIndexByte(s, ' ')
  66. if spaceIdx > -1 {
  67. s = s[:spaceIdx]
  68. }
  69. }
  70. return s, truncated
  71. }
  72. // Truncate truncates the given text to the provided limit, returning the original string if it's shorter than the limit.
  73. func Truncate(s string, l int) string {
  74. c := []rune(s)
  75. if len(c) > l {
  76. s = string(c[:l])
  77. }
  78. return s
  79. }