mcpField
L
libreoffice-writer

libreoffice-writer

github.com/dfk1352ドキュメント7149 回インストール3 日前に更新
リポジトリ

libreoffice-writer について

libreoffice-writerは、UNO経由でLibreOffice Writer文書を操作するモジュール群です。文書を扱うエージェント向けに、構造化編集、書式設定、パッチ操作、メタデータ変更、エクスポート、レイアウト確認用のページ撮影を提供します。

主な機能

  1. 01Writer文書の作成と編集
  2. 02テキスト、表、画像、リストの指定
  3. 03順序付きパッチ操作の適用
  4. 04文書メタデータと書式の設定
  5. 05文書のエクスポートとページ撮影

活用シーン

  1. 01既存レポートの構造化編集
  2. 02文書変更の一括適用
  3. 03書式設定や編集後のページレイアウト確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dfk1352/libreoffice-skills --skill libreoffice-writer

インストール後、Claude Code で/libreoffice-writerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
troubleshooting.md
scripts/
colors.py
constants.py
exceptions.py
patch_base.py
session.py
uno_bridge.py
scripts/writer/
__init__.py
core.py
exceptions.py
patch.py
session.py
snapshot.py
targets.py

詳細

LibreOffice Writer

UNO 対応の Writer ドキュメントを操作するには、同梱の 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,
)
ターゲットの種類
種類サポートされるフィールド用途
texttext、after、before、occurrence一致したテキストの読み取り、置換、削除、書式設定
insertiontext、after、before、occurrence解決された境界、または一致した範囲の後に挿入
tablename または index表の更新/削除
imagename または index画像の更新/削除
listtext、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,
)

注:

  • 文字書式と段落書式は、1 回の呼び出しで組み合わせられます。
  • align などの段落プロパティは、一致した範囲だけでなく、その範囲を含む段落全体に適用されます。
  • 書式フィールドを少なくとも 1 つ設定する必要があります。

リスト項目

from writer import ListItem

ListItem(text="Confirm scope", level=0)
  • level は、0 から始まるネストレベルです。
  • レベルを飛ばしたネストはできません。
  • ordered=True は番号付きスタイルを、ordered=False は箇条書きを使用します。

メタデータ

  • set_metadata() は、キーと値のペアを格納した辞書を受け取ります。
  • サポートされているキーは title、author、subject、keywords、description です。
  • keywords はカンマ区切りの文字列を指定できます。get_metadata() はキーワードを 1 つのカンマ区切り文字列として返します。

パッチ 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_text
  • replace_text
  • delete_text
  • format_text
  • insert_table
  • update_table
  • delete_table
  • insert_image
  • update_image
  • delete_image
  • insert_list
  • replace_list
  • delete_list
パッチ値のルール
  • ターゲットの定義には target.* フィールドを使用します。
  • ドキュメントの末尾に追加するには、すべての target.* フィールドを省略します。アンカーなしで target.kind = insertion だけを指定しないでください。
  • 書式設定ペイロードには format.* フィールドを使用します。
  • リスト操作には list.ordered と JSON の items を使用します。
  • items と data は有効な JSON である必要があります。
  • 複数行のテキストまたは JSON には、<<TAG ... TAG の形式でヒアドキュメントブロックを使用できます。
モード
  • atomic は最初の失敗時に停止し、セッションをリセットして、何も保存しません。
  • best_effort は、先行する操作のうち成功したものを保持し、失敗を記録します。

PatchApplyResult のフィールド:

  • mode
  • overall_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をカンマとスペースで区切った1つの文字列に正規化します。

よくある間違い

  • 相対パスを渡すこと。UNOに対応するWriter APIでは、絶対ファイルパスが必要です。
  • 繰り返し出現するテキストにoccurrenceを指定せず、曖昧さのエラーが発生すること。
  • アンカーが短すぎたり、一般的すぎたりすること。可能な場合は、文全体または段落単位のアンカーテキストに加えて、after/beforeの境界を指定してください。
  • alignがフレーズだけに適用されると考えること。Writerでは、段落の配置はそのフレーズを含む段落全体に適用されます。
  • itemsまたはdataのパッチフィールドに不正なJSONを指定すること。
  • 確認後に、取得したスナップショットを削除し忘れること。
  • session.close()の後に、session.export()やその他のメソッドを呼び出すこと。
  • Markdownのインポート/エクスポート用フィルターを使用するには、LibreOffice 26.2以降が必要です。
  • 段落配置の"start"および"end"オプションを使用するには、LibreOffice 26.2以降が必要です。

コメント