From 4f58eddfda22944f94e306e7cf45f6b8b4568451 Mon Sep 17 00:00:00 2001
From: Aki Kareha
Date: Sun, 14 Dec 2025 08:14:58 +0900
Subject: [PATCH] Add InterWikiLink
---
himewiki.yaml.example | 6 +++++
internal/config/config.go | 7 ++++++
internal/config/public.go | 4 +++
internal/format/creole/apply.go | 34 ++++++++++++++++++++++++++
internal/format/creole/config.go | 2 ++
internal/format/markdown/apply.go | 34 ++++++++++++++++++++++++++
internal/format/markdown/config.go | 2 ++
internal/format/nomark/apply.go | 34 ++++++++++++++++++++++++++
internal/format/nomark/config.go | 2 ++
internal/templates/templates/info.html | 11 +++++++++
10 files changed, 136 insertions(+)
diff --git a/himewiki.yaml.example b/himewiki.yaml.example
index e762ec5..d3d5085 100644
--- a/himewiki.yaml.example
+++ b/himewiki.yaml.example
@@ -55,3 +55,9 @@ gnome:
recent: 10
prompts-path: "./prompts.yaml"
+
+links:
+ - key: "Code"
+ url: "https://link.example.org/code/"
+ - key: "GitHub"
+ url: "https://link.example.org/github/"
diff --git a/internal/config/config.go b/internal/config/config.go
index f3c9576..f0d2e0e 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -7,6 +7,11 @@ import (
"gopkg.in/yaml.v3"
)
+type Link struct {
+ Key string `yaml:"key"`
+ URL string `yaml:"url"`
+}
+
type Config struct {
App struct {
Mode string `yaml:"mode"`
@@ -71,6 +76,8 @@ type Config struct {
PromptsPath string `yaml:"prompts-path"`
Prompts *Prompts
+
+ Links []Link `yaml:"links"`
}
func Load(path string) *Config {
diff --git a/internal/config/public.go b/internal/config/public.go
index 478d648..0003785 100644
--- a/internal/config/public.go
+++ b/internal/config/public.go
@@ -38,6 +38,8 @@ type Public struct {
}
Prompts Prompts
+
+ Links []Link
}
func Publish(cfg *Config) Public {
@@ -104,5 +106,7 @@ func Publish(cfg *Config) Public {
},
Prompts: *cfg.Prompts,
+
+ Links: cfg.Links,
}
}
diff --git a/internal/format/creole/apply.go b/internal/format/creole/apply.go
index 56a7003..9459f6a 100644
--- a/internal/format/creole/apply.go
+++ b/internal/format/creole/apply.go
@@ -441,6 +441,38 @@ func link(s *state) bool {
return true
}
+func interLink(s *state) bool {
+ line := s.input[s.index:s.lineEnd]
+ for _, item := range s.config.links {
+ if strings.HasPrefix(line, item.Key + ":") {
+ end := nonURLIndex(line[len(item.Key) + 1:])
+ rawURL := line[:len(item.Key) + 1 + end]
+
+ _, err := url.Parse(rawURL[len(item.Key) + 1:])
+ if err != nil {
+ continue
+ }
+
+ s.text.WriteString(rawURL)
+
+ s.plain.WriteString(rawURL)
+
+ htmlURL := template.HTMLEscapeString(rawURL)
+ htmlPath := template.HTMLEscapeString(rawURL[len(item.Key) + 1:])
+ s.html.WriteString("")
+ s.html.WriteString(htmlURL)
+ s.html.WriteString("")
+
+ s.index += len(rawURL)
+ return true
+ }
+ }
+ return false
+}
+
func html(s *state) bool {
c := s.input[s.index]
if c == '&' {
@@ -487,6 +519,8 @@ func handleLine(s *state) {
continue
} else if em(s) {
continue
+ } else if interLink(s) {
+ continue
} else if camel(s) {
continue
} else if wikiLink(s) {
diff --git a/internal/format/creole/config.go b/internal/format/creole/config.go
index ad8510f..dd48355 100644
--- a/internal/format/creole/config.go
+++ b/internal/format/creole/config.go
@@ -11,11 +11,13 @@ type imageConfig struct {
type formatConfig struct {
image imageConfig
+ links []config.Link
}
func ToFormatConfig(cfg *config.Config) formatConfig {
fc := formatConfig{}
fc.image.domains = cfg.Image.Domains
fc.image.extensions = cfg.Image.Extensions
+ fc.links = cfg.Links
return fc
}
diff --git a/internal/format/markdown/apply.go b/internal/format/markdown/apply.go
index 14fd46f..25ae05e 100644
--- a/internal/format/markdown/apply.go
+++ b/internal/format/markdown/apply.go
@@ -515,6 +515,38 @@ func link(s *state) bool {
return true
}
+func interLink(s *state) bool {
+ line := s.input[s.index:s.lineEnd]
+ for _, item := range s.config.links {
+ if strings.HasPrefix(line, item.Key + ":") {
+ end := nonURLIndex(line[len(item.Key) + 1:])
+ rawURL := line[:len(item.Key) + 1 + end]
+
+ _, err := url.Parse(rawURL[len(item.Key) + 1:])
+ if err != nil {
+ continue
+ }
+
+ s.text.WriteString(rawURL)
+
+ s.plain.WriteString(rawURL)
+
+ htmlURL := template.HTMLEscapeString(rawURL)
+ htmlPath := template.HTMLEscapeString(rawURL[len(item.Key) + 1:])
+ s.html.WriteString("")
+ s.html.WriteString(htmlURL)
+ s.html.WriteString("")
+
+ s.index += len(rawURL)
+ return true
+ }
+ }
+ return false
+}
+
func html(s *state) bool {
c := s.input[s.index]
if c == '&' {
@@ -565,6 +597,8 @@ func handleLine(s *state) {
continue
} else if altEm(s) {
continue
+ } else if interLink(s) {
+ continue
} else if camel(s) {
continue
} else if wikiLink(s) {
diff --git a/internal/format/markdown/config.go b/internal/format/markdown/config.go
index 18082a6..98c5dfd 100644
--- a/internal/format/markdown/config.go
+++ b/internal/format/markdown/config.go
@@ -11,11 +11,13 @@ type imageConfig struct {
type formatConfig struct {
image imageConfig
+ links []config.Link
}
func ToFormatConfig(cfg *config.Config) formatConfig {
fc := formatConfig{}
fc.image.domains = cfg.Image.Domains
fc.image.extensions = cfg.Image.Extensions
+ fc.links = cfg.Links
return fc
}
diff --git a/internal/format/nomark/apply.go b/internal/format/nomark/apply.go
index 4832380..f350143 100644
--- a/internal/format/nomark/apply.go
+++ b/internal/format/nomark/apply.go
@@ -447,6 +447,38 @@ func link(s *state) bool {
return true
}
+func interLink(s *state) bool {
+ line := s.input[s.index:s.lineEnd]
+ for _, item := range s.config.links {
+ if strings.HasPrefix(line, item.Key + ":") {
+ end := nonURLIndex(line[len(item.Key) + 1:])
+ rawURL := line[:len(item.Key) + 1 + end]
+
+ _, err := url.Parse(rawURL[len(item.Key) + 1:])
+ if err != nil {
+ continue
+ }
+
+ s.text.WriteString(rawURL)
+
+ s.plain.WriteString(rawURL)
+
+ htmlURL := template.HTMLEscapeString(rawURL)
+ htmlPath := template.HTMLEscapeString(rawURL[len(item.Key) + 1:])
+ s.html.WriteString("")
+ s.html.WriteString(htmlURL)
+ s.html.WriteString("")
+
+ s.index += len(rawURL)
+ return true
+ }
+ }
+ return false
+}
+
func html(s *state) bool {
c := s.input[s.index]
if c == '&' {
@@ -493,6 +525,8 @@ func handleLine(s *state) {
continue
} else if em(s) {
continue
+ } else if interLink(s) {
+ continue
} else if camel(s) {
continue
} else if wikiLink(s) {
diff --git a/internal/format/nomark/config.go b/internal/format/nomark/config.go
index e853f75..d21bb04 100644
--- a/internal/format/nomark/config.go
+++ b/internal/format/nomark/config.go
@@ -11,11 +11,13 @@ type imageConfig struct {
type formatConfig struct {
image imageConfig
+ links []config.Link
}
func ToFormatConfig(cfg *config.Config) formatConfig {
fc := formatConfig{}
fc.image.domains = cfg.Image.Domains
fc.image.extensions = cfg.Image.Extensions
+ fc.links = cfg.Links
return fc
}
diff --git a/internal/templates/templates/info.html b/internal/templates/templates/info.html
index 17b30ee..d7c9458 100644
--- a/internal/templates/templates/info.html
+++ b/internal/templates/templates/info.html
@@ -155,6 +155,17 @@ Gnome =
{{.Public.Prompts.Gnome}}
+Links
+{{range .Public.Links}}
+
+{{.Key}} = {{.URL}}
+
+{{else}}
+
+(none)
+
+{{end}}
+