mirror of
git://f0xx.org/android_cast
synced 2026-07-29 07:39:15 +03:00
docs update, be sync
This commit is contained in:
@@ -1,5 +1,17 @@
|
||||
# Media service (SFU / MCU) — AI deployment prerequisites
|
||||
|
||||
|
||||
<!-- doc-meta:start -->
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Author | Anton Afanasyeu |
|
||||
| Revision | R1 |
|
||||
| Creation date | 2026-06-12 |
|
||||
| Last modification date | 2026-06-12 |
|
||||
| Co-authored | |
|
||||
| Severity | medium |
|
||||
<!-- doc-meta:end -->
|
||||
|
||||
**Document type:** Requirements / handoff (pre-SPEC)
|
||||
**Date:** 2026-06-12
|
||||
**Audience:** PO / sysop → AI agent for full deploy + tune on fresh Alpine HVM(s)
|
||||
@@ -13,6 +25,7 @@
|
||||
|
||||
---
|
||||
|
||||
\newpage
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
@@ -29,6 +42,7 @@
|
||||
- [11. PO checklist (copy before handoff)](#11-po-checklist-copy-before-handoff)
|
||||
- [12. Changelog](#12-changelog)
|
||||
<!-- /toc -->
|
||||
\newpage
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ from reportlab.platypus import (
|
||||
Table,
|
||||
TableStyle,
|
||||
)
|
||||
from page_footer import NumberedCanvas
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
BUILD = Path(__file__).resolve().parent
|
||||
@@ -369,7 +370,7 @@ def build_pdf() -> None:
|
||||
title="Android Cast — Next-gen egress review",
|
||||
author="Android Cast project",
|
||||
)
|
||||
doc.build(story)
|
||||
doc.build(story, canvasmaker=NumberedCanvas)
|
||||
print(f"Wrote {OUT_PDF}")
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ from reportlab.platypus import (
|
||||
Table,
|
||||
TableStyle,
|
||||
)
|
||||
from page_footer import NumberedCanvas
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
BUILD = Path(__file__).resolve().parent
|
||||
@@ -320,7 +321,7 @@ def build_pdf() -> None:
|
||||
topMargin=2 * cm,
|
||||
bottomMargin=2 * cm,
|
||||
)
|
||||
doc.build(story)
|
||||
doc.build(story, canvasmaker=NumberedCanvas)
|
||||
print(f"Wrote {OUT_PDF}")
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from reportlab.lib.pagesizes import A4
|
||||
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
|
||||
from reportlab.lib.units import cm
|
||||
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle
|
||||
from page_footer import NumberedCanvas
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
OUT_PDF = ROOT / "docs" / "GRAFANA_vs_others_graphvis_pivot.pdf"
|
||||
@@ -207,7 +208,7 @@ def build_pdf() -> None:
|
||||
title="Grafana vs Others GraphVis Pivot",
|
||||
author="Android Cast project",
|
||||
)
|
||||
doc.build(story)
|
||||
doc.build(story, canvasmaker=NumberedCanvas)
|
||||
print(f"Wrote {OUT_PDF}")
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
@@ -27,6 +27,7 @@ from mermaid_render import (
|
||||
diagram_flowables,
|
||||
ensure_diagram_caption_style,
|
||||
)
|
||||
from page_footer import NumberedCanvas
|
||||
|
||||
|
||||
def _xml(text: str) -> str:
|
||||
@@ -173,6 +174,44 @@ def build_pdf_from_markdown(
|
||||
story.append(Paragraph(_inline_md(doc_subtitle), small))
|
||||
story.append(Spacer(1, 0.15 * cm))
|
||||
|
||||
# Optional first-page metadata table (doc template block)
|
||||
meta_start = next((i for i, ln in enumerate(lines) if ln.strip() == "<!-- doc-meta:start -->"), None)
|
||||
meta_end = next((i for i, ln in enumerate(lines) if ln.strip() == "<!-- doc-meta:end -->"), None)
|
||||
if meta_start is not None and meta_end is not None and meta_end > meta_start:
|
||||
meta_rows = [ln for ln in lines[meta_start + 1 : meta_end] if ln.strip().startswith("|")]
|
||||
if len(meta_rows) >= 2:
|
||||
headers = _parse_table_row(meta_rows[0])
|
||||
data = [[_cell(h, tbl_head) for h in headers]]
|
||||
for row_line in meta_rows[2:]: # skip separator row
|
||||
row = _parse_table_row(row_line)
|
||||
padded = row + [""] * (len(headers) - len(row))
|
||||
data.append([_cell(c, tbl_body) for c in padded[: len(headers)]])
|
||||
if data and len(headers) > 0:
|
||||
col_widths = [5.2 * cm, 11.0 * cm] if len(headers) == 2 else [(16.2 * cm) / len(headers)] * len(headers)
|
||||
meta_tbl = Table(data, colWidths=col_widths)
|
||||
meta_tbl.setStyle(
|
||||
TableStyle(
|
||||
[
|
||||
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#1565C0")),
|
||||
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
|
||||
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
|
||||
("FONTSIZE", (0, 0), (-1, -1), 8),
|
||||
("VALIGN", (0, 0), (-1, -1), "TOP"),
|
||||
("GRID", (0, 0), (-1, -1), 0.5, colors.lightgrey),
|
||||
("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#F5F5F5")]),
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 4),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 4),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 3),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 3),
|
||||
]
|
||||
)
|
||||
)
|
||||
story.append(meta_tbl)
|
||||
story.append(Spacer(1, 0.2 * cm))
|
||||
|
||||
# Page 1: title + metadata, page 2: TOC
|
||||
story.append(PageBreak())
|
||||
|
||||
# Table of contents (clickable internal links)
|
||||
story.append(Paragraph("Table of contents", toc_title))
|
||||
for level, title, slug in headings:
|
||||
@@ -219,6 +258,18 @@ def build_pdf_from_markdown(
|
||||
if line.strip().startswith("**Documentation index:**"):
|
||||
i += 1
|
||||
continue
|
||||
if line.strip() == "<!-- doc-meta:start -->":
|
||||
while i < len(lines) and lines[i].strip() != "<!-- doc-meta:end -->":
|
||||
i += 1
|
||||
i += 1
|
||||
continue
|
||||
if line.strip() == "<!-- doc-meta:end -->":
|
||||
i += 1
|
||||
continue
|
||||
if line.strip() == "\\newpage":
|
||||
story.append(PageBreak())
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.strip().startswith("```"):
|
||||
if in_code:
|
||||
@@ -338,5 +389,5 @@ def build_pdf_from_markdown(
|
||||
title=doc_title,
|
||||
author="Android Cast project",
|
||||
)
|
||||
doc.build(story)
|
||||
doc.build(story, canvasmaker=NumberedCanvas)
|
||||
print(f"Wrote {out_pdf} ({len(headings)} TOC entries from markdown headings)")
|
||||
|
||||
36
docs/_pdf_build/page_footer.py
Normal file
36
docs/_pdf_build/page_footer.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""Shared PDF footer canvas: bottom-right `current / total` page counter."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from reportlab.lib import colors
|
||||
from reportlab.pdfgen import canvas
|
||||
|
||||
|
||||
class NumberedCanvas(canvas.Canvas):
|
||||
"""Canvas that renders `N / total` footer on every page."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._saved_page_states: list[dict] = []
|
||||
|
||||
def showPage(self) -> None:
|
||||
self._saved_page_states.append(dict(self.__dict__))
|
||||
self._startPage()
|
||||
|
||||
def save(self) -> None:
|
||||
total = len(self._saved_page_states)
|
||||
for state in self._saved_page_states:
|
||||
self.__dict__.update(state)
|
||||
self._draw_page_footer(total)
|
||||
super().showPage()
|
||||
super().save()
|
||||
|
||||
def _draw_page_footer(self, total_pages: int) -> None:
|
||||
self.saveState()
|
||||
self.setFillColor(colors.HexColor("#BDBDBD"))
|
||||
self.setFont("Helvetica", 8)
|
||||
label = f"{self._pageNumber} / {total_pages}"
|
||||
x = self._pagesize[0] - 1.5 * 28.3465 # ~1.5 cm from right
|
||||
y = 0.9 * 28.3465 # ~0.9 cm from bottom
|
||||
self.drawRightString(x, y, label)
|
||||
self.restoreState()
|
||||
Reference in New Issue
Block a user