--html-head can take a filepath and/or jinja2

This commit is contained in:
ed 2024-05-01 20:24:18 +00:00
parent e8db3dd37f
commit b6cf2d3089
5 changed files with 50 additions and 7 deletions

View file

@ -1067,7 +1067,7 @@ tweaking the ui
* to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Cirle,tags/.tn,tags/Artist,tags/Title,href` * to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Cirle,tags/.tn,tags/Artist,tags/Title,href`
* to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at` * to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at`
see [./docs/rice](./docs/rice) for more see [./docs/rice](./docs/rice) for more, including how to add stuff (css/`<meta>`/...) to the html `<head>` tag
## file indexing ## file indexing

View file

@ -1269,7 +1269,7 @@ def add_ui(ap, retry):
ap2.add_argument("--mpmc", metavar="URL", type=u, default="", help="change the mediaplayer-toggle mouse cursor; URL to a folder with {2..5}.png inside (or disable with [\033[32m.\033[0m])") ap2.add_argument("--mpmc", metavar="URL", type=u, default="", help="change the mediaplayer-toggle mouse cursor; URL to a folder with {2..5}.png inside (or disable with [\033[32m.\033[0m])")
ap2.add_argument("--js-browser", metavar="L", type=u, help="URL to additional JS to include") ap2.add_argument("--js-browser", metavar="L", type=u, help="URL to additional JS to include")
ap2.add_argument("--css-browser", metavar="L", type=u, help="URL to additional CSS to include") ap2.add_argument("--css-browser", metavar="L", type=u, help="URL to additional CSS to include")
ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages") ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages; can be @PATH to send the contents of a file at PATH, and/or begin with % to render as jinja2 template (volflag=html_head)")
ap2.add_argument("--ih", action="store_true", help="if a folder contains index.html, show that instead of the directory listing by default (can be changed in the client settings UI, or add ?v to URL for override)") ap2.add_argument("--ih", action="store_true", help="if a folder contains index.html, show that instead of the directory listing by default (can be changed in the client settings UI, or add ?v to URL for override)")
ap2.add_argument("--textfiles", metavar="CSV", type=u, default="txt,nfo,diz,cue,readme", help="file extensions to present as plaintext") ap2.add_argument("--textfiles", metavar="CSV", type=u, default="txt,nfo,diz,cue,readme", help="file extensions to present as plaintext")
ap2.add_argument("--txt-max", metavar="KiB", type=int, default=64, help="max size of embedded textfiles on ?doc= (anything bigger will be lazy-loaded by JS)") ap2.add_argument("--txt-max", metavar="KiB", type=int, default=64, help="max size of embedded textfiles on ?doc= (anything bigger will be lazy-loaded by JS)")

View file

@ -61,6 +61,7 @@ def vf_vmap() -> dict[str, str]:
} }
for k in ( for k in (
"dbd", "dbd",
"html_head",
"lg_sbf", "lg_sbf",
"md_sbf", "md_sbf",
"nrand", "nrand",
@ -81,7 +82,6 @@ def vf_cmap() -> dict[str, str]:
for k in ( for k in (
"exp_lg", "exp_lg",
"exp_md", "exp_md",
"html_head",
"mte", "mte",
"mth", "mth",
"mtp", "mtp",
@ -201,7 +201,7 @@ flagcats = {
"grid": "show grid/thumbnails by default", "grid": "show grid/thumbnails by default",
"sort": "default sort order", "sort": "default sort order",
"unlist": "dont list files matching REGEX", "unlist": "dont list files matching REGEX",
"html_head=TXT": "includes TXT in the <head>", "html_head=TXT": "includes TXT in the <head>, or @PATH for file at PATH",
"robots": "allows indexing by search engines (default)", "robots": "allows indexing by search engines (default)",
"norobots": "kindly asks search engines to leave", "norobots": "kindly asks search engines to leave",
"no_sb_md": "disable js sandbox for markdown files", "no_sb_md": "disable js sandbox for markdown files",

View file

@ -217,6 +217,12 @@ class HttpCli(object):
ka["favico"] = self.args.favico ka["favico"] = self.args.favico
ka["s_name"] = self.args.bname ka["s_name"] = self.args.bname
ka["s_doctitle"] = self.args.doctitle ka["s_doctitle"] = self.args.doctitle
zso = self.vn.flags.get("html_head")
if zso:
ka["this"] = self
self._build_html_head(zso, ka)
ka["html_head"] = self.html_head ka["html_head"] = self.html_head
return tpl.render(**ka) # type: ignore return tpl.render(**ka) # type: ignore
@ -718,6 +724,31 @@ class HttpCli(object):
or ("; Trident/" in self.ua and not k304) or ("; Trident/" in self.ua and not k304)
) )
def _build_html_head(self, maybe_html: Any, kv: dict[str, Any]) -> bool:
html = str(maybe_html)
is_jinja = html[:2] in "%@%"
if is_jinja:
html = html.replace("%", "", 1)
if html.startswith("@"):
with open(html[1:], "rb") as f:
html = f.read().decode("utf-8")
if html.startswith("%"):
html = html[1:]
is_jinja = True
if is_jinja:
print("applying jinja")
with self.conn.hsrv.mutex:
if html not in self.conn.hsrv.j2:
j2env = jinja2.Environment()
tpl = j2env.from_string(html)
self.conn.hsrv.j2[html] = tpl
html = self.conn.hsrv.j2[html].render(**kv)
self.html_head += html + "\n"
def send_headers( def send_headers(
self, self,
length: Optional[int], length: Optional[int],
@ -3484,7 +3515,6 @@ class HttpCli(object):
targs = { targs = {
"r": self.args.SR if self.is_vproxied else "", "r": self.args.SR if self.is_vproxied else "",
"ts": self.conn.hsrv.cachebuster(), "ts": self.conn.hsrv.cachebuster(),
"html_head": self.html_head,
"edit": "edit" in self.uparam, "edit": "edit" in self.uparam,
"title": html_escape(self.vpath, crlf=True), "title": html_escape(self.vpath, crlf=True),
"lastmod": int(ts_md * 1000), "lastmod": int(ts_md * 1000),
@ -3495,6 +3525,13 @@ class HttpCli(object):
"md": boundary, "md": boundary,
"arg_base": arg_base, "arg_base": arg_base,
} }
zfv = self.vn.flags.get("html_head")
if zfv:
targs["this"] = self
self._build_html_head(zfv, targs)
targs["html_head"] = self.html_head
zs = template.render(**targs).encode("utf-8", "replace") zs = template.render(**targs).encode("utf-8", "replace")
html = zs.split(boundary.encode("utf-8")) html = zs.split(boundary.encode("utf-8"))
if len(html) != 2: if len(html) != 2:
@ -3610,8 +3647,6 @@ class HttpCli(object):
self.reply(zb, mime="text/plain; charset=utf-8") self.reply(zb, mime="text/plain; charset=utf-8")
return True return True
self.html_head += self.vn.flags.get("html_head", "")
html = self.j2s( html = self.j2s(
"splash", "splash",
this=self, this=self,

View file

@ -47,3 +47,11 @@ and if you want to have a monospace font in the fancy markdown editor, do this:
NB: `<textarea id="mt">` and `<div id="mtr">` in the regular markdown editor must have the same font; none of the suggestions above will cause any issues but keep it in mind if you're getting creative NB: `<textarea id="mt">` and `<div id="mtr">` in the regular markdown editor must have the same font; none of the suggestions above will cause any issues but keep it in mind if you're getting creative
# `<head>`
to add stuff to the html `<head>`, for example a css `<link>` or `<meta>` tags, use either the global-option `--html-head` or the volflag `html_head`
if you give it the value `@ASDF` it will try to open a file named ASDF and send the text within
if the value starts with `%` it will assume a jinja2 template and expand it; the template has access to the `HttpCli` object through a property named `this` as well as everything in `j2a` and the stuff added by `self.j2s`; see [browser.html](https://github.com/9001/copyparty/blob/hovudstraum/copyparty/web/browser.html) for inspiration or look under the hood in [httpcli.py](https://github.com/9001/copyparty/blob/hovudstraum/copyparty/httpcli.py)