LaTeXからMarkdownへの変換ツール

LaTeXドキュメントをMarkdownに効率的に変換する

目次

LaTeXドキュメントをMarkdownに変換は、静的サイトジェネレータ、ドキュメンテーションプラットフォーム、バージョン管理システムと統合しながら、読みやすさとシンプルさを保ったまま、現代の出版ワークフローにおいて不可欠となっています。

latex-to-markdown

なぜLaTeXからMarkdownに変換するのか?

LaTeXは数十年にわたり学術および技術ドキュメント作成の金標準であり、並外れたタイプセット品質と数学記号のサポートを提供してきました。LaTeXドキュメントを使用している方には、私たちのLaTeXチートシートが、一般的なLaTeX構文の包括的な例を提供しています。しかし、現代の出版の風景は進化しており、Markdownは軽量な代替手段として、いくつかの重要な利点があります:

シンプルさと読みやすさ:Markdownファイルは人間が読めるプレーンテキストであり、LaTeXの冗長な構文に比べて編集、レビュー、バージョン管理がより簡単です。Markdownに初めて触れるか、すぐに参照が必要な場合は、私たちのMarkdownチートシートを確認してください。構文と機能の完全な概要が含まれています。

ウェブファーストの出版:Hugo、Jekyll、MkDocsなどの静的サイトジェネレータはMarkdownをネイティブにサポートしており、ドキュメンテーションから高速で現代的なウェブサイトを作成できます。GitHub、GitLab、さまざまなウィキはMarkdownを自動的にレンダリングします。

協力:非技術的なステークホルダーはLaTeX構文を学ばずにMarkdownを読むことができ、協力的な執筆のバリアを下げます。

ツールエコシステム:現代のエディタはライブプレビュー、リント、拡張機能を備えた優れたMarkdownサポートを提供しています。CI/CDパイプラインとの統合も簡単です。

移動性:Pandocなどのツールを使用して、MarkdownをHTML、PDF(LaTeX経由)、DOCX、EPUBなど複数の出力形式に変換でき、LaTeXの複雑さを保たずに柔軟性を維持できます。

主な変換ツール

Pandoc: 万能ドキュメント変換ツール

Pandocは最も強力で多機能なドキュメント変換ツールです。哲学者兼開発者であるJohn MacFarlaneによって作成され、40以上のマーキアップ形式をサポートし、それらの間でスマートに変換できます。

インストール

LaTeX変換を開始する前に、LaTeXディストリビューションがインストールされていることを確認してください。Windowsユーザーは、LaTeX on Windows 11 & 10: Distributions, Comparisons, and Step-by-Step Installsガイドを参照してください。または、LaTeX Overview and Installガイドを確認して、クロスプラットフォームのインストール手順を確認してください。

# Ubuntu/Debian
sudo apt-get install pandoc

# macOS
brew install pandoc

# Windows
choco install pandoc

# または https://pandoc.org/installing.html からダウンロード

基本変換

# 簡単な変換
pandoc document.tex -o document.md

# 特定の出力形式で変換
pandoc document.tex -f latex -t markdown -o document.md

# 数式を保持
pandoc document.tex -t markdown+tex_math_dollars -o document.md

高度なオプション

# ビブリオグラフィー付き変換
pandoc document.tex --bibliography=refs.bib --citeproc -o document.md

# 埋め込まれた画像を抽出
pandoc document.tex --extract-media=./media -o document.md

# メタデータ付きのスタンドアロンドキュメント
pandoc document.tex -s --wrap=none -o document.md

# カスタムテンプレート
pandoc document.tex --template=custom.md -o document.md

LaTeXML: 論理的な変換

LaTeXMLはLaTeXドキュメントの論理構造を保持することに焦点を当てており、意味を保持する必要がある数学や科学のコンテンツに特に適しています。

# インストール
sudo apt-get install latexml

# 基本変換
latexml document.tex | latexmlpost --dest=document.html -

# MathMLで数式を処理
latexmlc document.tex --dest=document.html --mathimages=false

Pythonベースのツール

いくつかのPythonツールはプログラマティックな変換機能を提供します。Webコンテンツを処理する際には、HTMLコンテンツをMarkdownに変換するLLMとOllamaの使用ガイドも役立ちます。現代的なAI駆動の変換技術を理解するためには、非常に役立ちます。

tex2pyとlatex2markdown

pip install latex2markdown

# コマンドラインでの使用
python -m latex2markdown document.tex document.md

Pandocfilters:カスタムのPandocフィルタを作成して、特定のLaTeX構文を処理します:

#!/usr/bin/env python3
from pandocfilters import toJSONFilter, Str

def custom_transform(key, value, format, meta):
    if key == 'Str':
        # 特定の文字列やパターンを変換
        if value.startswith('\\customcommand'):
            return Str(value.replace('\\customcommand', 'Custom: '))

if __name__ == "__main__":
    toJSONFilter(custom_transform)

使用方法:

pandoc document.tex --filter=./custom_filter.py -o document.md

継続的な変換ワークフロー

ステップ1: 準備

変換の前にLaTeXドキュメントを準備してください:

オリジナルファイルのバックアップ

# バックアップを作成
cp -r latex_project/ latex_project_backup/
git commit -am "Pre-conversion backup"

カスタムコマンドのインベントリ

# すべてのカスタムコマンドを抽出
grep -E '\\newcommand|\\def|\\newenvironment' *.tex > custom_commands.txt

複雑なパッケージの簡略化:Markdownに等価なパッケージがない場合、コメントアウトまたは置き換えます:

% 置き換えまたは削除
% \usepackage{tikz}
% \usepackage{custom_package}

ステップ2: 初期変換

適切なオプションで変換を実行します:

# 継続的な変換コマンド
pandoc main.tex \
  --from=latex \
  --to=markdown+pipe_tables+backtick_code_blocks+fenced_code_attributes \
  --wrap=none \
  --extract-media=./assets \
  --standalone \
  --bibliography=references.bib \
  --citeproc \
  --output=output.md

backtick_code_blocks拡張機能は出力のコードフォーマットを確保します。コードブロックに関する詳しい情報については、Markdownコードブロックの使用ガイドを参照してください。

ステップ3: 後処理

初期変換後はクリーンアップが必要です:

テーブルフォーマットの修正

Pandocは不自然なテーブルを作成する可能性があります。sedや手動編集を使用してください:

# テーブルをクリーンアップするスクリプト
sed -i 's/|:--|:--|/|:---|:---|/g' output.md

引用文献の処理

引用文献を使用している場合、引用が正しく変換されていることを確認してください:

# 引用形式を確認
grep -E '\[@\w+\]|\@\w+' output.md

画像のパスの修正

# 相対パスを更新
sed -i 's|!\[\](assets/|![](../assets/|g' output.md

数学の検証

ターゲットプラットフォームで数学の記号が正しく動作するか確認してください:

# 行内数式を確認
grep -E '\$[^$]+\$' output.md

# 表示用数式を確認
grep -E '\$\$[^$]+\$\$' output.md

ステップ4: 自動検証

検証スクリプトを作成してください:

#!/usr/bin/env python3
import re
import sys

def validate_markdown(filename):
    with open(filename, 'r') as f:
        content = f.read()
    
    issues = []
    
    # 変換されていないLaTeXコマンドを確認
    latex_commands = re.findall(r'\\[a-zA-Z]+\{', content)
    if latex_commands:
        issues.append(f"変換されていないLaTeXコマンド: {set(latex_commands)}")
    
    # 破損したリンクを確認
    links = re.findall(r'\[([^\]]+)\]\(([^\)]+)\)', content)
    for text, url in links:
        if url.startswith('file://'):
            issues.append(f"ファイルプロトコルリンク: {url}")
    
    # 数式記号を確認
    single_dollars = re.findall(r'(?<!\$)\$(?!\$)[^$]+\$(?!\$)', content)
    if len(single_dollars) % 2 != 0:
        issues.append("不一致な行内数式記号")
    
    return issues

if __name__ == "__main__":
    issues = validate_markdown(sys.argv[1])
    if issues:
        print("検証に問題が見つかりました:")
        for issue in issues:
            print(f"  - {issue}")
        sys.exit(1)
    else:
        print("検証に成功しました!")
        sys.exit(0)

一般的な課題の処理

複雑な数学

数学が多いため、LaTeXの数学記号を保持します:

# LaTeXの数学記号をそのままで保持
pandoc document.tex -t markdown+raw_tex -o output.md

または、特定の数学拡張機能を使用します:

pandoc document.tex -t markdown_strict+tex_math_dollars+raw_tex -o output.md

引用文献と引用

引用文献ファイルを変換し、引用を処理します:

# .bibをYAMLに変換
pandoc-citeproc --bib2yaml refs.bib > refs.yaml

# 変換時に使用
pandoc document.tex --metadata bibliography=refs.yaml --citeproc -o output.md

テーブル

LaTeXのテーブルは不完全に変換されることがあります。以下の方法を考慮してください:

  1. pipe_tablesまたはgrid_tables拡張機能を使用
  2. 複雑なレイアウトの場合、手動でテーブルを再構築
  3. 完全に複雑な場合は、テーブルを画像に変換
# 異なるテーブルスタイルを試す
pandoc document.tex -t markdown+pipe_tables -o output1.md
pandoc document.tex -t markdown+grid_tables -o output2.md

図とグラフィック

図を抽出し、整理します:

# すべてのメディアを整理されたディレクトリに抽出
pandoc document.tex --extract-media=./figures -o output.md

# 相対パスで処理
pandoc document.tex --resource-path=.:./figures --extract-media=./assets/img -o output.md

カスタムLaTeXコマンド

事前処理を通じてカスタムコマンドを処理します:

#!/usr/bin/env python3
import re
import sys

def expand_custom_commands(content):
    # カスタムコマンドのマッピングを定義
    commands = {
        r'\\customemph\{([^}]+)\}': r'***\1***',
        r'\\customsection\{([^}]+)\}': r'\n## \1\n',
        r'\\code\{([^}]+)\}': r'`\1`',
    }
    
    for pattern, replacement in commands.items():
        content = re.sub(pattern, replacement, content)
    
    return content

if __name__ == "__main__":
    with open(sys.argv[1], 'r') as f:
        content = f.read()
    
    expanded = expand_custom_commands(content)
    
    with open(sys.argv[2], 'w') as f:
        f.write(expanded)

使用方法:

# 事前処理してから変換
python expand_commands.py document.tex document_expanded.tex
pandoc document_expanded.tex -o document.md

自動化とバッチ処理

ディレクトリ変換のためのBashスクリプト

#!/bin/bash
# convert_all.sh - ディレクトリ内のすべての.texファイルをMarkdownに変換

INPUT_DIR="${1:-.}"
OUTPUT_DIR="${2:-./markdown_output}"

mkdir -p "$OUTPUT_DIR"

find "$INPUT_DIR" -name "*.tex" | while read -r tex_file; do
    base_name=$(basename "$tex_file" .tex)
    output_file="$OUTPUT_DIR/${base_name}.md"
    
    echo "変換中: $tex_file -> $output_file"
    
    pandoc "$tex_file" \
        --from=latex \
        --to=markdown \
        --wrap=none \
        --extract-media="$OUTPUT_DIR/media" \
        --standalone \
        --output="$output_file"
    
    if [ $? -eq 0 ]; then
        echo "✓ 成功: $base_name"
    else
        echo "✗ 変換エラー: $base_name"
    fi
done

echo "バッチ変換完了!"

Pythonバッチ処理

#!/usr/bin/env python3
import os
import subprocess
from pathlib import Path

def batch_convert(input_dir, output_dir, extensions=['.tex']):
    """ディレクトリツリー内のすべてのLaTeXファイルをMarkdownに変換します。"""
    
    input_path = Path(input_dir)
    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)
    
    for ext in extensions:
        for tex_file in input_path.rglob(f'*{ext}'):
            # ディレクトリ構造を保持
            relative_path = tex_file.relative_to(input_path)
            output_file = output_path / relative_path.with_suffix('.md')
            output_file.parent.mkdir(parents=True, exist_ok=True)
            
            print(f"変換中: {tex_file}")
            
            cmd = [
                'pandoc',
                str(tex_file),
                '--from=latex',
                '--to=markdown',
                '--wrap=none',
                f'--extract-media={output_file.parent}/media',
                '--standalone',
                f'--output={output_file}'
            ]
            
            try:
                subprocess.run(cmd, check=True, capture_output=True, text=True)
                print(f"✓ 成功: {output_file}")
            except subprocess.CalledProcessError as e:
                print(f"✗ エラー: {tex_file}")
                print(f"  {e.stderr}")

if __name__ == "__main__":
    import sys
    input_dir = sys.argv[1] if len(sys.argv) > 1 else '.'
    output_dir = sys.argv[2] if len(sys.argv) > 2 else './markdown'
    
    batch_convert(input_dir, output_dir)

コミット時に自動変換のためのGitフック

コミット時に変換を自動化します:

#!/bin/bash
# .git/hooks/pre-commit

# 変更された.texファイルをすべて見つける
changed_tex=$(git diff --cached --name-only --diff-filter=ACM | grep '\.tex$')

if [ -n "$changed_tex" ]; then
    echo "変更されたLaTeXファイルを変換中..."
    
    for tex_file in $changed_tex; do
        md_file="${tex_file%.tex}.md"
        pandoc "$tex_file" -o "$md_file"
        git add "$md_file"
        echo "変換およびステージング: $md_file"
    done
fi

構造化プロジェクトのためのMakefile

# Makefile - LaTeXからMarkdownへの変換

SRC_DIR := latex_src
OUT_DIR := markdown_out
TEX_FILES := $(wildcard $(SRC_DIR)/*.tex)
MD_FILES := $(patsubst $(SRC_DIR)/%.tex,$(OUT_DIR)/%.md,$(TEX_FILES))

.PHONY: all clean validate

all: $(MD_FILES)

$(OUT_DIR)/%.md: $(SRC_DIR)/%.tex
	@mkdir -p $(OUT_DIR)
	pandoc $< \
		--from=latex \
		--to=markdown \
		--wrap=none \
		--extract-media=$(OUT_DIR)/media \
		--standalone \
		--output=$@
	@echo "変換完了: $< -> $@"

clean:
	rm -rf $(OUT_DIR)

validate: $(MD_FILES)
	@for md in $(MD_FILES); do \
		echo "検証中: $$md..."; \
		python validate_markdown.py $$md; \
	done

静的サイトジェネレータとの統合

Hugoとの統合

LaTeXをHugo対応のMarkdownに変換します。Hugoとそのさまざまな機能について詳しく知るには、Hugoチートシートを参照してください。

#!/bin/bash
# LaTeX記事をHugo投稿に変換

INPUT_TEX="$1"
OUTPUT_DIR="content/posts"
POST_NAME=$(basename "$INPUT_TEX" .tex)

# 変換
pandoc "$INPUT_TEX" \
    --to=markdown \
    --wrap=none \
    --extract-media="static/img/$POST_NAME" \
    --output="temp_$POST_NAME.md"

# Hugoフロントマターを追加
cat > "$OUTPUT_DIR/$POST_NAME.md" << EOF
---
title: "$(grep '\\title' "$INPUT_TEX" | sed 's/\\title{\(.*\)}/\1/')"
date: $(date +%Y-%m-%dT%H:%M:%S%z)
draft: false
math: true
---

EOF

# 変換した内容を追加
cat "temp_$POST_NAME.md" >> "$OUTPUT_DIR/$POST_NAME.md"

# 画像のパスを修正
sed -i "s|media/|/img/$POST_NAME/|g" "$OUTPUT_DIR/$POST_NAME.md"

# クリーンアップ
rm "temp_$POST_NAME.md"

echo "Hugo投稿が作成されました: $OUTPUT_DIR/$POST_NAME.md"

Jekyllとの統合

#!/bin/bash
# Jekyll投稿に変換

INPUT_TEX="$1"
POST_DATE=$(date +%Y-%m-%d)
POST_NAME=$(basename "$INPUT_TEX" .tex)
OUTPUT_FILE="_posts/$POST_DATE-$POST_NAME.md"

pandoc "$INPUT_TEX" \
    --to=markdown_strict \
    --extract-media="assets/img" \
    --template=jekyll_template.md \
    --output="$OUTPUT_FILE"

echo "Jekyll投稿が作成されました: $OUTPUT_FILE"

最佳実践とヒント

1. すべてをバージョン管理する

LaTeXソースとMarkdown出力を常にバージョン管理してください:

git init latex-to-markdown-project
git add latex_src/ markdown_out/
git commit -m "初期LaTeXソースとMarkdown変換"

2. 変換プロセスのドキュメンテーションを維持する

変換プロセスをドキュメンテーションしてください:

# 変換ノート

## カスタムコマンドのマッピング
- `\customemph{text}``***text***`
- `\code{text}` → `` `text` ``

## 知られている問題
- 複雑なTikZ図はプレースホルダに変換される
- 一部のテーブルの配置は手動で調整が必要

## 後処理ステップ
1. `fix_tables.py`を実行
2. `validate_markdown.py`で検証
3. プレビューで数式のレンダリングを確認

3. 段階的にテストする

一度に全文書を変換しないでください:

# 章ごとに変換
pandoc chapter1.tex -o chapter1.md
# レビューおよび修正
pandoc chapter2.tex -o chapter2.md
# レビューおよび修正
# など

4. Pandoc Luaフィルタを使用する

複雑な変換のためにLuaフィルタは強力です:

-- custom_filter.lua
function Math(el)
  if el.mathtype == "InlineMath" then
    return pandoc.RawInline('markdown', '$' .. el.text .. '$')
  else
    return pandoc.RawBlock('markdown', '$$' .. el.text .. '$$')
  end
end

function Image(el)
  -- カスタムクラスや属性を追加
  el.classes = {'responsive-image'}
  return el
end

適用方法:

pandoc document.tex --lua-filter=custom_filter.lua -o output.md

5. 複雑な要素のためにLaTeXを保持する

場合によってはLaTeXを保持するのが最良の選択です:

# Markdownで複雑なケースのためにraw LaTeXを許可
pandoc document.tex -t markdown+raw_tex -o output.md

これにより、複雑な式、TikZ図、カスタムパッケージをそのままで保持でき、最終出力形式に応じて別途レンダリングできます。

質量保証

自動テスト

#!/usr/bin/env python3
# test_conversion.py
import subprocess
import difflib

def test_conversion():
    """変換が予期した出力を生成することをテストします。"""
    
    # テストファイルを変換
    subprocess.run([
        'pandoc', 'test_input.tex',
        '-o', 'test_output.md'
    ], check=True)
    
    # 予期された出力と比較
    with open('test_output.md', 'r') as f:
        actual = f.readlines()
    
    with open('expected_output.md', 'r') as f:
        expected = f.readlines()
    
    diff = list(difflib.unified_diff(expected, actual, lineterm=''))
    
    if diff:
        print("変換出力は予期されたものと異なります:")
        print('\n'.join(diff))
        return False
    else:
        print("✓ 変換テストに成功しました")
        return True

if __name__ == "__main__":
    import sys
    sys.exit(0 if test_conversion() else 1)

視覚的比較

複雑なフォーマットを持つドキュメントの場合:

# LaTeXからPDFを生成
pdflatex document.tex

# 変換されたMarkdownからPDFを生成
pandoc output.md -o output_from_markdown.pdf

# 両方のPDFを視覚的に比較

リンクチェック

#!/usr/bin/env python3
import re
import os
from pathlib import Path

def check_links(md_file):
    """Markdown内のすべてのリンクが有効であるかを確認します。"""
    
    with open(md_file, 'r') as f:
        content = f.read()
    
    # すべてのリンクを抽出
    links = re.findall(r'\[([^\]]+)\]\(([^\)]+)\)', content)
    
    broken_links = []
    for text, url in links:
        if not url.startswith(('http://', 'https://', '#')):
            # ファイルが存在するか確認
            link_path = Path(md_file).parent / url
            if not link_path.exists():
                broken_links.append((text, url))
    
    return broken_links

if __name__ == "__main__":
    import sys
    broken = check_links(sys.argv[1])
    
    if broken:
        print("破損したリンクが見つかりました:")
        for text, url in broken:
            print(f"  [{text}]({url})")
        sys.exit(1)
    else:
        print("✓ すべてのリンクは有効です")
        sys.exit(0)

パフォーマンス最適化

大規模なドキュメントやバッチ処理のために:

並列処理

#!/usr/bin/env python3
from multiprocessing import Pool
import subprocess
from pathlib import Path

def convert_file(tex_file):
    """1つのファイルを変換します。"""
    output_file = tex_file.with_suffix('.md')
    subprocess.run([
        'pandoc', str(tex_file),
        '-o', str(output_file)
    ], check=True)
    return str(output_file)

def parallel_convert(input_dir, num_processes=4):
    """ファイルを並列に変換します。"""
    tex_files = list(Path(input_dir).rglob('*.tex'))
    
    with Pool(num_processes) as pool:
        results = pool.map(convert_file, tex_files)
    
    return results

if __name__ == "__main__":
    import sys
    converted = parallel_convert(sys.argv[1])
    print(f"{len(converted)}ファイルを変換しました")

キャッシュ

#!/usr/bin/env python3
import hashlib
import subprocess
from pathlib import Path
import pickle

CACHE_FILE = '.conversion_cache.pkl'

def file_hash(filepath):
    """ファイルハッシュを計算します。"""
    with open(filepath, 'rb') as f:
        return hashlib.md5(f.read()).hexdigest()

def cached_convert(tex_file, cache):
    """ファイルが変更された場合にのみ変換します。"""
    current_hash = file_hash(tex_file)
    
    if tex_file in cache and cache[tex_file] == current_hash:
        print(f"{tex_file}をスキップ (変更なし)")
        return
    
    # ファイルを変換
    output_file = tex_file.with_suffix('.md')
    subprocess.run([
        'pandoc', str(tex_file),
        '-o', str(output_file)
    ], check=True)
    
    # キャッシュを更新
    cache[tex_file] = current_hash
    print(f"{tex_file}を変換しました")

def main():
    # キャッシュを読み込む
    try:
        with open(CACHE_FILE, 'rb') as f:
            cache = pickle.load(f)
    except FileNotFoundError:
        cache = {}
    
    # ファイルを処理
    for tex_file in Path('.').rglob('*.tex'):
        cached_convert(tex_file, cache)
    
    # キャッシュを保存
    with open(CACHE_FILE, 'wb') as f:
        pickle.dump(cache, f)

if __name__ == "__main__":
    main()

有用なリソースとツール

必須のツール

  • Pandoc: https://pandoc.org/ - ユニバーサルドキュメントコンバーター
  • LaTeXML: https://dlmf.nist.gov/LaTeXML/ - LaTeXをXML/HTMLに変換
  • pandoc-citeproc: 参考文献の処理
  • pandocfilters: Pandocフィルター用のPythonライブラリ

オンラインコンバーター

  • Pandoc Online: インストール不要で迅速なコンバート
  • Overleaf: LaTeXプロジェクトをさまざまな形式でエクスポート
  • TeXLive: コンバートツールを含む包括的なLaTeXディストリビューション

ドキュメントとガイド

  • Pandoc User’s Guide: 総合的なドキュメント
  • LaTeX Stack Exchange: コミュニティによるQ&A
  • コンバートスクリプトとフィルターを含むGitHubリポジトリ

エディタのサポート

  • VS Code: LaTeX Workshop + Markdown All in One拡張機能
  • Vim: vim-pandocプラグイン
  • Emacs: LaTeXおよびMarkdownをサポートするorg-mode

検証ツール

  • markdown-lint: Markdownスタイルチェッカー
  • vale: スタイルガイド付きのプロセラインター
  • link-checker: Markdownファイル内のリンクを検証

結論

LaTeXをMarkdownに変換することは、現代の技術出版ワークフローにおいて実用的な必要性です。Pandocはほとんどのコンバートを優れた性能で処理しますが、利用可能なツール、一般的な課題、および自動化戦略を理解することで、スムーズな移行が可能です。

成功したコンバートの鍵は次のとおりです:

  1. 準備: コンバートする前にLaTeXを整理し、ドキュメント化する
  2. 段階的なアプローチ: 全体のコンバート前に小さな部分でテストする
  3. 自動化: バッチ処理と検証用のスクリプトを構築する
  4. 品質保証: テストと検証ワークフローを実装する
  5. メンテナンス: 決定をドキュメント化し、コンバートスクリプトを維持する

学術論文をスタティックサイトジェネレーターに移行する、ドキュメントをGitHub Wikiに変換する、またはMarkdownの柔軟性を維持しながらLaTeXの品質を保つなど、さまざまな目的に対して、ここに提示されたツールとワークフローは堅実な基盤を提供します。

ロバストなコンバートパイプラインの構築に投資することで、出版時の摩擦を軽減し、協力作業を改善し、現代のウェブ出版ツールにアクセスしながら、LaTeX作成の厳密性と正確性を維持できるようになります。

有用なリンク