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

Various QoL and code-quality changes #361

Merged
merged 22 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
87d619f
add 'product-table' directive
daringer Dec 14, 2024
eb04d65
product-table: enforce build cancel on bad args
daringer Dec 14, 2024
ea5f99c
nk_product_table.py: cleanups
daringer Dec 14, 2024
1603393
update all sources to use 'product-table' instead of includes
daringer Dec 14, 2024
538a1e5
faq_item: add 'faq' directive for better rendering and semantics
daringer Dec 14, 2024
e830ee3
faq-anchors: switch to directive based creation
daringer Dec 14, 2024
798c1c4
product-table: extension cleanups
daringer Dec 14, 2024
3ed0352
product-table: various improvements
daringer Dec 14, 2024
50fe32a
local build: enable js-scripts loading locally; disable rewrite depen…
daringer Dec 14, 2024
f94e87b
ci: accept new directives during rstcheck
daringer Dec 14, 2024
8970708
ci: use make check for rstcheck; ignore certain messages
daringer Dec 14, 2024
1a5b5ff
ci: initial preview deployment
daringer Dec 14, 2024
d7f89a3
ci: include hidden files in archive upload
daringer Dec 14, 2024
ed545c4
ci: use python:3.11 image; use new deploy script; replace common task…
daringer Dec 14, 2024
2eb3159
faq: migrate the last hiding FAQ entries
daringer Dec 14, 2024
0db271d
Makefile: minor improvements
daringer Dec 14, 2024
9c7006f
css: product-table headline font size reduction
daringer Dec 14, 2024
b946be1
ci: comment with successful preview deployment url
daringer Dec 14, 2024
6471356
Makefile: add 'clean' + 'cleaner'
daringer Dec 14, 2024
a850595
product-table: prepare (not activated) tooltips; changed header wordi…
daringer Dec 14, 2024
6e7d443
product-table: change order
daringer Dec 14, 2024
891a252
update README.md
daringer Dec 14, 2024
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
15 changes: 4 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,14 @@ jobs:

runs-on: ubuntu-latest
container:
image: sphinxdoc/sphinx
image: python:3.11
#options: --user 1001 (only if we don't need apt-get)

env:
MAIN_LANGS: en
OTHER_LANGS: de es fr ru nl it ja el bg da et fi lv lt pl pt ro sv sk sl cs hu zh_CN

steps:
- name: Install git
run: |
apt-get -y update
apt-get -y install git ssh curl

- name: Checkout
uses: actions/checkout@v4

Expand All @@ -32,10 +27,7 @@ jobs:

- name: Quick build docs
run: |
mkdir -p dist/en
mkdir -p build/en/doctrees
venv/bin/sphinx-build -j auto -b html -D language=en -d build/en/doctrees source dist/en
rm -rf dist/en/_sources
make
cp -r redirects/.htaccess dist

- name: Upload quick build artifact
Expand All @@ -44,6 +36,7 @@ jobs:
with:
name: generated documentation (en)
path: dist
include-hidden-files: true

- name: Trigger docs server to download artifact
uses: appleboy/[email protected]
Expand All @@ -52,7 +45,7 @@ jobs:
username: docs
port: ${{ secrets.DOCS_PORT }}
key: ${{ secrets.DEPLOY_AUTH_KEY }}
script: /var/www/docs/deploy/github-trigger.sh en ${{ steps.upload-quick.outputs.artifact-id }} ${{ secrets.DOWNLOAD_TOKEN }}
script: /var/www/docs/deploy/gh-trigger.sh en ${{ steps.upload-quick.outputs.artifact-id }} ${{ secrets.DOWNLOAD_TOKEN }}

- name: Checkout data repository
uses: actions/checkout@v4
Expand Down
39 changes: 32 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,45 @@ jobs:
- name: Create virtual environment
run: make venv
- name: Syntax check
run: |
. venv/bin/activate
rstcheck --recursive --ignore-directives "tabs" source/
run: make check

build-error-check:
name: Check build error
build-check-and-preview-upload:
name: Check Build and Upload to Preview
runs-on: ubuntu-latest
container: python:3.11
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Create virtual environment
run: make venv

- name: Build documentation
run: |
. venv/bin/activate
sphinx-build -W -j 1 -a -D language='en' -b html source dist/en
make
cp -r redirects/.htaccess dist

- name: Upload quick build artifact
id: upload-quick
uses: actions/upload-artifact@v4
with:
name: generated documentation (en)
path: dist
include-hidden-files: true

- name: Trigger docs server to download artifact
uses: appleboy/[email protected]
with:
host: ${{ secrets.DOCS_HOST }}
username: docs
port: ${{ secrets.DOCS_PORT }}
key: ${{ secrets.DEPLOY_AUTH_KEY }}
script: /var/www/docs/deploy/gh-trigger.sh preview+${{ github.event.number }} ${{ steps.upload-quick.outputs.artifact-id }} ${{ secrets.DOWNLOAD_TOKEN }}

- name: Confirm Deployment with PR Comment
uses: thollander/actions-comment-pull-request@v3
with:
message: |
The successful documentation build was deployed for preview:
* https://docspreview.nitrokey.com/PR-${{ github.event.number }}

27 changes: 23 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@



all: venv
.PHONY: docs
docs: venv
venv/bin/sphinx-build -j auto -b html -D language=en -d build/en/doctrees source dist/en

venv:
python -m venv venv
venv/bin/pip3 install -r requirements.txt

clean:
rm -rf dist build venv
.PHONY: check
check: venv
# ignore-messages is needed due to links being used in directives, which
# are not visible by rstcheck as these directives are ignored (mostly faq)
venv/bin/rstcheck --recursive --ignore-directives tabs,faq,product-table \
--ignore-messages "faq(.*)Hyperlink target(.*)is not referenced" \
source

pkg: venv docs
mv dist/en/_images dist/_images
rm -rf dist/*/_sources dist/*/_images
cp redirects/.htaccess dist


clean:
rm -rf dist build

cleaner: clean
rm -rf venv

.PHONY: docs check pkg
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ The (english) result is to be found in `dist/en`, to show run:
firefox dist/en/index.html
```

### More Makefile Targets

* `clean` will clean up generated files
* `cleaner` includes `venv/`
* `check` runs `rstcheck` for the sources
* `venv` creates a virtualenv with all deps
* `docs` first target, default, will quick-build the english docs
* `pkg` assembles a package for deployment in `dist` (unused)

### Localization

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ sphinxcontrib-serializinghtml==2.0.0
sphinxprettysearchresults==0.3.5
urllib3==2.2.3
setuptools==75.6.0
docutils==0.21.2
71 changes: 71 additions & 0 deletions source/_ext/faq_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import urllib.parse
import re

from docutils import nodes

from docutils.parsers.rst import directives
from sphinx.util.docutils import SphinxDirective
from sphinx.util.typing import ExtensionMetadata
from sphinx.application import Sphinx


class FAQItem(SphinxDirective):
"""
Directive for a FAQ item
"""

has_content = True
required_arguments = 1
optional_arguments = 30
final_argument_whitespace = True
option_spec = {
"class": directives.class_option,
}

def _make_slug(self, s: str) -> str:
"""Sluggify some string for inclusion into URL"""

s = s.lower().strip()
s = re.sub(r"[^\w\s-]", "", s)
s = re.sub(r"[\s_-]+", "-", s)
s = re.sub(r"^-+|-+$", "", s)
return urllib.parse.quote_plus(s)

def run(self) -> list[nodes.Node]:

# answer (block content)
content = nodes.container()
# ... parse
self.state.nested_parse(self.content, self.content_offset, content)
answer = nodes.definition("", *content.children)
# ... assemble
a_item = nodes.definition_list_item("", answer)

# question:
question = " ".join(self.arguments)
# ... get slug
slug = self._make_slug(question)
# ... get formatted text
prefix = nodes.strong(text="Q: ")
q_node = nodes.Text(question)
# ... link with anchor name (slug)
attrs = {"refuri": f"#{slug}", "ids": [slug]}
anchor_link = nodes.reference("", "", prefix, q_node, **attrs)
# ... assemble `term`
term = nodes.term("", "", anchor_link)
q_item = nodes.definition_list_item("", term)

# add both to output (def-list)
li = nodes.definition_list("", q_item, a_item)

return [li]


def setup(app: Sphinx) -> ExtensionMetadata:
app.add_directive("faq", FAQItem)

return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
142 changes: 142 additions & 0 deletions source/_ext/nk_product_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from collections import OrderedDict

from docutils import nodes
from docutils.parsers.rst import directives

from sphinx.util.docutils import SphinxDirective
from sphinx.util.typing import ExtensionMetadata
from sphinx.application import Sphinx


class NitrokeyProductTable(SphinxDirective):
"""
Directive for the Nitrokey Variants Header Table
"""

KEYS = OrderedDict(
**{
"nitrokey3": "3A/C/Mini",
"passkey": "Passkey",
"hsm": "HSM 2",
"pro": "Pro 2",
"fido2": "FIDO2",
"storage": "Storage 2",
"start": "Start",
"u2f": "U2F",
}
)

ALIASES = {"nk3": "nitrokey3", "nkpk": "passkey", "pk": "passkey"}

has_content = False
required_arguments = 1
optional_arguments = len(KEYS) - 1
final_argument_whitespace = True
option_spec = {
"class": directives.class_option,
}

def run(self) -> list[nodes.Node]:
table = nodes.table()

# set table class
if "class" in self.options:
table["classes"] += self.options["class"]
table["classes"] += ["products-table"]

tgroup = nodes.tgroup(cols=len(self.KEYS))
table += tgroup

# col specs
for _ in enumerate(self.KEYS):
colspec = nodes.colspec(colwidth=100)
tgroup += colspec

thead = nodes.thead()
row0 = nodes.row()
# title header
entry = nodes.entry(morecols=len(self.KEYS) - 1)
entry += nodes.paragraph(text="Compatible Nitrokeys")
entry["classes"] += ["products-table-head"]

row0 += entry
thead += row0

row1 = nodes.row()

# headers (product names / links)
for key, name in self.KEYS.items():
entry = nodes.entry()

# TODO: use relative !!
url = f"https://docs.nitrokey.com/nitrokeys/{key}"
# url = f"/nitrokeys/{key}"
entry += nodes.paragraph(
"",
"",
nodes.reference("", name, refuri=url),
)

row1 += entry

thead += row1
tgroup += thead

# get used_products from arguments
used_products = list(self.arguments)
# apply aliases
used_products = [self.ALIASES.get(x, x) for x in used_products]
# accepted keys (include "all")
ok_keys = list(self.KEYS.keys()) + ["all"]
# check if all keys exist
check = all(x in ok_keys for x in used_products)
if not check:
print()
print("ERROR in product-table (_ext/nk_product_table.py)")
print("ERROR found invalid product-table arguments")
print()
assert check

# checkmark row creation
row2 = nodes.row()
yes = "✓"
no = "⨯"
for key, name in self.KEYS.items():
if "all" in used_products:
val = yes
else:
val = yes if key in used_products else no
entry = nodes.entry()
icon = nodes.paragraph(text=val)
entry += icon
entry["classes"] += ["tooltip"]

if val == yes:
entry["classes"] += ["active"]
tooltip = nodes.paragraph(text="active")
tooltip["classes"] += ["tooltiptext"]
else:
entry["classes"] += ["inactive"]
tooltip = nodes.paragraph(text="inactive")
tooltip["classes"] += ["tooltiptext"]

# entry += tooltip
icon += tooltip

row2 += entry

tbody = nodes.tbody()
tbody += row2
tgroup += tbody

return [table]


def setup(app: Sphinx) -> ExtensionMetadata:
app.add_directive("product-table", NitrokeyProductTable)

return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
Loading
Loading