Initial release: export 1C Help to Gitea wiki.
Convert Ext/Help/ru.html to Markdown and push to a wiki git repository.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
"""Wiki page titles and Gitea filename encoding."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import re
|
||||
from urllib.parse import quote, unquote
|
||||
|
||||
from export1c_help.discover import HelpPage
|
||||
|
||||
_INVALID = re.compile(r'[\\/:*?"<>|#\[\]]+')
|
||||
_SPACES = re.compile(r"\s+")
|
||||
_MAX_NAME_BYTES = 180
|
||||
|
||||
|
||||
def sanitize_title(title: str) -> str:
|
||||
title = _SPACES.sub(" ", title).strip()
|
||||
title = _INVALID.sub(" ", title)
|
||||
title = _SPACES.sub(" ", title).strip()
|
||||
return title or "untitled"
|
||||
|
||||
|
||||
def _truncate_utf8(s: str, max_bytes: int) -> str:
|
||||
raw = s.encode("utf-8")
|
||||
if len(raw) <= max_bytes:
|
||||
return s
|
||||
raw = raw[:max_bytes]
|
||||
while raw:
|
||||
try:
|
||||
return raw.decode("utf-8").rstrip("- ")
|
||||
except UnicodeDecodeError:
|
||||
raw = raw[:-1]
|
||||
return "page"
|
||||
|
||||
|
||||
def _short_hash(s: str) -> str:
|
||||
return hashlib.sha1(s.encode("utf-8")).hexdigest()[:8]
|
||||
|
||||
|
||||
def wiki_filename(title: str, *, meta_key: str | None = None) -> str:
|
||||
"""Unicode wiki slug (spaces → «-»)."""
|
||||
slug = sanitize_title(title).replace(" ", "-")
|
||||
# reserve room for optional -xxxxxxxx suffix
|
||||
slug = _truncate_utf8(slug, _MAX_NAME_BYTES)
|
||||
return f"{slug}.md"
|
||||
|
||||
|
||||
def wiki_filename_gitea_legacy(title: str) -> str:
|
||||
slug = sanitize_title(title).replace(" ", "-")
|
||||
slug = _truncate_utf8(slug, 80)
|
||||
return quote(slug, safe="-_.") + ".md"
|
||||
|
||||
|
||||
def decode_wiki_filename(name: str) -> str:
|
||||
base = name[:-3] if name.endswith(".md") else name
|
||||
return unquote(base)
|
||||
|
||||
|
||||
def assign_titles(
|
||||
pages: list[HelpPage],
|
||||
h1_by_meta: dict[str, str | None],
|
||||
) -> tuple[dict[str, str], dict[str, str]]:
|
||||
"""
|
||||
Returns (meta_key → title, meta_key → filename).
|
||||
|
||||
Filenames are unique even after UTF-8 truncation.
|
||||
"""
|
||||
used_title: set[str] = set()
|
||||
used_file: set[str] = set()
|
||||
titles: dict[str, str] = {}
|
||||
files: dict[str, str] = {}
|
||||
|
||||
for p in pages:
|
||||
h1 = h1_by_meta.get(p.meta_key)
|
||||
base = sanitize_title(h1 or p.synonym or p.meta_key)
|
||||
title = base
|
||||
n = 2
|
||||
while title.casefold() in used_title:
|
||||
if p.is_form and p.form_name and n == 2:
|
||||
title = sanitize_title(f"{base} — {p.form_name}")
|
||||
elif n == 2:
|
||||
title = sanitize_title(f"{base} — {p.object_name}")
|
||||
else:
|
||||
title = sanitize_title(f"{base} ({n})")
|
||||
n += 1
|
||||
if n > 5000:
|
||||
title = sanitize_title(p.meta_key)
|
||||
break
|
||||
|
||||
fname = wiki_filename(title)
|
||||
if fname.casefold() in used_file:
|
||||
stem = fname[:-3]
|
||||
stem = _truncate_utf8(stem, _MAX_NAME_BYTES - 9)
|
||||
fname = f"{stem}-{_short_hash(p.meta_key)}.md"
|
||||
# last-resort unique
|
||||
guard = 0
|
||||
while fname.casefold() in used_file:
|
||||
fname = f"page-{_short_hash(p.meta_key + str(guard))}.md"
|
||||
guard += 1
|
||||
|
||||
used_title.add(title.casefold())
|
||||
used_file.add(fname.casefold())
|
||||
titles[p.meta_key] = title
|
||||
files[p.meta_key] = fname
|
||||
|
||||
return titles, files
|
||||
Reference in New Issue
Block a user