3 Commits

5 changed files with 70 additions and 22 deletions

View File

@@ -41,7 +41,7 @@ jobs:
run: | run: |
flatpak --user install -y zoitechat.flatpak flatpak --user install -y zoitechat.flatpak
app_dir="$(flatpak info --user --show-location net.zoite.Zoitechat)" app_dir="$(flatpak info --user --show-location net.zoite.Zoitechat)"
test -f "$app_dir/files/share/doc/net.zoite.Zoitechat/html/index.html" test -f "$app_dir/files/share/zoitechat/offline-docs/index.html"
- name: Upload Flatpak Bundle - name: Upload Flatpak Bundle
id: upload_flatpak id: upload_flatpak

View File

@@ -1,42 +1,89 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import html import html
import io import io
import pathlib import pathlib
import shutil import shutil
import sys import sys
import tarfile import tarfile
import tempfile
import urllib.error import urllib.error
import urllib.request import urllib.request
url = sys.argv[1] url = sys.argv[1]
out_dir = pathlib.Path(sys.argv[2]) out_dir = pathlib.Path(sys.argv[2])
source_dir = pathlib.Path(sys.argv[3]) if len(sys.argv) > 3 else pathlib.Path.cwd() source_dir = pathlib.Path(sys.argv[3]) if len(sys.argv) > 3 else pathlib.Path.cwd()
docs_dir = out_dir / 'offline-docs' docs_dir = out_dir / "offline-docs"
if docs_dir.exists(): if docs_dir.exists():
shutil.rmtree(docs_dir) shutil.rmtree(docs_dir)
docs_dir.mkdir(parents=True, exist_ok=True) docs_dir.mkdir(parents=True, exist_ok=True)
def write_source_docs():
parts = ['<!doctype html><html><head><meta charset="utf-8"><title>ZoiteChat Documentation</title></head><body><h1>ZoiteChat Documentation</h1>'] def write_source_docs() -> None:
for name in ('readme.md', 'troubleshooting.md', 'changelog.rst'): parts = [
'<!doctype html><html><head><meta charset="utf-8">'
"<title>ZoiteChat Documentation</title></head><body>"
"<h1>ZoiteChat Documentation</h1>"
]
for name in ("readme.md", "troubleshooting.md", "changelog.rst"):
path = source_dir / name path = source_dir / name
if path.exists(): if path.exists():
parts.append(f'<h2>{html.escape(name)}</h2><pre>{html.escape(path.read_text(encoding="utf-8", errors="replace"))}</pre>') parts.append(
parts.append('</body></html>') f"<h2>{html.escape(name)}</h2>"
(docs_dir / 'index.html').write_text('\n'.join(parts), encoding='utf-8') f"<pre>{html.escape(path.read_text(encoding='utf-8', errors='replace'))}</pre>"
)
parts.append("</body></html>")
(docs_dir / "index.html").write_text("\n".join(parts), encoding="utf-8")
def safe_extract(tar: tarfile.TarFile, target: pathlib.Path) -> None:
target = target.resolve()
for member in tar.getmembers():
member_path = (target / member.name).resolve()
if not str(member_path).startswith(str(target) + "/"):
raise tarfile.TarError(f"unsafe archive path: {member.name}")
tar.extractall(target)
def copy_index_tree(extracted_dir: pathlib.Path) -> bool:
indexes = sorted(extracted_dir.rglob("index.html"))
if not indexes:
return False
root = indexes[0].parent
for item in root.iterdir():
dest = docs_dir / item.name
if item.is_dir():
shutil.copytree(item, dest, dirs_exist_ok=True)
else:
shutil.copy2(item, dest)
return (docs_dir / "index.html").exists()
if url: if url:
try: try:
with urllib.request.urlopen(url, timeout=30) as r: with urllib.request.urlopen(url, timeout=30) as response:
data = r.read() data = response.read()
with tarfile.open(fileobj=io.BytesIO(data), mode='r:gz') as tar:
try: with tempfile.TemporaryDirectory() as tmp:
tar.extractall(docs_dir, filter='data') extract_dir = pathlib.Path(tmp)
except TypeError: with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as tar:
tar.extractall(docs_dir) safe_extract(tar, extract_dir)
if not copy_index_tree(extract_dir):
write_source_docs()
except (OSError, tarfile.TarError, urllib.error.URLError) as error: except (OSError, tarfile.TarError, urllib.error.URLError) as error:
print(f'offline docs download failed: {error}', file=sys.stderr) print(f"offline docs download failed: {error}", file=sys.stderr)
write_source_docs() write_source_docs()
else: else:
write_source_docs() write_source_docs()
(out_dir / 'offline-docs.stamp').write_text('ok')
(out_dir / "offline-docs.stamp").write_text("ok", encoding="utf-8")

View File

@@ -57,7 +57,8 @@
"-Dwith-perl=perl", "-Dwith-perl=perl",
"-Dwith-python=python3", "-Dwith-python=python3",
"-Dwith-lua=lua", "-Dwith-lua=lua",
"-Doffline-docs-package=net.zoite.Zoitechat" "-Doffline-docs-package=net.zoite.Zoitechat",
"-Doffline-docs-dir=share/zoitechat/offline-docs"
], ],
"build-options": { "build-options": {
"cflags": "-Wno-error=missing-include-dirs" "cflags": "-Wno-error=missing-include-dirs"

View File

@@ -63,12 +63,12 @@ option('with-perl-legacy-api', type: 'boolean', value: false,
description: 'Enables the legacy IRC perl module for compatibility with old scripts' description: 'Enables the legacy IRC perl module for compatibility with old scripts'
) )
option('offline-docs-url', type: 'string', value: '', option('offline-docs-url', type: 'string', value: 'https://dl.zoitechat.org/offlinedocs/zoitechat-docs-html-2.18.1.tar.gz',
description: 'URL for offline documentation archive (tar.gz)' description: 'URL for offline documentation archive (tar.gz)'
) )
option('offline-docs-package', type: 'string', value: '', option('offline-docs-package', type: 'string', value: '',
description: 'Package or app id to use under the installed documentation directory' description: 'Package or app id to use under the installed documentation directory'
) )
option('offline-docs-dir', type: 'string', value: 'https://dl.zoitechat.org/offlinedocs/zoitechat-docs-html-2.18.1.tar.gz', option('offline-docs-dir', type: 'string', value: '',
description: 'Installed offline documentation directory relative to prefix' description: 'Installed offline documentation directory relative to prefix'
) )

View File

@@ -1,6 +1,6 @@
#define APPNAM "ZoiteChat" #define APPNAM "ZoiteChat"
#define APPVER "<#= [string]::Join('.', $versionParts) #>" #define APPVER "<#= [string]::Join('.', $versionParts) #>"
#define OFFLINEDOCSURL "https://dl.zoitechat.org/offlinedocs/zoitechat-docs-html-{#APPVER}.tar.gz" #define OFFLINEDOCSURL "https://dl.zoitechat.org/offlinedocs/zoitechat-docs-html-" + APPVER + ".tar.gz"
; These are defined by our installer project at build time ; These are defined by our installer project at build time
;#define APPARCH "x64" ;#define APPARCH "x64"
;#define PROJECTDIR "C:\...\zoitechat\win32\installer\" ;#define PROJECTDIR "C:\...\zoitechat\win32\installer\"
@@ -340,7 +340,7 @@ begin
'Remove-Item -LiteralPath ''' + DocsDir + ''' -Recurse -Force -ErrorAction SilentlyContinue; ' + 'Remove-Item -LiteralPath ''' + DocsDir + ''' -Recurse -Force -ErrorAction SilentlyContinue; ' +
'New-Item -ItemType Directory -LiteralPath ''' + DocsDir + ''' -Force | Out-Null; ' + 'New-Item -ItemType Directory -LiteralPath ''' + DocsDir + ''' -Force | Out-Null; ' +
'Copy-Item -Path (Join-Path $i.DirectoryName ''*'') -Destination ''' + DocsDir + ''' -Recurse -Force'; 'Copy-Item -Path (Join-Path $i.DirectoryName ''*'') -Destination ''' + DocsDir + ''' -Recurse -Force';
if not Exec(GetSysDir() + 'WindowsPowerShell\v1.0\powershell.exe', '-NoProfile -ExecutionPolicy Bypass -Command "' + Script + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then if not Exec(ExpandConstant('{sys}\WindowsPowerShell\v1.0\powershell.exe'), '-NoProfile -ExecutionPolicy Bypass -Command "' + Script + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
Result := False Result := False
else else
Result := ResultCode = 0; Result := ResultCode = 0;