# -*- coding: utf-8 -*-
from docutils import nodes
from docutils.parsers.rst import directives
import sphinx
from sphinx.locale import _
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
from docutils.statemachine import StringList
from sphinx.util.nodes import nested_parse_with_titles
from ..language import TITLES
class quote_node(nodes.admonition):
"""
Defines ``quote`` node.
"""
pass
[docs]
class QuoteNode(BaseAdmonition):
"""
A ``quotedef`` entry, displayed in the form of an admonition.
It takes the following options:
* *author*
* *book* or *manga* or *film* or *show* or *disc* or
*comic* or *child* or *ado*
* *year*
* *pages*
* *tag*
* *source*
* *lid* or *label*
* *index*, additional index words beside the title and the author
* *date*, if the text was written or declared at specific date
* *title1*, by default, the author comes first, if True, the title is
Example::
.. quote::
:author: author
:book: book
:year: year
:pages: pages (optional)
:tag: something
:lid: id (used for further reference)
:source: optional
:index: word
A monkey could...
"""
node_class = quote_node
has_content = True
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec = {
"author": directives.unchanged,
"book": directives.unchanged,
"manga": directives.unchanged,
"disc": directives.unchanged,
"ado": directives.unchanged,
"child": directives.unchanged,
"comic": directives.unchanged,
"show": directives.unchanged,
"film": directives.unchanged,
"year": directives.unchanged,
"pages": directives.unchanged,
"tag": directives.unchanged,
"lid": directives.unchanged,
"label": directives.unchanged,
"source": directives.unchanged,
"class": directives.class_option,
"index": directives.unchanged,
"date": directives.unchanged,
"title1": directives.unchanged,
}
def run(self):
"""
Builds the mathdef text.
"""
env = (
self.state.document.settings.env
if hasattr(self.state.document.settings, "env")
else None
)
docname = None if env is None else env.docname
if docname is not None:
docname = docname.replace("\\", "/").split("/")[-1]
language_code = (
self.state.document.settings.language_code
if hasattr(self.state.document.settings, "language_code")
else "en"
)
if not self.options.get("class"):
self.options["class"] = ["admonition-quote"]
# body
(quote,) = super(QuoteNode, self).run()
if isinstance(quote, nodes.system_message):
return [quote] # pragma: no cover
# mid
tag = self.options.get("tag", "quotetag").strip()
if len(tag) == 0:
raise ValueError("tag is empty") # pragma: no cover
def __(text):
if text:
return _(text)
return ""
# book
author = __(self.options.get("author", "").strip())
book = __(self.options.get("book", "").strip())
manga = __(self.options.get("manga", "").strip())
comic = __(self.options.get("comic", "").strip())
ado = __(self.options.get("ado", "").strip())
child = __(self.options.get("child", "").strip())
disc = __(self.options.get("disc", "").strip())
film = __(self.options.get("film", "").strip())
show = __(self.options.get("show", "").strip())
pages = __(self.options.get("pages", "").strip())
year = __(self.options.get("year", "").strip())
source = __(self.options.get("source", "").strip())
index = __(self.options.get("index", "").strip())
date = __(self.options.get("date", "").strip())
title1 = __(self.options.get("title1", "").strip()) in (
"1",
1,
"True",
True,
"true",
)
indexes = []
if index:
indexes.append(index) # pragma: no cover
# add a label
lid = self.options.get("lid", self.options.get("label", None))
if lid:
tnl = ["", f".. _{lid}:", ""]
else:
tnl = [] # pragma: no cover
if title1:
if ado:
tnl.append(f"**{ado}**")
if child:
tnl.append(f"**{child}**")
if comic:
tnl.append(f"**{comic}**")
if disc:
tnl.append(f"**{disc}**")
if book:
tnl.append(f"**{book}**")
if manga:
tnl.append(f"**{manga}**")
if show:
tnl.append(f"**{show}**")
if film:
tnl.append(f"**{film}**")
if author:
tnl.append(f"*{author}*, ")
else:
if author:
tnl.append(f"**{author}**, ")
if ado:
tnl.append(f"*{ado}*")
if child:
tnl.append(f"*{child}*")
if comic:
tnl.append(f"*{comic}*")
if disc:
tnl.append(f"*{disc}*")
if book:
tnl.append(f"*{book}*")
if manga:
tnl.append(f"*{manga}*")
if show:
tnl.append(f"*{show}*")
if film:
tnl.append(f"*{film}*")
if author:
indexes.append(author)
indexes.append(TITLES[language_code]["author"] + "; " + author)
if ado:
indexes.append(ado)
indexes.append(TITLES[language_code]["ado"] + "; " + ado)
if child:
indexes.append(child)
indexes.append(TITLES[language_code]["child"] + "; " + child)
if comic:
indexes.append(comic)
indexes.append(TITLES[language_code]["comic"] + "; " + comic)
if disc:
indexes.append(disc)
indexes.append(TITLES[language_code]["disc"] + "; " + disc)
if book:
indexes.append(book)
indexes.append(TITLES[language_code]["book"] + "; " + book)
if manga:
indexes.append(manga)
indexes.append(TITLES[language_code]["manga"] + "; " + manga)
if show:
indexes.append(show)
indexes.append(TITLES[language_code]["show"] + "; " + show)
if film:
indexes.append(film)
indexes.append(TITLES[language_code]["film"] + "; " + film)
if pages:
tnl.append(f", {pages}")
if date:
tnl.append(f"({date})")
if year:
tnl.append(f"({year})")
if source:
if source.startswith("http"):
tnl.append(f", `source <{source}>`__")
else:
tnl.append(f", {source}")
tnl.append("")
tnl.append(".. index:: " + ", ".join(indexes))
tnl.append("")
content = StringList(tnl)
content = content + self.content
node = quote_node()
try:
nested_parse_with_titles(self.state, content, node)
except Exception as e: # pragma: no cover
from sphinx.util import logging
logger = logging.getLogger("blogpost")
logger.warning(
"[blogpost] unable to parse %r - %r - %r", author, book or manga, e
)
raise e
node["tag"] = tag
node["author"] = author
node["pages"] = pages
node["year"] = year
node["label"] = lid
node["source"] = source
node["book"] = book
node["manga"] = manga
node["disc"] = disc
node["comic"] = comic
node["ado"] = ado
node["child"] = child
node["film"] = film
node["show"] = show
node["index"] = index
node["content"] = "\n".join(self.content)
node["classes"] += ["quote"]
return [node]
def visit_quote_node(self, node):
"""
visit_quote_node
"""
self.visit_admonition(node)
def depart_quote_node(self, node):
"""
depart_quote_node,
see https://github.com/sphinx-doc/sphinx/blob/master/sphinx/writers/html.py
"""
self.depart_admonition(node)
def visit_quote_node_rst(self, node):
"""
visit_quote_node
"""
self.new_state(0)
self.add_text(".. quote::")
for k, v in sorted(node.attributes.items()):
if k in ("content", "classes"):
continue
if v:
self.new_state(4)
self.add_text(f":{k}: {v}")
self.end_state(wrap=False, end=None)
self.add_text(self.nl)
self.new_state(4)
self.add_text(node["content"])
self.end_state()
self.end_state()
raise nodes.SkipNode
def depart_quote_node_rst(self, node):
"""
depart_quote_node,
see https://github.com/sphinx-doc/sphinx/blob/master/sphinx/writers/html.py
"""
pass
def setup(app):
"""
setup for ``mathdef`` (sphinx)
"""
if hasattr(app, "add_mapping"):
app.add_mapping("quote", quote_node)
app.add_node(
quote_node,
html=(visit_quote_node, depart_quote_node),
epub=(visit_quote_node, depart_quote_node),
elatex=(visit_quote_node, depart_quote_node),
latex=(visit_quote_node, depart_quote_node),
text=(visit_quote_node, depart_quote_node),
md=(visit_quote_node, depart_quote_node),
rst=(visit_quote_node_rst, depart_quote_node_rst),
)
app.add_directive("quote", QuoteNode)
return {"version": sphinx.__display_version__, "parallel_read_safe": True}