general.nim 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import uri, strutils, strformat
  2. import karax/[karaxdsl, vdom]
  3. import renderutils
  4. import ../utils, ../types, ../prefs, ../formatters
  5. import jester
  6. const
  7. doctype = "<!DOCTYPE html>\n"
  8. lp = readFile("public/lp.svg")
  9. proc renderNavbar*(title, rss: string; req: Request): VNode =
  10. let twitterPath = getTwitterLink(req.path, req.params)
  11. var path = $(parseUri(req.path) ? filterParams(req.params))
  12. if "/status" in path: path.add "#m"
  13. buildHtml(nav):
  14. tdiv(class="inner-nav"):
  15. tdiv(class="nav-item"):
  16. a(class="site-name", href="/"): text title
  17. a(href="/"): img(class="site-logo", src="/logo.png")
  18. tdiv(class="nav-item right"):
  19. icon "search", title="Search", href="/search"
  20. if rss.len > 0:
  21. icon "rss-feed", title="RSS Feed", href=rss
  22. icon "bird", title="Open in Twitter", href=twitterPath
  23. a(href="https://liberapay.com/zedeus"): verbatim lp
  24. icon "info", title="About", href="/about"
  25. iconReferer "cog", "/settings", path, title="Preferences"
  26. proc renderHead*(prefs: Prefs; cfg: Config; titleText=""; desc=""; video="";
  27. images: seq[string] = @[]; ogTitle=""; theme=""; rss=""): VNode =
  28. let ogType =
  29. if video.len > 0: "video"
  30. elif rss.len > 0: "object"
  31. elif images.len > 0: "photo"
  32. else: "article"
  33. var opensearchUrl = ""
  34. if cfg.useHttps:
  35. opensearchUrl = "https://" & cfg.hostname & "/opensearch"
  36. else:
  37. opensearchUrl = "http://" & cfg.hostname & "/opensearch"
  38. buildHtml(head):
  39. link(rel="stylesheet", type="text/css", href="/css/style.css?v=3")
  40. link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=2")
  41. if theme.len > 0:
  42. link(rel="stylesheet", type="text/css", href=(&"/css/themes/{theme}.css"))
  43. link(rel="apple-touch-icon", sizes="180x180", href="/apple-touch-icon.png")
  44. link(rel="icon", type="image/png", sizes="32x32", href="/favicon-32x32.png")
  45. link(rel="icon", type="image/png", sizes="16x16", href="/favicon-16x16.png")
  46. link(rel="manifest", href="/site.webmanifest")
  47. link(rel="mask-icon", href="/safari-pinned-tab.svg", color="#ff6c60")
  48. link(rel="search", type="application/opensearchdescription+xml", title=cfg.title,
  49. href=opensearchUrl)
  50. if rss.len > 0:
  51. link(rel="alternate", type="application/rss+xml", href=rss, title="RSS feed")
  52. if prefs.hlsPlayback:
  53. script(src="/js/hls.light.min.js", `defer`="")
  54. script(src="/js/hlsPlayback.js", `defer`="")
  55. if prefs.infiniteScroll:
  56. script(src="/js/infiniteScroll.js", `defer`="")
  57. title:
  58. if titleText.len > 0:
  59. text titleText & " | " & cfg.title
  60. else:
  61. text cfg.title
  62. meta(name="viewport", content="width=device-width, initial-scale=1.0")
  63. meta(property="og:type", content=ogType)
  64. meta(property="og:title", content=(if ogTitle.len > 0: ogTitle else: titleText))
  65. meta(property="og:description", content=stripHtml(desc))
  66. meta(property="og:site_name", content="Nitter")
  67. meta(property="og:locale", content="en_US")
  68. for url in images:
  69. let image = "https://" & cfg.hostname & getPicUrl(url)
  70. meta(property="og:image", content=image)
  71. meta(property="twitter:image:src", content=image)
  72. if rss.len > 0:
  73. meta(property="twitter:card", content="summary")
  74. else:
  75. meta(property="twitter:card", content="summary_large_image")
  76. if video.len > 0:
  77. meta(property="og:video:url", content=video)
  78. meta(property="og:video:secure_url", content=video)
  79. meta(property="og:video:type", content="text/html")
  80. proc renderMain*(body: VNode; req: Request; cfg: Config; prefs=defaultPrefs;
  81. titleText=""; desc=""; ogTitle=""; rss=""; video="";
  82. images: seq[string] = @[]): string =
  83. var theme = toLowerAscii(prefs.theme).replace(" ", "_")
  84. if "theme" in req.params:
  85. theme = toLowerAscii(req.params["theme"]).replace(" ", "_")
  86. let node = buildHtml(html(lang="en")):
  87. renderHead(prefs, cfg, titleText, desc, video, images, ogTitle, theme, rss)
  88. body:
  89. renderNavbar(cfg.title, rss, req)
  90. tdiv(class="container"):
  91. body
  92. result = doctype & $node
  93. proc renderError*(error: string): VNode =
  94. buildHtml(tdiv(class="panel-container")):
  95. tdiv(class="error-panel"):
  96. span: verbatim error