Spaces:
Running
Running
Download index.html from getreadystack/wcag-clause-audit: direct link, hf CLI and curl.
- Browser
- Download file 43.2 kB
-
https://huggingface.co/spaces/getreadystack/wcag-clause-audit/resolve/main/index.html
- Command line
-
hf download hf://spaces/getreadystack/wcag-clause-audit/index.html
-
curl -L -o index.html https://huggingface.co/spaces/getreadystack/wcag-clause-audit/resolve/main/index.html
43.2 kB
| <html lang="en"> | |
| <meta charset="utf-8"> | |
| <title>WCAG 2.1 AA Audit: ADA Title II, EAA, 508</title> | |
| <meta name="viewport" content="width=device-width,initial-scale=1"> | |
| <meta name="description" content="Flags accessibility failures in the open file, cites the exact WCAG success criterion and EN 301 549 clause, and tells you which standard version and deadline actually bind you."> | |
| <style> | |
| *{box-sizing:border-box} | |
| body{margin:0;font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:#12151a;background:#f6f7f9} | |
| .wrap{max-width:960px;margin:0 auto;padding:26px 20px 60px} | |
| h1{font-size:26px;line-height:1.25;margin:0 0 6px} | |
| .sub{color:#4a5260;margin:0 0 18px;max-width:70ch} | |
| .card{background:#fff;border:1px solid #e0e4ea;border-radius:10px;padding:16px 18px;margin:0 0 16px} | |
| label{display:block;font-weight:600;font-size:13px;margin:0 0 6px} | |
| select,textarea{width:100%;font-size:14px;border:1px solid #ccd2db;border-radius:7px;padding:9px 10px;background:#fff;color:#12151a} | |
| textarea{min-height:132px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5} | |
| button.go{margin-top:10px;background:#12151a;color:#fff;border:0;border-radius:7px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer} | |
| .bind{background:#0f172a;color:#e8edf5;border-radius:10px;padding:14px 16px;margin:0 0 16px} | |
| .bind .std{font-size:19px;font-weight:700;color:#fff} | |
| .bind .when{font-size:14px;margin-top:3px;color:#9fd0ff} | |
| .bind .note{font-size:12.5px;margin-top:8px;color:#b8c2d1;line-height:1.5} | |
| .cnt{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:#4a5260;margin:18px 0 8px} | |
| ul.f{list-style:none;margin:0;padding:0} | |
| ul.f li{border-left:3px solid #d0d5dd;background:#fff;border-radius:0 7px 7px 0;padding:8px 12px;margin:0 0 6px;font-size:13.5px} | |
| li.error{border-left-color:#c0392b}li.warn{border-left-color:#d68910}li.info{border-left-color:#8a94a6} | |
| li .ln{font-family:ui-monospace,Menlo,Consolas,monospace;color:#6b7280;margin-right:8px} | |
| .out-of{opacity:.72} | |
| .out-of li{border-left-style:dashed} | |
| .why{font-size:13px;color:#4a5260;margin:6px 0 0} | |
| .buy{display:inline-block;background:#1a5fd4;color:#fff;text-decoration:none;border-radius:7px;padding:11px 20px;font-weight:600;margin-top:4px} | |
| .paid{background:#fff;border:1px solid #e0e4ea;border-radius:10px;padding:16px 18px;margin:16px 0 0} | |
| .paid ul{margin:8px 0 12px;padding-left:20px;font-size:14px} | |
| .terms{font-size:12.5px;color:#6b7280;margin:8px 0 0} | |
| footer{margin-top:34px;font-size:12.5px;color:#6b7280;line-height:1.6} | |
| </style> | |
| <div class="wrap"> | |
| <h1>WCAG 2.1 AA Audit: ADA Title II, EAA, 508</h1> | |
| <p class="sub">Flags accessibility failures in the open file, cites the exact WCAG success criterion and EN 301 549 clause, and tells you which standard version and deadline actually bind you.</p> | |
| <div class="card"> | |
| <label for="regime">Who are you shipping to?</label> | |
| <select id="regime"></select> | |
| <label for="src" style="margin-top:14px">Paste your markup, JSX or CSS</label> | |
| <textarea id="src" spellcheck="false"></textarea> | |
| <button class="go" id="go">Audit this file</button> | |
| </div> | |
| <div id="bind" class="bind"></div> | |
| <div id="out"></div> | |
| <div class="paid"> | |
| <p style="margin:0 0 2px;font-weight:600">This page audits one file. The extension does the rest.</p> | |
| <ul> | |
| <li>Scan every file in the workspace, not just the one that is open</li> | |
| <li>Write the conformance report to a file (CSV/JSON/HTML) you can hand to an auditor</li> | |
| <li>Machine-readable JSON so CI can fail the build on new violations</li> | |
| <li>Re-audit automatically every time you save</li> | |
| </ul> | |
| <a href="https://getreadystack.com" class="buy">Get the full version - $29</a> | |
| <p class="terms">$29 once - one licence key per person or team seat. | |
| A one-off professional WCAG audit runs about $1,250-$2,750; a procurement-grade VPAT starts near $350.</p> | |
| </div> | |
| <footer> | |
| <strong>Sources.</strong> ADA Title II deadlines: US DOJ interim final rule of 2026-04-17, which moved the | |
| 2026-04-24 and 2027-04-26 dates back by one year; technical standard WCAG 2.1 Level AA, unchanged. | |
| Section 508: Revised 508 Standards, in force 2018-01-18, referencing WCAG 2.0 Level AA. | |
| EAA: applies since 2025-06-28; harmonised standard EN 301 549 v3.2.1 (WCAG 2.1 AA); v4.1.0 entered final | |
| deliverable voting in June 2026; pre-existing service contracts may run to 2027-06-28, with 2030-06-28 as the | |
| final catch-all.<br> | |
| <strong>Limits.</strong> These 23 checks are line-scoped regular expressions. They cannot see tags split | |
| across lines, computed markup, colour contrast or focus order, and they do not replace manual and | |
| assistive-technology testing. They tell you which criteria bind you and catch the failures that are visible | |
| on a single line. | |
| </footer> | |
| </div> | |
| <script> | |
| var RULES = [{"pattern": "<img\\b(?![^>]*\\s(?:alt(?=[\\s=/>])|aria-label\\s*=|aria-labelledby\\s*=|role\\s*=\\s*[\"\\']?(?:presentation|none)\\b|aria-hidden\\s*=\\s*[\"\\']?true\\b))[^>]*>", "flags": "i", "message": "SC 1.1.1 (A) img has no alt attribute - EN 301 549 9.1.1.1 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<img[^>]*\\balt\\s*=\\s*[\"\\'](?:image|photo|picture|graphic|icon|logo|spacer)[\"\\']", "flags": "i", "message": "SC 1.1.1 (A) alt text is a placeholder word, not a description - EN 301 549 9.1.1.1 [508 . ADA . EAA]", "sev": "warn", "wcag": "2.0"}, {"pattern": "<html(?![^>]*\\blang\\s*=)[^>]*>", "flags": "i", "message": "SC 3.1.1 (A) html element has no lang attribute - EN 301 549 9.3.1.1 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<input(?![^>]*\\btype\\s*=\\s*[\"\\'](?:hidden|submit|button|reset|image)[\"\\'])(?![^>]*\\baria-label)(?![^>]*\\baria-labelledby)(?![^>]*\\bid\\s*=)[^>]*>", "flags": "i", "message": "SC 4.1.2 (A) input has no id, aria-label or aria-labelledby, so it can never be labelled - EN 301 549 9.4.1.2 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<(?:select|textarea)\\b(?![^>]*\\baria-label)(?![^>]*\\baria-labelledby)(?![^>]*\\bid\\s*=)[^>]*>", "flags": "i", "message": "SC 4.1.2 (A) select/textarea has no id or aria-label, so it has no accessible name - EN 301 549 9.4.1.2 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<iframe(?![^>]*\\btitle\\s*=)[^>]*>", "flags": "i", "message": "SC 4.1.2 (A) iframe has no title attribute - EN 301 549 9.4.1.2 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "\\btabindex\\s*=\\s*[\"\\']?[1-9]", "flags": "i", "message": "SC 2.4.3 (A) positive tabindex overrides the natural focus order - EN 301 549 9.2.4.3 [508 . ADA . EAA]", "sev": "warn", "wcag": "2.0"}, {"pattern": "<a\\b(?![^>]*\\bhref\\s*=)[^>]*>", "flags": "i", "message": "SC 2.1.1 (A) anchor without href is not keyboard focusable - EN 301 549 9.2.1.1 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<(?:div|span|li|td|p|img)\\b[^>]*\\bonclick\\s*=", "flags": "i", "message": "SC 2.1.1 (A) click handler on a non-interactive element - no keyboard access - EN 301 549 9.2.1.1 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "(?:^|<(?!(?:button|input|select|textarea|summary)\\b|(?:a|area)\\b[^>]*\\shref\\s*=)[a-z][a-z0-9]*\\b)(?![^<>]*\\btabindex\\s*=)[^<>]*?\\brole\\s*=\\s*[\"\\']button[\"\\'](?![^>]*\\btabindex\\s*=)", "flags": "i", "message": "SC 2.1.1 (A) role=\"button\" without tabindex is not reachable by keyboard - EN 301 549 9.2.1.1 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<(?:a\\b(?=[^>]*\\shref\\s*=)|(?:button|input|select|textarea)\\b)(?![^>]*\\stabindex\\s*=\\s*[\"\\']?-1)(?![^>]*\\sdisabled(?=[\\s=/>]|$))[^>]*\\baria-hidden\\s*=\\s*[\"\\']true[\"\\']", "flags": "i", "message": "SC 4.1.2 (A) aria-hidden=\"true\" on a focusable control hides it from AT but keeps focus - EN 301 549 9.4.1.2 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<(?:video|audio)\\b[^>]*\\bautoplay\\b", "flags": "i", "message": "SC 1.4.2 (A) media autoplays with no mechanism to stop it - EN 301 549 9.1.4.2 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<video\\b(?![^>]*\\bcontrols\\b)[^>]*>", "flags": "i", "message": "SC 1.4.2 (A) video without controls gives no way to pause or mute - EN 301 549 9.1.4.2 [508 . ADA . EAA]", "sev": "warn", "wcag": "2.0"}, {"pattern": "<th\\b(?![^>]*\\bscope\\s*=)[^>]*>", "flags": "i", "message": "SC 1.3.1 (A) th has no scope, so the header-cell relationship is not programmatic - EN 301 549 9.1.3.1 [508 . ADA . EAA]", "sev": "warn", "wcag": "2.0"}, {"pattern": "<meta[^>]*viewport[^>]*(?:user-scalable\\s*=\\s*[\"\\']?no|maximum-scale\\s*=\\s*[\"\\']?1(?:\\.0)?\\b)", "flags": "i", "message": "SC 1.4.4 (AA) viewport blocks zoom - text cannot be resized to 200% - EN 301 549 9.1.4.4 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "outline\\s*:\\s*(?:0|none)\\b", "flags": "i", "message": "SC 2.4.7 (AA) outline removed - confirm a visible focus style replaces it - EN 301 549 9.2.4.7 [508 . ADA . EAA]", "sev": "warn", "wcag": "2.0"}, {"pattern": "<svg\\b(?![^>]*\\baria-hidden)(?![^>]*\\baria-label)(?![^>]*\\brole\\s*=)[^>]*>", "flags": "i", "message": "SC 1.1.1 (A) svg is neither labelled nor marked decorative with aria-hidden - EN 301 549 9.1.1.1 [508 . ADA . EAA]", "sev": "info", "wcag": "2.0"}, {"pattern": "<button\\b(?![^>]*\\baria-label)(?![^>]*\\btitle\\s*=)[^>]*>\\s*<(?:i|svg)\\b", "flags": "i", "message": "SC 4.1.2 (A) icon-only button has no accessible name - EN 301 549 9.4.1.2 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "\\baccesskey\\s*=", "flags": "i", "message": "SC 2.1.1 (A) accesskey often collides with AT and browser shortcuts - EN 301 549 9.2.1.1 [508 . ADA . EAA]", "sev": "warn", "wcag": "2.0"}, {"pattern": "<(?:blink|marquee)\\b", "flags": "i", "message": "SC 2.2.2 (A) blink/marquee moves or blinks with no way to pause it - EN 301 549 9.2.2.2 [508 . ADA . EAA]", "sev": "error", "wcag": "2.0"}, {"pattern": "<label\\b(?![^>]*\\bfor\\s*=)[^>]*>", "flags": "i", "message": "SC 1.3.1 (A) label has no for attribute - confirm it wraps its own control - EN 301 549 9.1.3.1 [508 . ADA . EAA]", "sev": "info", "wcag": "2.0"}, {"pattern": "<input[^>]*\\bname\\s*=\\s*[\"\\'](?:email|e-mail|fname|firstname|first_name|lname|lastname|last_name|tel|telephone|phone|address|street|city|zip|postcode|postal|country|cc-number|cc-name)[\"\\'](?![^>]*\\bautocomplete\\s*=)", "flags": "i", "message": "SC 1.3.5 (AA) personal-data input has no autocomplete token - EN 301 549 9.1.3.5 - WCAG 2.1 ONLY [ADA . EAA - NOT 508]", "sev": "warn", "wcag": "2.1"}, {"pattern": "screen\\.orientation\\.lock\\s*\\(", "flags": "i", "message": "SC 1.3.4 (AA) orientation is locked - EN 301 549 9.1.3.4 - WCAG 2.1 ONLY [ADA . EAA - NOT 508]", "sev": "error", "wcag": "2.1"}]; | |
| var REGIMES = [ | |
| { | |
| id: 'us_ada_t2_large', | |
| label: 'US - ADA Title II, public entity serving 50,000+', | |
| standard: 'WCAG 2.1 Level AA', | |
| wcag: '2.1', | |
| deadline: '2027-04-26', | |
| note: 'DOJ issued an interim final rule on 2026-04-17 that moved this from 2026-04-24 by one year. ' | |
| + 'Checklists and chatbots written before that date still quote 2026-04-24, which is no longer the deadline. ' | |
| + 'The technical standard and the content scope did not change.' | |
| }, | |
| { | |
| id: 'us_ada_t2_small', | |
| label: 'US - ADA Title II, public entity under 50,000 or special district', | |
| standard: 'WCAG 2.1 Level AA', | |
| wcag: '2.1', | |
| deadline: '2028-04-26', | |
| note: 'Also moved by one year by the DOJ interim final rule of 2026-04-17 (from 2027-04-26). ' | |
| + 'There is no small-entity exemption - the standard is identical, only the date differs.' | |
| }, | |
| { | |
| id: 'us_508', | |
| label: 'US - Section 508 (federal ICT and its vendors)', | |
| standard: 'WCAG 2.0 Level AA', | |
| wcag: '2.0', | |
| deadline: null, | |
| inForce: '2018-01-18', | |
| note: 'The Revised 508 Standards still reference WCAG 2.0 Level AA (38 criteria). ' | |
| + 'The 17 success criteria added by WCAG 2.1 are NOT required by Section 508. ' | |
| + 'A scanner set to WCAG 2.1 or 2.2 will flag work you are not legally obliged to do here.' | |
| }, | |
| { | |
| id: 'eu_eaa_new', | |
| label: 'EU - European Accessibility Act, product or service placed on the market since 2025-06-28', | |
| standard: 'EN 301 549 v3.2.1 -> WCAG 2.1 Level AA', | |
| wcag: '2.1', | |
| deadline: null, | |
| inForce: '2025-06-28', | |
| note: 'v3.2.1 is the harmonised version and it incorporates WCAG 2.1 AA. EN 301 549 v4.1.0 entered final ' | |
| + 'deliverable voting in June 2026 and v4.1.1 is expected to move to WCAG 2.2 - until it is cited, ' | |
| + 'WCAG 2.1 AA is what binds. Microenterprises (under 10 staff and turnover at most EUR 2M) are exempt ' | |
| + 'for SERVICES only, never for products they place on the market.' | |
| }, | |
| { | |
| id: 'eu_eaa_legacy', | |
| label: 'EU - EAA, service under a contract concluded before 2025-06-28', | |
| standard: 'EN 301 549 v3.2.1 -> WCAG 2.1 Level AA', | |
| wcag: '2.1', | |
| deadline: '2027-06-28', | |
| note: 'Service contracts already in force on 2025-06-28 may continue unchanged until 2027-06-28. ' | |
| + 'From 2030-06-28 every in-scope product and service must comply regardless of when it was released.' | |
| } | |
| ]; | |
| var ORDER = {'2.0':0,'2.1':1,'2.2':2}; | |
| function inScope(w, rg){ return ORDER[String(w||'2.0')] <= ORDER[String(rg.wcag)]; } | |
| function daysUntil(iso){ | |
| if(!iso) return null; | |
| return Math.round((new Date(iso+'T00:00:00Z') - new Date()) / 86400000); | |
| } | |
| function whenText(rg){ | |
| var d = daysUntil(rg.deadline); | |
| if(rg.deadline === null) return 'in force since ' + rg.inForce; | |
| if(d < 0) return 'deadline ' + rg.deadline + ' has PASSED (' + (-d) + ' days ago)'; | |
| return 'deadline ' + rg.deadline + ' \u2014 ' + d + ' days left'; | |
| } | |
| function scan(text){ | |
| var lines = String(text).split(/\r?\n/), hits = [], i, k, r, re; | |
| for(i=0;i<lines.length;i++){ | |
| for(k=0;k<RULES.length;k++){ | |
| r = RULES[k]; | |
| try { re = new RegExp(r.pattern, r.flags||''); } catch(e){ continue; } | |
| if(re.test(lines[i])) hits.push({line:i+1, msg:r.message, sev:r.sev||'warn', wcag:r.wcag||'2.0'}); | |
| } | |
| } | |
| return hits; | |
| } | |
| function esc(t){ return String(t).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); } | |
| function render(){ | |
| var rg = REGIMES.filter(function(x){ return x.id === document.getElementById('regime').value; })[0] || REGIMES[0]; | |
| document.getElementById('bind').innerHTML = | |
| '<div class="std">' + esc(rg.standard) + '</div>' + | |
| '<div class="when">' + esc(whenText(rg)) + '</div>' + | |
| '<div class="note">' + esc(rg.note) + '</div>'; | |
| var hits = scan(document.getElementById('src').value); | |
| var req = [], not = [], i; | |
| for(i=0;i<hits.length;i++){ (inScope(hits[i].wcag, rg) ? req : not).push(hits[i]); } | |
| function list(a, cls){ | |
| var s = '<ul class="f' + (cls||'') + '">', j; | |
| for(j=0;j<a.length;j++){ | |
| s += '<li class="' + a[j].sev + '"><span class="ln">line ' + a[j].line + '</span>' + esc(a[j].msg) + '</li>'; | |
| } | |
| return s + '</ul>'; | |
| } | |
| var h = ''; | |
| if(!hits.length){ | |
| h = '<p class="cnt">0 findings</p><p class="why">No matches for the ' + RULES.length + | |
| ' shipped rules. Line-scoped checks cannot see multi-line tags or computed markup \u2014 keep manual testing.</p>'; | |
| } else { | |
| h += '<p class="cnt">' + req.length + ' finding' + (req.length===1?'':'s') + ' you must fix for this regime</p>'; | |
| h += req.length ? list(req) : '<p class="why">Nothing in this file is required by the regime you selected.</p>'; | |
| if(not.length){ | |
| h += '<p class="cnt">' + not.length + ' finding' + (not.length===1?'':'s') + ' NOT required here</p>'; | |
| h += '<p class="why">' + esc(rg.standard.indexOf('2.0') > -1 | |
| ? 'These are WCAG 2.1 criteria. Section 508 still cites WCAG 2.0 Level AA, so you are not legally obliged to fix them \u2014 a scanner set to WCAG 2.2 would bill you for this work anyway.' | |
| : 'Outside the version this regime cites.') + '</p>'; | |
| h += list(not, ' out-of'); | |
| } | |
| } | |
| document.getElementById('out').innerHTML = h; | |
| } | |
| (function init(){ | |
| var sel = document.getElementById('regime'), i, o; | |
| for(i=0;i<REGIMES.length;i++){ | |
| o = document.createElement('option'); | |
| o.value = REGIMES[i].id; o.textContent = REGIMES[i].label; | |
| sel.appendChild(o); | |
| } | |
| sel.value = "us_508"; | |
| document.getElementById('src').value = "<html>\n <img src=\"hero.png\">\n <div onclick=\"submit()\">Send</div>\n <input name=\"email\" placeholder=\"Email\">\n <button><svg viewBox=\"0 0 16 16\"></svg></button>\n</html>"; | |
| document.getElementById('go').addEventListener('click', render); | |
| sel.addEventListener('change', render); | |
| render(); // a completed result is on screen at first paint | |
| })(); | |
| </script> | |
| </html> | |
| <section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://www.npmjs.com/package/@readystack/wcag-clause-audit" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'wcag-clause-audit',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://hub.docker.com/r/getreadystack/wcag-clause-audit" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'wcag-clause-audit',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">npx @readystack/wcag-clause-audit <file> | |
| docker run --rm -v "$PWD:/w" getreadystack/wcag-clause-audit /w</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section> | |
| <section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get one email when this rule changes</b><div style="opacity:.78;margin:.35rem 0 .8rem">We watch the regulation and vendor sources behind WCAG 2.1 AA Audit: ADA Title II, EAA, 508 every day. When a rule changes, you get a single email with what changed and the updated check. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Notify me</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">You're on the list. One email when it changes.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"wcag-clause-audit",lang:"en",source:"rule_alert"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section> | |
| <section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">Flags accessibility failures in the open file, cites the exact WCAG success criterion and EN 301 549 clause, and tells you which standard version and deadline actually bind you.</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">A one-off professional WCAG audit runs about $1,250-$2,750 for a typical site, and a procurement-grade VPAT/ACR starts around $350 and reaches $3,000-$15,000 for government procurement.</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_S4Q2ATU1yHnb0CDupM8ykagoorbx7NrWOZ6XY0QFsxj" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section> | |
| <!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&","<":"<",">":">",'"':"""}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div><section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-09">Updated 2026-09-09</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-09","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku21264_result_card.jpg" alt="WCAG 2.1 AA Audit: ADA Title II, EAA, 508" loading="lazy" style="max-width:100%;border-radius:6px"></p> | |
| <p>Six lines of ordinary HTML fail WCAG 2.1 Level AA, and if you build for a US city, county or school district, one of those six is not actually your problem. That distinction is the whole job, and almost no tooling makes it.</p> | |
| <p>Here is the part most teams have wrong. On 17 April 2026 the US Department of Justice issued an interim final rule moving the ADA Title II web accessibility deadlines back by one year. Public entities serving 50,000 or more now have until 26 April 2027. Smaller entities and special districts have until 26 April 2028. The technical standard did not change: it is still WCAG 2.1 Level AA. But every guide, wiki page and chatbot answer written before that April date still quotes 24 April 2026, and teams are planning sprints around a date that no longer exists.</p> | |
| <p>The second thing teams get wrong is the version. These three regimes do not cite the same one:</p> | |
| <ul><li>ADA Title II cites WCAG 2.1 Level AA (55 criteria).</li><li>Section 508 still cites WCAG 2.0 Level AA (38 criteria), unchanged since the 2017 refresh took effect in January 2018.</li><li>The European Accessibility Act, applicable since 28 June 2025, works through EN 301 549 v3.2.1, which incorporates WCAG 2.1 Level AA. Version 4.1.0 entered final deliverable voting in June 2026 and v4.1.1 is expected to move to WCAG 2.2 - but until it is cited, 2.1 is what binds.</li></ul> | |
| <p>So take one line:</p> | |
| <pre><code><input name="email" placeholder="Email"></code></pre> | |
| <p>Under ADA Title II that trips two criteria: SC 4.1.2, because with no id and no aria-label it can never be given an accessible name, and SC 1.3.5 Identify Input Purpose, because a personal-data field carries no autocomplete token. Under Section 508, only the first one counts. SC 1.3.5 was added in WCAG 2.1 and Section 508 never adopted it. A federal team running a scanner set to WCAG 2.2 gets handed a backlog it is under no legal obligation to clear.</p> | |
| <p>That is what this extension does. It audits the file you have open, cites every finding to its exact success criterion and the matching EN 301 549 clause, then splits the list into what your regime requires and what it does not - and shows the date you are working towards, counted from today. Twenty-three checks ship inside, all line-scoped regular expressions.</p> | |
| <p>It is deliberately not an axe replacement. axe, Lighthouse and eslint-plugin-jsx-a11y detect far more than twenty-three patterns and you should keep running them. They also cannot see tags split across lines, and neither can this. What they will not tell you is which of their findings you are legally required to fix, or when. That answer is worth more than another hundred rules.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku21264_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku21264_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does this extension actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It scans the file you have open and flags accessibility failures line by line. Every finding names the exact WCAG success criterion and the matching EN 301 549 clause, and marks which regimes it is in scope for. It then resolves your jurisdiction to the standard version and compliance date that legally bind you, so you fix what is required rather than everything a generic scanner reports.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Front-end and full-stack developers at agencies, SaaS teams and public-sector vendors who ship web interfaces to EU consumers under the European Accessibility Act, or to US state and local government buyers under ADA Title II, or to federal buyers under Section 508. It is written for the person editing the markup, not for the compliance officer.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just use axe, Lighthouse or eslint-plugin-jsx-a11y?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Those tools detect more than this one does, and you should keep using them. What none of them do is tell you which standard version binds you. They report against WCAG 2.2 by default, yet Section 508 still cites WCAG 2.0 AA and ADA Title II cites WCAG 2.1 AA. So they flag criteria you are not legally required to meet.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what needs a licence key?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free covers one file completely: all rules run, every finding is cited, and the jurisdiction, standard version and deadline are resolved. Nothing is watermarked, timed or locked after N runs. The licence key covers a different job: scanning the whole workspace, exporting the conformance report file, emitting CI JSON, and re-auditing on every save.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What would this cost me otherwise?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A one-off professional WCAG audit runs roughly $1,250 to $2,750 for a typical site, and far more for large ones. A procurement-grade VPAT or Accessibility Conformance Report starts around $350 and reaches $3,000 to $15,000 when it is written for government procurement. This extension is $29 once, and it does not replace that audit - it stops you paying for findings you could have fixed first.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does this extension actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It scans the file you have open and flags accessibility failures line by line. Every finding names the exact WCAG success criterion and the matching EN 301 549 clause, and marks which regimes it is in scope for. It then resolves your jurisdiction to the standard version and compliance date that legally bind you, so you fix what is required rather than everything a generic scanner reports."}}, {"@type": "Question", "name": "Who is this for?", "acceptedAnswer": {"@type": "Answer", "text": "Front-end and full-stack developers at agencies, SaaS teams and public-sector vendors who ship web interfaces to EU consumers under the European Accessibility Act, or to US state and local government buyers under ADA Title II, or to federal buyers under Section 508. It is written for the person editing the markup, not for the compliance officer."}}, {"@type": "Question", "name": "Why not just use axe, Lighthouse or eslint-plugin-jsx-a11y?", "acceptedAnswer": {"@type": "Answer", "text": "Those tools detect more than this one does, and you should keep using them. What none of them do is tell you which standard version binds you. They report against WCAG 2.2 by default, yet Section 508 still cites WCAG 2.0 AA and ADA Title II cites WCAG 2.1 AA. So they flag criteria you are not legally required to meet."}}, {"@type": "Question", "name": "What is free and what needs a licence key?", "acceptedAnswer": {"@type": "Answer", "text": "Free covers one file completely: all rules run, every finding is cited, and the jurisdiction, standard version and deadline are resolved. Nothing is watermarked, timed or locked after N runs. The licence key covers a different job: scanning the whole workspace, exporting the conformance report file, emitting CI JSON, and re-auditing on every save."}}, {"@type": "Question", "name": "What would this cost me otherwise?", "acceptedAnswer": {"@type": "Answer", "text": "A one-off professional WCAG audit runs roughly $1,250 to $2,750 for a typical site, and far more for large ones. A procurement-grade VPAT or Accessibility Conformance Report starts around $350 and reaches $3,000 to $15,000 when it is written for government procurement. This extension is $29 once, and it does not replace that audit - it stops you paying for findings you could have fixed first."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:21264,slug:"wcag-clause-audit",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/wcag21-aa-legal-baseline-audit"><span class="yj-rel-t">WCAG 2.1 AA Legal Baseline Audit for templates</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/ada-title-ii-deadline-lint"><span class="yj-rel-t">ADA Title II Deadline Lint (WCAG 2.1 AA)</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/en301549-lint"><span class="yj-rel-t">EN 301 549 Lint — European Accessibility Act rules, with the clause number, in</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/wordpress-ada-compliance-plugin"><span class="yj-rel-t">ADA Compliance Plugin for WordPress: Title II Grievance Form</span><span class="yj-rel-p">$60</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/web-ui-kit-figma-sketch"><span class="yj-rel-t">Web UI Kit for SaaS Dashboards — 8 Components, 32 Variant States (Figma plugin</span><span class="yj-rel-p">$168</span></a><a class="yj-rel-c" href="https://getreadystack.com/en/p/build-6-procreate-lettering-brushes-that-feel-like-ink-the-e"><span class="yj-rel-t">Build 6 Procreate Lettering Brushes That Feel Like Ink — The Exact-Settings Wo</span><span class="yj-rel-p">$39</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section> | |
| <script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script> | |
| <script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script> | |