khan / tota11y Goto Github PK
View Code? Open in Web Editor NEWan accessibility (a11y) visualization toolkit
Home Page: http://khan.github.io/tota11y/
License: MIT License
an accessibility (a11y) visualization toolkit
Home Page: http://khan.github.io/tota11y/
License: MIT License
Hi,
I'm getting the following error when trying to require tota11y with a webpack build:
ERROR in ./~/tota11y/index.js
Module parse failed: /[...]/node_modules/tota11y/index.js Line 53: Unexpected token <
You may need an appropriate loader to handle this file type.
| let $defaultPlugins = plugins.default.map((Plugin) => { // eslint-disable-line no-unused-vars
| // Render each plugin with the bound click handler
| return ;
| });
I'll try and investigate this more but I wanted to post here incase there is something obvious I'm doing wrong.
Related to #32. This may not be specific to FF.
Tracing through GoogleChrome/accessibility-developer-tools on FF, the following parseColor
method:
/**
* @param {string} colorString The color string from CSS.
* @return {?axs.color.Color}
*/
axs.color.parseColor = function(colorString) {
var rgbRegex = /^rgb\((\d+), (\d+), (\d+)\)$/;
var match = colorString.match(rgbRegex);
if (match) {
var r = parseInt(match[1], 10);
var g = parseInt(match[2], 10);
var b = parseInt(match[3], 10);
var a = 1;
return new axs.color.Color(r, g, b, a);
}
var rgbaRegex = /^rgba\((\d+), (\d+), (\d+), (\d*(\.\d+)?)\)/;
match = colorString.match(rgbaRegex);
if (match) {
var r = parseInt(match[1], 10);
var g = parseInt(match[2], 10);
var b = parseInt(match[3], 10);
var a = parseFloat(match[4]);
return new axs.color.Color(r, g, b, a);
}
return null;
};
When this method returns null
, the getBgColor
method that's used to compute the contrast ratio will also return null
- which is causing the error.
This method expects to find rgb(...)
and rgba(...)
values for the CSSStyleDeclaration's backgroundColor
property. In Firefox, unstyled elements have a backgroundColor
of "transparent"
, while on Chrome the value is "rgba(0, 0, 0, 0)"
.
This might be worth reporting upstream, but in the meantime I can see if this is an isolated edge case and put up a quick patch.
tota11y is flagging links on a colored background for having insufficient contrast, but if I change the colors to its recommendation, I find, even with my exceptional eyesight, I have difficulty distinguishing the links from the regular text.
It would be great if there was some tool to assess the contrast of link text. I've been going back and forth trying to make the links have sufficient contrast from both the background, and the other text.
Hi @jdan ,
Please add build/ folder in gitignore. Since changing/updating code requires rebuilding from source again to test the output, this proves to be a pain when the changes has to be pushed to the master and this possibly results in conflicts.
Thanks!
Hi all!
I'm using this plugin to my ZF2 web application and I have one question. When I execute npm run build
it shows to me some messages advising about a deprecated function. The message is the following:
Container#eachAtRule is deprecated. Use Container#walkAtRules instead.
Container#eachRule is deprecated. Use Container#walkRules instead.
Container#eachDecl is deprecated. Use Container#walkDecls instead.
Node#style() is deprecated. Use Node#raw()
Node#_value was deprecated. Use Node#raws.value
Hash: 02954ab3b14e71c533a7
Version: webpack 1.12.2
Time: 4923ms
Asset Size Chunks Chunk Names
tota11y.min.js 257 kB 0 [emitted] app
+ 52 hidden modules
WARNING in tota11y.min.js from UglifyJs
Condition always true [./~/jquery/dist/jquery.js:9170,0]
Side effects in initialization of unused variable sourceMap [./~/style-loader/addStyles.js:185,0]
Side effects in initialization of unused variable media [./~/style-loader/addStyles.js:203,0]
Condition always false [./~/style-loader/addStyles.js:23,0]
Dropping unreachable code [./~/style-loader/addStyles.js:24,0]
Condition always false [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./less/tota11y.less:9,0]
Dropping unreachable code [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./less/tota11y.less:11,0]
Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./less/tota11y.less:7,0]
Condition always false [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/a11y-text-wand/style.less:9,0]
Dropping unreachable code [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/a11y-text-wand/style.less:11,0]
Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/a11y-text-wand/style.less:7,0]
Condition always false [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/contrast/style.less:9,0]
Dropping unreachable code [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/contrast/style.less:11,0]
Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/contrast/style.less:7,0]
Condition always false [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/headings/style.less:9,0]
Dropping unreachable code [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/headings/style.less:11,0]
Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/headings/style.less:7,0]
Condition always false [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/shared/annotate/style.less:9,0]
Dropping unreachable code [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/shared/annotate/style.less:11,0]
Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/shared/annotate/style.less:7,0]
Condition always false [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/shared/info-panel/style.less:9,0]
Dropping unreachable code [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/shared/info-panel/style.less:11,0]
Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./~/postcss-loader!./~/autoprefixer-loader?{browsers:['> 1%']}!./~/less-loader!./plugins/shared/info-panel/style.less:7,0]
> [email protected] dev /var/www/dtome/guido/vendor/khan/tota11y
> webpack -d --devtool hidden --output-file=tota11y.js
output.file will be deprecated: Use 'output.filename' instead
Container#eachAtRule is deprecated. Use Container#walkAtRules instead.
Container#eachRule is deprecated. Use Container#walkRules instead.
Container#eachDecl is deprecated. Use Container#walkDecls instead.
Node#style() is deprecated. Use Node#raw()
Node#before is deprecated. Use Node#raws.before
Node#_value was deprecated. Use Node#raws.value
Hash: b8fcf00dab043270ca34
Version: webpack 1.12.2
There's something wrong with the plugin or the problem is in other way?
Thanks!
They use filters on an iframe - way cool!
If the host page uses something like height: 100vh
the panel becomes unusable. This can be solved by adding height: auto !important;
to the .tota11y *
block.
Here’s a page that uses height: 100vh;
I hope you guys don't mind this
If an element has a background-color with insufficient contrast, and a background-image, the dev will be informed of a contrast violation even though the background-image may be sufficient.
This makes sense, because the background-image may not load, leaving the visitor of the site with text on the original background color with contrast issues.
We should communicate this better in the error messages of the Contrast plugin.
I was excited to try tota11y, but the tool itself is actually not accessible via keyboard or speech recognition. Technically it can be used via a screen reader, but realistically it would be almost impossible to use via screen reader without being able to see. (It doesn't make any announcements on dynamic updates, and checking a box to open up a flag on inaccessible content doesn't move the focus to the new content warning, making it almost impossible for the screen reader user to find the newly-opened warning box.)
This is important to fix for two reasons:
Thanks for building the tool and thanks for caring about accessibility!
Blank summary page
Seems to run real slow as well, tested against the tota11y thread.
It's my understanding that an img
tag with aria-hidden="true"
set doesn't need alt text (since it'll be invisible to screen readers anyways). The "Image alt-text" plugin flags such images anyways though.
On line 78 of /plugins/link-text/index.js there is no check to ensure that axs is defined.
let extractedText = axs.properties.findTextAlternatives(
el, alts);
and I've seen this when clicking the Link text test:
Uncaught TypeError: Cannot read property 'properties' of undefined
(anonymous function) @ tota11y.js:12651
jQuery.extend.each @ tota11y.js:672
jQuery.fn.jQuery.each @ tota11y.js:437
run @ tota11y.js:12636
activate @ tota11y.js:10118
handlePluginClick @ tota11y.js:113
$checkbox.buildElement.onClick @ tota11y.js:10074
jQuery.event.dispatch @ tota11y.js:4733
elemData.handle @ tota11y.js:4419
I'm also able to trigger similar errors for rules other than the Headings rule tracing back to a similar problem with axs not being defined in /plugins/shared/audit.js for config = new axs.AuditConfiguration();
I'm still trying to track down additional information as I'm including the script when pages are rendered in the CMS I'm using. I haven't yet figured out if it is part of the CMS wrapping, or code on the rendered page that could be interfering. It appears that the use of requirejs on a page in the CMS may interfere, as pages without that appear to be working.
After implementing the contrast suggestion preview, I think it might be useful to have a way to toggle annotations on and off. For smaller elements, the annotation can completely cover the element, which can be inconvenient generally speaking, but also makes it impossible to preview the suggested colors, and could prove obstructing in future plugins.
Working with various accessibility plugins and continuously testing our site, we noticed that when we include the tota11y.js plugin, the appended area is created as a <div>
with <li>
s inside. This causes the various accessibility testing we're doing to fail, as it's not valid HTML.
The plugin should probably create a valid HTML structure.
The building instructions for tota11y doesn't specify any OS. I tried building the package on Windows 7 (x64) with latest tota11y source. I am using command prompt for running the commands.
npm -v
2.5.1
I used these commands:
npm install
npm run build
The first command worked fine and installed the dependencies. However, the second command produced the following error (I am pasting the npm-debug.log here):
0 info it worked if it ends with ok
1 verbose cli [ 'C:\\Program Files\\nodejs\\\\node.exe',
1 verbose cli 'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli 'run',
1 verbose cli 'build' ]
2 info using [email protected]
3 info using [email protected]
4 verbose node symlink C:\Program Files\nodejs\\node.exe
5 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
6 info prebuild [email protected]
7 info build [email protected]
8 verbose unsafe-perm in lifecycle true
9 info [email protected] Failed to exec build script
10 verbose stack Error: [email protected] build: `webpack -p`
10 verbose stack Exit status 1
10 verbose stack at EventEmitter.<anonymous> (C:\Program Files\nodejs\node_modules\npm\lib\utils\lifecycle.js:213:16)
10 verbose stack at EventEmitter.emit (events.js:110:17)
10 verbose stack at ChildProcess.<anonymous> (C:\Program Files\nodejs\node_modules\npm\lib\utils\spawn.js:14:12)
10 verbose stack at ChildProcess.emit (events.js:110:17)
10 verbose stack at maybeClose (child_process.js:1008:16)
10 verbose stack at Process.ChildProcess._handle.onexit (child_process.js:1080:5)
11 verbose pkgid [email protected]
12 verbose cwd D:\Documents\General\Github\tota11y
13 error Windows_NT 6.1.7601
14 error argv "C:\\Program Files\\nodejs\\\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "run" "build"
15 error node v0.12.0
16 error npm v2.5.1
17 error code ELIFECYCLE
18 error [email protected] build: `webpack -p`
18 error Exit status 1
19 error Failed at the [email protected] build script 'webpack -p'.
19 error This is most likely a problem with the tota11y package,
19 error not with npm itself.
19 error Tell the author that this fails on your system:
19 error webpack -p
19 error You can get their info via:
19 error npm owner ls tota11y
19 error There is likely additional logging output above.
20 verbose exit [ 1, true ]
On searching for build instructions for Node.js on Windows, I found out that this issue is related to the relative paths and could be simply resolved by running this command for building (Don't use the run keyword on Windows):
npm build
This should be updated in documentation for build instructions.
Other than this, testing also fails on Windows:
npm test
gives out errors:
> open http://localhost:8080/webpack-dev-server/ && webpack-dev-server --hot
'open' is not recognized as an internal or external command,
operable program or batch file.
npm ERR! Test failed. See above for more details.
Changing
"test": "open http://localhost:8080/webpack-dev-server/ && webpack-dev-server --hot"
to
"test": "start http://localhost:8080/webpack-dev-server/ && webpack-dev-server --hot"
in package.json file solved the testing error on Windows.
I suggest not to force open a the debug URL while testing, this would ensure compatibility across different platforms.
"test": "webpack-dev-server --hot"
And then the debug environment can be accessed on http://localhost:8080/webpack-dev-server/
.
@jdan
I have ported your project to the axe-core library. You can find it here.
https://github.com/dylanb/tota11y
There are some significant differences including:
The axe-core library includes a bunch more rules that the Google library and has support for all the ARIA labelling techniques, so the image rule now supports aria-label, aria-labelledby etc.
There are some other minor differences and I also uncovered a bug in axe-core related to role="presentation" on images...
I would submit it as a PR but I am not sure you are interested in using the axe-core library in addition to the Google library, if you are, I will go ahead an submit the PR, I am also open to collaborating on making the integration as kick-ass as possible.
I get exception "object doesn't support property or method "requestAnimationFrame" in tota11y.min.js
This is IE 11 or Edge on Windows 7 and 10 on the following website: https://www.mylambton.ca
The following line, found on another GitHub issue, added to the bookmarklet seems to fix it, but it might be better added to the min.js? Sorry I don't know that much about JS.
window.requestAnimationFrame = window.requestAnimationFrame || function(callback) { window.setTimeout(callback,16) };
tota11y plugins run on the current state of a document, and do not update with any changes until they are toggled off and on again.
Wouldn't it be cool if plugins ran every 100ms or so?
There's a performance consideration for massive UIs (you'll notice that tota11y annotations sort of fade in over a few ms to keep 60fps on the page).
As reported by @MichelleTodd
It would be helpful if these error messages included the value of the
src
attribute so it's easier to find the image.
Similar to #18. We use this technique in LabelsPlugin.
This is because of contextify: brianmcd/contextify#180, which is required by jsdom. We might just need to upgrade jsdom and verify that npm test
still works.
If all else fails, maybe add an engines
field to package.json? http://stackoverflow.com/questions/29349684/how-can-i-specify-the-required-node-js-version-in-packages-json
Sometimes it's very tricky to spot violating elements, even when highlighting them or scrolling to them. Let's consider adding the actual HTML source of the violation as part of the expanded error message.
Is it possible to add an error counter badge to the tota11y button as well as in the different plugin rows with the number of errors for that plugin?
Right now it comes up with the following message for the image link on the gh-pages.
The text " " is unclear without context
and may be confusing to screen readers. Consider
rearranging the <a></a> tags or
including special screen reader text.
It would be nice if it said something like:
You have an image link without alt text. Please add an alt attribute to the img tag.
The positioning code for the info panel places the panel using CSS's bottom
and right
fields. This makes intuitive sense, given that the panel is initially placed in the bottom right corner of the page, but becomes confusing once the user resizes the screen (which often occurs from the bottom-right corner)
In this case, the user is required to size the page back so they can move the info panel, or must re-run the plugin.
If we position based on top and left, we can avoid this issue for the majority of users.
When using this awesome bookmarklet, even on your site, the alt text test always shows at least 45 errors. It seems to add any real errors to that amount.
For example, on http://khan.github.io/tota11y/#Try-it it says 46 when I can only actually find one error in your test area.
We check for role="presentation"
and the existence of alt
. We'll also need to check for aria-label
and aria-labelledby
(and make sure that ID exists).
As far as I know title
is not good enough.
Since starting tota11y I've been on the fence to make it a full-fledged browser extension, or keep it as a bookmarklet.
Bookmarklet pros:
Bookmarklet cons:
<script>
tag into the DOM because its code is so large, sites like GitHub block these requests)Extension pros:
getEventListeners(DOMElement)
)Extension cons:
There's also the question of having both a bookmarklet and extension.
Would love to hear your thoughts!
Css for the button (it's a <a>
):
I don't know if you have a "warning" type. But, as this is kind of hard to know programatically, maybe cases like this should check all colors used in the gradient, then, if only some of those colors are below contrast ratio you should get a warning.
Don't know if it matters, but linear-gradient
might actually be defined as background-image
:
Great job with this, wondering if there are plans for a browser plugin?
I would be happy to work on one to help out.
I think it would be useful to be able to preview the suggested new colors to fix insufficient contrast ratio errors; perhaps a toggle button next to the error that toggles between the original colors and the suggested colors.
From @Charlotteis on twitter:
Specifically the scrolling part. Highlighting works okay unless the user is able to scroll the document while the highlight is active (I'm not sure if this is possible now).
But essentially if a violating element has a fixed position and we attempt to scroll to it using the errors panel (by clicking the magnifying glass), you'll notice some janky behavior in the following gif.
"Headings" produces an empty summary. Clicking "Labels" does, well, nothing. Expected because there are no inputs, but maybe a little strange.
This is for the link text plugin specifically, but I've seen this happen for labels.
return "" === axs.properties.findTextAlternatives(a, {}).trim() ? !1 : !0;
In this case the element, a
, is the page container. So something wonky is happening when traversing up the tree.
It might be nice to have a page on gh-pages that shows off all of the warnings.
When running it on my site https://donatstudios.com, I receive in my console Cannot read property 'css' of undefined
and it fails to show up.
I'd like to add custom plugin support to tota11y, as well as the ability to toggle plugins.
Custom plugins:
tota11y.addPlugin('my-plugin', {
run: function() {
// ...
},
cleanup: function() {
// ...
}
});
Toggling plugins:
tota11y.hidePlugins(['contrast', 'link-text']);
Thoughts?
When selecting an error type, the window that opens up on the right that describes the error and proposes a fix has text that can't be selected for copy and paste. It will be really nice to let folks copy and paste from there.
For instance, I was trying to see what the new colors it proposes looks like and had to go back and forth from browser to the DevTool style tool or my text editor when I'd really like to just copy and paste it in.
...and some other sites with a CSP.
Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src assets-cdn.github.com collector-cdn.github.com".
We should find a way to provide an error message to the user (currently it looks like the bookmarklet does nothing), and instruct them to get an extension instead.
Although good for production code, a minified file is not much help for development and debugging. Is it possible to have both a minified, and a non minified version of the file? It would help greatly when reporting bugs and suggestions.
All of the plugins have a different namespace for annotation, which is used to generate their ANNOTATION_CLASS
, which is then applied to the annotations for that plugin. The contrast plugin uses "labels" as its namespace, when it should probably use "contrast".
The plugin selection in the toolbar essentially functions as a group of radio buttons, as only one plugin can be selected at a time. However, the graphic for when a plugin is selected is a white check in a green circle, which indicates they might function as checkboxes, allowing multiple plugins to be selected simultaneously. When I used tota11y for the first time, I thought I could select multiple plugins because of this. Maybe it would be clearer to remove the check and just have a green circle, or something else that suggests radio button more than checkbox.
line 12355 of latest build has
$.axs.properties.getTextFromDescendantContent(el) // where el = <a class="navbar-brand" href="/"></a>
which is returning null for me.
Full trace:
Uncaught TypeError: Cannot read property 'replace' of nullis
DescriptiveText @ tota11y.js?body=1:formatted:12626
validateTextContent @ tota11y.js?body=1:formatted:12644
(anonymous function) @ tota11y.js?body=1:formatted:12692
jQuery.extend.each @ tota11y.js?body=1:formatted:610
jQuery.fn.jQuery.each @ tota11y.js?body=1:formatted:374
run @ tota11y.js?body=1:formatted:12673
(anonymous function) @ tota11y.js?body=1:formatted:10067
jQuery.event.dispatch @ tota11y.js?body=1:formatted:4679
jQuery.event.add.elemData.handle @ tota11y.js?body=1:formatted:4365
Hey,
I'm having an issue with the bookmarklet when using the Link Text and Labels tools. When I click on either, I see the following error in the console
Uncaught TypeError: Cannot read property 'trim' of null
arising from this line of code
return "" === axs.properties.findTextAlternatives(a, {}).trim() ? !1 : !0;
The expression axs.properties.findTextAlternatives(a, {})
is returning null
.
I see this error on a number of sites - Gmail, for example. Curiously enough, both tools work fine when I test on http://khan.github.io/tota11y/
I'm using the latest version of Chrome.
I've added the snippet to my bookmarks bar. Then clicked on it. But nothing happened. Tried on another page. Same. After 10 mins, I discovered the small sun glass icon in the bottom left corner and that's easy to miss. Mainly for the First Time users.
Its better to Open and activate the First comment first. But only for Bookmarked users, not for those who inserts the script
version.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.