✒️
バラバラの原稿ファイルから、青空文庫形式、Pixiv形式、pdfファイルを生成する
動機
- 原稿をUlyssesで書いている
- 適度に分割している
- チェックがしやすいよう、青空文庫形式
- i文庫Sに入れて読んだりする
- 最終的な行き先として以下がある
- 小説家になろう(ノクターンノベルズ)へ投稿
- Pixivへ投稿
- リクエストへ青空文庫形式txt/pdfで納品
- Pixiv投稿およびリクエスト納品用に、バラバラのファイルをそれぞれのフォーマットに応じた単一ファイルにまとめる作業がある
- Ulyssesだとまとめるのは簡単だが、フォーマット変換ができない
- 特に両フォーマットへの変換を同時に行いたい
- ついでに執筆状況管理のための文字数カウントも統合したい
ワークフロー
今回作成したスクリプトでは、青空文庫形式txtおよびPixiv形式txtを同時に生成し、さらに青空文庫形式txtからpdfを生成する
Pixivに投稿する際は、生成されたファイルの内容をコピペする
フォーマットの相違
青空文庫形式とPixiv形式では要素に微妙な違いがある
要素 | 青空文庫 | Pixiv |
---|---|---|
タイトル | ファイル名、大見出し | ファイル名 |
章タイトル | 中見出し | チャプター |
改ページ | あり | あり |
改丁 | あり | なし |
違いを抽出すると、
- 青空文庫形式では本文に大見出しを含める
- Pixivでは改丁できない
ソースファイルのフォーマット
上記の要素をソースファイルに組み込む必要がある
今回は以下の通り組み込んだ
要素 | ソースで |
---|---|
タイトル | ヘッダ1 |
章タイトル | ファイル名の一部 |
改ページ | ファイル区切り |
改丁 | ファイル区切り/ファイル名の一部 |
- タイトル
- フォルダ名にはしたくない
- 最後に決めることが多い
- 仮タイトルのほうが管理しやすい
- フォルダ名にはしたくない
- 章タイトル
- ページの途中に入れることがないので、改ページ(改丁)とまとめたほうがよい
- 改ページ
- ページごとに別のファイルとする
- 改丁
- 基本的に改ページと同様
- 改ページと区別するためにマーカーを付ける
具体的には、
本文内にタイトルを以下のように記述
# 超かっこいいタイトル
ファイル名を以下のように設定
1_2-超エモい章タイトル*
先頭はソートのためのナンバリング
末尾の*
は改丁マーカー
実装
スクリプト内容
bashスクリプトの内容は以下の通り
#!/bin/bash
# [メモ]
# タイトルは文中に含めるが、サブタイトルは含めない。理由は以下の通り
# 1. ファイルの切れ目=ページの切れ目であり、サブタイトルは必ずページの切れ目に位置すること
# 2. 執筆中にサブタイトルが見えていた方がよいこと
# 引数を受け取る
for f in "$@"
do
export LANG="ja_JP.UTF-8"
cd "$f"
# 文字数カウント
find . -type f -name "*.md" -exec cat {} \; | tr -d '\n' | tr -d '\r' | wc -m | pbcopy # Ulyssesのカウントに合わせるため改行を除く
osascript -e "display notification \"$(pbpaste) chacters\" with title \"Count characters of files in folder(multibyte)\""
# パラメータのチェック
if [ -z "$1" ]; then
echo "ディレクトリパスを指定してください。"
exit 1
fi
# ディレクトリの存在確認
if [ ! -d "$1" ]; then
echo "指定されたディレクトリが存在しません。"
exit 1
fi
# 親ディレクトリの特定
parent_dir=$(dirname "$1")
# プロダクトディレクトリの作成
product_dir="$parent_dir/product"
mkdir -p "$product_dir"
# タイトルの抽出とプロダクトファイルの初期化
title=$(grep -h "^# " ./*.md | sed -n 's/^# *\(.*\)/\1/p')
tmp_file_ao="$product_dir"/tmp_ao.txt
echo "${title}[#「${title}」は大見出し]" >> "$tmp_file_ao"
tmp_file_px="$product_dir"/tmp_px.txt
product_file_ao="$product_dir/$title".txt
product_file_aop="$product_dir/$title".pdf
product_file_px="$product_dir/$title"_pixiv.txt
# echo "" > "$product_file"
# ソースファイルの結合
for file in "$1"/*.md; do
filename=$(basename "$file")
numbering=$(echo "$filename" | sed 's/\([0-9_-]*\).*\.md/\1/')
# 青空文庫
header_ao=$(echo "$filename" | sed -n 's/^[0-9_-]*\(.*\).md/\1/p' | sed 's/*//' | sed -n 's/\(..*\)/\1[#「\1」は中見出し]/p') # ヘッダを抽出し、文字列があれば中見出しに変換
if [ -n "$numbering" ]; then # ナンバリングのあるファイルの場合
if echo "$filename" | grep -q "*.md$"; then # ファイル名の末尾が "*" の場合
echo "[#改丁]" >> "$tmp_file_ao"
else
echo "[#改ページ]" >> "$tmp_file_ao"
fi
fi
# Pixiv
if [ "${#header_ao}" != 0 ]; then # 見出しのあるファイルの場合:空文字列判定がうまく動作しなかったため文字数判定
echo "$header_ao" >> "$tmp_file_ao"
fi
cat "$file" | sed '/^#/d' >> "$tmp_file_ao" # タイトルを除いて追記
header_px=$(echo "$filename" | sed -n 's/^[0-9_-]*\(.*\).md/\1/p' | sed 's/*//' | sed -n 's/\(..*\)/[chapter:\1]/p') # ヘッダを抽出し、文字列があれば中見出しに変換
if [ -n "$numbering" ]; then # ナンバリングのあるファイルの場合
echo "[newpage]" >> "$tmp_file_px"
fi
if [ "${#header_px}" != 0 ]; then # 見出しのあるファイルの場合:空文字列判定がうまく動作しなかったため文字数判定
echo "$header_px" >> "$tmp_file_px"
fi
cat "$file" | sed '/^#/d' >> "$tmp_file_px" # タイトルを除いて追記
done
# Mac濁点・半濁点対策
iconv -f utf-8-mac -t utf-8 "$tmp_file_ao" > "$product_file_ao"
iconv -f utf-8-mac -t utf-8 "$tmp_file_px" > "$product_file_px"
rm "$product_dir"/tmp_*.txt
# 最初の改ページまたは改丁を削除/Pixiv用ルビに変換
sed -i '' -E -e 2d "$product_file_ao" # [#todo] 大見出し有無判定
sed -i '' -E -e 's/|([^《]+)《([^》]+)》/[[rb:\1 > \2]]/g' -e 1d "$product_file_px"
# 青空文庫ファイルpdf変換
# [#note] Dropbox内のファイルを直接ソース/アウトプットに指定するとエラーになるためcpコマンドで変換前後にコピー
cd ~/Documents/aop310/
cp -f "$product_file_ao" source.txt
java -jar AOP3.jar -encoding UTF-8 source.txt product_ao.pdf aop.xml
cp -f product_ao.pdf "$product_file_aop"
rm source.txt
echo "プロダクトファイルが作成されました"
# プロダクトディレクトリを開く
open "$product_dir"
done
Automator構成
種類はアプリケーション
上記のスクリプトにファイルを渡すだけ
Alfred Workflow
File Actionをトリガーとし、上記アプリケーションに引き渡す
対象フォルダを検索し、タブキーでファイルアクションを起動、このワークフローを選択
Discussion