mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Switch to Sphinx 1.0 to generate User Manual
This commit is contained in:
parent
a69641ac1b
commit
48df7c38bd
@ -73,11 +73,11 @@ class Manual(Command):
|
|||||||
os.makedirs(d)
|
os.makedirs(d)
|
||||||
if not os.path.exists('.build'+os.sep+'html'):
|
if not os.path.exists('.build'+os.sep+'html'):
|
||||||
os.makedirs('.build'+os.sep+'html')
|
os.makedirs('.build'+os.sep+'html')
|
||||||
os.environ['__appname__']= __appname__
|
os.environ['__appname__'] = __appname__
|
||||||
os.environ['__version__']= __version__
|
os.environ['__version__'] = __version__
|
||||||
subprocess.check_call(['sphinx-build', '-b', 'custom', '-t', 'online',
|
subprocess.check_call(['sphinx-build', '-b', 'html', '-t', 'online',
|
||||||
'-d', '.build/doctrees', '.', '.build/html'])
|
'-d', '.build/doctrees', '.', '.build/html'])
|
||||||
subprocess.check_call(['sphinx-build', '-b', 'epub', '-d',
|
subprocess.check_call(['sphinx-build', '-b', 'myepub', '-d',
|
||||||
'.build/doctrees', '.', '.build/epub'])
|
'.build/doctrees', '.', '.build/epub'])
|
||||||
shutil.copyfile(self.j('.build', 'epub', 'calibre.epub'), self.j('.build',
|
shutil.copyfile(self.j('.build', 'epub', 'calibre.epub'), self.j('.build',
|
||||||
'html', 'calibre.epub'))
|
'html', 'calibre.epub'))
|
||||||
|
@ -37,7 +37,7 @@ qthelp:
|
|||||||
|
|
||||||
epub:
|
epub:
|
||||||
mkdir -p .build/qthelp .build/doctrees
|
mkdir -p .build/qthelp .build/doctrees
|
||||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) .build/epub
|
$(SPHINXBUILD) -b myepub $(ALLSPHINXOPTS) .build/epub
|
||||||
@echo
|
@echo
|
||||||
@echo "Build finished."
|
@echo "Build finished."
|
||||||
|
|
||||||
|
@ -23,9 +23,11 @@ custom
|
|||||||
# General configuration
|
# General configuration
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
|
needs_sphinx = '1.0'
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
# coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
|
# coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
|
||||||
extensions = ['sphinx.ext.autodoc', 'custom']
|
extensions = ['sphinx.ext.autodoc', 'custom', 'sphinx.ext.viewcode']
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['templates']
|
templates_path = ['templates']
|
||||||
@ -36,6 +38,9 @@ source_suffix = '.rst'
|
|||||||
# The master toctree document.
|
# The master toctree document.
|
||||||
master_doc = 'index'
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# The language
|
||||||
|
language = 'en'
|
||||||
|
|
||||||
# General substitutions.
|
# General substitutions.
|
||||||
project = __appname__
|
project = __appname__
|
||||||
copyright = '2008, Kovid Goyal'
|
copyright = '2008, Kovid Goyal'
|
||||||
@ -81,7 +86,6 @@ pygments_style = 'sphinx'
|
|||||||
# given in html_static_path.
|
# given in html_static_path.
|
||||||
html_theme = 'default'
|
html_theme = 'default'
|
||||||
html_theme_options = {'stickysidebar':'true', 'relbarbgcolor':'black'}
|
html_theme_options = {'stickysidebar':'true', 'relbarbgcolor':'black'}
|
||||||
html_style = 'calibre.css'
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
@ -100,8 +104,16 @@ html_use_smartypants = True
|
|||||||
html_title = 'calibre User Manual'
|
html_title = 'calibre User Manual'
|
||||||
html_short_title = 'Start'
|
html_short_title = 'Start'
|
||||||
html_logo = 'resources/logo.png'
|
html_logo = 'resources/logo.png'
|
||||||
|
|
||||||
epub_author = 'Kovid Goyal'
|
epub_author = 'Kovid Goyal'
|
||||||
epub_cover = 'resources/epub_cover.jpg'
|
epub_cover = 'epub_cover.jpg'
|
||||||
|
epub_publisher = 'Kovid Goyal'
|
||||||
|
epub_identifier = 'http://calibre-ebook.com/user_manual'
|
||||||
|
epub_scheme = 'url'
|
||||||
|
epub_uid = 'S54a88f8e9d42455e9c6db000e989225f'
|
||||||
|
epub_tocdepth = 4
|
||||||
|
epub_tocdup = True
|
||||||
|
epub_pre_files = [('epub_titlepage.html', 'Cover')]
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
# Custom sidebar templates, maps document names to template names.
|
||||||
#html_sidebars = {}
|
#html_sidebars = {}
|
||||||
|
@ -9,9 +9,6 @@ sys.path.insert(0, os.path.abspath('../../'))
|
|||||||
sys.extensions_location = '../plugins'
|
sys.extensions_location = '../plugins'
|
||||||
sys.resources_location = '../../../resources'
|
sys.resources_location = '../../../resources'
|
||||||
|
|
||||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
||||||
from qthelp import QtHelpBuilder
|
|
||||||
from epub import EPUBHelpBuilder
|
|
||||||
from sphinx.util import rpartition
|
from sphinx.util import rpartition
|
||||||
from sphinx.util.console import bold
|
from sphinx.util.console import bold
|
||||||
from sphinx.ext.autodoc import prepare_docstring
|
from sphinx.ext.autodoc import prepare_docstring
|
||||||
@ -20,12 +17,7 @@ from docutils import nodes
|
|||||||
|
|
||||||
sys.path.append(os.path.abspath('../../../'))
|
sys.path.append(os.path.abspath('../../../'))
|
||||||
from calibre.linux import entry_points
|
from calibre.linux import entry_points
|
||||||
|
from epub import EPUBHelpBuilder
|
||||||
class CustomBuilder(StandaloneHTMLBuilder):
|
|
||||||
name = 'custom'
|
|
||||||
|
|
||||||
class CustomQtBuild(QtHelpBuilder):
|
|
||||||
name = 'customqt'
|
|
||||||
|
|
||||||
def substitute(app, doctree):
|
def substitute(app, doctree):
|
||||||
pass
|
pass
|
||||||
@ -305,9 +297,6 @@ def auto_member(dirname, arguments, options, content, lineno,
|
|||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
app.add_config_value('epub_cover', None, False)
|
app.add_config_value('epub_cover', None, False)
|
||||||
app.add_config_value('epub_author', '', False)
|
|
||||||
app.add_builder(CustomBuilder)
|
|
||||||
app.add_builder(CustomQtBuild)
|
|
||||||
app.add_builder(EPUBHelpBuilder)
|
app.add_builder(EPUBHelpBuilder)
|
||||||
app.add_directive('automember', auto_member, 1, (1, 0, 1))
|
app.add_directive('automember', auto_member, 1, (1, 0, 1))
|
||||||
app.connect('doctree-read', substitute)
|
app.connect('doctree-read', substitute)
|
||||||
|
@ -6,75 +6,19 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os, mimetypes, uuid, shutil
|
import os, time
|
||||||
from datetime import datetime
|
|
||||||
from docutils import nodes
|
|
||||||
from xml.sax.saxutils import escape, quoteattr
|
|
||||||
from urlparse import urldefrag
|
|
||||||
from zipfile import ZipFile, ZIP_STORED, ZipInfo
|
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx.builders.epub import EpubBuilder
|
||||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
||||||
|
|
||||||
NCX = '''\
|
class EPUBHelpBuilder(EpubBuilder):
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
name = 'myepub'
|
||||||
<ncx version="2005-1"
|
|
||||||
xml:lang="en"
|
|
||||||
xmlns="http://www.daisy.org/z3986/2005/ncx/"
|
|
||||||
xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata"
|
|
||||||
>
|
|
||||||
<head>
|
|
||||||
<meta name="dtb:uid" content="{uid}"/>
|
|
||||||
<meta name="dtb:depth" content="{depth}"/>
|
|
||||||
<meta name="dtb:generator" content="sphinx"/>
|
|
||||||
<meta name="dtb:totalPageCount" content="0"/>
|
|
||||||
<meta name="dtb:maxPageNumber" content="0"/>
|
|
||||||
</head>
|
|
||||||
<docTitle><text>Table of Contents</text></docTitle>
|
|
||||||
<navMap>
|
|
||||||
{navpoints}
|
|
||||||
</navMap>
|
|
||||||
</ncx>
|
|
||||||
'''
|
|
||||||
|
|
||||||
OPF = '''\
|
def add_cover(self, outdir, cover_fname):
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
href = '_static/'+cover_fname
|
||||||
<package version="2.0"
|
opf = os.path.join(self.outdir, 'content.opf')
|
||||||
xmlns="http://www.idpf.org/2007/opf"
|
|
||||||
unique-identifier="sphinx_id"
|
|
||||||
>
|
|
||||||
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf" xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata">
|
|
||||||
<dc:title>{title}</dc:title>
|
|
||||||
<dc:creator opf:role="aut">{author}</dc:creator>
|
|
||||||
<dc:contributor opf:role="bkp">Sphinx</dc:contributor>
|
|
||||||
<dc:identifier opf:scheme="sphinx" id="sphinx_id">{uid}</dc:identifier>
|
|
||||||
<dc:date>{date}</dc:date>
|
|
||||||
<meta name="calibre:publication_type" content="sphinx_manual" />
|
|
||||||
<meta name="cover" content="cover"/>
|
|
||||||
</metadata>
|
|
||||||
<manifest>
|
|
||||||
{manifest}
|
|
||||||
</manifest>
|
|
||||||
<spine toc="ncx">
|
|
||||||
{spine}
|
|
||||||
</spine>
|
|
||||||
<guide>
|
|
||||||
{guide}
|
|
||||||
</guide>
|
|
||||||
</package>
|
|
||||||
'''
|
|
||||||
|
|
||||||
CONTAINER='''\
|
cover = '''\
|
||||||
<?xml version="1.0"?>
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||||
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
|
||||||
<rootfiles>
|
|
||||||
<rootfile full-path="{0}" media-type="application/oebps-package+xml"/>
|
|
||||||
</rootfiles>
|
|
||||||
</container>
|
|
||||||
'''
|
|
||||||
|
|
||||||
SVG_TEMPLATE = '''\
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta name="calibre:cover" content="true" />
|
<meta name="calibre:cover" content="true" />
|
||||||
@ -92,212 +36,23 @@ SVG_TEMPLATE = '''\
|
|||||||
<image width="600" height="800" xlink:href="%s"/>
|
<image width="600" height="800" xlink:href="%s"/>
|
||||||
</svg>
|
</svg>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
'''
|
'''%href
|
||||||
|
self.files.append('epub_titlepage.html')
|
||||||
class TOC(list):
|
open(os.path.join(outdir, self.files[-1]), 'wb').write(cover)
|
||||||
|
|
||||||
def __init__(self, title=None, href=None):
|
|
||||||
list.__init__(self)
|
|
||||||
self.title, self.href = title, href
|
|
||||||
|
|
||||||
def create_child(self, title, href):
|
|
||||||
self.append(TOC(title, href))
|
|
||||||
return self[-1]
|
|
||||||
|
|
||||||
def depth(self):
|
|
||||||
try:
|
|
||||||
return max(node.depth() for node in self)+1
|
|
||||||
except ValueError:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
class EPUBHelpBuilder(StandaloneHTMLBuilder):
|
raw = open(opf, 'rb').read()
|
||||||
"""
|
raw = raw.replace('</metadata>',
|
||||||
Builder that also outputs Qt help project, contents and index files.
|
('<meta name="cover" content="%s"/>\n'
|
||||||
"""
|
'<dc:date>%s</dc:date>\n</metadata>') %
|
||||||
name = 'epub'
|
(href.replace('/', '_'), time.strftime('%Y-%m-%d')))
|
||||||
|
raw = raw.replace('</manifest>',
|
||||||
# don't copy the reST source
|
('<item id="{0}" href="{0}" media-type="application/xhtml+xml"/>\n</manifest>').\
|
||||||
copysource = False
|
format('epub_titlepage.html'))
|
||||||
|
open(opf, 'wb').write(raw)
|
||||||
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
|
|
||||||
'image/jpeg']
|
|
||||||
|
|
||||||
# don't add links
|
|
||||||
add_permalinks = False
|
|
||||||
# don't add sidebar etc.
|
|
||||||
embedded = True
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
StandaloneHTMLBuilder.init(self)
|
|
||||||
self.out_suffix = '.html'
|
|
||||||
self.link_suffix = '.html'
|
|
||||||
self.html_outdir = self.outdir = os.path.join(self.outdir, 'src')
|
|
||||||
self.conf = self.config
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
StandaloneHTMLBuilder.finish(self)
|
|
||||||
self.create_titlepage()
|
|
||||||
self.outdir = os.path.dirname(self.outdir)
|
|
||||||
cwd = os.getcwd()
|
|
||||||
os.chdir(self.html_outdir)
|
|
||||||
try:
|
|
||||||
self.generate_manifest()
|
|
||||||
self.generate_toc()
|
|
||||||
self.render_opf()
|
|
||||||
self.render_epub()
|
|
||||||
finally:
|
|
||||||
os.chdir(cwd)
|
|
||||||
|
|
||||||
def render_epub(self):
|
|
||||||
container = CONTAINER.format('content.opf')
|
|
||||||
path = os.path.abspath('..'+os.sep+self.conf.project+'.epub')
|
|
||||||
zf = ZipFile(path, 'w')
|
|
||||||
zi = ZipInfo('mimetype')
|
|
||||||
zi.compress_type = ZIP_STORED
|
|
||||||
zf.writestr(zi, 'application/epub+zip')
|
|
||||||
zf.writestr('META-INF/container.xml', container)
|
|
||||||
for url in self.manifest:
|
|
||||||
fp = os.path.join(self.html_outdir, *url.split('/'))
|
|
||||||
zf.write(fp, url)
|
|
||||||
zf.close()
|
|
||||||
self.info('EPUB created at: '+path)
|
|
||||||
|
|
||||||
|
|
||||||
def render_opf(self):
|
|
||||||
manifest = []
|
|
||||||
for href in self.manifest:
|
|
||||||
mt, id = self.manifest[href]
|
|
||||||
manifest.append(' '*8 + '<item id=%s href=%s media-type=%s />'%\
|
|
||||||
tuple(map(quoteattr, (id, href, mt))))
|
|
||||||
manifest = '\n'.join(manifest)
|
|
||||||
spine = [' '*8+'<itemref idref=%s />'%quoteattr(x) for x in self.spine]
|
|
||||||
spine = '\n'.join(spine)
|
|
||||||
guide = ''
|
|
||||||
|
|
||||||
opf = OPF.format(title=escape(self.conf.html_title),
|
|
||||||
author=escape(self.conf.epub_author), uid=str(uuid.uuid4()),
|
|
||||||
date=datetime.now().isoformat(), manifest=manifest, spine=spine,
|
|
||||||
guide=guide)
|
|
||||||
open('content.opf', 'wb').write(opf)
|
|
||||||
self.manifest['content.opf'] = ('application/oebps-package+xml', 'opf')
|
|
||||||
|
|
||||||
def create_titlepage(self):
|
|
||||||
self.cover_image_url = None
|
|
||||||
if self.conf.epub_cover:
|
|
||||||
img = '_static/'+os.path.basename(self.conf.epub_cover)
|
|
||||||
shutil.copyfile(self.conf.epub_cover, os.path.join(self.html_outdir,
|
|
||||||
*img.split('/')))
|
|
||||||
self.cover_image_url = img
|
|
||||||
tp = SVG_TEMPLATE%img.split('/')[-1]
|
|
||||||
open(os.path.join(self.html_outdir, '_static', 'titlepage.html'),
|
|
||||||
'wb').write(tp)
|
|
||||||
|
|
||||||
def generate_manifest(self):
|
|
||||||
self.manifest = {}
|
|
||||||
id = 1
|
|
||||||
for dirpath, dirnames, filenames in os.walk('.'):
|
|
||||||
for fname in filenames:
|
|
||||||
if fname == '.buildinfo':
|
|
||||||
continue
|
|
||||||
fpath = os.path.abspath(os.path.join(dirpath, fname))
|
|
||||||
url = os.path.relpath(fpath).replace(os.sep, '/')
|
|
||||||
self.manifest[url] = mimetypes.guess_type(url, False)[0]
|
|
||||||
if self.manifest[url] is None:
|
|
||||||
self.warn('Unknown mimetype for: ' + url)
|
|
||||||
self.manifest[url] = 'application/octet-stream'
|
|
||||||
if self.manifest[url] == 'text/html':
|
|
||||||
self.manifest[url] = 'application/xhtml+xml'
|
|
||||||
if self.cover_image_url and url.endswith(self.cover_image_url):
|
|
||||||
id_ = 'cover'
|
|
||||||
else:
|
|
||||||
id_ = 'id'+str(id)
|
|
||||||
id += 1
|
|
||||||
self.manifest[url] = (self.manifest[url], id_)
|
|
||||||
|
|
||||||
def isdocnode(self, node):
|
|
||||||
if not isinstance(node, nodes.list_item):
|
|
||||||
return False
|
|
||||||
if len(node.children) != 2:
|
|
||||||
return False
|
|
||||||
if not isinstance(node.children[0], addnodes.compact_paragraph):
|
|
||||||
return False
|
|
||||||
if not isinstance(node.children[0][0], nodes.reference):
|
|
||||||
return False
|
|
||||||
if not isinstance(node.children[1], nodes.bullet_list):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def generate_toc(self):
|
|
||||||
tocdoc = self.env.get_and_resolve_doctree(self.config.master_doc, self,
|
|
||||||
prune_toctrees=False)
|
|
||||||
istoctree = lambda node: (
|
|
||||||
isinstance(node, addnodes.compact_paragraph)
|
|
||||||
and node.has_key('toctree'))
|
|
||||||
toc = TOC()
|
|
||||||
for node in tocdoc.traverse(istoctree):
|
|
||||||
self.extend_toc(toc, node)
|
|
||||||
self._parts = []
|
|
||||||
self._po = 0
|
|
||||||
self._po_map = {}
|
|
||||||
self.spine_map = {}
|
|
||||||
self.spine = []
|
|
||||||
self.render_toc(toc)
|
|
||||||
navpoints = '\n'.join(self._parts).strip()
|
|
||||||
ncx = NCX.format(uid=str(uuid.uuid4()), depth=toc.depth(),
|
|
||||||
navpoints=navpoints)
|
|
||||||
open('toc.ncx', 'wb').write(ncx)
|
|
||||||
self.manifest['toc.ncx'] = ('application/x-dtbncx+xml', 'ncx')
|
|
||||||
self.spine.insert(0, self.manifest[self.conf.master_doc+'.html'][1])
|
|
||||||
if self.conf.epub_cover:
|
|
||||||
self.spine.insert(0, self.manifest['_static/titlepage.html'][1])
|
|
||||||
|
|
||||||
def add_to_spine(self, href):
|
|
||||||
href = urldefrag(href)[0]
|
|
||||||
if href not in self.spine_map:
|
|
||||||
for url in self.manifest:
|
|
||||||
if url == href:
|
|
||||||
self.spine_map[href]= self.manifest[url][1]
|
|
||||||
self.spine.append(self.spine_map[href])
|
|
||||||
|
|
||||||
def render_toc(self, toc, level=2):
|
|
||||||
for child in toc:
|
|
||||||
if child.title and child.href:
|
|
||||||
href = child.href
|
|
||||||
self.add_to_spine(href)
|
|
||||||
title = escape(child.title)
|
|
||||||
if isinstance(title, unicode):
|
|
||||||
title = title.encode('utf-8')
|
|
||||||
if child.href in self._po_map:
|
|
||||||
po = self._po_map[child.href]
|
|
||||||
else:
|
|
||||||
self._po += 1
|
|
||||||
po = self._po
|
|
||||||
self._parts.append(' '*(level*4)+
|
|
||||||
'<navPoint id="%s" playOrder="%d">'%(uuid.uuid4(),
|
|
||||||
po))
|
|
||||||
self._parts.append(' '*((level+1)*4)+
|
|
||||||
'<navLabel><text>%s</text></navLabel>'%title)
|
|
||||||
self._parts.append(' '*((level+1)*4)+
|
|
||||||
'<content src=%s />'%quoteattr(href))
|
|
||||||
self.render_toc(child, level+1)
|
|
||||||
self._parts.append(' '*(level*4)+'</navPoint>')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def extend_toc(self, toc, node):
|
|
||||||
if self.isdocnode(node):
|
|
||||||
refnode = node.children[0][0]
|
|
||||||
parent = toc.create_child(refnode.astext(), refnode['refuri'])
|
|
||||||
for subnode in node.children[1]:
|
|
||||||
self.extend_toc(parent, subnode)
|
|
||||||
elif isinstance(node, (nodes.list_item, nodes.bullet_list,
|
|
||||||
addnodes.compact_paragraph)):
|
|
||||||
for subnode in node:
|
|
||||||
self.extend_toc(toc, subnode)
|
|
||||||
elif isinstance(node, nodes.reference):
|
|
||||||
parent = toc.create_child(node.astext(), node['refuri'])
|
|
||||||
|
|
||||||
|
|
||||||
|
def build_epub(self, outdir, *args, **kwargs):
|
||||||
|
if self.config.epub_cover:
|
||||||
|
self.add_cover(outdir, self.config.epub_cover)
|
||||||
|
EpubBuilder.build_epub(self, outdir, *args, **kwargs)
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
@import url("default.css");
|
|
||||||
|
|
||||||
table.docutils td, table.docutils th { padding: 1em; border-bottom: 0; }
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 10 KiB |
Loading…
x
Reference in New Issue
Block a user