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

feat: deprecate the use doT.js for messages #1938

Merged
merged 11 commits into from Dec 18, 2019
Merged

feat: deprecate the use doT.js for messages #1938

merged 11 commits into from Dec 18, 2019

Conversation

straker
Copy link
Contributor

@straker straker commented Dec 11, 2019

Removes doT.js from processing our check messages, allowing us to run translated messages on sites with a strict CSP. Doing so required a change in structure to some of our messages:

To handle all this without using eval, we'll need to deconstruct our doT.js translation strings into a different structure that doesn't need to use any logic to determine the final output. This means that the translation object inside the check metadata files will change based on the type of data used.

First, for data as a string, the structure won't change but we can just replace the doT.js syntax with regular template string syntax which the translation function will replace with the value.

// no-implicit-explicit-label.json
"incomplete": "Check that the <label> does not need be part of the ARIA ${data} field's name"

To handle data as an array we can split the translation message into separate singular and plural messages. The messages can use the comma-separated list of values by using the ${data.values} substitution value in the string (the function will provide this value automatically).

// aria-allowed-attr.json
"fail": {
  "singular": "ARIA role ${data.values} is not allowed for given element",
  "plural": "ARIA roles ${data.values} are not allowed for given element"
}

Finally, to handle data as an object when just accessing the values of properties, no structure change is needed other than replace the doT.js syntax with regular template string syntax. For handling different messages based on the value of a property, we'll change the code to use a messageKey property and then use that property to determine which message to display.

// fieldset.json
"fail": {
  "no-legend": "Fieldset does not have a legend as its first child",
  "empty-legend": "Legend does not have text that is visible to screen readers"
}

The changes are backward compatible with the old doT style template strings. The configure and build code looks at each string to see if it includes doT syntax, and if it does then runs it through the doT template. Otherwise it just leaves it as a string (the new style format). This means messages can be either a doT function or a string, which the code will handle appropriately.

Please manually test that:

  1. default config (english) works (test a few combinations of different rules that uses different styles of check messages)
  2. axe.configure() with a non-en locale works
  3. grunt build --lang=<langcode> with a non-en locale works
  4. grunt translate --lang=<langcode> output uses the newer structure

Reviewer checks

Required fields, to be filled out by PR reviewer(s)

  • Follows the commit message policy, appropriate for next version
  • Code is reviewed for security

@straker straker requested a review from a team as a code owner December 11, 2019 17:17
@straker straker changed the title feat: dont use doT.js for messages feat: deprate the use doT.js for messages Dec 11, 2019
@straker straker changed the title feat: deprate the use doT.js for messages feat: deprecate the use doT.js for messages Dec 11, 2019
@@ -3,7 +3,9 @@ let nodeName = node.nodeName.toUpperCase();
let type = (node.getAttribute('type') || '').toLowerCase();
let label = node.getAttribute('value');

this.data(label);
if (label) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message for this check used the existence of a label to determine the output, which doesn't work with the current schema. So I updated it since the data only needed to know a label was present and not what it was.

@@ -5,7 +5,10 @@
"impact": "critical",
"messages": {
"pass": "ARIA attributes are used correctly for the defined role",
"fail": "ARIA attribute{{=it.data && it.data.length > 1 ? 's are' : ' is'}} not allowed:{{~it.data:value}} {{=value}}{{~}}"
"fail": {
"singular": "ARIA attribute is not allowed: ${data.values}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is 1,000,000x easier to read/follow ❤️

lib/core/utils/process-message.js Outdated Show resolved Hide resolved
lib/core/utils/process-message.js Show resolved Hide resolved
lib/checks/lists/listitem.json Outdated Show resolved Hide resolved
lib/core/utils/process-message.js Outdated Show resolved Hide resolved
lib/core/utils/process-message.js Outdated Show resolved Hide resolved
lib/core/utils/process-message.js Outdated Show resolved Hide resolved
lib/core/utils/process-message.js Outdated Show resolved Hide resolved
lib/core/utils/process-message.js Show resolved Hide resolved
build/configure.js Outdated Show resolved Hide resolved
lib/core/utils/publish-metadata.js Outdated Show resolved Hide resolved
var templates = require('./templates');
var buildManual = require('./build-manual');
var entities = new (require('html-entities')).AllHtmlEntities();
var dotRegex = /\{\{.+?\}\}/g;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think I'm familiar with a .+? in regex, what does that do?

Copy link
Contributor Author

@straker straker Dec 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ? makes the .+ not greedy. So instead of {{foo bar}} {{foo}} matching the entire string, it will stop at the first set of }} so you get 2 matches. Not that it really matters in this case but I'm use to making things not greedy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh, didn't know that. Cool

lib/core/base/audit.js Outdated Show resolved Hide resolved
pass: 'function (out) { return "passed with " + out.data }',
fail: 'function (out) { return "failed with " + out.data }',
incomplete:
'function (out) { return "incomplete with " + out.data }'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you revert this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To show that the code still works with backwards compatibility

lib/core/utils/process-message.js Show resolved Hide resolved
lib/core/utils/process-message.js Outdated Show resolved Hide resolved
@straker straker merged commit a2ddba3 into develop Dec 18, 2019
@straker straker deleted the noDot branch December 18, 2019 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants