Skip to content
This repository has been archived by the owner. It is now read-only.

KaTeX A11y Mode #41

Merged
merged 11 commits into from Jun 24, 2015
Merged

KaTeX A11y Mode #41

merged 11 commits into from Jun 24, 2015

Conversation

@jeresig
Copy link
Member

jeresig commented Jun 17, 2015

This adds a new mode to the TeX.jsx module in which a new English-string form of the Math formula will be generated.

For example, if given the math string "4 + x" it'll generate something that looks like:

<span>
    <span class="mathjax" aria-hidden="true">...</span>
    <span class="katex" aria-hidden="true">...</span>
    <span class="katexA11y sr-only">4, plus, x</span>
</span>

Thus when someone accesses the above with a screen reader it'll read off "4, plus, x" and ignore the mathjax and katex spans. Likewise for a user that isn't using a screen reader they'll see the katex/mathjax render as normal. Note that the above only happens if the new katex-a11y module can successfully translate the math string into an English string. If it cannot then it abandons the attempt and just leaves the katex/mathjax in place, letting the screen reader handle it as-is.

To ensure that everything works as we expect it to I've added a bunch of tests. Specifically I've brought over the KaTeX tests and ensured that all of the existing TeX strings are converted into an English form that makes sense. Additionally I've exported every single KaTeX-parseable Math string from a selection of our curriculum on Khan Academy and have ensured that the new katex-a11y module is capable of translating them into an English string (I don't check the conversions as there are 15,000+ math strings and it would be really time consuming).

The important files are:

  • js/katex-a11y.js: This is all of the new logic for converting a KaTeX-generated tree into an English string. I attempted to handle all the cases that I could find, although I'm sure there are a bunch that I haven't been able to spot and even more where the conversion doesn't make sense. This is probably a decent first attempt, though.
  • js/tex.jsx: This is the module into which katex-a11y.js is imported and used. Some light modifications where made to make sure that the right spans were visible/invisible to the screen reader.
  • test/katex-a11y-test.jsx: These are the tests which are run in the main mocha test runner.

There are two additional areas that I want to explore, but can wait a little bit to attempt:

  • I've started work on making the math much more navigable. I've started to break the text into sub-spans with the hope of making it possible to navigate them using a keyboard. I initially added a tabIndex="0" to them but that made things pretty confusing, especially for non-screen-reader users.
  • I want to mark all the strings up for i18n. Some more thought is going to have to go in to this but we primarily are worried about the English case, at the moment.
@@ -30,5 +30,8 @@ docs/index.html: pydeps
docs/preview-bundle.js: jsdeps
./node_modules/.bin/browserify -d -t [ reactify --es6 ] reactify-components.jsx -o docs/preview-bundle.js

watch-preview: jsdeps

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

I added this in as I found it to be super convenient while doing development. I can remove it if we don't want it in this diff.

@@ -143,6 +191,12 @@ var TeX = React.createClass({
jax.Remove();
}
}
},

emptyNode: function(node) {

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

For some reason we were using jQuery just to empty out nodes. I made a little method to remove that dependency.

@jeresig

This comment has been minimized.

Copy link
Member Author

jeresig commented Jun 17, 2015

One note: The changes to the katex files in the docs/ directory are due to the fact that I've pulled in the latest version of the lib. Additionally I've moved the font files to be in the stylesheets directory (which is where they should have been, seemingly). I was getting all sorts of errors in the console about that.


var relMap = {
"=": "equals",
"\\approx": "approximately",

This comment has been minimized.

Copy link
@sophiebits

sophiebits Jun 17, 2015

Contributor

\approx is a verb, so maybe "is approximately" or "approximately equals". Same comment for geq, ge, leq, le, >, <.

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

Oh yes - good point! Will tweak.

jeresig added 2 commits Jun 17, 2015

rule: function(tree, a11yStrings) {
// NOTE: Is there something more useful that we can put here?
a11yStrings.push("rule");

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

Maybe "black box"? I don't think this is really used anywhere.

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

Hmm - maybe! As far as I can tell the height and width of this is variable, so it's not always box-like. Considering that it's not used (at least not in our sample set) it probably doesn't matter what we name it. I think I'll leave it as "rule" for now and we can re-explore this later.

https://en.wikibooks.org/wiki/LaTeX/Rules_and_Struts

sqrt: function(tree, a11yStrings) {
buildRegion(a11yStrings, function(a11yStrings) {
if (tree.value.index) {
a11yStrings.push("square root");

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

Should this just be "root"? (since it's not a square root?)

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

Ah yes, silly me! Fixing.

if (tree.value.sup) {
// There are some cases that just read better if we don't have
// the extra start/end baggage, so we skip the extra text
var newPower = (powerMap[tree.value.sup] ||

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

Can you describe what these are testing?

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

Yep - will add some more comments.

a11yNode.appendChild(doc.createTextNode(a11yString));
} else {
var newBaseNode = doc.createElement("span");
//newBaseNode.tabIndex = 0;

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

Remove?

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

Ah yeah, I meant to leave a comment explaining what its purpose was, for if/when we want to enable it. Will do so.

padding: 0,
position: "absolute",
width: "1px"
};

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

Can this be moved into a stylesheet somewhere?

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

I thought about that but it doesn't appear as if we have any stylesheets for the react-components - and adding in one for a single stylesheet rule seems cumbersome. I'm open to thoughts here, though!

var a11yString = a11yStrings[i];

if (i > 0) {
a11yNode.appendChild(doc.createTextNode(", "));

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

Do we add commas here to make the screenreader put space in between the words or something? Might want to mention why in a comment.

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 17, 2015

Author Member

Yes! Will add a comment.

jeresig added 2 commits Jun 17, 2015
} else if (type === "close") {
ret = (str in closeMap ? closeMap[str] : stringMap[str] || str);
} else if (type === "math") {
ret = mathMap[str] || str;

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

What is this? Is type ever "math"?

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 18, 2015

Author Member

Good catch! Just removed this.

},

color: function(tree, a11yStrings) {
var color = tree.value.color.replace(/katex-/, "");

This comment has been minimized.

Copy link
@xymostech

xymostech Jun 17, 2015

Contributor

This could also be from \color{#abcdef}{x}, do you want to handle that separately?

(Edit: here tree.value.color would be #abcdef)

This comment has been minimized.

Copy link
@jeresig

jeresig Jun 18, 2015

Author Member

@xymostech I'm not sure if there really is a way to ideally handle custom colors. I have a test case for this and right now:

\blue{a}\color{#0f0}{b}\color{red}{c}

Is turned in to:

start color blue, a, end color blue, start color #0f0, b, end color #0f0, start color red, c, end color red

Which is probably as good as we're going to get. I mean communicating a name is probably better than a weird hex thing, but at least the hexes will be consistent? \color is mostly being used as a way to denote that some portion of the formula is different from another portion - and I think it will succeed in that regard.

@jeresig

This comment has been minimized.

Copy link
Member Author

jeresig commented Jun 19, 2015

@xymostech I think I've tackled (or addressed) all the feedback that you've provided so far (thank you!!). Anything else that you'd like me to address or am I ok to land?

jeresig added a commit that referenced this pull request Jun 24, 2015
KaTeX A11y Mode
@jeresig jeresig merged commit 32cd36c into master Jun 24, 2015
2 checks passed
2 checks passed
continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details
@zgotsch

This comment has been minimized.

Copy link
Contributor

zgotsch commented Jun 24, 2015

Nice work guys! I love seeing this a11y work happen :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
4 participants
You can’t perform that action at this time.