Python builder for generating OVAPortableText / Report Profile v1 JSON documents
Project description
OVAPortableText
A Python package for building JSON documents that conform to the OVAPortableText / Report Profile v1.0 protocol.
OVAPortableText 的目标不是直接渲染 PDF,而是让 Python 端以强类型、可校验、可维护的方式,生成符合协议的 JSON;再交给渲染器去渲染 PDF。
Current scope / 当前实现范围
The package currently implements an intentionally selected, production-usable subset of the v1.0 protocol rather than every reserved taxonomy item. 当前实现是 v1.0 协议里一个可生产使用的已落地子集,并不是把规范里所有预留 taxonomy 一次性全部实现。
Implemented today:
- top-level document / section skeleton
- content body items
- Portable Text
block/span - protocol-approved text styles for v1
- decorator marks + annotation
markDefs - list semantics:
listItem/level - inline objects:
hard_breakxrefcitation_reffootnote_refglossary_term
- block objects:
imagecharttablemath_blockcallout
- typed registries:
assets.images / logos / backgrounds / icons / attachmentsdatasets.tables / charts(pie) / metricsbibliography / footnotes / glossary
- append-style builder APIs
- section / figure / table / equation numbering helpers
- global resolver / index builder
- structured document validation report with issue context
- round-trip helpers:
from_dict()/from_json()/save_json()/load_json()
Not yet implemented as first-class authoring helpers:
- reserved or future taxonomy items that are present in the protocol but not yet exposed as stable Python helpers
- a full generated symbol reference for every internal class or helper
This boundary is intentional: the package focuses on the pieces that are already stable enough for Python authoring and downstream renderer handoff. 这个边界是有意为之:当前包优先把已经稳定、适合 Python 生产 JSON 和交给下游渲染器的部分做好。
Install / 安装
PIP
pip install OVAPortableText
Quick start / 快速开始
from ova_portable_text import create_document
report = create_document(
title="Patent Valuation Report",
language="en",
documentType="report",
strict_ids=True,
)
intro = report.new_section(id="sec-1", level=1, title="Executive Summary")
intro.append_paragraph("This is the opening introduction of the chapter.")
background = intro.new_subsection(id="sec-1-1", title="Background")
background.append_paragraph("This is the body text of subsection 1.1.")
intro.append_paragraph_to_last_content("This is a concluding paragraph after subsection 1.1.")
report.assert_valid()
print(report.to_json())
Recommended workflow / 推荐工作流
- create one
Document - append sections and registries
- enable
strict_ids=Trueduring authoring when you want duplicate IDs to fail early - call
validate()during development - call
assert_valid()before exporting or handing off to Java - export with
to_dict()/to_json()
Common authoring patterns / 常见写法
1) Append sections naturally / 顺手追加章节
from ova_portable_text import create_document
report = create_document(title="Demo", language="en")
sec = report.new_section(id="sec-intro", level=1, title="Introduction")
sec.append_lead("This report summarises the project scope.")
sec.append_bullet_item("Point A")
sec.append_bullet_item("Point B")
2) Add registry resources, then reference them / 先放 registry,再在正文引用
from ova_portable_text import (
create_document,
image_asset,
pie_chart_from_parallel_arrays,
table_column,
table_dataset,
)
report = create_document(title="Data Demo", language="en")
report.add_image_asset(
image_asset(
id="img-cover",
src="https://example.com/cover.png",
alt="Cover image",
)
)
report.add_table_dataset(
table_dataset(
id="table-summary",
columns=[
table_column(key="year", header="Year"),
table_column(key="revenue", header="Revenue"),
],
rows=[
{"year": "2024", "revenue": "12.3M"},
{"year": "2025", "revenue": "13.8M"},
],
)
)
report.add_chart_dataset(
pie_chart_from_parallel_arrays(
id="chart-area-share",
area_en=["Technology", "Finance"],
area_zh=["技术", "金融"],
value=[60, 40],
)
)
3) Fail duplicate IDs earlier when needed / 需要时尽早拦截重复 ID
from ova_portable_text import create_document
report = create_document(title="Strict IDs", language="en", strict_ids=True)
report.new_section(id="sec-1", level=1, title="Intro")
# Raises immediately instead of waiting until validate()
report.new_section(id="sec-1", level=1, title="Duplicate Intro")
4) Keep a continuous content flow / 保持连续 content 语义
from ova_portable_text import create_document
report = create_document(title="Flow Demo", language="en")
sec = report.new_section(id="sec-1", level=1, title="Intro")
sec.append_paragraph("Opening paragraph.")
sec.append_paragraph_to_last_content("Still part of the same content item.")
sub = sec.new_subsection(id="sec-1-1", title="Background")
sub.append_paragraph("Subsection text.")
sec.append_paragraph_to_last_content("This now starts a new content item after the subsection.")
5) Validate before export / 导出前校验
validation = report.validate()
print(validation.to_text())
report.assert_valid()
6) Save JSON to disk and read it back / 落盘 JSON 再读回
from pathlib import Path
from ova_portable_text import create_document, Document
report = create_document(title="Disk Round Trip", language="en")
report.new_section(id="sec-1", level=1, title="Intro").append_paragraph("Saved to disk.")
out_path = report.save_json(Path("build/report.json"))
restored = Document.load_json(out_path)
print(restored.meta.title)
Validation and resolver / 校验与解析器
validate() returns a structured ValidationReport.
validate() 会返回结构化的 ValidationReport。
Each issue tries to include maintenance-friendly context, such as: 每条 issue 会尽量附带更适合维护的上下文,例如:
sectionIdsectionTitlecontextTypecontextIdcontextAnchorsuggestion
validation = report.validate()
for issue in validation.issues:
print(issue.code, issue.sectionId, issue.contextType, issue.suggestion)
Resolver usage:
resolver = report.build_resolver()
print(resolver.debug_summary())
print(resolver.resolve_xref(target_type="section", target_id="sec-1"))
Protocol-aligned authoring notes / 与协议对齐的写作说明
Section.numberingonly accepts"auto","none", or"manual".strict_ids=Trueis an authoring-time safety helper and is not serialized into the final JSON.append_*_to_last_content(...)helpers are ergonomic helpers for preserving the protocol meaning of a continuouscontentitem.- The recommended chart dataset structure is the protocol-native pie
slices[]shape;pie_chart_from_parallel_arrays(...)is a compatibility/helper layer for older parallel-array inputs.
Included docs / 附带文档
docs/QUICKSTART.mddocs/API_REFERENCE.mddocs/VALIDATION_AND_RESOLVER.mddocs/TEST_MATRIX.mddocs/REAL_WORLD_RECIPES.mddocs/USER_TESTING_CHECKLIST.mddocs/PROTOCOL_ALIGNMENT.mddocs/PUBLISHING_CHECKLIST.md
Included examples / 附带样例
examples/minimal_report.pyexamples/inline_objects_report.pyexamples/registry_blocks_report.pyexamples/validation_report.pyexamples/marks_and_lists_report.pyexamples/builder_numbering_roundtrip_demo.pyexamples/extended_registries_demo.pyexamples/validation_context_demo.pyexamples/full_report_workflow_demo.pyexamples/save_and_load_json_demo.pyexamples/patent_valuation_style_report.py
Version / 版本
import ova_portable_text
print(ova_portable_text.__version__)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ovaportabletext-0.1.2.tar.gz.
File metadata
- Download URL: ovaportabletext-0.1.2.tar.gz
- Upload date:
- Size: 118.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9de496acac7ea7c41071f5ff1d76accb45851957caec775204b7394a132edac8
|
|
| MD5 |
0b59caa0b41133a6d9daf4542709d444
|
|
| BLAKE2b-256 |
fb1b9daa8228b657894e189718153f847d0dd124c446ca0971ae43a146ebcca8
|
File details
Details for the file ovaportabletext-0.1.2-py3-none-any.whl.
File metadata
- Download URL: ovaportabletext-0.1.2-py3-none-any.whl
- Upload date:
- Size: 57.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
206d29027ce168d546a56d5f48f17b81b6cbb023c1b848f63e463633f15a9a2b
|
|
| MD5 |
7c891ceab237a820533a359689c2a0ca
|
|
| BLAKE2b-256 |
2a43928d610f5fa45e5180bcca72a62a0bd3ad0e0586db7b32a8f5e5ea06155f
|