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

add semantically meaningful outputs to the project #44

Merged
merged 15 commits into from
Mar 26, 2024
30 changes: 21 additions & 9 deletions nbconvert_a11y/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""

import builtins
from copy import copy, deepcopy
import json
from contextlib import suppress
from datetime import datetime
Expand Down Expand Up @@ -73,7 +74,7 @@ class Table:
}


class PostProcess(Exporter):
class PostProcess(HTMLExporter):
"""an exporter that allows post processing after the templating step

this class introduces the `post_process_html` protocol that can be used to modify
Expand All @@ -88,7 +89,7 @@ def from_notebook_node(self, nb, resources=None, **kw):
def post_process_html(self, body): ...


class A11yExporter(PostProcess, HTMLExporter):
class A11yExporter(PostProcess):
"""an accessible reference implementation for computational notebooks implemented for ipynb files.

this template provides a flexible screen reader experience with settings to control and customize the reading experience.
Expand All @@ -99,7 +100,7 @@ class A11yExporter(PostProcess, HTMLExporter):
config=True
)
axe_url = CUnicode(AXE, help="the remote source for the axe resources.").tag(config=True)
include_sa11y = Bool(False, help="include sa11y accessibility authoring tool").tag(config=True)
include_sa11y = Bool(True, help="include sa11y accessibility authoring tool").tag(config=True)
include_settings = Bool(False, help="include configurable accessibility settings dialog.").tag(
config=True
)
Expand All @@ -126,7 +127,7 @@ class A11yExporter(PostProcess, HTMLExporter):
include_upload = Bool(False, help="include template for uploading new content").tag(config=True)
allow_run_mode = Bool(False, help="enable buttons for a run mode").tag(config=True)
hide_anchor_links = Bool(False).tag(config=True)
exclude_anchor_links = Bool(False).tag(config=True)
hidden_anchor_links = Bool(False).tag(config=True)
code_theme = Enum(list(THEMES), "gh-high", help="an accessible pygments dark/light theme").tag(
config=True
)
Expand All @@ -140,6 +141,7 @@ class A11yExporter(PostProcess, HTMLExporter):
prompt_out = CUnicode("Out").tag(config=True)
prompt_left = CUnicode("[").tag(config=True)
prompt_right = CUnicode("]").tag(config=True)
validate_nb = Bool(False).tag(config=True)

def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -177,9 +179,7 @@ def default_config(self):
return c

def init_resources(self, resources=None):
if resources is None:
resources = {}
resources = resources or {}
resources = self._init_resources(resources)
resources["include_axe"] = self.include_axe
resources["include_settings"] = self.include_settings
resources["include_help"] = self.include_help
Expand All @@ -196,7 +196,7 @@ def init_resources(self, resources=None):
resources["prompt_out"] = self.prompt_out
resources["prompt_left"] = self.prompt_left
resources["prompt_right"] = self.prompt_right
resources["exclude_anchor_links"] = self.exclude_anchor_links
resources["hidden_anchor_links"] = self.hidden_anchor_links
resources["hide_anchor_links"] = self.hide_anchor_links
resources["table_pattern"] = getattr(Roles, self.table_pattern)
resources["allow_run_mode"] = self.allow_run_mode
Expand All @@ -218,6 +218,18 @@ def post_process_html(self, body):
details.append(toc(soup))
return soup.prettify(formatter="html5")

def _preprocess(self, nb, resources):
nbc = deepcopy(nb)
resc = deepcopy(resources)

for preprocessor in self._preprocessors:
nbc, resc = preprocessor(nbc, resc)

if self.validate_nb:
self._validate_preprocessor(nbc, preprocessor)

return nbc, resc


class SectionExporter(A11yExporter):
template_file = Unicode("a11y/section.html.j2").tag(config=True)
Expand Down Expand Up @@ -303,7 +315,7 @@ def toc(html):
level = int(header.name[-1])
if last_level > level:
for l in range(level, last_level):
last_level -= 1
last_level -= 1
ol = ol.parent.parent
elif last_level < level:
for l in range(last_level, level):
Expand Down
164 changes: 164 additions & 0 deletions nbconvert_a11y/outputs.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/* css to accompany the semantic outputs.py

these styles make the semantic html appear like python styled reprs.
prettifying python combines content and style, but with html
we can seperate these concerns. */

:root {
--quote: '"';
}

data[value],
[itemscope]:not([itemtype$=DataFrame]),
[itemscope]:not([itemtype$=Series]) {
font-family: monospace;
}

.jp-RenderedHTMLCommon kbd {
font-size: unset;
}

samp[itemscope]::before,
samp[itemscope]::after {
content: var(--quote);
}

.jp-RenderedHTMLCommon [itemscope] {
color: var(--jp-mirror-editor-number-color);
}

.jp-RenderedHTMLCommon data[value] {
color: var(--jp-mirror-editor-keyword-color);
font-weight: bold;
}

.jp-RenderedHTMLCommon samp[itemscope] {
color: var(--jp-mirror-editor-string-color);
}

ol[itemscope],
ul[itemscope] {
li {
display: inline;

&::after {
content: ", ";
}

&:first-child::before {
content: '[';
color: var(--jp-mirror-editor-bracket-color);
}

&:last-child::after {
content: ']';
color: var(--jp-mirror-editor-bracket-color);
}
}
}

ol[itemtype$=tuple] li {
&:first-child::before {
content: '(';
}

&:last-child::after {
content: ')';
}
}

ul[itemtype$=set] li {
&:first-child::before {
content: '{';
}

&:last-child::after {
content: '}';
}
}

.jp-OutputArea-output table caption,
table caption {

dl,
dd,
dt {
padding-left: .5em;
padding-right: .5em;
}

}


.jp-OutputArea-output dd,
.jp-OutputArea-output dt {
float: unset;
display: unset;
}

dl[itemscope] dd,
dl[itemscope] dt {
display: inline;
}

dl[itemtype] {

dt:first-child::before {
content: "{";
color: var(--jp-mirror-editor-bracket-color);
}

dd:last-child::after {
content: "}";
color: var(--jp-mirror-editor-bracket-color);

}

dt::after {
content: ": ";
}

dd::after {
content: ", ";
}
}

.visually-hidden:not(:active):not(:focus-within),
.non-visual,
.nv {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}

table[itemtype$=ndarray] {
text-align: right;

td:first-child::before {
content: "[";
float: left;
}

td::after {
content: ",";
}

td:last-child::after {
content: "]";
}
}

:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon td,
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon th,
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon tr {
vertical-align: unset;
text-align: unset;
}

.jp-RenderedHTMLCommon tr {
padding: unset;
}
Loading
Loading