diff --git a/.github/workflows/release-pdf.yml b/.github/workflows/release-pdf.yml new file mode 100644 index 000000000..2605a9a32 --- /dev/null +++ b/.github/workflows/release-pdf.yml @@ -0,0 +1,74 @@ +name: Release PDF +on: + push: + branches: + - master + paths: + - .github/workflows/release-pdf.yml + - docs/release-notes.md +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Install fonts + run: | + mkdir -p ~/.fonts + mkdir -p ~/.fonts/palatino-linotype + mkdir -p ~/.fonts/source-han-serif + wget https://github.com/dolbydu/font/raw/master/Serif/Palatino/Palatino%20Linotype%20Bold%20Italic.ttf -O ~/.fonts/palatino-linotype/Palatino-Linotype-Bold-Italic.ttf + wget https://github.com/dolbydu/font/raw/master/Serif/Palatino/Palatino%20Linotype%20Bold.ttf -O ~/.fonts/palatino-linotype/Palatino-Linotype-Bold.ttf + wget https://github.com/dolbydu/font/raw/master/Serif/Palatino/Palatino%20Linotype%20Italic.ttf -O ~/.fonts/palatino-linotype/Palatino-Linotype-Italic.ttf + wget https://github.com/dolbydu/font/raw/master/Serif/Palatino/Palatino%20Linotype.ttf -O ~/.fonts/palatino-linotype/Palatino-Linotype.ttf + wget https://github.com/adobe-fonts/source-han-serif/raw/release/SubsetOTF/CN/SourceHanSerifCN-Bold.otf -O ~/.fonts/source-han-serif/SourceHanSerifCN-Bold.otf + wget https://github.com/adobe-fonts/source-han-serif/raw/release/SubsetOTF/CN/SourceHanSerifCN-ExtraLight.otf -O ~/.fonts/source-han-serif/SourceHanSerifCN-ExtraLight.otf + wget https://github.com/adobe-fonts/source-han-serif/raw/release/SubsetOTF/CN/SourceHanSerifCN-Heavy.otf -O ~/.fonts/source-han-serif/SourceHanSerifCN-Heavy.otf + wget https://github.com/adobe-fonts/source-han-serif/raw/release/SubsetOTF/CN/SourceHanSerifCN-Light.otf -O ~/.fonts/source-han-serif/SourceHanSerifCN-Light.otf + wget https://github.com/adobe-fonts/source-han-serif/raw/release/SubsetOTF/CN/SourceHanSerifCN-Medium.otf -O ~/.fonts/source-han-serif/SourceHanSerifCN-Medium.otf + wget https://github.com/adobe-fonts/source-han-serif/raw/release/SubsetOTF/CN/SourceHanSerifCN-Regular.otf -O ~/.fonts/source-han-serif/SourceHanSerifCN-Regular.otf + wget https://github.com/adobe-fonts/source-han-serif/raw/release/SubsetOTF/CN/SourceHanSerifCN-SemiBold.otf -O ~/.fonts/source-han-serif/SourceHanSerifCN-SemiBold.otf + fc-cache -f -v ~/.fonts + echo "Fonts installed" + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y texlive-xetex texlive-lang-chinese texlive-latex-recommended librsvg2-bin + wget https://github.com/jgm/pandoc/releases/download/2.14.1/pandoc-2.14.1-1-amd64.deb + sudo dpkg -i pandoc-2.14.1-1-amd64.deb + sudo npm install -g --save-dev --save-exact prettier + xelatex --version + pandoc --version + prettier --version + echo "Dependencies installed" + - name: Clone repository + uses: actions/checkout@v2 + - name: Build pdf + run: | + cd docs + python3 compile.py + - name: Set up release env + id: setup + run: | + echo "::set-output name=version::$(head -n 1 docs/release-notes.md)" + echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" + echo "::set-output name=date::$(date +%Y-%m-%d)" + - name: Create pdf release + id: create_release + uses: actions/create-release@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.setup.outputs.version }}-${{ steps.setup.outputs.sha_short }} + release_name: Release ${{ steps.setup.outputs.date }} + body_path: docs/release-notes.md + draft: false + prerelease: true + - name: Upload pdf release + id: upload_release + uses: actions/upload-release-asset@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: docs/build/target/release.pdf + asset_name: dive-into-dl-pytorch.pdf + asset_content_type: application/pdf diff --git a/.gitignore b/.gitignore index 3a9f19f29..c82b687b5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ data/pikachu* # Pascal VOC2012数据集, 约2G data/VOCdevkit* + +docs/build \ No newline at end of file diff --git a/docs/compile.py b/docs/compile.py new file mode 100644 index 000000000..3e53f9229 --- /dev/null +++ b/docs/compile.py @@ -0,0 +1,96 @@ +import os +import re +import glob +from utils import get_content_files, downgrade_heading, create_empty_page, pure_markdown + + +def init(): + os.system("rm -rf build") + os.system("mkdir -p build/docs") + os.system("mkdir -p build/target") + os.system("cp -r img tex -t build") + os.system("cp _sidebar.md -t build") + for file in get_content_files(): + print("Found", file) + os.system("cp {} build/docs".format(file)) # move all markdown files to build/docs + os.chdir("build") + print("Inited.", end="\n\n") + + +def create_chapter(): + files = [] + with open("_sidebar.md", "r") as f: + for line in f.readlines(): + # 提取页面文件 + res = re.findall(r"\]\((.+)\)$", line) + + if len(res) > 0: # 存在对应 markdown 文件 + filename = "docs/{}".format(re.sub(r"^(.+)\/", "", res[0])) + if line[0] == " ": + # 将子章节内的标题统一降一级 + downgrade_heading(filename) + + else: # 不存在对应 markdown 文件 + # 提取页面标题 + title = re.findall(r"\*\s?\[?(.+?)\]?\(?\)?$", line)[0].replace("\\", "") + filename = "docs/{}.md".format(title.replace(" ", "")) + + # this is a work around for not including this chapter + if title == "简介": + continue + + if line[0] == " ": + # 针对子章节生成提示 + create_empty_page(filename, title, is_chapter=False) + else: + # 针对章节生成标题 + create_empty_page(filename, title, is_chapter=True) + files.append(filename) + return files + + +def format(): + print("Formating docs...") + for filename in glob.glob("docs/*.md"): + pure_markdown(filename) + os.system("prettier --write docs") + + +def build(files): + print("Building...") + title = r"《动手学深度学习》PyTorch 实现" + toc_title = r"目录" + author = r"原书作者:阿斯顿・张、李沐、扎卡里C.立顿、\\ 亚历山大J.斯莫拉、以及其他社区贡献者 \thanks{GitHub 地址: https://github.com/d2l-ai/d2l-zh}" + date = r"\today" + + os.system("pandoc {} -o target/release.pdf \ + --from=markdown+link_attributes+footnotes+blank_before_header \ + --to=pdf \ + --toc \ + --toc-depth=2 \ + --resource-path=./docs \ + --listings \ + --pdf-engine=xelatex \ + --template=tex/custom_template.tex \ + -V documentclass=book \ + -V mathspec \ + -V graphicx \ + -V colorlinks \ + -V title='{}' \ + -V toc-title='{}' \ + -V author='{}' \ + -V date='{}' \ + --include-before-body=tex/cover.tex".format(" ".join(files), title, toc_title, author, date) + ) + + print("Done.", end="\n\n") + + +def main(): + init() + files = create_chapter() + format() + build(files) + +if __name__ == "__main__": + main() diff --git a/docs/release-notes.md b/docs/release-notes.md new file mode 100644 index 000000000..b0197cf38 --- /dev/null +++ b/docs/release-notes.md @@ -0,0 +1,3 @@ +v0.0.1 + +This release is auto generated by Github Actions. \ No newline at end of file diff --git a/docs/tex/cover.tex b/docs/tex/cover.tex new file mode 100644 index 000000000..b3cd32108 --- /dev/null +++ b/docs/tex/cover.tex @@ -0,0 +1,5 @@ +本项目将《动手学深度学习》 原书中 MXNet 代码实现改为 PyTorch 实现。项目地址:\href{https://github.com/ShusenTang/Dive-into-DL-PyTorch}{https://github.com/ShusenTang/Dive-into-DL-PyTorch} 此书的中英版本存在一些不同,针对此书英文版的 PyTorch 重构可参考这个项目。 + +There are some differences between the Chinese and English versions of this book. For the PyTorch modifying of the English version, you can refer to this repo. + +\thispagestyle{empty} \ No newline at end of file diff --git a/docs/tex/custom_template.tex b/docs/tex/custom_template.tex new file mode 100644 index 000000000..67663041a --- /dev/null +++ b/docs/tex/custom_template.tex @@ -0,0 +1,232 @@ +$if(colorlinks)$ +\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor} +$endif$ + +\documentclass{book} +\usepackage{iftex} +\usepackage{amsmath,amssymb} +\usepackage{mathspec} +\usepackage{lmodern} + +% +% geometry +% +\usepackage[a4paper]{geometry} +\geometry{ + left=2.54cm, + right=2.54cm, + top=3.18cm, + bottom=3.18cm, + footskip=1.48cm, + headsep=.5cm, + headheight=1.5cm +} +\usepackage{caption} +\captionsetup[figure]{labelformat=empty} +\renewcommand{\baselinestretch}{1.3} % 行间距 +\usepackage{indentfirst} + +% +% listings +% +\usepackage{listings} +\usepackage{xcolor} +\newcommand{\passthrough}[1]{#1} + +\lstdefinestyle{lfonts}{ + basicstyle = \small\ttfamily, + stringstyle = \color{purple}, + keywordstyle = \color{blue!60!black}\bfseries, + commentstyle = \color{gray}, +} +\lstdefinestyle{lnumbers}{ + numbers = left, + numberstyle = \small, + numbersep = 1em, + firstnumber = 1, + stepnumber = 1, +} +\lstdefinestyle{llayout}{ + breaklines = true, + postbreak = \mbox{\textcolor{red}{\(\hookrightarrow\)}\space}, + showspaces = false, + showtabs = false, + tabsize = 4, + columns = flexible, +} +\lstdefinestyle{lgeometry}{ + xleftmargin = 20pt, + xrightmargin = 0pt, + frame = tb, + framesep = \fboxsep, + framexleftmargin = 20pt, + aboveskip=1em, +} +\lstdefinestyle{lgeneral}{ + style = lfonts, + style = lnumbers, + style = llayout, + style = lgeometry, +} +\lstdefinelanguage{Python}{ + morekeywords={ + % normal keywords (without data types) + False, await, else, import, pass, + None, break, except,, in, raise, + True, class, finally, is, return, + and, continue, for, lambda, try, + as, def, from, nonlocal, while, + assert, del, global, not, with, + async, elif, if, or, yield + }, + morekeywords={[2] + % built-ins + abs, delattr, hash, memoryview, set, all, dict, help, min, setattr, any, dir, hex, next, slice, ascii, divmod, id, object, sorted, bin, enumerate, input, oct, staticmethod, bool, eval, int, open, str, breakpoint, exec, isinstance, ord, sum, bytearray, filter, issubclass, pow, super, bytes, float, iter, print, tuple, callable, format, len, property, type, chr, frozenset, list, range, vars, classmethod, getattr, locals, repr, zip, compile, globals, map, reversed, __import__, complex, hasattr, max, round, + }, + sensitive, +} +\lstset{ + style = lgeneral, +} + +% +% fonts +% +\usepackage{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{textcomp} % provide euro and other symbols +\usepackage{fontspec} +\PassOptionsToPackage{space}{xeCJK} +\usepackage{xeCJK} +\setmainfont{Palatino Linotype} +\setCJKmainfont{Source Han Serif CN} +% Use upquote if available, for straight quotes in verbatim environments +\IfFileExists{upquote.sty}{\usepackage{upquote}}{} +\IfFileExists{microtype.sty}{% use microtype if available + \usepackage[$for(microtypeoptions)$$microtypeoptions$$sep$,$endfor$]{microtype} + \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts +}{} + + +% +% link +% +\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available +\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} +\hypersetup{ + colorlinks=true, + linkcolor={$if(linkcolor)$$linkcolor$$else$Maroon$endif$}, + filecolor={$if(filecolor)$$filecolor$$else$Maroon$endif$}, + citecolor={$if(citecolor)$$citecolor$$else$Blue$endif$}, + urlcolor={$if(urlcolor)$$urlcolor$$else$Blue$endif$}, + pdfcreator={LaTeX via pandoc}} +\urlstyle{same} % disable monospaced font for URLs + +% +% table +% +$if(tables)$ +\usepackage{longtable,booktabs,array} +$if(multirow)$ +\usepackage{multirow} +$endif$ +\usepackage{calc} +\usepackage{etoolbox} +\makeatletter +\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} +\makeatother +\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} +\makesavenoteenv{longtable} +$endif$ + +% +% graphics +% +$if(graphics)$ +\usepackage{graphicx} +\makeatletter +\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi} +\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} +\makeatother +\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} +\makeatletter +\def\fps@figure{htbp} +\makeatother +$endif$ + + +\setlength{\emergencystretch}{3em} % prevent overfull lines +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt} +} + +% +% blockquotes +% +\definecolor{blockquote-border}{RGB}{221,221,221} +\definecolor{blockquote-text}{RGB}{119,119,119} +\usepackage{mdframed} +\newmdenv[ + rightline = false, + bottomline = false, + topline = false, + linewidth = 4pt, + linecolor = blockquote-border, + skipabove = \parskip +]{customblockquote} +\renewenvironment{quote}{\vspace{4pt}\begin{customblockquote}\list{}{\rightmargin=1pt\leftmargin=1pt}\item\relax\color{blockquote-text}\ignorespaces}{\unskip\unskip\endlist\end{customblockquote}\vspace{4pt}} + +% +% numbering +% +$if(numbersections)$ +\setcounter{secnumdepth}{$if(secnumdepth)$$secnumdepth$$else$5$endif$} +$else$ +\setcounter{secnumdepth}{-\maxdimen} % remove section numbering +$endif$ + +% +% metainfo +% +$if(title)$ +\title{$title$$if(thanks)$\thanks{$thanks$}$endif$} +$endif$ + +\author{$for(author)$$author$$sep$ \and $endfor$} +\date{$date$} + +$for(header-includes)$ +$header-includes$ +$endfor$ + + +\begin{document} +$if(title)$ +\maketitle +$endif$ + +$for(include-before)$ +$include-before$ +$endfor$ + +% +% toc +% +$if(toc)$ +$if(toc-title)$ + \renewcommand*\contentsname{$toc-title$} +$endif$ +$if(colorlinks)$ + \hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$} +$endif$ +\setcounter{tocdepth}{$toc-depth$} +\tableofcontents +$endif$ + +$body$ + +$for(include-after)$ +$include-after$ +$endfor$ + +\end{document} diff --git a/docs/utils.py b/docs/utils.py new file mode 100644 index 000000000..a7bdc14db --- /dev/null +++ b/docs/utils.py @@ -0,0 +1,74 @@ +import re + + +def get_content_files(sidebar_filename="_sidebar.md"): + """ + parse the sidebar file and return a list of all content files + """ + + with open(sidebar_filename, "r") as f: + files = re.findall(r"\]\((.+)\)$", f.read(), re.M) + return files + + +def downgrade_heading(filename): + """ + downgrade all headings by 1 level + """ + + print("Downgrading headings in {}".format(filename)) + with open(filename, "r") as f: + lines = f.readlines() + + with open(filename, "w") as f: + is_codeblock = False + for line in lines: + if line.startswith("```"): + is_codeblock = not is_codeblock + elif line.startswith("#") and not is_codeblock: + line = "#" + line + f.write(line) + + +def create_empty_page(filename, title, is_chapter): + """ + create an empty page with the given title + """ + + print("Create new page for {}".format(filename)) + with open(filename, "w") as f: + if is_chapter: + f.write(f"# {title}\n") + else: + f.write(f"## {title}\n\n此章节仍未编写完成,敬请期待。\n") + + +def pure_markdown(filename): + """ + convert all markdown to pure markdown + """ + + with open(filename, "r") as f: + lines = f.readlines() + + with open(filename, "w") as f: + i = 0 + while i < len(lines): + window = lines[i : i + 4] + if window[0].startswith("(.+?)", window[-1]) + re.findall( + r"(.+?)", window[-1] + ) + cap = "" if cap == [] else cap[0].replace("\n", "").replace("\t", "").replace(" ", "") + f.write("\n![{}]({}){{ width={} }}\n\n".format(cap, src, width)) + if cap == "": + i += 3 + else: + i += 4 + else: + f.write(lines[i]) + i += 1