aboutsummaryrefslogtreecommitdiff
path: root/sphinx_ascii_theme
diff options
context:
space:
mode:
authorneodarz <neodarz@neodarz.net>2020-06-26 21:24:30 +0200
committerneodarz <neodarz@neodarz.net>2020-06-26 21:24:30 +0200
commit947190c41995f599353be1227d84a20e4b6ef48f (patch)
tree2a360daa19079dd01d3372a0c578a21c860964d5 /sphinx_ascii_theme
downloadwebsite_theme-947190c41995f599353be1227d84a20e4b6ef48f.tar.xz
website_theme-947190c41995f599353be1227d84a20e4b6ef48f.zip
Inital commit
Diffstat (limited to '')
-rw-r--r--sphinx_ascii_theme/__init__.py161
-rw-r--r--sphinx_ascii_theme/layout.html235
-rw-r--r--sphinx_ascii_theme/navigation.html18
-rw-r--r--sphinx_ascii_theme/postinfo.html91
-rw-r--r--sphinx_ascii_theme/search.html57
-rw-r--r--sphinx_ascii_theme/static/ascii.css468
-rw-r--r--sphinx_ascii_theme/theme.conf9
7 files changed, 1039 insertions, 0 deletions
diff --git a/sphinx_ascii_theme/__init__.py b/sphinx_ascii_theme/__init__.py
new file mode 100644
index 0000000..160932e
--- /dev/null
+++ b/sphinx_ascii_theme/__init__.py
@@ -0,0 +1,161 @@
+from os import path
+import docutils
+
+"""
+The code of the function add_toctree_functions and docutils_node_to_jinja are
+on the following license:
+
+BSD 3-Clause License
+
+Copyright (c) 2018, pandas
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+It's based on the following project:
+ https://github.com/pandas-dev/pydata-sphinx-theme
+"""
+
+def add_toctree_functions(app, pagename, templatename, context, doctree):
+ """Add functions so Jinja templates can add toctree objects.
+ This converts the docutils nodes into a nested dictionary that Jinja can
+ use in our templating.
+ """
+ from sphinx.environment.adapters.toctree import TocTree
+
+ def get_nav_object(maxdepth=None, collapse=True, **kwargs):
+ """Return a list of nav links that can be accessed from Jinja.
+ Parameters
+ ----------
+ maxdepth: int
+ How many layers of TocTree will be returned
+ collapse: bool
+ Whether to only include sub-pages of the currently-active page,
+ instead of sub-pages of all top-level pages of the site.
+ kwargs: key/val pairs
+ Passed to the `TocTree.get_toctree_for` Sphinx method
+ """
+ # The TocTree will contain the full site TocTree including sub-pages.
+ # "collapse=True" collapses sub-pages of non-active TOC pages.
+ # maxdepth controls how many TOC levels are returned
+ toctree = TocTree(app.env).get_toctree_for(
+ pagename, app.builder, collapse=collapse, maxdepth=maxdepth, **kwargs
+ )
+ # If no toctree is defined (AKA a single-page site), skip this
+ if toctree is None:
+ return []
+
+ # toctree has this structure
+ # <caption>
+ # <bullet_list>
+ # <list_item classes="toctree-l1">
+ # <list_item classes="toctree-l1">
+ # `list_item`s are the actual TOC links and are the only thing we want
+ toc_items = [
+ item
+ for child in toctree.children
+ for item in child
+ if isinstance(item, docutils.nodes.list_item)
+ ]
+
+ # Now convert our docutils nodes into dicts that Jinja can use
+ nav = [docutils_node_to_jinja(child, only_pages=True) for child in toc_items]
+
+ return nav
+
+ def get_page_toc_object():
+ """Return a list of within-page TOC links that can be accessed from Jinja."""
+ self_toc = TocTree(app.env).get_toc_for(pagename, app.builder)
+
+ try:
+ # If there's only one child, assume we have a single "title" as top header
+ # so start the TOC at the first item's children (AKA, level 2 headers)
+ if len(self_toc.children) == 1:
+ nav = docutils_node_to_jinja(self_toc.children[0]).get("children", [])
+ else:
+ nav = [docutils_node_to_jinja(item) for item in self_toc.children]
+ return nav
+ except Exception:
+ return {}
+
+ context["get_nav_object"] = get_nav_object
+ context["get_page_toc_object"] = get_page_toc_object
+
+
+def docutils_node_to_jinja(list_item, only_pages=False):
+ """Convert a docutils node to a structure that can be read by Jinja.
+ Parameters
+ ----------
+ list_item : docutils list_item node
+ A parent item, potentially with children, corresponding to the level
+ of a TocTree.
+ only_pages : bool
+ Only include items for full pages in the output dictionary. Exclude
+ anchor links (TOC items with a URL that starts with #)
+ Returns
+ -------
+ nav : dict
+ The TocTree, converted into a dictionary with key/values that work
+ within Jinja.
+ """
+ if not list_item.children:
+ return None
+
+ # We assume this structure of a list item:
+ # <list_item>
+ # <compact_paragraph >
+ # <reference> <-- the thing we want
+ reference = list_item.children[0].children[0]
+ title = reference.astext()
+ url = reference.attributes["refuri"]
+ active = "current" in list_item.attributes["classes"]
+
+ # If we've got an anchor link, skip it if we wish
+ if only_pages and "#" in url:
+ return None
+
+ # Converting the docutils attributes into jinja-friendly objects
+ nav = {}
+ nav["title"] = title
+ nav["url"] = url
+ nav["active"] = active
+
+ # Recursively convert children as well
+ # If there are sub-pages for this list_item, there should be two children:
+ # a paragraph, and a bullet_list.
+ nav["children"] = []
+ if len(list_item.children) > 1:
+ # The `.children` of the bullet_list has the nodes of the sub-pages.
+ subpage_list = list_item.children[1].children
+ for sub_page in subpage_list:
+ child_nav = docutils_node_to_jinja(sub_page, only_pages=only_pages)
+ if child_nav is not None:
+ nav["children"].append(child_nav)
+ return nav
+
+def setup(app):
+ app.connect("html-page-context", add_toctree_functions)
+ app.add_html_theme('ascii', path.abspath(path.dirname(__file__)))
diff --git a/sphinx_ascii_theme/layout.html b/sphinx_ascii_theme/layout.html
new file mode 100644
index 0000000..fecb7d0
--- /dev/null
+++ b/sphinx_ascii_theme/layout.html
@@ -0,0 +1,235 @@
+{#
+ basic/layout.html
+ ~~~~~~~~~~~~~~~~~
+
+ Master layout template for Sphinx themes.
+
+ :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- block doctype -%}{%- if html5_doctype %}
+<!DOCTYPE html>
+{%- else %}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{%- endif %}{%- endblock %}
+{%- set reldelim1 = reldelim1 is not defined and ' &#187;' or reldelim1 %}
+{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
+{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
+ (sidebars != []) %}
+{%- set url_root = pathto('', 1) %}
+{# XXX necessary? #}
+{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
+{%- if not embedded and docstitle %}
+ {%- set titlesuffix = " &#8212; "|safe + docstitle|e %}
+{%- else %}
+ {%- set titlesuffix = "" %}
+{%- endif %}
+
+{%- macro relbar() %}
+ <div class="related" role="navigation" aria-label="related navigation">
+ <h3>{{ _('Navigation') }}</h3>
+ <ul>
+ {%- for rellink in rellinks %}
+ <li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
+ <a href="{{ pathto(rellink[0])|e }}" title="{{ rellink[1]|striptags|e }}"
+ {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+ {%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
+ {%- endfor %}
+ {%- block rootrellink %}
+ <li class="nav-item nav-item-0"><a href="{{ pathto(master_doc)|e }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
+ {%- endblock %}
+ {%- for parent in parents %}
+ <li class="nav-item nav-item-{{ loop.index }}"><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
+ {%- endfor %}
+ <li class="nav-item nav-item-this"><a href="{{ link|e }}">{{ title }}</a></li>
+ {%- block relbaritems %} {% endblock %}
+ </ul>
+ </div>
+{%- endmacro %}
+
+{%- macro sidebar() %}
+ {%- if render_sidebar %}
+ <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+ <div class="sphinxsidebarwrapper">
+ {%- block sidebarlogo %}
+ <a class="title-header" href="{{ pathto('index') }}">
+ <div>
+ <pre>
+ ██
+ ░██
+ ███████ █████ ██████ ░██ ██████ ██████ ██████
+ ░░██░░░██ ██░░░██ ██░░░░██ ██████ ░░░░░░██ ░░██░░█░░░░██
+ ░██ ░██░███████░██ ░██ ██░░░██ ███████ ░██ ░ ██
+ ░██ ░██░██░░░░ ░██ ░██░██ ░██ ██░░░░██ ░██ ██
+ ███ ░██░░██████░░██████ ░░██████░░████████░███ ██████
+ ░░░ ░░ ░░░░░░ ░░░░░░ ░░░░░░ ░░░░░░░░ ░░░ ░░░░░░
+
+ </pre>
+ </div>
+ </a>
+ {%- if logo %}
+ <p class="logo"><a href="{{ pathto(master_doc)|e }}">
+ <img class="logo" src="{{ pathto('_static/' + logo, 1)|e }}" alt="Logo"/>
+ </a></p>
+ {%- endif %}
+ {%- endblock %}
+ {%- if sidebars != None %}
+ {#- new style sidebar: explicitly include/exclude templates #}
+ {%- for sidebartemplate in sidebars %}
+ {%- include sidebartemplate %}
+ {%- endfor %}
+ {%- else %}
+ {#- old style sidebars: using blocks -- should be deprecated #}
+ {%- block sidebartoc %}
+ {%- include "localtoc.html" %}
+ {%- endblock %}
+ {%- block sidebarrel %}
+ {%- include "relations.html" %}
+ {%- endblock %}
+ {%- block sidebarsourcelink %}
+ {%- include "sourcelink.html" %}
+ {%- endblock %}
+ {%- if customsidebar %}
+ {%- include customsidebar %}
+ {%- endif %}
+ {%- block sidebarsearch %}
+ {%- include "searchbox.html" %}
+ {%- endblock %}
+ {%- endif %}
+ {% include 'postinfo.html' %}
+ </div>
+ </div>
+ {%- endif %}
+{%- endmacro %}
+
+{%- macro script() %}
+ <script id="documentation_options" data-url_root="{{ pathto('', 1) }}" src="{{ pathto('_static/documentation_options.js', 1) }}"></script>
+ {%- for js in script_files %}
+ {{ js_tag(js) }}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro css() %}
+ <link rel="stylesheet" href="{{ pathto('_static/' + style, 1)|e }}" type="text/css" />
+ <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
+ {%- for css in css_files %}
+ {%- if css|attr("filename") %}
+ {{ css_tag(css) }}
+ {%- else %}
+ <link rel="stylesheet" href="{{ pathto(css, 1)|e }}" type="text/css" />
+ {%- endif %}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- if html_tag %}
+{{ html_tag }}
+{%- else %}
+<html{% if not html5_doctype %} xmlns="http://www.w3.org/1999/xhtml"{% endif %}{% if language is not none %} lang="{{ language }}"{% endif %}>
+{%- endif %}
+ <head>
+ {%- if not html5_doctype and not skip_ua_compatible %}
+ <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+ {%- endif %}
+ {%- if use_meta_charset or html5_doctype %}
+ <meta charset="{{ encoding }}" />
+ {%- else %}
+ <meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
+ {%- endif %}
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ {{- metatags }}
+ {%- block htmltitle %}
+ <title>{{ title|striptags|e }}{{ titlesuffix }}</title>
+ {%- endblock %}
+ {%- block css %}
+ {{- css() }}
+ {%- endblock %}
+ {%- if not embedded %}
+ {%- block scripts %}
+ {{- script() }}
+ {%- endblock %}
+ {%- if pageurl %}
+ <link rel="canonical" href="{{ pageurl|e }}" />
+ {%- endif %}
+ {%- if use_opensearch %}
+ <link rel="search" type="application/opensearchdescription+xml"
+ title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
+ href="{{ pathto('_static/opensearch.xml', 1) }}"/>
+ {%- endif %}
+ {%- if favicon %}
+ <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1)|e }}"/>
+ {%- endif %}
+ {%- endif %}
+{%- block linktags %}
+ {%- if hasdoc('about') %}
+ <link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
+ {%- endif %}
+ {%- if hasdoc('genindex') %}
+ <link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
+ {%- endif %}
+ {%- if hasdoc('search') %}
+ <link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
+ {%- endif %}
+ {%- if hasdoc('copyright') %}
+ <link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
+ {%- endif %}
+ {%- if next %}
+ <link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
+ {%- endif %}
+ {%- if prev %}
+ <link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
+ {%- endif %}
+{%- endblock %}
+{%- block extrahead %} {% endblock %}
+ </head>
+ {%- block body_tag %}<body>{% endblock %}
+{%- block header %}{% endblock %}
+
+{%- block relbar1 %}{{ relbar() }}{% endblock %}
+
+{%- block content %}
+ {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
+
+
+ <div class="document">
+ {%- block sidebar2 %}{{ sidebar() }}{% endblock %}
+ {%- block document %}
+ <div class="documentwrapper">
+ {%- if render_sidebar %}
+ <div class="bodywrapper">
+ {%- endif %}
+ <div class="body" role="main">
+ {% block body %} {% endblock %}
+ <div class="clearer"></div>
+ </div>
+ {%- if render_sidebar %}
+ </div>
+ {%- endif %}
+ </div>
+ {%- endblock %}
+
+ <div class="clearer"></div>
+ </div>
+{%- endblock %}
+
+{%- block relbar2 %}{{ relbar() }}{% endblock %}
+
+{%- block footer %}
+ <div class="footer" role="contentinfo">
+ <div>
+ <p>·.:</p>
+ {%- if show_copyright %}
+ {% trans copyright=copyright|e %}<a href="{{ theme_copyright_link }}">{{ copyright }}</a> ||{% endtrans %}
+ {%- endif %}
+ {%- if last_updated %}
+ {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
+ {%- endif %}
+ {%- if show_sphinx %}
+ {% trans sphinx_version=sphinx_version|e %}<a href="{{ theme_source_link }}">&#8249;Source code&#8250;</a>{% endtrans %}
+ {%- endif %}
+ <p>:.·</p>
+ </div>
+ </div>
+{%- endblock %}
+ </body>
+</html>
diff --git a/sphinx_ascii_theme/navigation.html b/sphinx_ascii_theme/navigation.html
new file mode 100644
index 0000000..efef6dc
--- /dev/null
+++ b/sphinx_ascii_theme/navigation.html
@@ -0,0 +1,18 @@
+<div class="navigation">
+ <div class="lang">
+ <a href="/en/{{pagename}}{{file_suffix}}">EN</a>
+ <a href="/fr/{{pagename}}{{file_suffix}}">FR</a>
+ </div>
+ <div class="nav">
+ {% for a in get_nav_object(collapse=true, maxdepth=1, includehidden=true) %}
+ {% if a.title == "Blog" %}
+ <hr/>
+ {% endif %}
+ <a href="{{a.url}}">
+ <span class="left"></span>
+ <span class="center">{{a.title}}</span>
+ <span class="right"></span>
+ </a>
+ {% endfor %}
+ </div>
+</div>
diff --git a/sphinx_ascii_theme/postinfo.html b/sphinx_ascii_theme/postinfo.html
new file mode 100644
index 0000000..8effd2a
--- /dev/null
+++ b/sphinx_ascii_theme/postinfo.html
@@ -0,0 +1,91 @@
+ {% if pagename in ablog %}
+ <div class="postcard">
+ {% set fa = ablog.fontawesome %}
+ {% set post = ablog[pagename] %}
+
+ <ul>
+ <li>
+ {% if post.published %}
+ {% if fa %}<i class="fa fa-calendar"></i>{% endif %}
+ {{gettext('Published on') }}: <br/> {{ post.date.strftime(ablog.post_date_format) }}
+ {% else %}
+ {% if fa %}<i class="fa fa-pencil"></i>{% endif %}
+ {% if post.date %}{{gettext('Draft from') }}: <br/> {{ post.date.strftime(ablog.post_date_format) }}
+ {% else %} {{ gettext('Draft') }} {% endif %}
+ {% endif %}
+ </li>
+
+ {% if post.published and post.date != post.update %}
+ <li id="published" ><span>{% if fa %}<i class="fa fa-pencil-square-o"></i>{% else %}{{ gettext('Update') }}:{% endif %}</span>
+ {{ post.update.strftime(ablog.post_date_format) }}</li>
+ {% endif %}
+
+ {% if post.author %}
+ <!-- usless since I'm the onlu author
+ <li id="author"><span>{% if fa %}<i class="fa-fw fa fa-user"></i>{% else %}{{ gettext('Author') }}:{% endif %}</span>
+ {% for coll in post.author %}
+ {% if coll|length %}
+ <a href="{{ pathto(coll.docname) }}">{{ coll }}</a>{% if loop.index < post.author|length %},{% endif %}
+ {% else %}{{ coll }}{% if loop.index < post.author|length %},{% endif %}{% endif %}
+ {% endfor %}</li>
+ -->
+ {% endif %}
+
+ {% if post.location %}
+ <li id="location"><span>{% if fa %}<i class="fa-fw fa fa-location-arrow"></i>{% else %}{{ gettext('Location') }}:{% endif %}</span>
+ {% for coll in post.location %}
+ {% if coll|length %}
+ <a href="{{ pathto(coll.docname) }}">{{ coll }}</a>{% if loop.index < post.location|length %},{% endif %}
+ {% else %}{{ coll }}{% if loop.index < post.location|length %},{% endif %}{% endif %}
+ {% endfor %}</li>
+ {% endif %}
+
+ {% if post.language %}
+ <li id="language"><span>{% if fa %}<i class="fa-fw fa fa-language"></i>{% else %}{{ gettext('Language') }}:{% endif %}</span>
+ {% for coll in post.language %}
+ {% if coll|length %}
+ <a href="{{ pathto(coll.docname) }}">{{ coll }}</a>{% if loop.index < post.language|length %},{% endif %}
+ {% else %}{{ coll }}{% if loop.index < post.language|length %},{% endif %}{% endif %}
+ {% endfor %}</li>
+ {% endif %}
+
+ {% if post.category %}
+ <li id="category"><span>{% if fa %}<i class="fa-fw fa fa-folder-open"></i>{% else %}{{ gettext('Category') }}:{% endif %}</span>
+ {% for coll in post.category %}
+ {% if coll|length %}
+ <a href="{{ pathto(coll.docname) }}">{{ coll }}</a>{% if loop.index < post.category|length %},{% endif %}
+ {% else %}{{ coll }}{% if loop.index < post.category|length %},{% endif %}{% endif %}
+ {% endfor %}</li>
+ {% endif %}
+
+ {% if post.tags %}
+ <li id="tags"><span>{% if post.tags|length > 1 %}{% if fa %}<i class="fa-fw fa fa-tags"></i>{% else %}{{ gettext('Tags') }}:{% endif %}
+ {% else %}{% if fa %}<i class="fa-fw fa fa-tag"></i>{% else %}{{ gettext('Tag') }}:{% endif %}{% endif %}</span>
+ {% for coll in post.tags %}
+ {% if coll|length %}
+ <a href="{{ pathto(coll.docname) }}">{{ coll }}</a>{% if loop.index < post.tags|length %}{% endif %}
+ {% else %}{{ coll }}{% if loop.index < post.tags|length %}{% endif %}{% endif %}
+ {% endfor %}</li>
+ {% endif %}
+ {% if ablog.disqus_shortname and (ablog[pagename].published or ablog.disqus_drafts) %}
+ <li id="comments">
+ <script type="text/javascript">
+ /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
+ var disqus_shortname = '{{ ablog.disqus_shortname }}'; // required: replace example with your forum shortname
+
+ /* * * DON'T EDIT BELOW THIS LINE * * */
+ (function () {
+ var s = document.createElement('script'); s.async = true;
+ s.type = 'text/javascript';
+ s.src = '//' + disqus_shortname + '.disqus.com/count.js';
+ (document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
+ }());
+ </script>
+ {% if fa %}<i class="fa-fw fa fa-comments"></i>{% endif %}
+ <a href="{% if pagename != post.docname%}{{ pathto(post.docname) }}{% endif %}#disqus_thread" data-disqus-identifier="/{{post.docname}}/"> {% if not fa %}Comments{% endif %}</a>
+ </li>
+ {% endif %}
+
+ </ul>
+</div>
+{% endif %}
diff --git a/sphinx_ascii_theme/search.html b/sphinx_ascii_theme/search.html
new file mode 100644
index 0000000..daca302
--- /dev/null
+++ b/sphinx_ascii_theme/search.html
@@ -0,0 +1,57 @@
+{#
+ basic/search.html
+ ~~~~~~~~~~~~~~~~~
+
+ Template for the search page.
+
+ :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{% set title = _('Search') %}
+{%- block scripts %}
+ {{ super() }}
+ <script src="{{ pathto('_static/searchtools.js', 1) }}"></script>
+{%- endblock %}
+{% block extrahead %}
+ <script src="{{ pathto('searchindex.js', 1) }}" defer></script>
+ {{ super() }}
+{% endblock %}
+{% block body %}
+ <h1 id="search-documentation">{{ _('Search') }}</h1>
+ <div id="fallback" class="admonition warning">
+ <script>$('#fallback').hide();</script>
+ <p>
+ {% trans %}Please activate JavaScript to enable the search
+ functionality.{% endtrans %}
+ </p>
+ </div>
+ <p>
+ {% trans %}Searching for multiple words only shows matches that contain
+ all words.{% endtrans %}
+ </p>
+ <div class="searchbox">
+ <form action="" method="get" class="search">
+ <input type="text" name="q" aria-labelledby="search-documentation" value="" />
+ <input type="submit" value="{{ _('search') }}" />
+ <span id="search-progress" style="padding-left: 10px"></span>
+ </form>
+ </div>
+ {% if search_performed %}
+ <h2>{{ _('Search Results') }}</h2>
+ {% if not search_results %}
+ <p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
+ {% endif %}
+ {% endif %}
+ <div id="search-results">
+ {% if search_results %}
+ <ul>
+ {% for href, caption, context in search_results %}
+ <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
+ <div class="context">{{ context|e }}</div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+{% endblock %}
diff --git a/sphinx_ascii_theme/static/ascii.css b/sphinx_ascii_theme/static/ascii.css
new file mode 100644
index 0000000..39f3ae7
--- /dev/null
+++ b/sphinx_ascii_theme/static/ascii.css
@@ -0,0 +1,468 @@
+@import url("basic.css");
+
+body {
+ background-color: black;
+ color: white;
+ font-family: Monospace, Georgia, serif;
+}
+
+div.document {
+ width: 940px;
+ margin: 30px auto 0 auto;
+}
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 220px;
+}
+
+div.body {
+ min-width: 0;
+ padding: 0 10px;
+ max-width: 800px;
+ border: 1px solid white;
+ margin-left: 20px;
+ padding: 0 10px 0 10px;
+}
+
+/* shitty css for shitty html */
+div.body .section:nth-child(2) .section span:nth-child(3) {
+ float: left !important;
+}
+
+div.sphinxsidebar {
+ width: 220px;
+ font-size: 14px;
+ line-height: 1.5;
+}
+
+div.footer {
+ width: 940px;
+ margin: 20px auto 30px auto;
+ font-size: 14px;
+ color: #888;
+ text-align: right;
+}
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+ -moz-hyphens: auto;
+ -ms-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+div.body .literal {
+ background: white;
+ color: black;
+ padding: 2px 2px;
+}
+
+a.reference:hover {
+ border-bottom: 1px solid #920097;
+}
+
+a.reference {
+ text-decoration: none;
+ border-bottom: 1px dotted white;
+}
+
+a:hover {
+ color: #920097;
+}
+
+a {
+ color: white;
+ text-decoration: underline;
+}
+
+div.highlight {
+ background: #000;
+ border: 1px solid white;
+ overflow: auto;
+ padding: 2px 10px;
+ margin: 0 -11px 0 -11px;
+}
+
+/* home page */
+
+div#neodarz h1 {
+ display: none;
+}
+
+/* titles */
+
+div.body h1 {
+ text-align: center;
+}
+
+div.body h2 {
+ text-align: center;
+ width: 100%;
+ margin: 0 16px 0 -11px;
+
+ display: flex;
+ justify-content: space-between;
+}
+
+div.body h2 a.headerlink {
+ display: contents;
+}
+
+div.body h2::before {
+ content: "█▓▒░";
+ float: left;
+}
+
+div.body h2::after {
+ content: "░▒▓█";
+ float: right;
+ margin-right: -16px;
+}
+
+div.body h3 {
+ text-align: center;
+ width: 100%;
+ margin: 15px 16px 0 -11px;
+}
+
+div.body h3::before {
+ content: ".:";
+ padding-right: 11px;
+}
+
+div.body h3::after {
+ content: ":.";
+ margin-right: -16px;
+}
+
+/* CV */
+
+div#competences .highlight {
+ text-align: center;
+ padding: 20px 0;
+}
+
+div#formations .highlight, div#experiences .highlight {
+ padding: 20px 15%;
+}
+
+div#formations .highlight pre, div#experiences .highlight pre {
+ width: 100%;
+ padding: 0 15% 0 0;
+}
+
+
+@media screen and (max-width: 600px) {
+
+ div#formations .highlight, div#experiences .highlight {
+ padding: 20px 0;
+ }
+}
+
+/* other */
+
+img {
+ width: 100%;
+}
+
+.related {
+ display:none;
+}
+
+hr {
+ height: 1px;
+ border: 0;
+ background-color: white;
+ margin: 0;
+ padding: 0;
+}
+
+ul {
+ padding-left: 16px;
+}
+
+li {
+ list-style: none;
+}
+
+ul li::before {
+ content: "\25b6 \00a0";
+ float: left;
+}
+
+li p {
+ margin: 0;
+}
+
+div[class^="highlight-"] {
+ margin: 0 0 -1px 0;
+}
+
+/* post */
+
+div#posts ul li::before, div#blog ul li::before {
+ display: none;
+}
+
+/* sidebar */
+
+a.title-header {
+ max-width: 223px;
+ margin: auto;
+ text-decoration: none;
+ cursor: pointer;
+ display: flex;
+}
+
+a.title-header pre {
+ font-size: 0.45em;
+ line-height: 0.9em;
+ letter-spacing: -0.15em;
+}
+
+.logo {
+ display: none;
+}
+
+/* navbar */
+
+div.sphinxsidebarwrapper {
+ padding: 0;
+}
+
+
+/* search */
+
+
+form.search {
+ text-align: center;
+}
+
+form.search input {
+ border: 1px solid white;
+ background: black;
+ color: white;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+form.search input[type="submit"] {
+ border-left: none;
+}
+
+form.search input[type="submit"] {
+ cursor: pointer;
+}
+
+form.search input[type="submit"]:hover {
+ color: black;
+ background: white;
+}
+
+dt:target, span.highlighted {
+ background-color: #6f6f6f;
+ color: #fff4f4;
+}
+/* sidebar search */
+
+div.sphinxsidebar form.search input {
+ margin: 0;
+}
+
+/* search page */
+
+.searchbox {
+ margin-bottom: 30px;
+}
+
+form.search input {
+ margin-left: -10px;
+}
+
+ul.search li {
+ background-image: none;
+}
+
+/* navigation */
+
+div.navigation .nav {
+ border: 1px solid white;
+ padding-bottom: 1px;
+}
+
+div.navigation a {
+ display: block;
+}
+
+div.navigation a .left::after {
+ content: "█▓▒░";
+ float: left;
+}
+
+div.navigation a .right::after {
+ content: "░▒▓█";
+ float: right;
+}
+
+div.navigation a:hover .left::after, div.navigation a:hover .right::after {
+ color: black;
+}
+
+div.navigation a {
+ text-align: center;
+ line-height: 1;
+ text-decoration: none;
+}
+
+div.navigation a:hover {
+ background: white;
+ color: black;
+}
+
+div.navigation .center {
+ padding: 0;
+}
+
+div.navigation .lang {
+ display: flex;
+ border: 1px solid white;
+ justify-content: space-around;
+ margin-bottom: 13px;
+ padding-bottom: 1px;
+}
+
+
+div.navigation .lang a {
+ width: 100%;
+}
+
+div.navigation .lang a::before {
+ content: "█▓▒░";
+ float: left;
+}
+
+div.navigation .lang a::after {
+ content: "░▒▓█";
+ float: right;
+}
+
+div.postcard ul li::before {
+ content: none;
+}
+
+/* admonition */
+
+div.admonition {
+ border: 1px solid #fff;
+ margin: 0 -11px -1px -11px;
+}
+
+div.admonition.warning {
+ background: #ff7c0533;
+}
+
+/* footer */
+
+div.footer {
+ text-align: center;
+ margin: 0 auto;
+ color: white;
+}
+
+div.footer div {
+ margin: 0 0 0 220px;
+}
+
+div.footer p {
+ display: inline;
+ margin: 0;
+}
+
+div.footer a {
+ text-decoration: none;
+ border-bottom: 1px dotted white;
+}
+
+div.footer a:hover {
+ border-bottom: 1px solid #920097;
+}
+
+/* author post list */
+
+ul.ablog-archive li::before{
+ content: none;
+}
+
+
+ul.ablog-archive li:nth-child(1)::after {
+ content: " -";
+}
+
+/* catalog */
+
+div.collection #author {
+ display: none;
+}
+
+@media screen and (max-width: 979px) {
+
+ div.document {
+ width: 100%;
+
+ }
+
+ div.body {
+ max-width: 100%;
+ margin: 0;
+ }
+
+ div.documentwrapper {
+ margin-left: 0;
+ margin-top: 0;
+ margin-right: 0;
+ margin-bottom: 0;
+ }
+
+ div.bodywrapper {
+ margin-top: 0;
+ margin-right: 0;
+ margin-bottom: 0;
+ margin-left: 0;
+ }
+
+ div.documentwrapper {
+ float: none;
+ #background: #fff;
+ }
+
+ div.sphinxsidebar {
+ display: block;
+ float: none;
+ width: 100%;
+ margin: -20px -30px 20px -20px;
+ padding: 10px 20px;
+ #background: #333;
+ #color: #FFF;
+ }
+
+ div.footer {
+ margin: 0;
+ width: 100%
+ }
+
+ div.footer div {
+ margin: 0;
+ }
+}
+
+@media screen and (min-width: 980px) {
+ div.sphinxsidebar {
+ position: fixed;
+ margin-left: 0;
+ }
+}
+
diff --git a/sphinx_ascii_theme/theme.conf b/sphinx_ascii_theme/theme.conf
new file mode 100644
index 0000000..e60f75b
--- /dev/null
+++ b/sphinx_ascii_theme/theme.conf
@@ -0,0 +1,9 @@
+[theme]
+inherit = basic
+stylesheet = ascii.css
+pygments_style = aparaiso-dark
+sidebars = relations.html, searchbox.html
+
+[options]
+copyright_link =
+source_link =