站点首页此前显示的是 Dashy 上游的 logo —— index.html 里那几条
<link rel=icon href=/web-icons/favicon-*.png> 优先级高于我们的门户图标,
而扩展的 PNG 是占位图(128px 只有 9 种颜色、alpha 通道还是乱的)。
- portal/favicon.svg:纸飞机(圆角渐变底 + 白色折纸机头朝右上 + 两道尾迹),
几何收在 8..56 安全区,避免贴边被圆角裁切
- 由该 SVG 派生 favicon.ico(16/32/48)、apple-touch-icon(180)、
web-icons/favicon-{16,32,64}、扩展 icon{16,48,96,128}
- patch-index.py:删掉上游 icon link 并显式指向 /favicon.svg(幂等,
重复执行 unchanged);上游 web-icons 那批也覆盖一份作双保险
- Dockerfile 与 zd-host.sh 都 COPY 这些图标进镜像
- 验证:nginx 沙箱实测 /favicon.svg、/web-icons/*、/apple-touch-icon.png 均 200;
16px 下人眼仍可辨识为纸飞机
- .amo-upload-uuid(web-ext 生成的 UUID)改为忽略
64 lines
2.6 KiB
Python
64 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
||
"""Idempotently inject the HomeDash stylesheet and script into Dashy's index.html.
|
||
|
||
Dashy's index.html does not always contain a `</body>` tag. A naive
|
||
`sed s#</body>#...#` therefore silently drops the injected script (and the
|
||
`</body>` marker itself). This script inserts before `</head>`/`</body>` when
|
||
those exist, otherwise before `</html>`, and restores a missing `</body>`.
|
||
"""
|
||
import re
|
||
import sys
|
||
|
||
CSS_TAG = '<link rel="stylesheet" href="/navi.css">'
|
||
JS_TAG = '<script src="/navi.js"></script>'
|
||
|
||
# Dashy 自带的 logo(/web-icons/favicon-*.png)会被浏览器优先选中,
|
||
# 于是站点标签栏显示上游 logo 而不是我们的纸飞机。
|
||
# 做法:删掉那些 <link rel=icon>,再显式指向我们自己的 /favicon.svg。
|
||
# 为什么用“删掉”而不是“改路径”:index.html 来自上游镜像,每次重建可能被重置,
|
||
# 删标签幂等,且不依赖上游将来还叫 web-icons。
|
||
ICON_LINK_RE = re.compile(r'[ \t]*<link[^>]*rel=["\']icon["\'][^>]*>\s*', re.I)
|
||
OUR_ICONS = ('<link rel="icon" type="image/svg+xml" href="/favicon.svg">\n'
|
||
'<link rel="apple-touch-icon" href="/apple-touch-icon.png">')
|
||
|
||
|
||
def patch(html: str) -> str:
|
||
html = re.sub(r'[ \t]*<link rel="stylesheet" href="/navi\.css">\s*', '', html)
|
||
html = re.sub(r'[ \t]*<script src="/navi\.js"></script>\s*', '', html)
|
||
html = re.sub(r'[ \t]*' + re.escape(OUR_ICONS) + r'\s*', '', html)
|
||
html = ICON_LINK_RE.sub('', html)
|
||
|
||
if '</head>' in html:
|
||
html = html.replace('</head>', CSS_TAG + OUR_ICONS + '</head>', 1)
|
||
|
||
if '</body>' in html:
|
||
html = html.replace('</body>', JS_TAG + '</body>', 1)
|
||
elif '</html>' in html:
|
||
html = html.replace('</html>', JS_TAG + '\n</body>\n</html>', 1)
|
||
else:
|
||
html = html + '\n' + JS_TAG + '\n'
|
||
return html
|
||
|
||
|
||
def main(path: str) -> int:
|
||
with open(path, encoding='utf-8') as fh:
|
||
original = fh.read()
|
||
patched = patch(original)
|
||
if 'href="/navi.css"' not in patched or 'src="/navi.js"' not in patched:
|
||
print('patch failed: tags missing after patch', file=sys.stderr)
|
||
return 1
|
||
if 'web-icons/favicon' in patched:
|
||
print('patch failed: upstream Dashy icon links survived', file=sys.stderr)
|
||
return 1
|
||
if '/favicon.svg' not in patched:
|
||
print('patch failed: our icon link missing', file=sys.stderr)
|
||
return 1
|
||
with open(path, 'w', encoding='utf-8') as fh:
|
||
fh.write(patched)
|
||
print('patched %s (%s)' % (path, 'changed' if patched != original else 'unchanged'))
|
||
return 0
|
||
|
||
|
||
if __name__ == '__main__':
|
||
raise SystemExit(main(sys.argv[1] if len(sys.argv) > 1 else '/app/dashy/index.html'))
|