Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ uv export --format requirements-txt > requirements.txt
```bash
pip install -r requirements.txt
```
## Lucide icons

Use `|icon download|` in RST (see `conf.py`). Icon names can be found in `lucide_icons.py`,
generated from `_themes/theme/static/js/lucide.min.js`:

```bash
python scripts/generate_lucide_icons.py
```

Run again after replacing `lucide.min.js`.

## Build
English `en` is the default language.
Expand Down
16 changes: 8 additions & 8 deletions _themes/theme/breadcrumbs.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,23 @@
{% if display_github %}
{% if check_meta and 'github_url' in meta %}
<!-- User defined GitHub URL -->
<a href="{{ meta['github_url'] }}" class="fa fa-github"> {{ _('Edit on GitHub') }}</a>
<a href="{{ meta['github_url'] }}"><i data-lucide="github" aria-hidden="true"></i> {{ _('Edit on GitHub') }}</a>
{% else %}
<a href="https://{{ github_host|default("github.com") }}/{{ github_user }}/{{ github_repo }}/{{ theme_vcs_pageview_mode|default("blob") }}/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-github"> {{ _('Edit on GitHub') }}</a>
<a href="https://{{ github_host|default("github.com") }}/{{ github_user }}/{{ github_repo }}/{{ theme_vcs_pageview_mode|default("blob") }}/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}"><i data-lucide="github" aria-hidden="true"></i> {{ _('Edit on GitHub') }}</a>
{% endif %}
{% elif display_bitbucket %}
{% if check_meta and 'bitbucket_url' in meta %}
<!-- User defined Bitbucket URL -->
<a href="{{ meta['bitbucket_url'] }}" class="fa fa-bitbucket"> {{ _('Edit on Bitbucket') }}</a>
<a href="{{ meta['bitbucket_url'] }}"><i data-lucide="folder-git" aria-hidden="true"></i> {{ _('Edit on Bitbucket') }}</a>
{% else %}
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ suffix }}?mode={{ theme_vcs_pageview_mode|default("view") }}" class="fa fa-bitbucket"> {{ _('Edit on Bitbucket') }}</a>
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ suffix }}?mode={{ theme_vcs_pageview_mode|default("view") }}"><i data-lucide="folder-git" aria-hidden="true"></i> {{ _('Edit on Bitbucket') }}</a>
{% endif %}
{% elif display_gitlab %}
{% if check_meta and 'gitlab_url' in meta %}
<!-- User defined GitLab URL -->
<a href="{{ meta['gitlab_url'] }}" class="fa fa-gitlab"> {{ _('Edit on GitLab') }}</a>
<a href="{{ meta['gitlab_url'] }}"><i data-lucide="gitlab" aria-hidden="true"></i> {{ _('Edit on GitLab') }}</a>
{% else %}
<a href="https://{{ gitlab_host|default("gitlab.com") }}/{{ gitlab_user }}/{{ gitlab_repo }}/{{ theme_vcs_pageview_mode|default("blob") }}/{{ gitlab_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-gitlab"> {{ _('Edit on GitLab') }}</a>
<a href="https://{{ gitlab_host|default("gitlab.com") }}/{{ gitlab_user }}/{{ gitlab_repo }}/{{ theme_vcs_pageview_mode|default("blob") }}/{{ gitlab_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}"><i data-lucide="gitlab" aria-hidden="true"></i> {{ _('Edit on GitLab') }}</a>
{% endif %}
{% elif show_source and source_url_prefix %}
<a href="{{ source_url_prefix }}{{ pagename }}{{ suffix }}">
Expand All @@ -82,10 +82,10 @@
{% if (theme_prev_next_buttons_location == 'top' or theme_prev_next_buttons_location == 'both') and (next or prev) %}
<div class="rst-breadcrumbs-buttons" role="navigation" aria-label="breadcrumb navigation">
{% if next %}
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n"> <!-- Next --> <span class="fa fa-arrow-circle-right"></span></a>
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n"><i data-lucide="circle-chevron-right" aria-hidden="true"></i></a>
{% endif %}
{% if prev %}
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p"><span class="fa fa-arrow-circle-left"></span> <!-- Previous --></a>
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p"><i data-lucide="circle-chevron-left" aria-hidden="true"></i></a>
{% endif %}
</div>
{% endif %}
Expand Down
4 changes: 2 additions & 2 deletions _themes/theme/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
{% if (theme_prev_next_buttons_location == 'bottom' or theme_prev_next_buttons_location == 'both') and (next or prev) %}
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
{% if next %}
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n" rel="next"> <!-- {{ _('Next') }} --> <span class="fa fa-arrow-circle-right"></span></a>
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n" rel="next"><i data-lucide="circle-chevron-right" aria-hidden="true"></i></a>
{% endif %}
{% if prev %}
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> <!-- {{ _('Previous') }} --> </a>
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p" rel="prev"><i data-lucide="circle-chevron-left" aria-hidden="true"></i></a>
{% endif %}
</div>
{% endif %}
Expand Down
14 changes: 13 additions & 1 deletion _themes/theme/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@

{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
<script src="{{ pathto('_static/js/modernizr.min.js', 1) }}"></script>
{# Lucide icons #}
<script src="{{ pathto('_static/js/lucide.min.js', 1) }}"></script>

</head>

Expand Down Expand Up @@ -151,8 +153,10 @@
{# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
<nav class="wy-nav-top" aria-label="top navigation">
{% block mobile_nav %}
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="{{ pathto(master_doc) }}">{{ project }}</a>
<span class="wy-nav-top-menu" data-toggle="wy-nav-top" role="button" tabindex="0" aria-label="{{ _('Menu') }}">
<i data-lucide="menu" aria-hidden="true"></i>
</span>
{% endblock %}
</nav>

Expand Down Expand Up @@ -221,6 +225,14 @@
});
</script>

{# Lucide Icons #}

<script>
document.addEventListener("DOMContentLoaded", function() {
lucide.createIcons();
});
</script>

{%- block footer %} {% endblock %}

</body>
Expand Down
45 changes: 33 additions & 12 deletions _themes/theme/static/css/cp-overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,39 @@
margin-bottom: 2rem;
}

.rst-content svg[class*="lucide-"] {
width: 1em;
height: 1em;
vertical-align: -0.15em;
}

.rst-footer-buttons svg.lucide,
.rst-breadcrumbs-buttons svg.lucide {
width: 1.25em;
height: 1.25em;
vertical-align: middle;
}
@media screen and (max-width: 800px) {
.wy-nav-top::before,
.wy-nav-top::after {
display: none;
content: none;
}

.wy-nav-top-menu {
position: absolute;
left: 1em;
top: 50%;
transform: translateY(-50%);
line-height: 0;
}

.wy-nav-top-menu svg.lucide {
width: 1.875rem;
height: 1.875rem;
}
}

h1, h2, h3 {
font-family: "IBM Plex Mono";
}
Expand Down Expand Up @@ -75,18 +108,6 @@ ul.simple li p {
padding: 0px 5px;
}

.badge-owner::before, .badge-user::before {
font-family: "FontAwesome";
}

.badge-user::before {
content: " ";
}

.badge-owner::before {
content: " ";
}

h3 {
margin: 40px 0px 15px 0px;
}
Expand Down
12 changes: 12 additions & 0 deletions _themes/theme/static/js/lucide.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions _themes/theme/versions.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
{# Add rst-badge after rst-versions for small badge style. #}
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span class="fa fa-book"> Read the Docs</span>
<span><i data-lucide="book" aria-hidden="true"></i> Read the Docs</span>
v: {{ current_version }}
<span class="fa fa-caret-down"></span>
<i data-lucide="chevron-down" aria-hidden="true"></i>
</span>
<div class="rst-other-versions">
<dl>
Expand Down
115 changes: 68 additions & 47 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
import os
import sys
sys.path.insert(0, os.path.abspath('.'))

import os
from sphinx import addnodes
from docutils.nodes import strong, emphasis, reference, Text
from docutils.parsers.rst.roles import set_classes
from docutils.nodes import strong, reference, Text, raw
from docutils.parsers.rst import Directive
import docutils.parsers.rst.directives as directives

Expand All @@ -35,13 +34,10 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
import sphinx_fontawesome

extensions = [
'recommonmark',
#'sphinx_markdown_tables'
# XXX causes an error at build, removing with possible issues with tables?
'sphinx_fontawesome',
'sphinx_sitemap'
]

Expand Down Expand Up @@ -81,16 +77,6 @@
# -- Substitutions
# ----------------------------------------------

# rst_prolog is used by the Fontawesome package
# to use it: rst_prolog = sphinx_fontawesome.prolog + "my prolog"

rst_epilog = """

.. role:: badge_user
.. role:: badge_owner
.. role:: badge_new

"""


# -- Options for HTML output -------------------------------------------------
Expand Down Expand Up @@ -138,43 +124,78 @@
gettext_compact = False
figure_language_filename = "{path}{language}/{basename}{ext}"

# Add support for cptools

def cptools_global(key=''):
def cptools(role, rawtext, text, lineno, inliner, options={}, content=[]):
options.update({'classes': []})
options['classes'].append('cptools')
if key:
options['classes'].append('cptools-%s' % key)
else:
for x in text.split(","):
options['classes'].append('cptools-%s' % x)
set_classes(options)
node = emphasis(**options)
return [node], []
return cptools

#add directive
class Cptools(Directive):
prolog = ''

# New 'raw' role for Lucide
prolog += '''.. role:: raw-html(raw)
:format: html\n'''

def make_badge_role(css_class, icon_name):
def role(name, rawtext, text, lineno, inliner, options=None, content=None):
html = f'<span class="{css_class}" data-icon="{icon_name}"><i data-lucide="{icon_name}"></i> {text}</span>'
return [raw(format="html", text=html)], []
return role

badge_user_role = make_badge_role("badge-user", "user")
badge_owner_role = make_badge_role("badge-owner", "crown")
badge_new_role = make_badge_role("badge-new", "sparkles")

# Lucide icon directive
class Lucide(Directive):

has_content = True

def run(self):
options= {'classes' : []}
options['classes'].append('cptools')
for x in self.content[0].split(' '):
options['classes'].append('cptools-%s' % x)
set_classes(options)
node = emphasis(**options)
icon_name = self.content[0]
node = raw(format="html", text=f"<i data-lucide='{icon_name}'></i>")
return [node]

cptools_icons = ['destroy', 'add-bottom', 'add-top', 'folder-upload', 'folder-no-color', 'slide', 'shared-folder', 'poll', 'file-upload', 'whiteboard', 'todo', 'pad', 'folder-open', 'kanban', 'folder', 'shared-folder-open', 'code', 'template', 'new-template', 'palette', 'form-poll', 'form-poll-maybe', 'form-list-check', 'form-grid-check', 'form-grid-radio', 'form-list-radio', 'form-page-break', 'form-paragraph', 'form-text', 'form-list-ordered', 'form-conditional', 'richtext']
# Import lucide icons file
from conf_icons import lucide_icons
from icon_mappings import shortcut_icon_map, cptools_icon_map

lucide_icon_set = set(lucide_icons)


prolog = '\n'.join(['.. |cptools %s| cptools:: %s' % (icon, icon) for icon in cptools_icons])
def mapped_icon(name, icon_map):
icon = icon_map.get(name, name)
return icon if icon in lucide_icon_set else None


def resolve_shortcut_icon(shortcut):
if shortcut.startswith('cptools '):
name = shortcut.split(' ', 1)[1].strip().lower()
icon = mapped_icon(name, cptools_icon_map)
return '.. |cptools %s| lucide:: %s' % (name, icon) if icon else None

name = shortcut.strip().lower().replace(' ', '-')
icon = mapped_icon(name, shortcut_icon_map)
return '.. |%s| lucide:: %s' % (shortcut, icon) if icon else None


lucide_substitutions = []

for icon in lucide_icons:
lucide_substitutions.append('.. |icon %s| lucide:: %s' % (icon, icon))

for shortcut in shortcut_icon_map:
substitution = resolve_shortcut_icon(shortcut)
if substitution:
lucide_substitutions.append(substitution)

for name in cptools_icon_map:
substitution = resolve_shortcut_icon('cptools ' + name)
if substitution:
lucide_substitutions.append(substitution)

prolog += '\n'.join(lucide_substitutions)
prolog += '\n'


def setup(app):
app.add_role('cptools', cptools_global())
app.add_directive('cptools', Cptools)
app.config.rst_prolog += prolog
app.add_directive('lucide', Lucide)
app.add_role('badge_user', badge_user_role)
app.add_role('badge_owner', badge_owner_role)
app.add_role('badge_new', badge_new_role)
app.config.rst_prolog = (app.config.rst_prolog or '') + prolog
return {'version': '0.0.1'}
Loading