| name | scientific-latex-formatter |
| description | Markdown 原稿を LaTeX 形式に変換し、ジャーナル指定のテンプレート(.cls/.sty)に
適合するフォーマッティングを行うスキル。数式・図表・引用・相互参照の LaTeX 構文変換、
ジャーナル別スタイル適用、コンパイル可能な .tex ファイル生成を担う。
「LaTeX に変換して」「投稿用 TeX を作って」「ジャーナルフォーマットにして」で発火。
|
| tu_tools | [{"key":"crossref","name":"Crossref","description":"参考文献メタデータ・DOI 解決"}] |
Scientific LaTeX Formatter
Markdown 原稿を LaTeX に変換し、ジャーナル指定テンプレートに適合する
投稿用 .tex ファイルを生成するスキル。
When to Use
- Markdown で執筆した原稿を LaTeX 形式に変換するとき
- ジャーナル指定の LaTeX テンプレート(revtex4, elsarticle 等)に合わせるとき
- 数式・図表・参照の LaTeX 構文を正確に生成したいとき
- 投稿用の .tex + .bib + figures/ 一式を準備するとき
- Supplementary Information も LaTeX で整形するとき
Quick Start
1. 変換ワークフロー
Markdown 原稿 (manuscript/manuscript.md)
├─ Phase 1: Markdown → LaTeX 基本変換
│ ├─ セクション見出し (#, ##, ###) → \section, \subsection
│ ├─ 太字・斜体 → \textbf, \textit
│ ├─ リスト → \begin{itemize/enumerate}
│ └─ コードブロック → \begin{lstlisting} or verbatim
├─ Phase 2: 学術要素の変換
│ ├─ 図の埋め込み → \begin{figure}...\includegraphics
│ ├─ 表 → \begin{table}...\begin{tabular}
│ ├─ 数式 ($...$, $$...$$) → \( \), \[ \], equation 環境
│ ├─ 引用 [1], [2-5] → \cite{key1}, \cite{key1,key2,...}
│ └─ 相互参照 (Figure 1, Table 2) → \ref{fig:1}, \ref{tab:2}
├─ Phase 3: ジャーナルテンプレート適用
│ ├─ documentclass の設定
│ ├─ タイトル・著者・所属の構造化
│ ├─ Abstract 環境の適用
│ └─ 参考文献スタイル (bibliographystyle) の設定
└─ Phase 4: ファイル出力
├─ manuscript/manuscript.tex
├─ manuscript/references.bib
└─ manuscript/figures/ (コピー)
2. ジャーナル別 LaTeX テンプレート
JOURNAL_TEMPLATES = {
"nature": {
"documentclass": r"\documentclass{nature}",
"packages": [
r"\usepackage{graphicx}",
r"\usepackage{amsmath}",
r"\usepackage{natbib}",
],
"bib_style": "naturemag",
"figure_width": r"0.8\textwidth",
"abstract_env": "abstract",
"title_cmd": r"\title{%s}",
"author_cmd": r"\author{%s}",
"affiliation_cmd": r"\affiliation{%s}",
},
"science": {
"documentclass": r"\documentclass[12pt]{article}",
"packages": [
r"\usepackage{graphicx}",
r"\usepackage{amsmath}",
r"\usepackage[numbers,sort&compress]{natbib}",
r"\usepackage{setspace}",
r"\doublespacing",
],
"bib_style": "Science",
"figure_width": r"0.9\textwidth",
"abstract_env": "abstract",
"title_cmd": r"\title{%s}",
"author_cmd": r"\author{%s}",
"affiliation_cmd": None,
},
"acs": {
"documentclass": r"\documentclass[journal=jacsat,manuscript=article]{achemso}",
"packages": [
r"\usepackage{graphicx}",
r"\usepackage{amsmath}",
],
"bib_style": "achemso",
"figure_width": r"3.25in",
"abstract_env": "abstract",
"title_cmd": r"\title{%s}",
"author_cmd": r"\author{%s}",
"affiliation_cmd": r"\affiliation{%s}",
},
"ieee": {
"documentclass": r"\documentclass[conference]{IEEEtran}",
"packages": [
r"\usepackage{graphicx}",
r"\usepackage{amsmath}",
r"\usepackage{cite}",
],
"bib_style": "IEEEtran",
"figure_width": r"\columnwidth",
"abstract_env": "abstract",
"title_cmd": r"\title{%s}",
"author_cmd": r"\author{%s}",
"affiliation_cmd": None,
},
"elsevier": {
"documentclass": r"\documentclass[preprint,12pt]{elsarticle}",
"packages": [
r"\usepackage{graphicx}",
r"\usepackage{amsmath}",
r"\usepackage{lineno}",
r"\modulolinenumbers[5]",
],
"bib_style": "elsarticle-num",
"figure_width": r"\textwidth",
"abstract_env": "abstract",
"title_cmd": r"\title{%s}",
"author_cmd": r"\author{%s}",
"affiliation_cmd": r"\address{%s}",
},
"revtex": {
"documentclass": r"\documentclass[aps,prl,twocolumn,superscriptaddress]{revtex4-2}",
"packages": [
r"\usepackage{graphicx}",
r"\usepackage{amsmath}",
],
"bib_style": "apsrev4-2",
"figure_width": r"\columnwidth",
"abstract_env": "abstract",
"title_cmd": r"\title{%s}",
"author_cmd": r"\author{%s}",
"affiliation_cmd": r"\affiliation{%s}",
},
}
3. Markdown → LaTeX 変換エンジン
import re
from pathlib import Path
def md_to_latex(md_text, journal_format="elsevier"):
"""
Markdown テキストを LaTeX に変換する。
Args:
md_text: str — Markdown 原稿テキスト
journal_format: str — ジャーナル形式
Returns:
str: LaTeX テキスト
"""
tex = md_text
tex = re.sub(r'^### (.+)$', r'\\subsubsection{\1}', tex, flags=re.MULTILINE)
tex = re.sub(r'^## (.+)$', r'\\subsection{\1}', tex, flags=re.MULTILINE)
tex = re.sub(r'^# (.+)$', r'\\section{\1}', tex, flags=re.MULTILINE)
tex = re.sub(r'\*\*\*(.+?)\*\*\*', r'\\textbf{\\textit{\1}}', tex)
tex = re.sub(r'\*\*(.+?)\*\*', r'\\textbf{\1}', tex)
tex = re.sub(r'\*(.+?)\*', r'\\textit{\1}', tex)
tex = re.sub(r'\$\$(.+?)\$\$', r'\\[\1\\]', tex, flags=re.DOTALL)
tex = _convert_figures(tex, journal_format)
tex = _convert_tables(tex)
tex = re.sub(r'\[(\d+(?:[-,\s]\d+)*)\]', _convert_citation, tex)
tex = _convert_lists(tex)
tex = tex.replace('&', r'\&')
tex = tex.replace(, )
tex
():
tmpl = JOURNAL_TEMPLATES.get(journal_format, JOURNAL_TEMPLATES[])
fig_width = tmpl[]
():
alt_text = m.group()
img_path = m.group()
img_base = Path(img_path).stem
fig_num = re.search(, alt_text)
label = fig_num
(
)
tex = re.sub(, fig_replacer, tex)
tex
():
lines = tex.split()
result = []
in_table =
table_lines = []
line lines:
re.(, line.strip()):
in_table:
in_table =
table_lines = []
table_lines.append(line.strip())
:
in_table:
result.append(_table_to_latex(table_lines))
in_table =
table_lines = []
result.append(line)
in_table:
result.append(_table_to_latex(table_lines))
.join(result)
():
headers = [c.strip() c table_lines[].strip().split()]
n_cols = (headers)
col_spec = + .join([] * n_cols) +
latex = [
,
,
,
,
+ .join( h headers) + ,
,
]
line table_lines[:]:
cells = [c.strip() c line.strip().split()]
latex.append( + .join(cells) + )
latex.extend([
,
,
,
,
,
])
.join(latex)
():
raw = m.group()
nums = []
part re.split(, raw):
part:
start, end = part.split()
nums.extend(((start), (end) + ))
:
nums.append((part))
keys = .join( n ((nums)))
():
lines = tex.split()
result = []
in_list =
list_type =
line lines:
ul_match = re.(, line)
ol_match = re.(, line)
ul_match in_list:
in_list =
list_type =
result.append()
result.append()
ul_match in_list list_type == :
result.append()
ol_match in_list:
in_list =
list_type =
result.append()
result.append()
ol_match in_list list_type == :
result.append()
:
in_list:
result.append()
in_list =
list_type =
result.append(line)
in_list:
result.append()
.join(result)
4. 完全な .tex ファイル生成
def generate_tex_file(manuscript_path, journal_format="elsevier",
title="", authors="", affiliations="",
abstract_text="", keywords=None, filepath=None):
"""
Markdown 原稿から完全な .tex ファイルを生成する。
Args:
manuscript_path: Path — 入力 Markdown ファイル
journal_format: str — ジャーナル形式
title, authors, affiliations: str — メタデータ
abstract_text: str — アブストラクト
keywords: list[str] — キーワード
filepath: Path — 出力先(デフォルト: manuscript/manuscript.tex)
"""
from pathlib import Path
if filepath is None:
filepath = BASE_DIR / "manuscript" / "manuscript.tex"
filepath.parent.mkdir(parents=True, exist_ok=True)
tmpl = JOURNAL_TEMPLATES.get(journal_format, JOURNAL_TEMPLATES["elsevier"])
with open(manuscript_path, "r", encoding="utf-8") as f:
md_text = f.read()
body_tex = md_to_latex(md_text, journal_format)
preamble = [tmpl["documentclass"]]
preamble.extend(tmpl["packages"])
preamble.append("")
doc_begin = [r"\begin{document}", ""]
if title:
doc_begin.append(tmpl["title_cmd"] % title)
if authors:
doc_begin.append(tmpl["author_cmd"] % authors)
if affiliations and tmpl.get():
doc_begin.append(tmpl[] % affiliations)
doc_begin.append()
abstract_text:
doc_begin.extend([
,
,
abstract_text,
,
])
keywords:
doc_begin.extend([
,
,
.join(keywords),
,
])
doc_end = [
,
,
,
,
,
]
full_tex = .join(preamble) + + .join(doc_begin) +
full_tex += body_tex +
full_tex += .join(doc_end) +
(filepath, , encoding=) f:
f.write(full_tex)
()
filepath
5. BibTeX ファイル生成
def generate_bib_file(references, filepath=None):
"""
引用リストから BibTeX ファイルを生成する。
Args:
references: list[dict] — 各参照のメタデータ
[{"key": "ref1", "type": "article", "author": "...",
"title": "...", "journal": "...", "year": "...", ...}]
filepath: Path — 出力先(デフォルト: manuscript/references.bib)
"""
from pathlib import Path
if filepath is None:
filepath = BASE_DIR / "manuscript" / "references.bib"
filepath.parent.mkdir(parents=True, exist_ok=True)
content = ""
for ref in references:
ref_type = ref.get("type", "article")
key = ref.get("key", "unknown")
fields = []
for field_name in ["author", "title", "journal", "year", "volume",
"number", "pages", "doi", "publisher", "booktitle",
"url", "note"]:
if field_name in ref and ref[field_name]:
fields.append(f" {field_name} = {{{ref[field_name]}}}")
content += f"@{ref_type}{{{key},\n"
content += ",\n".join(fields)
content +=
(filepath, , encoding=) f:
f.write(content)
()
filepath
6. LaTeX 変換パイプライン統合
def run_latex_pipeline(manuscript_path, journal_format="elsevier",
title="", authors="", affiliations="",
abstract_text="", keywords=None, references=None):
"""
Markdown → LaTeX 変換パイプラインを実行する。
出力ファイル:
manuscript/manuscript.tex — メイン LaTeX ファイル
manuscript/references.bib — BibTeX 参照データベース
"""
print("=" * 60)
print("LaTeX Formatter Pipeline")
print("=" * 60)
print("\n[Phase 1-3] Markdown → LaTeX 変換...")
tex_path = generate_tex_file(
manuscript_path, journal_format=journal_format,
title=title, authors=authors, affiliations=affiliations,
abstract_text=abstract_text, keywords=keywords,
)
if references:
print("\n[Phase 4] BibTeX ファイル生成...")
generate_bib_file(references)
print("\n" + "=" * 60)
print("LaTeX 変換完了!")
print(f" コンパイル: pdflatex manuscript.tex && bibtex manuscript && pdflatex manuscript.tex × 2")
print("=" * 60)
return tex_path
ToolUniverse 連携
| TU Key | ツール名 | 連携内容 |
|---|
crossref | Crossref | 参考文献メタデータ・DOI 解決 |
References
Output Files
| ファイル | 形式 | 生成タイミング |
|---|
manuscript/manuscript.tex | LaTeX メインファイル | 変換完了時 |
manuscript/references.bib | BibTeX 参照データベース | 変換完了時 |
対応ジャーナルテンプレート
| テンプレート | documentclass | bib_style |
|---|
| Nature 系 | nature | naturemag |
| Science 系 | article (12pt) | Science |
| ACS 系 | achemso | achemso |
| IEEE 系 | IEEEtran | IEEEtran |
| Elsevier 系 | elsarticle | elsarticle-num |
| APS/PRL 系 | revtex4-2 | apsrev4-2 |
参照スキル
| スキル | 連携 |
|---|
scientific-academic-writing | 入力: manuscript/manuscript.md (Markdown 原稿) |
scientific-supplementary-generator | SI の LaTeX 変換にも対応 |
scientific-citation-checker | 引用キーの整合性を検証後に BibTeX 生成 |
scientific-publication-figures | figures/ の図パスを \includegraphics に変換 |