关于 libreoffice-writer
libreoffice-writer 是一组通过 UNO 操作 LibreOffice Writer 文档的模块,面向需要处理文档的 Agent。它支持结构化编辑、格式设置、补丁操作、元数据修改、导出及页面快照,可用于检查版面。
主要功能
- 01创建和编辑 Writer 文档
- 02定位文本、表格、图片和列表
- 03执行有序补丁操作
- 04设置文档元数据和格式
- 05导出文档并截取页面快照
适用场景
- 01结构化修改现有报告
- 02批量应用文档更改
- 03在格式调整或编辑后检查页面布局
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dfk1352/ libreoffice-skills --skill libreoffice-writer安装后在 Claude Code 中输入/libreoffice-writer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/troubleshooting.mdscripts/colors.pyconstants.pyexceptions.pypatch_base.pysession.pyuno_bridge.pyscripts/writer/__init__.pycore.pyexceptions.pypatch.pysession.pysnapshot.pytargets.py详细介绍
LibreOffice Writer
使用捆绑的 writer 模块执行基于 UNO 的 Writer 文档操作。
所有路径都必须是绝对路径。捆绑模块位于此技能目录下的 scripts/ 中,因此请设置 PYTHONPATH=<skill_base_dir>/scripts。
如果出现设置或运行时问题,请查看 references/troubleshooting.md。
API 概览
# Non-session utilities
create_document(path, source=None) # source: path to .md file to import
export_document(path, output_path, export_format) # formats: "pdf", "docx", "md"
snapshot_page(doc_path, output_path, page=1, dpi=150)
# Session (primary editing API)
WriterSession(path) -> context manager
WriterSession methods:
read_text(target: WriterTarget | None = None) -> str
insert_text(text, target: WriterTarget | None = None)
replace_text(target: WriterTarget, new_text)
delete_text(target: WriterTarget)
format_text(target: WriterTarget, formatting: TextFormatting)
insert_table(rows, cols, data=None, name=None, target: WriterTarget | None = None)
update_table(target: WriterTarget, data)
delete_table(target: WriterTarget)
insert_image(image_path, width=None, height=None, name=None, target: WriterTarget | None = None)
update_image(target: WriterTarget, image_path=None, width=None, height=None)
delete_image(target: WriterTarget)
insert_list(items: list[ListItem], ordered: bool, target: WriterTarget | None = None)
replace_list(target: WriterTarget, items: list[ListItem], ordered: bool | None = None)
delete_list(target: WriterTarget)
set_metadata(values: dict[str, str])
get_metadata() -> dict[str, str]
patch(patch_text, mode="atomic") -> PatchApplyResult
export(output_path, export_format)
reset()
close(save=True)
# Standalone patch utility
patch(path, patch_text, mode="atomic") -> PatchApplyResult
结构化目标:WriterTarget
from writer import WriterTarget
WriterTarget(
kind="text" | "insertion" | "table" | "image" | "list",
text=None,
after=None,
before=None,
occurrence=None,
name=None,
index=None,
)
目标类型
| 类型 | 支持的字段 | 用途 |
|---|---|---|
text | text、after、before、occurrence | 读取、替换、删除或设置匹配文本的格式 |
insertion | text、after、before、occurrence | 在已解析的边界处或匹配文本范围后插入内容 |
table | name 或 index | 更新/删除表格 |
image | name 或 index | 更新/删除图像 |
list | text、after、before、occurrence | 替换/删除一个逻辑列表块 |
解析规则
- 省略
target可读取完整文档,或在文档末尾追加插入内容。 - 使用
after和before限定搜索范围。 - 预期文本会重复出现时使用
occurrence;否则匹配项必须唯一。 - 对于
text、after和before锚点,优先使用完整句子或具有辨识度的段落级短语;在实际文本编辑中,单个词作为锚点往往过于脆弱。 - 对于表格/图像目标,优先使用
name;仅当顺序稳定时才使用index。 - 在行内文本后插入时,Writer 会在匹配文本范围后的边界处插入;段落分隔符必须包含在插入文本中,或由会话辅助函数提供。
格式载荷
from writer import TextFormatting
TextFormatting(
bold=None,
italic=None,
underline=None,
font_name=None,
font_size=None,
color=None, # named color or integer
align=None, # "left" | "center" | "right" | "justify" | "start" | "end"
line_spacing=None,
spacing_before=None,
spacing_after=None,
)
注意:
- 字符格式和段落格式可以在一次调用中组合设置。
align等段落属性会应用于包含匹配内容的整个段落,而不仅是精确匹配的文本范围。- 必须至少设置一个格式字段。
列表项
from writer import ListItem
ListItem(text="Confirm scope", level=0)
level表示从零开始的嵌套级别。- 嵌套级别不能跳级。
ordered=True使用编号样式;ordered=False使用项目符号。
元数据
set_metadata()接受由键值对组成的字典。- 支持的键包括
title、author、subject、keywords和description。 keywords可以是逗号分隔的字符串;get_metadata()会将其作为一个逗号分隔的字符串返回。
补丁 DSL
使用 patch() 或 session.patch() 按顺序应用操作。
[operation]
type = format_text
target.kind = text
target.text = Quarterly revenue grew 18%.
target.after = Financial Summary
target.before = Action Items
format.bold = true
format.align = center
[operation]
type = insert_list
target.kind = insertion
target.after = Action Items
list.ordered = false
items <<JSON
[
{"text": "Confirm scope", "level": 0},
{"text": "Review output", "level": 0},
{"text": "Update packaging", "level": 1}
]
JSON
支持的操作类型
insert_textreplace_textdelete_textformat_textinsert_tableupdate_tabledelete_tableinsert_imageupdate_imagedelete_imageinsert_listreplace_listdelete_list
补丁值规则
- 使用
target.*字段定义目标。 - 若要在文档末尾追加内容,请省略所有
target.*字段;不要在没有锚点时仅设置target.kind = insertion。 - 使用
format.*字段设置格式载荷。 - 列表操作使用
list.ordered和 JSONitems。 items和data必须是有效的 JSON。- 多行文本或 JSON 支持使用
<<TAG ... TAG格式的 HereDoc 块。
模式
atomic会在首次失败时停止、重置会话且不保存任何内容。best_effort会保留此前成功的操作并记录失败项。
PatchApplyResult 字段:
modeoverall_status="ok" | "partial" | "failed"operations=PatchOperationResult列表document_persisted
对于独立的 patch(path, ...),document_persisted 表示更改已保存到磁盘。对于 session.patch(...),它表示补丁在当前打开的会话状态中产生了成功的修改。
示例:在会话中编辑报告
from pathlib import Path
from writer import ListItem, TextFormatting, WriterSession, WriterTarget
from writer.core import create_document
output = str(Path("test-output/report.odt").resolve())
create_document(output)
with WriterSession(output) as session:
session.insert_text(
"Executive Summary\n\n"
"Financial Summary\n\n"
"Quarterly revenue grew 18%.\n\n"
"Action Items"
)
session.format_text(
WriterTarget(
kind="text",
text="Quarterly revenue grew 18%.",
after="Financial Summary",
before="Action Items",
),
TextFormatting(bold=True, align="center"),
)
session.insert_list(
[
ListItem(text="Confirm scope", level=0),
ListItem(text="Review output", level=0),
ListItem(text="Update packaging", level=1),
],
ordered=False,
target=WriterTarget(kind="insertion", after="Action Items"),
)
示例:修补现有文档
from writer import patch
result = patch(
"/abs/path/report.odt",
"""
[operation]
type = replace_text
target.kind = text
target.text = Draft
new_text = Final
[operation]
type = update_table
target.kind = table
target.name = Summary
data = [["Metric", "Value"], ["Revenue", "$2M"]]
[operation]
type = replace_list
target.kind = list
target.text = Confirm scope
items = [{"text": "Approve release", "level": 0}, {"text": "Notify team", "level": 1}]
list.ordered = true
""",
mode="best_effort",
)
print(result.overall_status)
快照
from pathlib import Path
from writer import snapshot_page
result = snapshot_page(doc_path, "/tmp/page1.png", page=1, dpi=150)
print(result.file_path, result.width, result.height)
Path(result.file_path).unlink(missing_ok=True) # clean up used snapshots
文档排版、编辑列表、放置图像或更改表格后,可使用快照检查布局。
- 如果文档已在
WriterSession中打开,优先使用session.export()。 - 如果要导出现有文件且不保持会话打开,请使用独立的
export_document()。 get_metadata()会将keywords规范化为以逗号和空格分隔的单个字符串。
常见错误
- 传入相对路径;面向 UNO 的 Writer API 需要绝对文件路径。
- 对重复文本省略
occurrence,随后导致歧义错误。 - 使用过短或过于常见的锚点;尽可能使用完整句子或段落级别的锚点文本,并搭配
after/before边界。 - 期望
align仅作用于短语;Writer 会对所在段落应用段落对齐方式。 - 在
items或data补丁字段中提供格式错误的 JSON。 - 检查后忘记清理已捕获的快照。
- 在
session.close()后调用session.export()或其他方法。 - Markdown 导入 / 导出的 Markdown 筛选器需要 LibreOffice 26.2+。
"start"和"end"段落对齐选项需要 LibreOffice 26.2+。
评论
支持 Markdown