From 5ec6c8f941efe572f4d27542903c3548ba07ae1a Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Fri, 21 Dec 2018 03:36:38 -0600 Subject: [PATCH] Add index utility (pull #951) For issue #752, adds a node script for generating two indexes: * Example by role * Examples by state or property The script lands the generated index.html in the /examples directory. --- aria-practices.html | 8 + examples/index.html | 464 ++++++++++++++++++++++++++++++ package-lock.json | 56 ++-- scripts/reference-tables.js | 389 +++++++++++++++++++++++++ scripts/reference-tables.template | 70 +++++ 5 files changed, 959 insertions(+), 28 deletions(-) create mode 100644 examples/index.html create mode 100644 scripts/reference-tables.js create mode 100644 scripts/reference-tables.template diff --git a/aria-practices.html b/aria-practices.html index 329c5f0ee9..44adcba05a 100644 --- a/aria-practices.html +++ b/aria-practices.html @@ -4754,6 +4754,14 @@

Roles That Automatically Hide Semantics by Making Their Descendants Presenta

Appendices

+ +
+

Indexes

+ +

Change History

diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 0000000000..4a5c970154 --- /dev/null +++ b/examples/index.html @@ -0,0 +1,464 @@ + + + + + + Index of ARIA Design Pattern Examples | WAI-ARIA Authoring Practices 1.1 + + + + + + + + + +
+

Index of ARIA Design Pattern Examples

+ +

+ This page includes the following indexes of example implementations of + ARIA design patterns included in + WAI-ARIA Authoring Practices 1.1. +

+ + + +
+ +

Examples by Role

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RoleExamples
article Feed
banner Banner Landmark
button
checkbox
columnheader Table
combobox
complementary Complementary Landmark
contentinfo Contentinfo Landmark
feed Feed
form Form Landmark
grid
gridcell Layout Grid
group
link Link
listbox
main Main Landmark
menu
menubar
menuitem
menuitemcheckbox Editor Menubar
menuitemradio Editor Menubar
navigation Navigation Landmark
none
option
radio
radiogroup
region Region Landmark
row
rowgroup Table
search Search Landmark
separator Editor Menubar
slider
tab
table Table
tablist
tabpanel
toolbar Toolbar
tree
treegrid Treegrid Email Inbox
treeitem
+ +
+ +
+ +

Examples By Properties and States

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Property or StateExamples
aria-activedescendant
aria-autocomplete
aria-busyFeed
aria-checked
aria-colcountData Grid
aria-controls
aria-describedby
aria-disabled
aria-expanded
aria-haspopup
aria-hiddenAlert Dialog
aria-label
aria-labelledby
aria-level
aria-liveAlert
aria-modalAlert Dialog
aria-multiselectable Listboxes with Rearrangeable Options
aria-orientationSlider with aria-orientation and aria-valuetext
aria-owns
aria-posinset
aria-pressedButton
aria-rowcount
aria-rowindex
aria-selected
aria-setsize
aria-sortData Grid
aria-valuemax
aria-valuemin
aria-valuenow
aria-valuetext
+ +
+ +
+ + + diff --git a/package-lock.json b/package-lock.json index 5f5b21a89a..d4ab5112af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1162,9 +1162,9 @@ } }, "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true }, "ci-info": { @@ -1613,14 +1613,14 @@ "dev": true }, "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true }, "es6-promisify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { @@ -2478,9 +2478,9 @@ "dev": true }, "geckodriver": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-1.12.2.tgz", - "integrity": "sha512-nhTroSDoAjbws1GAALCBFGWcjUI7Uy5nLKJFKmOfOmVGCyn7TazdIYQJFpnre/vtKcieKwXOC8RqBD48g0a/4A==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-1.14.1.tgz", + "integrity": "sha512-4Lia4i5MGd7aLbgHXKAxjWxZ/HqwqX9fr7HfHLKKqRvF3jNzbO/FxnLUfcRKgdMSHXunRfgi/OxfdkHPMyUhnA==", "dev": true, "requires": { "adm-zip": "0.4.11", @@ -2492,13 +2492,13 @@ "dependencies": { "bluebird": { "version": "3.4.6", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz", "integrity": "sha1-AdqNgh2HgT0ViWfnQ9X+bGLPjA8=", "dev": true }, "got": { "version": "5.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-5.6.0.tgz", + "resolved": "http://registry.npmjs.org/got/-/got-5.6.0.tgz", "integrity": "sha1-ux1+4WO3gIK7yOuDbz85UATqb78=", "dev": true, "requires": { @@ -3550,9 +3550,9 @@ "dev": true }, "minipass": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.4.tgz", - "integrity": "sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -3566,17 +3566,17 @@ "dev": true }, "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true } } }, "minizlib": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.1.tgz", + "integrity": "sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==", "dev": true, "requires": { "minipass": "^2.2.1" @@ -3630,7 +3630,7 @@ }, "node-status-codes": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", "dev": true }, @@ -4667,9 +4667,9 @@ }, "dependencies": { "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true } } @@ -4840,9 +4840,9 @@ } }, "vnu-jar": { - "version": "18.7.23", - "resolved": "https://registry.npmjs.org/vnu-jar/-/vnu-jar-18.7.23.tgz", - "integrity": "sha512-40X+8KQ/dTkbOswDG64G7CKzxSlwv1b45dCBc9VAXd+aAdxUu0sN6sHkol/GkO85phj5CoYT8zCrN0aJvmhOug==", + "version": "18.11.5", + "resolved": "https://registry.npmjs.org/vnu-jar/-/vnu-jar-18.11.5.tgz", + "integrity": "sha512-XxTYLOUgQYdvIlAgX1BtxZiQ97/OKuBaEojqZdjMnjI+OXDkSyQGNGpzUQIQygeRrFVdQ1/eAVfiRE/iIlV0fg==", "dev": true }, "well-known-symbols": { diff --git a/scripts/reference-tables.js b/scripts/reference-tables.js new file mode 100644 index 0000000000..75978e91ae --- /dev/null +++ b/scripts/reference-tables.js @@ -0,0 +1,389 @@ +/* +* This content is licensed according to the W3C Software License at +* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document +* +* File: reference-tables.js +*/ + +var fs = require('fs'); +var i; + +var fileNameTemplate = 'reference-tables.template'; +var fileNameIndex = '../examples/index.html'; +var examplesDirectory = '../examples/'; + +var ariaRoles = [ + 'application', + 'article', + 'banner', + 'button', + 'cell', + 'checkbox', + 'columnheader', + 'combobox', + 'complementary', + 'contentinfo', + 'definition', + 'directory', + 'document', + 'feed', + 'figure', + 'form', + 'grid', + 'gridcell', + 'group', + 'heading', + 'img', + 'link', + 'list', + 'listbox', + 'listitem', + 'main', + 'math', + 'menu', + 'menubar', + 'menuitem', + 'menuitemcheckbox', + 'menuitemradio', + 'navigation', + 'none', + 'note', + 'option', + 'presentation', + 'progressbar', + 'radio', + 'radiogroup', + 'row', + 'rowgroup', + 'rowheader', + 'scrollbar', + 'search', + 'searchbox', + 'separator', + 'slider', + 'spinbutton', + 'switch', + 'tab', + 'table', + 'tablist', + 'tabpanel', + 'term', + 'textbox', + 'toolbar', + 'tooltip', + 'tree', + 'treegrid', + 'treeitem' +]; + +var ariaPropertiesAndStates = [ + 'aria-activedescendant', + 'aria-atomic', + 'aria-autocomplete', + 'aria-busy', + 'aria-checked', + 'aria-colcount', + 'aria-colindex', + 'aria-colspan', + 'aria-controls', + 'aria-current', + 'aria-describedby', + 'aria-details', + 'aria-disabled', + 'aria-dropeffect', + 'aria-errormessage', + 'aria-expanded', + 'aria-flowto', + 'aria-grabbed', + 'aria-haspopup', + 'aria-hidden', + 'aria-invalid', + 'aria-keyshortcuts', + 'aria-label', + 'aria-labelledby', + 'aria-level', + 'aria-live', + 'aria-modal', + 'aria-multiline', + 'aria-multiselectable', + 'aria-orientation', + 'aria-owns', + 'aria-placeholder', + 'aria-posinset', + 'aria-pressed', + 'aria-readonly', + 'aria-relevant', + 'aria-required', + 'aria-roledescription', + 'aria-rowcount', + 'aria-rowindex', + 'aria-rowspan', + 'aria-selected', + 'aria-setsize', + 'aria-sort', + 'aria-valuemax', + 'aria-valuemin', + 'aria-valuenow', + 'aria-valuetext' +]; + +var indexOfRoles = []; +var indexOfPropertiesAndStates = []; + +console.log('Generating index...'); + +function replaceSection (id, content, newContent) { + var indexStart = content.indexOf(id); + + if (indexStart > 0) { + indexStart = content.indexOf('>', indexStart) + 1; + indexEnd = indexStart + 1; + + console.log('Replacing at: ' + indexStart + ' .... ' + indexEnd); + + content = content.slice(0, indexStart) + newContent + content.slice(indexEnd); + } + + return content; +} + +function getTitle (data) { + title = data.substring(data.indexOf('') + 7, data.indexOf('')); + + title = title.split('|'); + + title = title[0].replace('Examples', ''); + title = title.replace('Example of', ''); + title = title.replace('Example', ''); + + return title; +} + +function getColumn (data, indexStart) { + var count = 0; + var index = data.lastIndexOf(' 0 && index <= indexStart) { + var indexTd = data.indexOf('', 0); + var indexEnd = data.indexOf('', indexStart); + + while (indexStart > 1 && indexEnd > 1) { + code = data.substring(indexStart + 6, indexEnd).trim(); + + for (var i = 0; i < ariaRoles.length; i++) { + if ((getColumn(data, indexStart) === 1) && + (code == ariaRoles[i]) && + (roles.indexOf(ariaRoles[i]) < 0)) { + roles.push(ariaRoles[i]); + } + } + + indexStart = data.indexOf('', indexEnd); + + if (indexStart > 0) { + indexEnd = data.indexOf('', indexStart); + } + } + + return roles; +} + +function getPropertiesAndStates (data) { + var propertiesAndStates = []; + + var indexStart = data.indexOf('', 0); + var indexEnd = data.indexOf('', indexStart); + + while (indexStart > 1 && indexEnd > 1) { + code = data.substring(indexStart + 6, indexEnd); + + for (var i = 0; i < ariaPropertiesAndStates.length; i++) { + if ((getColumn(data, indexStart) === 2) && + (code.indexOf(ariaPropertiesAndStates[i]) >= 0) && + (propertiesAndStates.indexOf(ariaPropertiesAndStates[i]) < 0)) { + propertiesAndStates.push(ariaPropertiesAndStates[i]); + } + } + + indexStart = data.indexOf('', indexEnd); + + if (indexStart > 0) { + indexEnd = data.indexOf('', indexStart); + } + } + + return propertiesAndStates; +} + +function addExampleToRoles (roles, example) { + for (var i = 0; i < roles.length; i++) { + var role = roles[i]; + + if (role === '') { + continue; + } + + if (!indexOfRoles[role]) { + indexOfRoles[role] = []; + } + indexOfRoles[role].push(example); + } +} + +function addExampleToPropertiesAndStates (props, example) { + + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + + if (prop === '') { + continue; + } + + if (!indexOfPropertiesAndStates[prop]) { + indexOfPropertiesAndStates[prop] = []; + } + indexOfPropertiesAndStates[prop].push(example); + } +} + +function addLandmarkRole (landmark, hasLabel, title, ref) { + var example = {}; + + example.title = title; + example.ref = ref; + addExampleToRoles(landmark, example); + if (hasLabel) { + addExampleToPropertiesAndStates([ 'aria-labelledby' ], example); + } +} + +var count = 0; + +function findHTMLFiles (path) { + fs.readdirSync(path).forEach(function (file) { + var newPath = path + '/' + file; + + var stats = fs.statSync(newPath); + + if (stats.isDirectory()) { + findHTMLFiles(newPath); + } + + if (stats.isFile() && + (newPath.indexOf('.html') > 0) && + (newPath.indexOf('index.html') < 0) && + (newPath.indexOf('landmark') < 0)) { + count += 1; + + var data = fs.readFileSync(newPath, 'utf8'); + + var ref = newPath; + var title = getTitle(data); + var roles = getRoles(data); + var props = getPropertiesAndStates(data); + + console.log('\nFile ' + count + ': ' + ref); + console.log('Title ' + count + ': ' + title); + console.log('Roles ' + count + ': ' + roles); + console.log('Props ' + count + ': ' + props); + + var example = {}; + + example.title = title; + example.ref = ref; + + addExampleToRoles(roles, example); + + addExampleToPropertiesAndStates(props, example); + } + }); +}; + +findHTMLFiles(examplesDirectory); + +// Add landmark examples, since they are a different format + +addLandmarkRole([ 'banner' ], false, 'Banner Landmark', examplesDirectory + 'landmarks/banner.html'); +addLandmarkRole([ 'complementary' ], true, 'Complementary Landmark', examplesDirectory + 'landmarks/complementary.html'); +addLandmarkRole([ 'contentinfo' ], false, 'Contentinfo Landmark', examplesDirectory + 'landmarks/contentinfo.html'); +addLandmarkRole([ 'form' ], true, 'Form Landmark', examplesDirectory + 'landmarks/form.html'); +addLandmarkRole([ 'main' ], true, 'Main Landmark', examplesDirectory + 'landmarks/main.html'); +addLandmarkRole([ 'navigation' ], true, 'Navigation Landmark', examplesDirectory + 'landmarks/navigation.html'); +addLandmarkRole([ 'region' ], true, 'Region Landmark', examplesDirectory + 'landmarks/region.html'); +addLandmarkRole([ 'search' ], true, 'Search Landmark', examplesDirectory + 'landmarks/search.html'); + +var exampleIndexFile = fs.readFileSync(fileNameTemplate, function (err) { + console.log('Error reading aria index:', err); +}); + +var sorted = []; + +for (role in indexOfRoles) { + sorted.push(role); +} + +sorted.sort(); + +var html = sorted.reduce(function (set,role) { + var examples = indexOfRoles[role]; + + var examplesHTML = ''; + if (examples.length === 1) { + examplesHTML = ' ' + examples[0].title + ''; + } + else { + function exampleListItem (item) { return '
  • ' + item.title + '
  • ';}; + examplesHTML = '
      ' + examples.map(exampleListItem).join('\n') + '
    '; + } + return set + '\n ' + role + '\n ' + examplesHTML + '\n'; +}, ''); + +exampleIndexFile = replaceSection('examples_by_role_tbody', exampleIndexFile, html); + +sorted = []; + +for (prop in indexOfPropertiesAndStates) { + sorted.push(prop); +} + +sorted.sort(); + +html = sorted.reduce(function (set,prop) { + var examples = indexOfPropertiesAndStates[prop]; + + var examplesHTML = ''; + if (examples.length === 1) { + examplesHTML = '' + examples[0].title + ''; + } + else { + function exampleListItem (item) { return '
  • ' + item.title + '
  • ';}; + examplesHTML = '
      ' + examples.map(exampleListItem).join('\n') + '
    '; + } + return set + '\n ' + prop + '\n ' + examplesHTML + '\n'; +}, ''); + +exampleIndexFile = replaceSection('examples_by_props_tbody', exampleIndexFile, html); + +fs.writeFile(fileNameIndex, exampleIndexFile, function (err) { + if (err) { + console.log('Error saving updated aria practices:', err); + } +}); diff --git a/scripts/reference-tables.template b/scripts/reference-tables.template new file mode 100644 index 0000000000..7c5549c777 --- /dev/null +++ b/scripts/reference-tables.template @@ -0,0 +1,70 @@ + + + + + + Index of ARIA Design Pattern Examples | WAI-ARIA Authoring Practices 1.1 + + + + + + + + + +
    +

    Index of ARIA Design Pattern Examples

    + +

    + This page includes the following indexes of example implementations of + ARIA design patterns included in + WAI-ARIA Authoring Practices 1.1. +

    + + + +
    + +

    Examples by Role

    + + + + + + + + + + +
    RoleExamples
    + +
    + +
    + +

    Examples By Properties and States

    + + + + + + + + + +
    Property or StateExamples
    + +
    + +
    + + +