Skip to content

Commit 30f331b

Browse files
committed
feat: add option --theme-dir
Add `--theme-dir` for developing and debugger theme files. Outout content will be evaluated for each request. If request a page rendering, template parsing will also performed.
1 parent dddef14 commit 30f331b

File tree

12 files changed

+1717
-5
lines changed

12 files changed

+1717
-5
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,18 @@ server [options]
215215
Specify key file of TLS certificate.
216216
217217
--theme <file>
218-
Use a custom theme file for rendering pages, instead of builtin one.
218+
Specify a zip archive file as custom theme for rendering page and assets, instead of builtin ones.
219219
Theme contents are cached in memory at runtime.
220+
--theme-dir <directory>
221+
Specify a directory which contains theme files.
222+
Theme contents will be evaluated for each request.
223+
It is convenient for developing themes.
224+
225+
Notes for theme options:
226+
--theme and --theme-dir are mutually exclusive.
227+
--theme-dir is prior.
228+
Page template filename is always "index.html".
229+
Use "?asset=<asset-path>" to reference an asset in theme.
220230
221231
--hsts
222232
Enable HSTS(HTTP Strict Transport Security).

README.zh-CN.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,18 @@ server [选项]
213213
指定TLS私钥文件。
214214
215215
--theme <主题文件>
216-
指定用于渲染页面的自定义主题,代替内建主题。
216+
指定用于渲染页面和静态资源的自定义主题zip压缩文件,代替内建主题。
217217
主题的内容在运行时一直缓存在内存中。
218+
--theme-dir <主题目录>
219+
指定主题文件所在的目录。
220+
每次请求时主题内容都会重新计算。
221+
这为开发主题提供了便利。
222+
223+
主题选项注意事项:
224+
--theme和--theme-dir是互斥的。
225+
--theme-dir更为优先。
226+
页面模板文件名固定为“index.html”。
227+
使用“?asset=<asset-path>”格式来引用主题中的静态资源。
218228
219229
--hsts
220230
启用HSTS(HTTP Strict Transport Security)。

src/app/main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ func NewApp(params []*param.Param) *App {
5353

5454
// theme
5555
var theme tpl.Theme
56-
if len(p.Theme) == 0 {
56+
if len(p.ThemeDir) > 0 {
57+
theme = tpl.DirTheme(p.ThemeDir)
58+
} else if len(p.Theme) == 0 {
5759
theme = tpl.DefaultTheme
5860
} else {
5961
themeKey, err := filepath.Abs(p.Theme)

src/param/cli.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ func init() {
134134
err = options.AddFlagValue("theme", "--theme", "GHFS_THEME", "", "external theme file")
135135
serverErrHandler.CheckFatal(err)
136136

137+
err = options.AddFlagValue("themedir", "--theme-dir", "GHFS_THEME_DIR", "", "external theme directory")
138+
serverErrHandler.CheckFatal(err)
139+
137140
err = options.AddFlag("globalhsts", "--hsts", "GHFS_HSTS", "enable HSTS(HTTP Strict Transport Security)")
138141
serverErrHandler.CheckFatal(err)
139142

@@ -248,6 +251,7 @@ func doParseCli() []*Param {
248251
param.GlobalAuth = result.HasKey("globalauth")
249252
param.HostNames, _ = result.GetStrings("hostnames")
250253
param.Theme, _ = result.GetString("theme")
254+
param.ThemeDir, _ = result.GetString("themedir")
251255
param.AccessLog, _ = result.GetString("accesslog")
252256
param.ErrorLog, _ = result.GetString("errorlog")
253257

src/param/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type Param struct {
5555
ListensTLS []string
5656
HostNames []string
5757
Theme string
58+
ThemeDir string
5859

5960
GlobalHsts bool
6061
GlobalHttps bool

src/tpl/dirTheme.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package tpl
2+
3+
import (
4+
"io"
5+
"net/http"
6+
"os"
7+
"path"
8+
"strings"
9+
)
10+
11+
type DirTheme string
12+
13+
func (dir DirTheme) RenderPage(w io.Writer, data interface{}) error {
14+
filename := string(dir) + "/" + templateFilename
15+
tplStr, err := os.ReadFile(filename)
16+
if err != nil {
17+
return err
18+
}
19+
20+
tpl, err := ParsePageTpl(string(tplStr))
21+
if err != nil {
22+
return err
23+
}
24+
25+
tpl.Execute(w, data)
26+
return nil
27+
}
28+
29+
func (dir DirTheme) RenderAsset(w http.ResponseWriter, r *http.Request, assetPath string) {
30+
filename := string(dir) + "/" + strings.Replace(path.Clean(assetPath), "../", "", -1)
31+
http.ServeFile(w, r, filename)
32+
}

src/tpl/memTheme.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func LoadMemTheme(themePath string) (theme MemTheme, err error) {
4242
if err != nil {
4343
return
4444
}
45-
if f.Name == "index.html" {
45+
if f.Name == templateFilename {
4646
currentTheme.template, err = ParsePageTpl(string(raw))
4747
if err != nil {
4848
return
@@ -57,7 +57,7 @@ func LoadMemTheme(themePath string) (theme MemTheme, err error) {
5757
return
5858
}
5959

60-
err = errors.New("lacks of page template 'index.html' in theme")
60+
err = errors.New("lacks of page template '" + templateFilename + "' in theme")
6161
return
6262
}
6363

src/tpl/theme.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"net/http"
66
)
77

8+
const templateFilename = "index.html"
9+
810
type Theme interface {
911
RenderPage(w io.Writer, data interface{}) error
1012
RenderAsset(w http.ResponseWriter, r *http.Request, assetPath string)

test/case/027.custom.theme-dir.bash

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
source "$root"/lib.bash
4+
5+
"$ghfs" -l 3003 -r "$fs"/vhost1 --hostname 127.0.0.1 ,, -l 3003 -r "$fs"/vhost2 --hostname 127.0.0.2 --theme-dir theme-dir &
6+
sleep 0.05 # wait server ready
7+
8+
(curl_get_body 'http://127.0.0.1:3003/' | grep -q -F '<meta http-equiv="comment" content="index.html from custom theme"/>') &&
9+
fail "Should not use custom theme for vhost 1"
10+
11+
(curl_get_body 'http://127.0.0.1:3003/?asset=index.css' | grep -q -F '/* index.css from custom theme */') &&
12+
fail "Should not use custom theme for vhost 1"
13+
14+
(curl_get_body 'http://127.0.0.1:3003/?asset=index.js' | grep -q -F '/* index.js from custom theme */') &&
15+
fail "Should not use custom theme for vhost 1"
16+
17+
(curl_get_body 'http://127.0.0.2:3003/' | grep -q -F '<meta http-equiv="comment" content="index.html from custom theme"/>') ||
18+
fail "Should use custom theme for vhost 2"
19+
20+
(curl_get_body 'http://127.0.0.2:3003/?asset=index.css' | grep -q -F '/* index.css from custom theme */') ||
21+
fail "Should use custom theme for vhost 2"
22+
23+
(curl_get_body 'http://127.0.0.2:3003/?asset=index.js' | grep -q -F '/* index.js from custom theme */') ||
24+
fail "Should use custom theme for vhost 2"
25+
26+
jobs -p | xargs kill

0 commit comments

Comments
 (0)