Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add cambridge latex style #56

Merged
merged 14 commits into from
Aug 3, 2022
55 changes: 48 additions & 7 deletions d2lbook/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import shutil
import subprocess
import sys
import tarfile
import zipfile
import requests

import nbformat
import notedown
Expand All @@ -33,23 +36,31 @@ def build():
parser.add_argument('commands', nargs='+', choices=commands)
parser.add_argument('--tab', default=None,
help='The tab to build, if multi-tab is enabled.')
parser.add_argument('--style', default=None,
help='The pdf style. It supports cambridge style and sphinx default.')
astonzhang marked this conversation as resolved.
Show resolved Hide resolved
args = parser.parse_args(sys.argv[2:])
config = Config(tab=args.tab)
builder = Builder(config)
for cmd in args.commands:
getattr(builder, cmd)()
if cmd == 'pdf':
getattr(builder, cmd)(args.style)
cheungdaven marked this conversation as resolved.
Show resolved Hide resolved
else:
getattr(builder, cmd)()

def _once(func):
# An decorator that run a method only once
def warp(self):
def warp(self, *args):
name = func.__name__
if self.config.tab:
name += '_' + self.config.tab
if name in self.done and self.done[name]:
return
full_name = 'd2lbook build ' + name
tik = datetime.datetime.now()
func(self)
if ("rst" in name or "pdf" in name) and len(args) > 0:
func(self, args[0])
else:
func(self)
logging.info('=== Finished "%s" in %s', full_name,
get_time_diff(tik, datetime.datetime.now()))
self.done[name] = True
Expand Down Expand Up @@ -222,6 +233,34 @@ def _copy_rst(self):
for src, tgt in updated_rst:
copy(src, tgt)
return rst_files

def _download_extract_latex(self, url, folder='latex_style', sha1_hash=None):
os.makedirs(folder, exist_ok=True)
fname = os.path.join(folder, url.split('/')[-1])
# Check if hit cache
if os.path.exists(fname) and sha1_hash:
sha1 = hashlib.sha1()
with open(fname, 'rb') as f:
while True:
data = f.read(1048576)
if not data:
break
sha1.update(data)
if sha1.hexdigest() == sha1_hash:
return fname
print(f'Downloading {fname} from {url}...')
r = requests.get(url, stream=True, verify=True)
with open(fname, 'wb') as f:
f.write(r.content)
base_dir = os.path.dirname(folder)
data_dir, ext = os.path.splitext(fname)
if ext == '.zip':
fp = zipfile.ZipFile(fname, 'r')
elif ext in ('.tar', '.gz'):
fp = tarfile.open(fname, 'r')
else:
assert False, 'Only zip/tar files can be extracted.'
fp.extractall(folder)

@_once
def merge(self):
Expand Down Expand Up @@ -276,7 +315,7 @@ def slides(self):
sd.generate_readme()

@_once
def rst(self):
def rst(self, style=None):
if self.config.tab == 'all':
self.merge()
else:
Expand All @@ -292,7 +331,7 @@ def rst(self):
mkdir(os.path.dirname(tgt))
ipynb2rst(src, tgt)
# Generate conf.py under rst folder
prepare_sphinx_env(self.config)
prepare_sphinx_env(self.config, style)
self._copy_rst()
self._copy_resources(self.config.src_dir, self.config.rst_dir)

Expand Down Expand Up @@ -354,8 +393,10 @@ def linkcheck(self):
'-b linkcheck -c', self.config.rst_dir, self.sphinx_opts])

@_once
def pdf(self):
self.rst()
def pdf(self, style=None):
self.rst(style)
if style:
self._download_extract_latex(self.config.pdf['latex_url'])
run_cmd([
'sphinx-build ', self.config.rst_dir, self.config.pdf_dir,
'-b latex -c', self.config.rst_dir, self.sphinx_opts])
Expand Down
11 changes: 7 additions & 4 deletions d2lbook/sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@

__all__ = ['prepare_sphinx_env']

def prepare_sphinx_env(config):
env = SphinxEnv(config)
def prepare_sphinx_env(config, style):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove style argument? See

prepare_sphinx_env(self.config)

env = SphinxEnv(config, style)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove style argument

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

env.prepare_env()

class SphinxEnv(object):
def __init__(self, config):
def __init__(self, config, style=None):
self.config = config
self.pyconf = template.sphinx_conf
if style == "cambridge":
self.pyconf = template.sphinx_conf_cambridge
else:
self.pyconf = template.sphinx_conf

def prepare_env(self):
self._copy_static_files()
Expand Down
184 changes: 181 additions & 3 deletions d2lbook/sphinx_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@

rsvg_converter_args = ['-z', '0.8']

astonzhang marked this conversation as resolved.
Show resolved Hide resolved
bibtex_bibfiles = ["BIBFILE"]
astonzhang marked this conversation as resolved.
Show resolved Hide resolved

latex_engine = 'xelatex' # for utf-8 supports
latex_show_pagerefs = True
latex_show_urls = 'footnote'
Expand Down Expand Up @@ -116,6 +114,186 @@ def setup(app):
app.add_directive('card', mxtheme.CardDirective)
"""

sphinx_conf_cambridge = r"""
import sys
sys.path.insert(0, '..')
sys.path.insert(0, '.')

project = "TITLE"
copyright = "COPYRIGHT"
author = "AUTHOR"
release = "RELEASE"

extensions = [EXTENSIONS]

templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
master_doc = 'INDEX'
numfig = True
numfig_secnum_depth = 2
math_numfig = True
math_number_all = True

suppress_warnings = ['misc.highlighting_failure']
linkcheck_ignore = [r'.*localhost.*']
linkcheck_timeout = 5
linkcheck_workers = 20

autodoc_default_options = {
'undoc-members': True,
'show-inheritance': True,
}


html_theme = 'mxtheme'
html_theme_options = {
'primary_color': 'blue',
'accent_color': 'deep_orange',
'header_links': [
HEADER_LINKS
],
'show_footer': False
}
html_static_path = ['_static']

html_favicon = 'FAVICON'

html_logo = 'HTML_LOGO'

latex_documents = [
(master_doc, "NAME.tex", "TITLE",
author, 'PT1'),
]



rsvg_converter_args = ['-z', '0.8']

astonzhang marked this conversation as resolved.
Show resolved Hide resolved
latex_engine = 'xelatex' # for utf-8 supports
latex_show_pagerefs = True
latex_show_urls = 'footnote'

latex_logo = 'LATEX_LOGO'

latex_elements = {
'papersize':'a4paper,prodtf,twoside',
'figure_align': 'htbp',
'pointsize': '11pt',
'fvset':r'''\fvset{fontsize=\small}''',
'preamble': r'''
\usepackage{graphicx}
\usepackage{booktabs}
\usepackage{amsthm}
\usepackage{color}
\usepackage[figuresright]{rotating}
\usepackage{floatpag}
\rotfloatpagestyle{empty}
\usepackage{makeidx}
\usepackage{natbib}
\usepackage[parfill]{parskip}
\usepackage{titlesec}
\usepackage{multicol}
\protected\def\sphinxcite{\citep}

% Add bib to TOC
\usepackage[nottoc,numbib]{tocbibind}

% QR code sidenotes for all footnotes
% Make sure to replace special charactors URL Encoding: https://www.urlencoder.io/learn/
\usepackage{sidenotes}
\usepackage{marginfix}
\setlength\marginparpush{20pt}
\usepackage{qrcode}
\newcommand{\qrsidenote}[1]{
\sidenote{
\qrcode[height=8mm]{#1}}
}
\newcommand{\relaxfootnote}[1][]{}

\makeatletter
\let\ps@normal\ps@headings
\let\sphinxthebibliography\thebibliography
\let\sphinxtheindex\theindex
\let\sphinxAtStartFootnote\!
\let\footnote\relaxfootnote
\let\sphinxnolinkurl\qrsidenote

% So some large pictures won't get the full page
\renewcommand{\floatpagefraction}{.8}

% Set the page margin size
\geometry{left=1.9in, right=1.4in, includefoot, bottom=0.5in}

% Section and subsection style
\titleformat{\section}{\LARGE\centering}{\thesection}%
{0.5em}{}[{\hspace{-1.65in}\raggedleft\includegraphics[width=35pc]{PT1secrule.eps}}]
\titleformat{\subsection}{\Large\centering}%
{\thesubsection}{0.5em}{}[{\color{gray}\titlerule[0.8pt]}]

% Code font style, for more font style, visit: https://tug.org/FontCatalogue/
\setmonofont{Inconsolata}
%\renewcommand\ttfamily{\sffamily}

% Resize all figures
\let\ORIincludegraphics\includegraphics
\renewcommand{\includegraphics}[2][]{\ORIincludegraphics[scale=0.75,#1]{#2}}
% main text font style
\usepackage{times}

% Rewrite table of contents
\renewcommand\tableofcontents{\@restonecolfalse
\if@twocolumn\@restonecoltrue\onecolumn\fi
%\AJW@addtocfalse
\chapter*{\contentsname}
%\@starttoc{toc}
%\AJW@addtoctrue
\if@restonecol\twocolumn\fi
\@starttoc{toc}
}

\newcommand\cambridge{PT1}
\theoremstyle{plain}% default
\newtheorem{theorem}{Theorem}[chapter]
\newtheorem{lemma}[theorem]{Lemma}
\newtheorem*{corollary}{Corollary}
\theoremstyle{definition}
\newtheorem{definition}[theorem]{Definition}
\newtheorem{condition}[theorem]{Condition}
\newtheorem{example-norules}[theorem]{Example}
\theoremstyle{remark}
\newtheorem*{remark}{Remark}
\newtheorem*{case}{Case}


\hyphenation{line-break line-breaks docu-ment triangle cambridge
amsthdoc cambridgemods baseline-skip author authors
cambridgestyle en-vir-on-ment polar astron-omers solu-tion}

\setcounter{tocdepth}{1}

\hbadness=99999 % or any number >=10000
\vfuzz=30pt
\hfuzz=30pt
''',
'maketitle':'\\maketitle',
'tableofcontents': '\\tableofcontents',
'fncychap':'',
'makeindex':'\\makeindex'
}

latex_additional_files = ["latex_style/PT1/PT1.cls", "latex_style/PT1header.eps", "latex_style/PT1secrule.eps", "latex_style/PT1/PT1box.eps", "latex_style/PT1/PT1chrule.eps", "latex_style/PT1/multind.sty", "latex_style/PT1/amsthm.sty", "latex_style/PT1/floatpag.sty","latex_style/PT1/rotating.sty", "latex_style/PT1/myriad-pt1.sty", "latex_style/PT1/natbib.sty", "latex_style/sphinx.sty", "latex_style/sphinxlatexstyleheadings.sty", "latex_style/sphinxlatexstylepage.sty", "latex_style/sphinxlatexindbibtoc.sty", "latex_style/sphinxmessages.sty", "latex_style/sphinxlatexobjects.sty",
"latex_style/PT1/natbib.dtx", "latex_style/sphinxpackagefootnote.sty", "latex_style/sphinxlatexlists.sty"]

SPHINX_CONFIGS

def setup(app):
# app.add_js_file('https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js')
app.add_js_file('d2l.js')
app.add_css_file('d2l.css')
import mxtheme
app.add_directive('card', mxtheme.CardDirective)
"""


google_tracker = """
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
Expand Down Expand Up @@ -409,7 +587,7 @@ def setup(app):
}

.mdl-tabs__tab.is-active {
background: rgb(0,0,0,.09);
background: rgb(0,0,0,.09);
}
"""

Expand Down