見出し画像

📘 Markdown + VSCodeで始めるKindle執筆完全ガイド

kindleを見ているとunlimitedにおいても参考になりそうな書籍がたくさんあります。このようなところに自分も出版してみたいですよね。そこで今回は、kindleへの出版をmarkdownを使って作成する方法を紹介してみたいと思います。

また、最近は技術書典でしか読めない書籍も増えてきました。このような場合にも今回紹介するノウハウは活かせると思います。


技術書を書く時に何が大変?


技術書執筆において、従来のWordやGoogle Docsでは満たされないニーズが多くあります。特にコードスニペットの扱いやバージョン管理などに悩まされることが多いのではないでしょうか。本ガイドでは、エンジニアにとって馴染み深いMarkdownとVSCode(visual studio code)を活用し、効率的に高品質な技術書を執筆するための完全なワークフローを解説します。

なぜMarkdownなのか ✍️


技術書執筆における課題には以下のようなものがあります:

  • コードスニペットの美しい表示

  • バージョン管理:複数ファイルや画像の管理が必要

  • 一貫性のあるフォーマット:複数章にわたるスタイルの統一

  • 画像の効率的な管理:章ごとの画像整理と適切なキャプション設定

Markdownは、これらの課題を効率的に解決します。VSCodeのプラグインとGitHubのバージョン管理を活用することで、エンジニアにとって理想的な執筆環境を構築できます。

1. 完璧な執筆環境の構築 🛠️


必要なツールのインストール

MacユーザーはHomebrewを利用することで、必要なツールを簡単にインストールできます:

# 基本ツールのインストール
brew install pandoc
brew install --cask kindle-previewer
brew install --cask visual-studio-code

brew install weasyprint 
brew install imagemagick

VSCodeの拡張機能セットアップ

以下の拡張機能を導入することで、執筆効率が向上します:

  1. Paste Image

    • スクリーンショットの即時挿入

    • 画像の自動リネームとフォルダ管理

  2. Markdown All in One

    • 目次の自動生成

    • Markdownのフォーマット補助

  3. Markdown Preview Enhanced

    • リアルタイムプレビュー

    • 数式のレンダリングサポート

2. プロジェクト構成 📂


書籍の規模が拡大しても管理しやすいよう、以下のディレクトリ構成を推奨します。

book-project/
├── src/
│   ├── chapters/           # 各章ごとのMarkdownファイル
│   │   ├── 00-preface.md      # はじめに
│   │   ├── 01-introduction.md # 第1章
│   │   └── 02-python-basics.md # 第2章
│   │   └── images/ # 各チャプターごとの画像
│   ├── cover/cover.png           # カバー画像
│   ├── title.txt              # 書籍情報
│   └── SUMMARY.md             # 目次構成
├── styles/
│   ├── kindle.css            # Kindle用スタイル
│   └── pdf.css              # PDF出力用スタイル
├── metadata.yaml             # メタデータ
├── cover.jpg                # 表紙画像
└── build.sh                 # ビルドスクリプト

こちらのフォルダ構成はterminal上で以下のコマンドで作成できます

mkdir -p book-project/{src/chapters,images/chapter1,images/chapter2,styles} \
&& touch book-project/src/chapters/{00-preface.md,01-introduction.md,02-python-basics.md} \
&& touch book-project/src/{title.txt,SUMMARY.md} \
&& touch book-project/styles/{kindle.css,pdf.css} \
&& touch book-project/{metadata.yaml,cover.jpg,build.sh}

以下のコマンドで作成した構造が正しいか確認しておきましょう

find . -print

3. 効率的な執筆ワークフロー 📄


メタデータの設定

書籍情報(タイトル、著者、公開日、権利情報)を`metadata.yaml`にまとめておきます。

---
title: "実践Python入門"
author: "著者名"
date: "2024年11月"
language: ja-JP
rights: |
  Copyright © 2024 著者名
  All rights reserved.
cover-image: cover.jpg
stylesheet: styles/kindle.css
toc: true
toc-depth: 2
---

VSCodeでの画像管理の自動化

Paste Image拡張機能が画像を自動で適切なフォルダに保存し、Markdownに挿入できるように、以下の設定をsettings.jsonに追加します。

cssの読み込みと一緒に設定しています。paste imageを行う場合に、ファイル名の指定もできるようにしています。

{
    // Kindle用スタイルシートの適用
    "markdown.styles": [
        "${workspaceFolder}/styles/kindle.css"
    ],

    // paste imageの設定
    "pasteImage.path": "${currentFileDir}/images/${currentFileNameWithoutExt}",
    
    "pasteImage.namePrefix": "${currentFileNameWithoutExt}_",
    "pasteImage.defaultName": "YYYYMMDDHHmmss",
    
    "pasteImage.insertPattern": "![${imageFileName}](./images/${currentFileNameWithoutExt}/${imageFileName})",
    
    "pasteImage.showFilePathConfirmInputBox": true,
    "pasteImage.filePathConfirmInputBoxMode": "onlyName"
}

4. プロフェッショナルなスタイリング 🎨


以下は、視認性を高めるためにカスタマイズされたKindle用のスタイル(`kindle.css`)の例です。

/* 基本スタイル */
body {
    /* ======================================
     * フォント切り替えオプション
     * 明朝体を使用する場合は、下記のコメントを解除し、
     * その下のフォント指定をコメントアウトしてください
     * ====================================== */
    font-family: "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif;
    /* font-family: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans CJK JP", sans-serif; */
    line-height: 1.7;
    text-align: justify;
    margin: 0;
    padding: 1em;
}


/* 見出しのスタイル */
h1 {
    /* 見出しの明朝体オプション */
    /* font-family: "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif; */
    border-left: 8px ridge #000000;
    border-bottom: 4px ridge #000000;
    padding: 0.5em;
    margin-top: 2em;
    page-break-before: always;
    line-height: 1.2;
}

h2, h3 {
    /* 見出しの明朝体オプション */
    /* font-family: "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif; */
    margin-top: 1.5em;
    margin-bottom: 0.5em;
    line-height: 1.2;
    border-bottom: 2px solid #000000;
    padding-bottom: 0.3em;
}

/* コードブロックのスタイル */
pre {
    background-color: #f5f5f5;
    border: 1px solid #ddd;
    border-radius: 5px;
    padding: 1em;
    margin: 1.5em 0;
    white-space: pre-wrap !important;
    word-wrap: break-word !important;
    font-family: "Source Code Pro", monospace;
    font-size: 0.9em;
    line-height: 1.4;
}

/* 下線を削除するための追加スタイル */
pre code {
    border: none !important;
    background: none !important;
    padding: 0 !important;
    text-decoration: none !important;
    font-family: "Source Code Pro", monospace;
}

.sourceCode {
    background-color: #f5f5f5 !important;
    text-decoration: none !important;
}

.sourceCode code {
    text-decoration: none !important;
    border-bottom: none !important;
    font-family: "Source Code Pro", monospace;
}

/* シンタックスハイライト用のスタイル */
.sourceCode .kw { color: #007020; font-weight: bold; text-decoration: none !important; }
.sourceCode .dt { color: #902000; text-decoration: none !important; }
.sourceCode .dv { color: #40a070; text-decoration: none !important; }
.sourceCode .bn { color: #40a070; text-decoration: none !important; }
.sourceCode .fl { color: #40a070; text-decoration: none !important; }
.sourceCode .ch { color: #4070a0; text-decoration: none !important; }
.sourceCode .st { color: #4070a0; text-decoration: none !important; }
.sourceCode .co { color: #60a0b0; font-style: italic; text-decoration: none !important; }
.sourceCode .ot { color: #007020; text-decoration: none !important; }
.sourceCode .fu { color: #06287e; text-decoration: none !important; }
.sourceCode .re { color: #0e84b5; font-weight: bold; text-decoration: none !important; }
.sourceCode .er { color: #ff0000; font-weight: bold; text-decoration: none !important; }

/* インラインコード */
code {
    background-color: #f5f5f5;
    border: 1px solid #ddd;
    border-radius: 3px;
    padding: 0 0.3em;
    font-size: 0.9em;
    font-family: "Source Code Pro", monospace;
    text-decoration: none !important;
}


/* 図表のスタイリング */
figure {
    margin: 1.5em 0;
    text-align: center;
}

figcaption {
    font-size: 0.9em;
    color: #666;
    margin-top: 0.5em;
}

/* 画像のスタイル */
img {
    max-width: 100%;
    height: auto;
    margin: 1em auto;
    display: block;
}

/* リストのスタイル */
ul, ol {
    padding-left: 2em;
    margin: 1em 0;
}

/* 表のスタイル */
table {
    width: 100%;
    border-collapse: collapse;
    margin: 1.5em 0;
}

th, td {
    border: 1px solid #ddd;
    padding: 0.8em;
}

th {
    background-color: #f5f5f5;
}

pdf.cssも同様に設定します

/* PDF出力用の基本設定 */
@page {
    margin: 2.5cm;
    size: A4;
}

/* 基本スタイル */
body {
    /* 明朝体バージョン */
    font-family: "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif;
    /* font-family: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans CJK JP", sans-serif; */
    line-height: 1.7;
    text-align: justify;
    margin: 0;
    padding: 1em;
}

/* 以下、他のスタイルは変更なし */
/* コードブロックのスタイルなど、前回のコードをそのまま維持 */

/* コードブロックの改善されたスタイル */
pre {
    background-color: #f5f5f5;
    border: 1px solid #ddd;
    border-radius: 5px;
    padding: 1.2em;
    margin: 1.5em 0;
    white-space: pre-wrap !important;
    word-wrap: break-word !important;
    word-break: break-all !important;
    overflow-wrap: break-word !important;
    font-family: "Source Code Pro", monospace;
    font-size: 0.9em;
    line-height: 1.4;
    page-break-inside: avoid;
    max-width: 100%;
    overflow-x: hidden !important;
}

/* コード内の要素のスタイル */
pre code {
    white-space: pre-wrap !important;
    word-wrap: break-word !important;
    word-break: break-all !important;
    overflow-wrap: break-word !important;
    display: block;
    width: 100%;
}

/* シンタックスハイライト用のスタイル */
.sourceCode {
    max-width: 100%;
    overflow-x: hidden !important;
}

/* その他のスタイルは変更なし */
/* 画像設定 */
img {
    display: block;
    max-width: 100%;
    height: auto;
    margin: 1.5em auto;
    page-break-inside: avoid;
}

/* 見出しスタイル */
h1 {
    font-size: 2em;
    border-left: 8px ridge #000000;
    border-bottom: 4px ridge #000000;
    padding: 0.5em;
    margin-top: 2em;
    page-break-before: always;
    page-break-after: avoid;
}

h2 {
    font-size: 1.5em;
    border-bottom: 2px solid #000000;
    padding-bottom: 0.3em;
    margin-top: 1.5em;
    page-break-after: avoid;
}

h3 {
    font-size: 1.2em;
    border-bottom: 1px solid #000000;
    padding-bottom: 0.2em;
    margin-top: 1.2em;
    page-break-after: avoid;
}

/* テーブルスタイル */
table {
    width: 100%;
    border-collapse: collapse;
    margin: 1.5em 0;
    page-break-inside: avoid;
}

th {
    background-color: #f5f5f5;
    font-weight: bold;
    text-align: left;
    padding: 0.8em;
    border: 1px solid #ddd;
}

td {
    padding: 0.8em;
    border: 1px solid #ddd;
}

このスタイル設定を用いることで、PDF表示でのレイアウトがさらに最適化され、ページ送りやコードブロックの視認性も高まります。特に技術書では、コードブロックや図表の配置が重要ですので、PDFプレビューでの確認は非常に効果的です。

5. 原稿執筆のベストプラクティス ✍️


コードブロックの記述

ファイル名や言語指定を明示し、コードブロックを読みやすくします。

【ファイル:hello.py】
```python
def greet(name: str) -> str:
    """ユーザーに挨拶を返す関数
    
    Args:
        name: 挨拶する対象の名前
    Returns:
        挨拶文字列
    """
    return f"Hello, {name}!"
```
### 画像の効果的な使用

1. スクリーンショットを撮影(`Cmd + Shift + 4`2. VSCodeで`Cmd + Option + V`を押して画像を挿入
3. 自動的に以下の形式で挿入されます:

```markdown
![実行結果の説明](./src/images/chapter1/xxx.png) \
```

改ページの制御

セクションの区切りには以下を挿入して、Kindle上で改ページを反映します:

<div style="page-break-before:always"></div>

6. 電子書籍への変換と品質管理 🔄

ビルドプロセスの自動化

`build.sh`スクリプトを使用し、MarkdownからEPUBやPDFへの変換を自動化します。

#!/bin/bash

# 作業ディレクトリの準備
mkdir -p build/images
rm -rf build/*

# 画像をbuildディレクトリにコピー
cp -r src/chapters/images build/images
mkdir -p build/cover
cp src/cover/cover.png build/cover/cover.png

# 画像をjpgに変更(kindle用)
magick src/cover/cover.png src/cover/cover.jpg

# カバー画像の処理
if [ -f "src/cover/cover.png" ]; then
    echo "カバー画像を処理しています..."
    mkdir -p build/cover
    COVER_OPTION="--epub-cover-image=build/cover/cover.png"
else
    echo "エラー: src/cover/cover.pngが見つかりません。"
    exit 1
fi

# Markdownファイルの結合と前処理
find src/chapters -type f -name "*.md" | sort -V | xargs cat | \
    sed -E 's#\!\[(.*)\]\(\./images/#\!\[\1\]\(build/images/#g' | \
    sed -E 's#\\#/#g' > build/combined.md

# EPUB形式への変換
pandoc build/combined.md \
    -f markdown+smart \
    --resource-path=.:build:build/images:build/cover \
    -t epub3 \
    --metadata-file=metadata.yaml \
    --css=styles/kindle.css \
    --highlight-style=tango \
    --toc --toc-depth=2 \
    --split-level=2 \
    $COVER_OPTION \
    --metadata title="Pythonで学ぶ実践データ分析:売上・顧客・商品データの価値を引き出す" \
    -o build/book.epub

# WeasyPrintを使用したPDF生成
pandoc build/combined.md \
    -f markdown+smart \
    --resource-path=.:build:build/images:build/cover \
    --pdf-engine=weasyprint \
    --css=styles/pdf.css \
    --highlight-style=tango \
    --metadata title="Pythonで学ぶ実践データ分析:売上・顧客・商品データの価値を引き出す" \
    --standalone \
    -o build/book.pdf

7. 最終チェックリスト ✅

以下のチェックリストを活用し、最終確認を行います。

  1. コンテンツの品質

    • コードブロックの表示確認

    • 画像の解像度(300dpi以上)

    • 文字化けの有無

    • リンクの動作確認

  2. レイアウト

    • 改ページ位置の適切性

    • 画像サイズとキャプション

    • 目次の階層構造

    • フォントの一貫性

  3. 技術的要件

    • ファイルサイズ(画像は5MB未満)

    • EPUBの検証

    • Kindleプレビューでの表示確認

補足:GitとMarkdownで効率的にバージョン管理 🗂️


最後に作成したmarkdownなどはdocxなどのwordファイルと違いバージョン管理がしやすいことも補足しておきますね。

Markdown形式での執筆は、Gitなどのバージョン管理システムと非常に相性が良い点が特長です。以下の利点があります:

  • 変更履歴の管理:Gitを活用すれば、ファイルごとの変更履歴を詳細に確認できるため、どの部分がいつ変更されたかを一目で把握できます。

  • 差分の確認:Markdownファイルはテキストベースのため、他の形式に比べて差分が分かりやすく、レビューやフィードバックがスムーズです。

  • バックアップとチーム作業の効率化:リモートリポジトリ(GitHub、GitLab、Bitbucket等)を利用してクラウド上にバックアップを保持することで、安全性を確保しつつ、チームでの共同執筆も円滑に進められます。

このように、MarkdownとGitを組み合わせることで、個人執筆からチーム執筆までスケーラブルな運用が可能になり、書籍制作のプロセスを効率的かつ安全に管理できます。

補足:PDFプレビューの確認方法


Kindle形式への変換前にPDF形式でプレビューを確認することで、レイアウトや表示品質を事前にチェックできます。技術書の場合、特に見出し、コードブロック、画像配置が重要になるため、以下の手順でPDFプレビューを効率よく行いましょう。

1. VSCodeでのリアルタイムプレビュー

Markdown Preview Enhancedプラグインを使用することで、執筆中にVSCode上でリアルタイムのPDFプレビューを確認できます。以下の手順でプレビューを開きます。

# VSCodeのコマンドパレットを開き(Cmd + Shift + P)
# 「Markdown Preview Enhanced: Open Preview to the Side」を選択

2. Pandocを使用してPDFファイルを生成

最終レイアウトの確認用に、PDFファイルを生成して全体をチェックします。以下のコマンドを`build.sh`スクリプトに追加することで、MarkdownからPDFを出力します。

# PDF出力用のコマンド
pandoc build/combined.md \
    -f markdown+smart \
    --pdf-engine=wkhtmltopdf \
    --css=styles/pdf.css \
    -o build/preview.pdf

3. Macの「プレビュー」アプリでPDFを確認

生成したPDFは、Mac標準の「プレビュー」アプリで以下のポイントを確認すると、技術書としてのレイアウト品質をしっかりチェックできます。

  • 表示の素早さ:ダブルクリックで即時プレビュー表示

  • 画像解像度や文字化け確認:インスペクタで画像の解像度や文字化けの有無をチェック

  • ファイルサイズ確認:メタデータでファイルサイズを確認し、適切な軽量化がされているかを確認


補足:プレビュー時の確認ポイント

PDFプレビューを通して、次の要素について細部まで確認し、Kindle用データへの最終調整に役立てましょう。

レイアウト確認

  • 見出しの階層構造が適切か

  • コードブロックが表示崩れなく整列しているか

  • 画像の配置・解像度が適正であるか

  • 改ページ位置が意図した箇所に設定されているか

品質チェック

  • フォントが意図した通りに表示されているか

  • 日本語や特殊文字が文字化けせずに表示されているか

  • 画像のアスペクト比が崩れていないか

  • 目次のリンクが正しく機能しているか

まとめ 🎉


本ガイドでは、MarkdownとVSCode、Pandocを活用し、技術書の執筆からKindleでの公開までを効率化する一貫したワークフローをご紹介しました。GitHubなどのバージョン管理を組み合わせることで、各工程の管理が容易になり、書籍の品質向上と共同作業の効率化が実現できます。執筆ツールに慣れたら、読者にとって価値のある情報を届けることを最優先にし、最高品質の技術書を目指しましょう。このワークフローが、あなたの執筆活動に役立つことを願っています。

サンプル


最後にmarkdownで作成した場合のドキュメントのサンプルを以下においておきますね。

なお \ の役割は以下の通りです。

以下のMarkdownでは、行末にバックスラッシュ (`\`) を追加することで、**次の行に改行を挿入せず**に表示が続くよう制御できます。特に画像のキャプションなど、余計な空行が入らないようにするために利用されています。キャプションや説明文がある場合、Markdownのレンダリングで不要な改行が避けられるため、整ったレイアウトを保てます。 以下は、画像を挿入しつつ、バックスラッシュを使用したキャプション制御のサンプルです。

# pandasで始める実用データ分析:店舗の売上をアップするための秘訣

売上データの分析は、店舗の戦略を決定し、売上向上のために非常に重要です。本章では、Pythonのデータ分析ライブラリである**pandas**を用いて、実際の売上データを基にしたデータ分析の基礎から応用までを解説します。まずは、pandasの基本操作から始め、売上分析に役立つ具体的な手法を学びましょう。

<div style="page-break-before:always"></div>

---

## はじめに

### pandasとは

pandasは、Pythonのデータ処理と分析のためのライブラリで、データフレーム(表形式のデータ構造)を扱うことに優れています。売上データや顧客データなど、表形式のデータを使った分析に最適で、効率的なデータ処理を行うことができます。

### 目標

この章では、pandasを使用して売上データの読み込みから、売上の傾向分析、商品別や店舗別の売上比較まで、具体的なステップを解説していきます。これにより、データから得られる洞察を売上アップの戦略に活用できるようになることを目指します。

<div style="page-break-before:always"></div>

---

## 第1章:pandasを用いたデータの基本操作

### 1-1. データの読み込み

まずは、売上データをpandasに読み込むところから始めます。売上データはCSV形式で提供されていると仮定し、**pandasの`read_csv`関数**を使って読み込みます。

```python
import pandas as pd

# 売上データの読み込み
data = pd.read_csv("sales_data.csv")
# データの先頭5行を表示
data.head()
```

### 1-2. データの概要確認

データの内容や型、欠損値の有無を確認するために、次のメソッドを使用します。

- **`info()`**:データフレームの基本情報を表示
- **`describe()`**:数値データの要約統計量を表示

```python
# データフレームの基本情報
data.info()

# 数値データの要約統計量
data.describe()
```

![データの基本情報表示](./images/chapter1/data_info.png) \  
*図1-1:pandasの`info()`メソッドと`describe()`メソッドを用いたデータ概要の表示*

<div style="page-break-before:always"></div>

---

## 第2章:売上データの詳細分析

### 2-1. 月ごとの売上傾向の分析

次に、月ごとの売上の傾向を確認し、季節的なトレンドや特定月の売上パフォーマンスを把握します。

```python
# 売上日付をdatetime型に変換
data['date'] = pd.to_datetime(data['date'])

# 月ごとの売上を集計
monthly_sales = data.resample('M', on='date')['sales'].sum()

# 結果の表示
print(monthly_sales)
```

**図2-1**:月ごとの売上傾向のグラフ  
![月ごとの売上推移グラフ](./images/chapter2/monthly_sales.png) \  
*月ごとの売上の推移をグラフ化することで、シーズンごとの傾向が視覚化されます。*

<div style="page-break-before:always"></div>

### 2-2. 商品別売上のランキング

どの商品が最も売れているのかを把握することは、在庫管理やプロモーション施策のために重要です。ここでは、商品ごとの売上ランキングを作成します。

```python
# 商品別の売上を集計
product_sales = data.groupby('product')['sales'].sum()

# 売上順に並べ替え
product_sales = product_sales.sort_values(ascending=False)

# 上位10商品の表示
print(product_sales.head(10))
```

---

## 第3章:店舗ごとの売上分析

### 3-1. 店舗ごとの売上比較

複数店舗が存在する場合、店舗ごとの売上を比較して、成功している店舗の特徴や改善の余地がある店舗を特定します。

```python
# 店舗ごとの売上を集計
store_sales = data.groupby('store')['sales'].sum()

# 店舗ごとの売上を棒グラフで表示
store_sales.plot(kind='bar', title="Store Sales Comparison")
```

![店舗ごとの売上比較](./images/chapter3/store_sales_comparison.png) \  
*図3-1:店舗ごとの売上比較。棒グラフにより、店舗ごとの売上状況が一目でわかります。*

<div style="page-break-before:always"></div>

### 3-2. 高パフォーマンス店舗の特定と分析

店舗別売上データから、売上の高い店舗とその要因を探ります。たとえば、売上トップの店舗における特定の商品の人気が売上を押し上げている場合、その成功要因を他店舗にも応用することで、全体の売上を底上げできます。

```python
# 売上上位の店舗のデータを抽出
top_store_sales = data[data['store'] == 'top_store']

# 商品別の売上を集計して確認
top_product_sales = top_store_sales.groupby('product')['sales'].sum()
print(top_product_sales)
```

<div style="page-break-before:always"></div>

---

## まとめと次のステップ

本章では、pandasを使った売上データの基本的な操作から、実践的な分析手法までを解説しました。データから得られた洞察を活用することで、売上向上の戦略を立てやすくなります。次の章では、さらに高度な分析手法として、顧客分析やリピート購入分析など、より具体的な戦略策定に役立つ手法を学びます。