markdown で書いて LibreOffice Writer でチェックして wordpress に貼り付けるまで、の計画

技術系の原稿を書くときに、何を使っているかと言うと最近はもっぱら vscode + markdown 形式です。まあ、markdown 形式のみで済むかと言うとそうではなくて、原稿の提出前に Word に貼り付けてチェックをしています。もともと Word の文書チェックの機能を使っていたのと、画面キャプチャのチェックに見た感じのものが必須だからですね。以前はテキストのみで書いていたことも多いのですが、提出した後に画像ファイル番号のずれが多くて、なかなか大変だったので事前に見た目でチェックしようという発想があります。つまりは、私が原稿を書くときに画像ファイル番号を間違えているわけですが。
最近では、markdown 形式のプレビュー機能を使ってチェックする場合も多いのですが、図の矢印とか吹き出しとかもあるので、やはり Word に貼り付けることが多いです。

で、同じパターンで markdown 形式で書いたものを wordpress に貼り付けたいわけですが、これが意外と面倒くさいです。
たいていは、vscode の markdown の原稿からコピペで貼り付けます。

  • 余分な空行がはいる(パラグラフの違い)
  • 箇条書きが1行ずつパラグラフになる
  • 画像が張り付かない
  • 見出しは太文字になる(なぜか、これは対応している)
  • 表は貼り付かない
  • コードブロックは貼り付かない

という問題があります。まあ、workdpress 自身、付属のビジュアルエディタで書くのベターなのでそれでもいいのですが、オフラインで vscode で書いたほうが編集がやりやすいのです。参照するコードとかが色々あるので。

markdown から LibreOffice Writer へ変換する

実験的に ExcelLikeUno ライブラリに connect_writer 関数を生やして、LibreOffice Writer に接続する機能を追加したのが次のコードです。
実は Writer 用に WriterDocument クラスを定義しただけで、paragraph まわりは実装していません。そのまま UNO API を使っています。ExcelLikeUno のほうで完全に網羅しなくても、網羅しきれないところは UNO API を直接使えばいいか、というわけでこの程度ならが書けなくもないか(ほとんど Copilot が書いていますが)というところです。

import uno
from excellikeuno import connect_writer

(desktop, doc) = connect_writer()
# パラグラフを取得して表示する

text = doc.getText()
print("Document Text Paragraphs:" + str(text))

paragraphs = text.createEnumeration()

# LibreOffice text implements enumeration instead of random access.

codeblock = False

while paragraphs.hasMoreElements():
    para = paragraphs.nextElement()
    # print(para.getString())

    # 先頭で ``` 始まるとコードブロックの開始
    if codeblock == True:
        # コードブロックスタイルを適用
        para.setPropertyValue("ParaStyleName", "コード")
        # コードブロック終了判定
        if para.getString().startswith("```"):
            codeblock = not codeblock
        continue
    elif para.getString().startswith("```"): 
        codeblock = not codeblock
         # コードブロックスタイルを適用
        para.setPropertyValue("ParaStyleName", "コード")
        continue

    # 先頭が # の場合、見出しとみなす
    if para.getString().startswith("#"):
        title = para.getString().lstrip("#").strip()
        print(f"Found title: {title}")
        
        # タイトルスタイルを適用
        style_families = doc.raw.getStyleFamilies()
        paragraph_styles = style_families.getByName("ParagraphStyles")
        title_style = paragraph_styles.getByName("Title")
        
        # 先頭が # のみの場合は "見出し1"
        # 先頭が ## の場合は "見出し2" とする
        # 先頭が ### の場合は "見出し3" とする
        level = len(para.getString()) - len(para.getString().lstrip("#"))
        if level == 1:
            para.setPropertyValue("ParaStyleName", "Heading 1")
        elif level == 2:
            para.setPropertyValue("ParaStyleName", "Heading 2")
        elif level == 3:
            para.setPropertyValue("ParaStyleName", "Heading 3")

    # 先頭が - の場合、箇条書きとみなす
    elif para.getString().startswith("-"):
        # 先頭の - を削除
        para.setString(para.getString().lstrip("-").strip())
        # 箇条書きスタイルを適用
        para.setPropertyValue("ParaStyleName", "List 1")

    # 先頭が ![ の場合は画像とみなす
    elif para.getString().startswith("!["):
        # 画像のパスを取得
        start_idx = para.getString().find("](") + 2
        end_idx = para.getString().find(")", start_idx)
        image_path = para.getString()[start_idx:end_idx]

        base_dir = "D:/work/blog/doc/"
        image_path = base_dir + image_path
        # 画像を挿入
        graphic = doc.raw.createInstance("com.sun.star.text.GraphicObject")
        graphic.GraphicURL = f"file:///{image_path}"
        
        print(f"Inserting image: {image_path}")
        # graphic.AnchorType = uno.getConstantByName("com.sun.star.text.TextContentAnchorType.AS_CHARACTER")

        text.insertTextContent(para.End, graphic, False)

        # 画像挿入後、元の段落を削除
        # text.removeTextContent(para)

変更前

変更後

見出し程度ならば手作業とかわらないだろう、ってのもありますが、表とコード、画像の貼りこみ位ができれば確認するにはよいかな、と。現状、図形の貼りこみは小さくなってしまっていますが、図を広げると貼りこまれていることがわかります。 これは、もうちょっと続きを作るのと、Writer 対応の ExcelLikeUno ライブラリを整備に使います。

カテゴリー: 開発, LibreOffice パーマリンク