aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hergès <william@herges.fr>2025-10-05 15:16:20 +0200
committerWilliam Hergès <william@herges.fr>2025-10-05 15:16:20 +0200
commitfa5ac4040e8e2fc57bef5c598e1ceda4c2fc0a73 (patch)
tree5dbbba0ec6101fb666ee88a977a21ef95d55a2e9
parent5d6198f168dd1a8598048718d149d1171df09c1a (diff)
feat(backend): add noreferer on external link and move target blank
-rw-r--r--README.md2
-rw-r--r--backend/config.go6
-rw-r--r--backend/templates/base.html6
-rw-r--r--frontend/index.ts6
-rw-r--r--markdown/ast_external.go12
5 files changed, 22 insertions, 10 deletions
diff --git a/README.md b/README.md
index 1b68cb4..f6b7a82 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ Backend written in modern Go.
Light CSS, light JS, runs everywhere.
SSR first.
-Maybe HTMX?
+Optional HTMX to fluidify the navigation.
Content written in markdown.
diff --git a/backend/config.go b/backend/config.go
index 8c111ae..d6cf25a 100644
--- a/backend/config.go
+++ b/backend/config.go
@@ -1,9 +1,11 @@
package backend
import (
+ "html/template"
"log/slog"
"os"
+ "git.anhgelus.world/anhgelus/small-world/markdown"
"github.com/pelletier/go-toml/v2"
)
@@ -12,6 +14,10 @@ type Link struct {
URL string `toml:"url"`
}
+func (l *Link) Render() template.HTML {
+ return markdown.RenderLink(l.Name, l.URL)
+}
+
type Logo struct {
Header string `toml:"header"`
Favicon string `toml:"favicon"`
diff --git a/backend/templates/base.html b/backend/templates/base.html
index cf0d834..3af37f9 100644
--- a/backend/templates/base.html
+++ b/backend/templates/base.html
@@ -27,15 +27,13 @@
<body hx-push-url="true">
<header>
<img src="{{ static .Logo.Header }}" alt="Logo">
- <nav>
- {{ range .Links }}<a href="{{ .URL }}">{{ .Name }}</a>{{end}}
- </nav>
+ <nav>{{ range .Links }}{{ .Render }}{{end}}</nav>
</header>
{{ template "body" . }}
<footer>
<p>&copy; 2025 - Anhgelus Morthuuzh</p>
<p id="quote">«&thinsp;{{ .Quote }}&thinsp;»</p>
- <p><a href="/legal">Mentions légales</a>, <a href="https://git.anhgelus.world/anhgelus/small-web">code source</a>.</p>
+ <p><a href="/legal">Mentions légales</a>, <a href="https://git.anhgelus.world/anhgelus/small-web" target="_blank" rel="noreferrer">code source</a>.</p>
</footer>
{{ $script := asset "index.js" }}<script src="{{ $script.Src }}" integrity="{{ $script.Checksum }}" defer></script>
</body>
diff --git a/frontend/index.ts b/frontend/index.ts
index 9babe4a..d4fbe2a 100644
--- a/frontend/index.ts
+++ b/frontend/index.ts
@@ -4,10 +4,8 @@ htmx.config.historyRestoreAsHxRequest = false;
function setupAnchors() {
document.querySelectorAll("a").forEach(e => {
- if (!e.href.startsWith(window.location.origin) && /https?:\/\//.test(e.href)) {
- e.target = "_blank";
- return
- }
+ // stuff related to external links are already handled in the backend
+ if (!e.href.startsWith(window.location.origin) && /https?:\/\//.test(e.href)) return
if (e.hasAttribute("hx-trigger")) return;
e.setAttribute("hx-get", e.href)
e.setAttribute("hx-trigger", "click")
diff --git a/markdown/ast_external.go b/markdown/ast_external.go
index f37a685..e648ad5 100644
--- a/markdown/ast_external.go
+++ b/markdown/ast_external.go
@@ -3,8 +3,11 @@ package markdown
import (
"fmt"
"html/template"
+ "regexp"
)
+var externalLink = regexp.MustCompile(`https?://`)
+
type astLink struct {
content block
href block
@@ -19,7 +22,14 @@ func (a *astLink) Eval(opt *Option) (template.HTML, *ParseError) {
if err != nil {
return "", err
}
- return template.HTML(fmt.Sprintf(`<a href="%s">%s</a>`, href, content)), nil
+ return RenderLink(string(content), string(href)), nil
+}
+
+func RenderLink(content, href string) template.HTML {
+ if !externalLink.Match([]byte(href)) {
+ return template.HTML(fmt.Sprintf(`<a href="%s">%s</a>`, href, content))
+ }
+ return template.HTML(fmt.Sprintf(`<a href="%s" target="_blank" rel="noreferer">%s</a>`, href, content))
}
type astImage struct {