diff --git a/.eslintrc.json b/.eslintrc.json index e8e3bc1df3..7e40af6dbc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -63,6 +63,14 @@ "strict": 0, "no-unused-vars": ["error", { "varsIgnorePattern": "SkipToConfig" }] } + }, + { + "files": [ "content/shared/js/app.js" ], + "parserOptions": { "ecmaVersion": 11 } + }, + { + "files": [ "content/shared/js/specLinks.mjs" ], + "parserOptions": { "sourceType": "module" } } ] } diff --git a/content/about/about.html b/content/about/about.html index 5b2b9e3ab9..1c9e5cb61c 100644 --- a/content/about/about.html +++ b/content/about/about.html @@ -7,15 +7,15 @@ - - - - + + + +

About

- +

Introduction

@@ -55,7 +55,7 @@

Introduction

Change History

- +

APG 1.1 supported ARIA 1.1, and this version, APG 1.2, includes changes to support version 1.2 of the ARIA specification. It also includes nearly 200 significant updates to improve the quality and breadth of content. @@ -103,7 +103,7 @@

Change History

- +

Acknowledgements

Editors

@@ -122,7 +122,7 @@

Editors

(Adobe)
- Zoë Bijl (Invited Expert) + Zoë Bijl (Invited Expert)
Michael Cooper @@ -179,7 +179,7 @@

Part
  • Shirisha Balusani (Microsoft Corporation)
  • Dorothy Bass (Wells Fargo Bank N.A.)
  • Curt Bellew (Oracle)
  • -
  • Zoë Bijl (Invited Expert)
  • +
  • Zoë Bijl (Invited Expert)
  • Michael Cooper (W3C)
  • @@ -205,7 +205,7 @@

    Part

    Other commenters and contributors to Version 1.1

    • Vyacheslav Aristov
    • -
    • J. Renée Beach
    • +
    • J. Renée Beach
    • Kasper Christensen
    • Gerard K. Cohen
    • Anne-Gaelle Colom
    • @@ -213,7 +213,7 @@

      Other commenters a
    • Cameron Cundiff
    • Manish Dahamiwal
    • Gilmore Davidson
    • -
    • Boris DuÅ¡ek
    • +
    • Boris Dušek
    • Michael Fairchild
    • Jeremy Felt
    • Rob Fentress
    • @@ -232,7 +232,7 @@

      Other commenters a
    • Christopher Tryens
    -
    +

    References

    @@ -293,7 +293,7 @@

    Informative references

    - +
    diff --git a/content/about/coverage-and-quality/coverage-and-quality-report.html b/content/about/coverage-and-quality/coverage-and-quality-report.html index 292aa7d4e3..6679f54b4a 100644 --- a/content/about/coverage-and-quality/coverage-and-quality-report.html +++ b/content/about/coverage-and-quality/coverage-and-quality-report.html @@ -118,45 +118,45 @@

    Roles with at Least One Guidance or Exampl alertdialog - Alert Dialog + Alert Dialog article - Feed + Feed columnheader - Table + Table complementary - Complementary + Complementary Complementary Landmark feed - Feed Pattern + Feed Pattern - Feed + Feed link - Link Pattern + Link Pattern - Link + Link main - Main + Main Main Landmark @@ -164,18 +164,18 @@

    Roles with at Least One Guidance or Exampl menuitemcheckbox - Editor Menubar + Editor Menubar rowgroup - Table + Table search - Search + Search Search Landmark @@ -183,20 +183,20 @@

    Roles with at Least One Guidance or Exampl separator - Editor Menubar + Editor Menubar tooltip - Tooltip Pattern + Tooltip Pattern treegrid - Treegrid Pattern + Treegrid Pattern - Treegrid Email Inbox + Treegrid Email Inbox @@ -217,23 +217,23 @@

    Roles with More than One Guidance or Exa alert banner - Banner + Banner @@ -241,61 +241,61 @@

    Roles with More than One Guidance or Exa button cell - Table + Table checkbox - Checkbox Pattern + Checkbox Pattern combobox contentinfo - Contentinfo + Contentinfo @@ -303,22 +303,22 @@

    Roles with More than One Guidance or Exa dialog form Form Landmark @@ -327,17 +327,17 @@

    Roles with More than One Guidance or Exa grid @@ -345,76 +345,76 @@

    Roles with More than One Guidance or Exa gridcell group listbox menu menubar - Menu and Menubar Pattern + Menu and Menubar Pattern @@ -422,11 +422,11 @@

    Roles with More than One Guidance or Exa menuitem @@ -434,34 +434,34 @@

    Roles with More than One Guidance or Exa menuitemradio meter - Meter + Meter navigation @@ -470,13 +470,13 @@

    Roles with More than One Guidance or Exa none @@ -484,25 +484,25 @@

    Roles with More than One Guidance or Exa option presentation @@ -510,16 +510,16 @@

    Roles with More than One Guidance or Exa radio @@ -527,23 +527,23 @@

    Roles with More than One Guidance or Exa radiogroup region - Region + Region @@ -552,78 +552,78 @@

    Roles with More than One Guidance or Exa row slider spinbutton - Spinbutton Pattern + Spinbutton Pattern switch - Switch Pattern + Switch Pattern tab - Keyboard Navigation Between Components (The Tab Sequence) + Keyboard Navigation Between Components (The Tab Sequence) table - Table + Table tablist @@ -631,34 +631,34 @@

    Roles with More than One Guidance or Exa tabpanel toolbar - Toolbar + Toolbar tree @@ -666,9 +666,9 @@

    Roles with More than One Guidance or Exa treeitem @@ -708,49 +708,49 @@

    Properties and States with at Least One Gu aria-atomic - Alert + Alert aria-busy - Feed + Feed aria-colcount - Using aria-colcount and aria-colindex + Using aria-colcount and aria-colindex - Data Grid + Data Grid aria-colspan - Defining cell spans using aria-colspan and aria-rowspan + Defining cell spans using aria-colspan and aria-rowspan aria-multiselectable - Listboxes with Rearrangeable Options + Listboxes with Rearrangeable Options aria-orientation - Vertical Temperature Slider + Vertical Temperature Slider aria-owns - Navigation Treeview + Navigation Treeview aria-rowspan - Defining cell spans using aria-colspan and aria-rowspan + Defining cell spans using aria-colspan and aria-rowspan @@ -771,20 +771,20 @@

    Properties and States with More than One aria-activedescendant - Managing Focus in Composites Using aria-activedescendant + Managing Focus in Composites Using aria-activedescendant @@ -792,11 +792,11 @@

    Properties and States with More than One aria-autocomplete @@ -804,53 +804,53 @@

    Properties and States with More than One aria-checked aria-colindex - Data Grid + Data Grid aria-controls @@ -858,25 +858,25 @@

    Properties and States with More than One aria-current aria-describedby - Describing by referencing content with aria-describedby + Describing by referencing content with aria-describedby @@ -884,9 +884,9 @@

    Properties and States with More than One aria-disabled @@ -894,28 +894,28 @@

    Properties and States with More than One aria-expanded @@ -923,15 +923,15 @@

    Properties and States with More than One aria-haspopup @@ -939,87 +939,87 @@

    Properties and States with More than One aria-hidden aria-label - Naming with a String Attribute Via aria-label + Naming with a String Attribute Via aria-label aria-labelledby - Naming with Referenced Content Via aria-labelledby - - diff --git a/img/DHTMLexample.png b/content/images/DHTMLexample.png similarity index 100% rename from img/DHTMLexample.png rename to content/images/DHTMLexample.png diff --git a/img/accessibleJSelement.png b/content/images/accessibleJSelement.png similarity index 100% rename from img/accessibleJSelement.png rename to content/images/accessibleJSelement.png diff --git a/img/accessibleelement.png b/content/images/accessibleelement.png similarity index 100% rename from img/accessibleelement.png rename to content/images/accessibleelement.png diff --git a/img/exampletree.png b/content/images/exampletree.png similarity index 100% rename from img/exampletree.png rename to content/images/exampletree.png diff --git a/img/index-1.svg b/content/images/index-1.svg similarity index 100% rename from img/index-1.svg rename to content/images/index-1.svg diff --git a/img/index-2.svg b/content/images/index-2.svg similarity index 100% rename from img/index-2.svg rename to content/images/index-2.svg diff --git a/img/index-3.svg b/content/images/index-3.svg similarity index 100% rename from img/index-3.svg rename to content/images/index-3.svg diff --git a/img/index-4.svg b/content/images/index-4.svg similarity index 100% rename from img/index-4.svg rename to content/images/index-4.svg diff --git a/img/index-5.svg b/content/images/index-5.svg similarity index 100% rename from img/index-5.svg rename to content/images/index-5.svg diff --git a/img/index-6.svg b/content/images/index-6.svg similarity index 100% rename from img/index-6.svg rename to content/images/index-6.svg diff --git a/img/index-7.svg b/content/images/index-7.svg similarity index 100% rename from img/index-7.svg rename to content/images/index-7.svg diff --git a/img/index-8.svg b/content/images/index-8.svg similarity index 100% rename from img/index-8.svg rename to content/images/index-8.svg diff --git a/img/inspectofpagetab.png b/content/images/inspectofpagetab.png similarity index 100% rename from img/inspectofpagetab.png rename to content/images/inspectofpagetab.png diff --git a/img/navlandmark.jpg b/content/images/navlandmark.jpg similarity index 100% rename from img/navlandmark.jpg rename to content/images/navlandmark.jpg diff --git a/img/taxonomy.png b/content/images/taxonomy.png similarity index 100% rename from img/taxonomy.png rename to content/images/taxonomy.png diff --git a/content/patterns/alertdialog/examples/alertdialog.html b/content/patterns/alertdialog/examples/alertdialog.html index c131c11f34..4a8921deac 100644 --- a/content/patterns/alertdialog/examples/alertdialog.html +++ b/content/patterns/alertdialog/examples/alertdialog.html @@ -46,7 +46,7 @@

    About This Example

  • Activate the "save" button to trigger an alert when the contents of the "Notes" text area is saved to - local storage. + local storage. diff --git a/content/practices/practices.html b/content/practices/practices.html new file mode 100644 index 0000000000..7c4fac74bd --- /dev/null +++ b/content/practices/practices.html @@ -0,0 +1,12 @@ + + + + + + + Practices + + + In a future iteration this file will contain a list of all practices. + + diff --git a/content/shared/css/core.css b/content/shared/css/core.css index 1cfa64e60e..ab1619cdb8 100644 --- a/content/shared/css/core.css +++ b/content/shared/css/core.css @@ -128,3 +128,56 @@ th .example-header { ); box-shadow: inset 0 3px 5px 1px hsl(216deg 82% 30%); } + +#support-notice[open] summary { + padding-bottom: 1em; + margin-bottom: 1em; +} + +#support-notice summary p { + display: inline; + margin-left: 5px; +} + +.note, +.warning, +.advisement { + border-right: none; + padding: 1em; + margin: 2em 0; +} + +.note > h2, +.note > h3, +.note > h4, +.note > h5, +.warning > h2, +.warning > h3, +.warning > h4, +.warning > h5, +.advisement > h2, +.advisement > h3, +.advisement > h4, +.advisement > h5 { + margin: 0 0 0.5em; + font-size: 1.2rem; + font-weight: 400; + color: black; +} + +.note > :first-child + *, +.warning > :first-child + *, +.advisement > :first-child + * { + margin-top: 0; +} + +.note > :last-child, +.warning > :last-child, +.advisement > :last-child { + margin-bottom: initial; +} + +.warning { + background-color: #fdd4e1; + border-left: 0.5em solid #c20d4a; +} diff --git a/content/shared/js/app.js b/content/shared/js/app.js index bf9991685a..65e55ea2f0 100644 --- a/content/shared/js/app.js +++ b/content/shared/js/app.js @@ -6,63 +6,41 @@ // Load syntax highlighting hljs.initHighlightingOnLoad(); - // Add support notice to all examples - window.addEventListener('DOMContentLoaded', addSupportNotice, false); + // Add usage warning to all examples + window.addEventListener('DOMContentLoaded', addExampleUsageWarning, false); - function addSupportNotice() { - // The "Example" heading - var headings = document.querySelectorAll('h2'); - var foundExampleHeading; - for (var i = 0; i < headings.length; ++i) { - if (headings[i].textContent.trim().match(/^Examples?$/)) { - foundExampleHeading = true; - break; - } - } - if (!foundExampleHeading) { - return; - } + // Rewrite links so they point to the proper spec document + window.addEventListener('DOMContentLoaded', resolveSpecLinks, false); - // The #browser_and_AT_support link - var supportLink = document.querySelector( - 'a[href$="#browser_and_AT_support"]' - ); - if (!supportLink) { - return; - } - - // Get the right relative URL to the root aria-practices page - var urlPrefix = supportLink.getAttribute('href').split('#')[0]; + async function addExampleUsageWarning() { + // Determine we are on an example page + if (!document.location.href.match(/examples\/[^/]+\.html/)) return; - // Expected outcome '../js/app.js' OR '../../js/app.js' - var scriptSource = document + // Generate the usage warning link using app.js link as a starting point + const scriptSource = document .querySelector('[src$="app.js"]') .getAttribute('src'); - // Replace 'app.js' part with 'notice.html' + const fetchSource = scriptSource.replace( + '/js/app.js', + '/templates/example-usage-warning.html' + ); + + // Load and parse the usage warning and insert it before the h1 + const html = await (await fetch(fetchSource)).text(); + const doc = new DOMParser().parseFromString(html, 'text/html'); + + // Pull out the relevant part, the details element + const warningElement = doc.querySelector('details'); + warningElement.classList.add('note'); // Needed for styling + + // Insert the usage warning before the page's h1 + const heading = document.querySelector('h1'); + heading.parentNode.insertBefore(warningElement, heading.nextSibling); + } - var fetchSource = scriptSource.replace('app.js', './notice.html'); - //fetch('https://raw.githack.com/w3c/aria-practices/1228-support-notice/examples/js/notice.html') - fetch(fetchSource) - .then(function (response) { - // Return notice.html as text - return response.text(); - }) - .then(function (html) { - // Parse response as text/html - var parser = new DOMParser(); - return parser.parseFromString(html, 'text/html'); - }) - .then(function (doc) { - // Get the details element from the parsed response - var noticeElement = doc.querySelector('details'); - // Rewrite links with the right urlPrefix - var links = doc.querySelectorAll('a[href^="/#"]'); - for (var i = 0; i < links.length; ++i) { - links[i].pathname = urlPrefix; - } - // Insert the support notice before the page's h1 - var heading = document.querySelector('h1'); - heading.parentNode.insertBefore(noticeElement, heading.nextSibling); - }); + async function resolveSpecLinks() { + const { specLinks } = await import('./specLinks.mjs'); + const fixSpecLink = specLinks({ specStatus: 'ED' }); + document.querySelectorAll('a[href]').forEach(fixSpecLink); } })(); diff --git a/content/shared/js/notice.html b/content/shared/js/notice.html deleted file mode 100644 index 15e117547f..0000000000 --- a/content/shared/js/notice.html +++ /dev/null @@ -1,21 +0,0 @@ - - - -support notice (template) -

    Read This First

    -
    - The code in this example is not intended for production environments. Before using it for any purpose, read this to understand why. -

    Note: This is an illustrative example of one way of using ARIA that conforms with the ARIA specification.

    - -
    - diff --git a/content/shared/js/specLinks.mjs b/content/shared/js/specLinks.mjs new file mode 100644 index 0000000000..199462fd49 --- /dev/null +++ b/content/shared/js/specLinks.mjs @@ -0,0 +1,78 @@ +// This file is an ES module to make it easier to use in both frontend and backend contexts. +// Allows APG authors to easily write links to the correct version of the ARIA specification or other related specs. +// A typical spec link looks like this: button. +// Other classes used for spec links include "property-reference" and "state-reference", and for a complete list, see below. + +const specData = { + ariaSpec: { + classes: [ + 'role-reference', + 'property-reference', + 'state-reference', + 'specref', + ], + statuses: { + ED: 'https://w3c.github.io/aria/', + FPWD: 'https://www.w3.org/TR/wai-aria-1.2/', + WD: 'https://www.w3.org/TR/wai-aria-1.2/', + REC: 'https://www.w3.org/TR/wai-aria/', + }, + }, + accNameURLs: { + classes: ['accname'], + statuses: { + ED: 'https://w3c.github.io/accname/', + WD: 'https://www.w3.org/TR/accname-1.2/', + FPWD: 'https://www.w3.org/TR/accname-1.2/', + REC: 'https://www.w3.org/TR/accname/', + }, + }, + coreMappingURLs: { + classes: ['core-mapping'], + statuses: { + ED: 'https://w3c.github.io/core-aam/', + WD: 'https://www.w3.org/TR/core-aam-1.2/', + FPWD: 'https://www.w3.org/TR/core-aam-1.2/', + REC: 'https://www.w3.org/TR/core-aam/', + }, + }, + htmlMappingURLs: { + classes: ['html-mapping'], + statuses: { + ED: 'https://w3c.github.io/html-aam/', + WD: 'https://www.w3.org/TR/html-aam-1.0/', + FPWD: 'https://www.w3.org/TR/html-aam-1.0/', + REC: 'https://www.w3.org/TR/html-aam-1.0/', + }, + }, +}; + +// Must be initialized with a spec status, which determines which spec link to use. +// When in doubt, use ED (Editor's Draft). +const specLinks = ({ specStatus }) => { + const baseUrls = Object.fromEntries( + Object.entries(specData).map(([spec, { statuses }]) => [ + spec, + statuses[specStatus], + ]) + ); + + // Returns a function which can be run over any link elements, and will correct the urls in the case the link is a spec link. + const fixSpecLink = (a) => { + const className = a.getAttribute('class'); + + const specClasses = Object.entries(specData).find(([, { classes }]) => + classes.includes(className) + ); + const spec = specClasses && specClasses[0]; + + if (spec) { + const currentHref = a.getAttribute('href'); + a.setAttribute('href', `${baseUrls[spec]}${currentHref}`); + } + }; + + return fixSpecLink; +}; + +export { specLinks }; diff --git a/content/shared/templates/example-usage-warning.html b/content/shared/templates/example-usage-warning.html new file mode 100644 index 0000000000..e081775b8c --- /dev/null +++ b/content/shared/templates/example-usage-warning.html @@ -0,0 +1,30 @@ + + + + Support Notice (Template) + +
    + +

    + The code in this example is not intended for production environments. + Before using it for any purpose, read this to understand why. +

    +
    +

    This is an illustrative example of one way of using ARIA that conforms with the ARIA specification.

    + +
    + + diff --git a/cspell.json b/cspell.json index 9fccf82ea6..36a32fb03d 100644 --- a/cspell.json +++ b/cspell.json @@ -287,6 +287,7 @@ "**/*.paint", "content/shared/css/github.css", "content/shared/js/skipto.js", + "content/shared/js/specLinks.mjs", "content/patterns/landmarks/examples/css/bootstrap.css", "content/patterns/landmarks/examples/css/bootstrap-theme.css", "content/patterns/landmarks/examples/js/visua11y.js", diff --git a/scripts/coverage-report.js b/scripts/coverage-report.js index fcad1db6dd..2244b571da 100644 --- a/scripts/coverage-report.js +++ b/scripts/coverage-report.js @@ -12,17 +12,22 @@ const glob = require('glob'); const cheerio = require('cheerio'); const HTMLParser = require('node-html-parser'); -const coverageReportPath = path.join( +const joinPaths = (...segments) => { + // Normalize paths to avoid backslash-based paths on Windows + return path.join(...segments).replace(/\\/g, '/'); +}; + +const coverageReportPath = joinPaths( __dirname, '../content/about/coverage-and-quality/coverage-and-quality-report.html' ); -const templatePath = path.join(__dirname, 'coverage-report.template'); +const templatePath = joinPaths(__dirname, 'coverage-report.template'); -const csvRoleFilePath = path.join( +const csvRoleFilePath = joinPaths( __dirname, '../content/about/coverage-and-quality/role-coverage.csv' ); -const csvPropFilePath = path.join( +const csvPropFilePath = joinPaths( __dirname, '../content/about/coverage-and-quality/prop-coverage.csv' ); @@ -445,7 +450,7 @@ function getExampleCodeId(html) { // Index roles, properties and states used in examples glob .sync('content/patterns/!(landmarks)/examples/**/!(index).html', { - cwd: path.join(__dirname, '..'), + cwd: joinPaths(__dirname, '..'), nodir: true, }) .forEach(function (file) { @@ -472,7 +477,7 @@ glob src.indexOf('app.js') < 0 ) { console.log(' [script]: ' + src); - dataJS += fs.readFileSync(path.join(dir, src), 'utf8'); + dataJS += fs.readFileSync(joinPaths(dir, src), 'utf8'); } dataJS += ' '; } @@ -487,12 +492,12 @@ glob href.indexOf('all.css') < 0 ) { console.log(' [link]: ' + href); - dataCSS += fs.readFileSync(path.join(dir, href), 'utf8'); + dataCSS += fs.readFileSync(joinPaths(dir, href), 'utf8'); } dataCSS += ' '; } - let ref = path.join('../../..', file); + let ref = joinPaths('../../..', file); let title = html .querySelector('title') .textContent.split('|')[0] @@ -673,11 +678,11 @@ function getRolesPropertiesAndStatesFromGuidance(html, url) { } const patternFiles = glob.sync('content/patterns/!(landmarks)/*-pattern.html', { - cwd: path.join(__dirname, '..'), + cwd: joinPaths(__dirname, '..'), }); const practiceFiles = glob.sync('content/practices/*/*-practice.html', { - cwd: path.join(__dirname, '..'), + cwd: joinPaths(__dirname, '..'), }); const guidanceFiles = [...patternFiles, ...practiceFiles]; @@ -687,7 +692,7 @@ guidanceFiles.forEach(function (file) { let html = HTMLParser.parse(data); - getRolesPropertiesAndStatesFromGuidance(html, path.join('../../../', file)); + getRolesPropertiesAndStatesFromGuidance(html, joinPaths('../../../', file)); }); // Add landmark examples, since they are a different format