@jrpool/kilotest 60.1.0 → 60.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.htmlhintrc +29 -0
  2. package/error.html +1 -5
  3. package/index.test.ts +8 -2
  4. package/index.ts +5 -5
  5. package/lhm.plugin.json +1 -1
  6. package/linkValidation.test.ts +1 -0
  7. package/logo.svg +15 -0
  8. package/openapi-3.0.yaml +1 -1
  9. package/openapi.yaml +1 -1
  10. package/package.json +3 -2
  11. package/server.json +1 -1
  12. package/smokeTest.ts +1 -1
  13. package/style.css +199 -0
  14. package/util.ts +22 -3
  15. package/web/ai0BalanceForm/index.html +1 -6
  16. package/web/deleteNotesForm/index.html +3 -8
  17. package/web/deleteNotesForm/index.ts +1 -1
  18. package/web/enqueue/index.html +1 -6
  19. package/web/enqueueForm/index.html +3 -8
  20. package/web/enqueueForm/index.ts +1 -1
  21. package/web/expungeReportsForm/index.html +3 -8
  22. package/web/head.partial +6 -0
  23. package/web/hideReportForm/index.html +1 -6
  24. package/web/home/home.test.ts +1 -1
  25. package/web/home/index.html +53 -41
  26. package/web/home/index.ts +2 -3
  27. package/web/listDiagnoses/index.html +1 -6
  28. package/web/listDiagnoses/index.ts +3 -3
  29. package/web/listIssues/index.html +1 -6
  30. package/web/listPages/index.html +1 -6
  31. package/web/listRules/index.html +1 -6
  32. package/web/listTopIssues/index.html +1 -6
  33. package/web/listViolators/index.html +1 -6
  34. package/web/listViolators/index.ts +1 -1
  35. package/web/manage/index.html +1 -6
  36. package/web/manage/index.ts +2 -3
  37. package/web/metrics/index.html +1 -6
  38. package/web/privacy/index.html +1 -6
  39. package/web/privacy/index.ts +2 -3
  40. package/web/pruneReportsForm/index.html +3 -8
  41. package/web/reannotate/index.html +1 -6
  42. package/web/reannotate/index.ts +2 -2
  43. package/web/reannotateForm/index.html +1 -6
  44. package/web/renewWCAG/index.html +1 -6
  45. package/web/renewWCAG/index.ts +2 -2
  46. package/web/renewWCAGForm/index.html +2 -7
  47. package/web/renewWCAGForm/index.ts +2 -3
  48. package/web/reportDeletion.ts +1 -1
  49. package/web/requestNewTest/index.html +1 -6
  50. package/web/requestNewTestForm/index.html +1 -6
  51. package/web/requestNewTestForm/index.ts +2 -3
  52. package/web/requestRetest/index.html +1 -6
  53. package/web/requestRetestForm/index.html +1 -6
  54. package/web/rewindReportsForm/index.html +3 -8
  55. package/web/showHiddenReportsForm/index.html +2 -7
  56. package/web/tutorialAI/index.html +1 -6
  57. package/web/tutorialAI/index.ts +9 -2
  58. package/web/tutorialWeb/index.html +1 -6
  59. package/web/tutorialWeb/index.ts +9 -2
  60. package/web/unhideReportForm/index.html +2 -7
  61. package/favicon.ico +0 -0
@@ -1,13 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Kilotest</title>
10
- <link rel="stylesheet" href="/style.css">
11
7
  <script type="application/ld+json">
12
8
  {
13
9
  "@context": "https://schema.org",
@@ -55,43 +51,59 @@
55
51
  }
56
52
  </script>
57
53
  </head>
58
- <body>
54
+ <body class="home">
55
+ <header>
56
+ <div class="header-inner">
57
+ <span class="brand">__logo__Kilotest</span>
58
+ <span class="brand-tag">Ensemble front-end testing</span>
59
+ </div>
60
+ </header>
59
61
  <main>
60
- <h1>Kilotest</h1>
61
- <p>Kilotest performs more than a thousand tests on a web page.</p>
62
- <details>
63
- <summary>More than a thousand? Really?</summary>
64
- <h2>Ensemble testing</h2>
65
- <p>Kilotest does <strong>ensemble testing</strong> of web pages for <a href="https://www.w3.org/mission/accessibility/">accessibility</a>, usability, and web standards, including HTML, CSS, ARIA, and WCAG.</p>
66
- <p>Efficient testing <strong>first</strong> leverages <strong>automated rule engines</strong> and corrects the defects that they discover, <strong>then</strong> employs human testers.</p>
67
- <p>Choosing among the <a href="https://www.w3.org/WAI/test-evaluate/tools/list/">many automated rule engines</a> is hard, because they <a href="https://arxiv.org/pdf/2304.07591">vary in what and how they test</a>.</p>
68
- <p><strong>Ensemble testing</strong>, instead of choosing only one, combines <strong>multiple rule engines</strong>. It can discover more issues than single-rule-engine testing, and the rule engines can check one another&rsquo;s quality.</p>
69
- <h2>The rule engines</h2>
70
- <p>The Kilotest ensemble is <a href="https://github.com/YRA-Tech/testaro?tab=readme-ov-file#dependencies">12 rule engines</a> developed by teams in Australia, Canada, Denmark, Luxembourg, Portugal, Spain, Switzerland, the United Kingdom, and the United States.</p>
71
- <p>The rule engines perform about 1,300 tests in total. <a href="https://medium.com/cvs-health-tech-blog/how-to-run-a-thousand-accessibility-tests-63692ad120c3">Open-source software</a> developed initially at CVS Health drives the rule engines, tries to weed out invalid results, and distills the findings into about 380 <q>issues</q>.</p>
72
- <h2>Features</h2>
73
- <p>With Kilotest, you can get results of already performed tests and propose web pages for testing. (Immediate testing on request may become available in a future version.)</p>
74
- <p>There is a <a href="/capability.md">capability document</a> that summarizes what Kilotest can do for human and AI-agent users.</p>
75
- <h2>How to use Kilotest</h2>
76
- <h3>If you are a human user on the web</h3>
77
- <p>You can use Kilotest starting on this page.</p>
78
- <p>If your main interest is accessibility, feel free to learn more about it with our <a href="/tutorialWeb.html">tutorial</a>.</p>
79
- <h3>If you are a human user of AI</h3>
80
- <p>An AI assistant can use the Kilotest MCP server to give you precise answers about the front-end quality of a web page. If the AI assistant does not already have permission to use Kilotest, you can grant that permission. <a href="/tutorialAI.html">Learn how to connect AI platforms to Kilotest</a>.</p>
81
- <h3>If you are an AI agent or model</h3>
82
- <p>Go to the <a href="/mcp">Kilotest MCP server</a>.</p>
83
- <h3>If you are developing an application</h3>
84
- <p>Your application can use the Kilotest API, which has an <a href="/openapi.yaml">OpenAPI specification</a>.</p>
85
- <h2>Comments?</h2>
86
- <p>Your suggestions, bug reports, and collaboration proposals are welcome! Post them on <a href="https://github.com/jrpool/kilotest/issues">GitHub</a> or email them to <a href="mailto:info@kilotest.com">info@kilotest.com</a>.</p>
87
- </details>
88
- <h2>What do you want to know?</h2>
89
- <ul class="nav">
90
- <li><a href="listPages.html">Which web pages have been tested?</a></li>
91
- <li><a href="listTopIssues.html">Which issues have been reported?</a></li>
92
- <li><a href="manage.html">What can Kilotest managers do?</a></li>
93
- <li><a href="privacy.html">Privacy policy</a></li>
94
- </ul>
62
+ <div class="hero">
63
+ <p class="eyebrow">12 rule engines · ~1,300 tests</p>
64
+ <h1>More than a thousand tests on every web page.</h1>
65
+ <p class="lede">Kilotest tests web pages for accessibility, usability, and web standards — and reports what matters, at the level of detail you choose.</p>
66
+ <details>
67
+ <summary>More than a thousand? Really?</summary>
68
+ <h2>Ensemble testing</h2>
69
+ <p>Kilotest does <strong>ensemble testing</strong> of web pages for <a href="https://www.w3.org/mission/accessibility/">accessibility</a>, usability, and web standards, including HTML, CSS, ARIA, and WCAG.</p>
70
+ <p>Efficient testing <strong>first</strong> leverages <strong>automated rule engines</strong> and corrects the defects that they discover, <strong>then</strong> employs human testers.</p>
71
+ <p>Choosing among the <a href="https://www.w3.org/WAI/test-evaluate/tools/list/">many automated rule engines</a> is hard, because they <a href="https://arxiv.org/pdf/2304.07591">vary in what and how they test</a>.</p>
72
+ <p><strong>Ensemble testing</strong>, instead of choosing only one, combines <strong>multiple rule engines</strong>. It can discover more issues than single-rule-engine testing, and the rule engines can check one another&rsquo;s quality.</p>
73
+ <h2>The rule engines</h2>
74
+ <p>The Kilotest ensemble is <a href="https://github.com/YRA-Tech/testaro?tab=readme-ov-file#dependencies">12 rule engines</a> developed by teams in Australia, Canada, Denmark, Luxembourg, Portugal, Spain, Switzerland, the United Kingdom, and the United States.</p>
75
+ <p>The rule engines perform about 1,300 tests in total. <a href="https://medium.com/cvs-health-tech-blog/how-to-run-a-thousand-accessibility-tests-63692ad120c3">Open-source software</a> developed initially at CVS Health drives the rule engines, tries to weed out invalid results, and distills the findings into about 380 <q>issues</q>.</p>
76
+ <h2>Features</h2>
77
+ <p>With Kilotest, you can get results of already performed tests and propose web pages for testing. (Immediate testing on request may become available in a future version.)</p>
78
+ <p>There is a <a href="/capability.md">capability document</a> that summarizes what Kilotest can do for human and AI-agent users.</p>
79
+ <h2>How to use Kilotest</h2>
80
+ <h3>If you are a human user on the web</h3>
81
+ <p>You can use Kilotest starting on this page.</p>
82
+ <p>If your main interest is accessibility, feel free to learn more about it with our <a href="/tutorialWeb.html">tutorial</a>.</p>
83
+ <h3>If you are a human user of AI</h3>
84
+ <p>An AI assistant can use the Kilotest MCP server to give you precise answers about the front-end quality of a web page. If the AI assistant does not already have permission to use Kilotest, you can grant that permission. <a href="/tutorialAI.html">Learn how to connect AI platforms to Kilotest</a>.</p>
85
+ <h3>If you are an AI agent or model</h3>
86
+ <p>Go to the <a href="/mcp">Kilotest MCP server</a>.</p>
87
+ <h3>If you are developing an application</h3>
88
+ <p>Your application can use the Kilotest API, which has an <a href="/openapi.yaml">OpenAPI specification</a>.</p>
89
+ <h2>Comments?</h2>
90
+ <p>Your suggestions, bug reports, and collaboration proposals are welcome! Post them on <a href="https://github.com/jrpool/kilotest/issues">GitHub</a> or email them to <a href="mailto:info@kilotest.com">info@kilotest.com</a>.</p>
91
+ </details>
92
+ </div>
93
+ <section class="nav-section" aria-labelledby="nav-heading">
94
+ <h2 id="nav-heading">What do you want to know?</h2>
95
+ <ul class="nav">
96
+ <li><a href="listPages.html"><span class="card-title">Which web pages have been tested?</span><span class="card-desc">Browse test results for every page in the Kilotest catalog.</span></a></li>
97
+ <li><a href="listTopIssues.html"><span class="card-title">Which issues have been reported?</span><span class="card-desc">See the most common defects found across all tested pages.</span></a></li>
98
+ </ul>
99
+ </section>
100
+ <section class="nav-section" aria-labelledby="more-heading">
101
+ <h2 id="more-heading">More …</h2>
102
+ <ul class="nav">
103
+ <li><a href="manage.html"><span class="card-title">Management actions</span><span class="card-desc">Approval, queue, and report administration for managers.</span></a></li>
104
+ <li><a href="privacy.html"><span class="card-title">Privacy policy</span><span class="card-desc">What Kilotest collects, stores, and shares.</span></a></li>
105
+ </ul>
106
+ </section>
95
107
  </main>
96
108
  </body>
97
109
  </html>
package/web/home/index.ts CHANGED
@@ -5,14 +5,13 @@
5
5
 
6
6
  // IMPORTS
7
7
 
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
8
+ import {populateTemplate} from '../../util.ts';
10
9
 
11
10
  // FUNCTIONS
12
11
 
13
12
  // Returns the home page.
14
13
  export const answer = async () => {
15
- const answerPage = await fs.readFile(path.join(import.meta.dirname, 'index.html'), 'utf8');
14
+ const answerPage = await populateTemplate(import.meta.dirname, {});
16
15
  return {
17
16
  status: 'ok',
18
17
  answerPage
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>HTML element __catalogIndex__ of __target__ for __issue__ issue | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -60,9 +60,9 @@ const populateQuery = async (
60
60
  // If the violator has a linkable text item, add a take-me-there link.
61
61
  if (catalogIndex && catalogItem?.textLinkable) {
62
62
  const href = getTextFragmentHref(catalogItem.text as string, url);
63
- const label = `Take me to element ${catalogIndex} on the page (in a new tab)`;
64
- const link = `<a href="${href}" target="_blank" aria-label="${label}">Take me there</a>`;
65
- query.takeMeThere = `${margin} <p>${link}</p>`;
63
+ const label = `Take me there (to element ${catalogIndex})`;
64
+ const link = `<a href="${href}" aria-label="${label}">Take me there</a>`;
65
+ query.takeMeThere = `${margin} <li>${link}</li>`;
66
66
  }
67
67
  else {
68
68
  query.takeMeThere = '';
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Issues reported for __target__ | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Pages tested | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Rules belonging to __issue__ issue| Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Issues reported | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Violations of __issue__ for __target__ | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -124,7 +124,7 @@ const populateQuery = async (
124
124
  // If any lines contain text-fragment links:
125
125
  if (takeMeAdviceNeeded) {
126
126
  // Include advice about them in the answer.
127
- query.takeMeThere = '<p><q>Take me there</q> links will open the page in a new tab and try to scroll to the element and highlight it. This does not always succeed. You can return here by closing the new tab.</p>';
127
+ query.takeMeThere = '<p><q>Take me there</q> links will open the page and try to scroll to the element and highlight it. This does not always succeed.</p>';
128
128
  }
129
129
  };
130
130
  // Returns a page answering the violators question.
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Management | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -5,15 +5,14 @@
5
5
 
6
6
  // IMPORTS
7
7
 
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
8
+ import {populateTemplate} from '../../util.ts';
10
9
 
11
10
  // FUNCTIONS
12
11
 
13
12
  // Returns the answer page.
14
13
  export const answer = async (): Promise<{status: string; answerPage: string}> => {
15
14
  // Get the answer page.
16
- const answerPage = await fs.readFile(path.join(import.meta.dirname, 'index.html'), 'utf8');
15
+ const answerPage = await populateTemplate(import.meta.dirname, {});
17
16
  // Return it.
18
17
  return {
19
18
  status: 'ok',
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Usage metrics | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="description" content="Kilotest privacy policy: what information Kilotest collects, uses, shares, and keeps">
9
6
  <title>Privacy policy | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -5,14 +5,13 @@
5
5
 
6
6
  // IMPORTS
7
7
 
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
8
+ import {populateTemplate} from '../../util.ts';
10
9
 
11
10
  // FUNCTIONS
12
11
 
13
12
  // Returns the privacy policy page.
14
13
  export const answer = async () => {
15
- const answerPage = await fs.readFile(path.join(import.meta.dirname, 'index.html'), 'utf8');
14
+ const answerPage = await populateTemplate(import.meta.dirname, {});
16
15
  return {
17
16
  status: 'ok',
18
17
  answerPage
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Prune reports | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -20,9 +15,9 @@
20
15
  __reports__
21
16
  </fieldset>
22
17
  <p><label>
23
- Authorization code: <input size="3" minLength="3" maxlength="3" name="authCode" required__disabled__>
18
+ Authorization code: <input size="3" minlength="3" maxlength="3" name="authCode" required __disabled__>
24
19
  </label></p>
25
- <p><button type="submit"__disabled__>Submit</button></p>
20
+ <p><button type="submit" __disabled__>Submit</button></p>
26
21
  </form>
27
22
  </main>
28
23
  </body>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Reannotation order | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -12,11 +12,11 @@ import {
12
12
  getReportPath,
13
13
  isReportError,
14
14
  isValidAuthCode,
15
+ populateTemplate,
15
16
  readdirOrCreate,
16
17
  reportsPath
17
18
  } from '../../util.ts';
18
19
  import fs from 'node:fs/promises';
19
- import path from 'node:path';
20
20
 
21
21
  // FUNCTIONS
22
22
 
@@ -57,7 +57,7 @@ export const answer = async (authCode: string) => {
57
57
  };
58
58
  }
59
59
  // If every annotation succeeded, get the answer page.
60
- const answerPage = await fs.readFile(path.join(import.meta.dirname, 'index.html'), 'utf8');
60
+ const answerPage = await populateTemplate(import.meta.dirname, {});
61
61
  // Return it.
62
62
  return {
63
63
  status: 'ok',
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Reannotation order | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>WCAG map renewed | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -7,7 +7,7 @@
7
7
 
8
8
  import fs from 'node:fs/promises';
9
9
  import path from 'node:path';
10
- import {getJSON, isValidAuthCode} from '../../util.ts';
10
+ import {getJSON, isValidAuthCode, populateTemplate} from '../../util.ts';
11
11
 
12
12
  // FUNCTIONS
13
13
 
@@ -38,7 +38,7 @@ export const answer = async (authCode: string) => {
38
38
  // Save the map, replacing any existing one.
39
39
  await fs.writeFile(path.join(import.meta.dirname, '..', '..', 'wcagMap.json'), getJSON(wcagMap));
40
40
  // Get the acknowledgment page.
41
- const answerPage = await fs.readFile(path.join(import.meta.dirname, 'index.html'), 'utf8');
41
+ const answerPage = await populateTemplate(import.meta.dirname, {});
42
42
  // Return it.
43
43
  return {
44
44
  status: 'ok',
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Renew WCAG map | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -16,7 +11,7 @@
16
11
  <p>Submit this form to renew the map of WCAG numeric to text identifiers.</p>
17
12
  <form action="/renewWCAG.html" method="post">
18
13
  <p><label>
19
- Authorization code: <input size="3" minLength="3" maxlength="3" name="authCode" required>
14
+ Authorization code: <input size="3" minlength="3" maxlength="3" name="authCode" required>
20
15
  </label></p>
21
16
  <p><button type="submit">Submit</button></p>
22
17
  </form>
@@ -5,15 +5,14 @@
5
5
 
6
6
  // IMPORTS
7
7
 
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
8
+ import {populateTemplate} from '../../util.ts';
10
9
 
11
10
  // FUNCTIONS
12
11
 
13
12
  // Returns a form for renewing the WCAG map.
14
13
  export const answer = async (): Promise<{status: string; answerPage: string}> => {
15
14
  // Get the map renewal form.
16
- const answerPage = await fs.readFile(path.join(import.meta.dirname, 'index.html'), 'utf8');
15
+ const answerPage = await populateTemplate(import.meta.dirname, {});
17
16
  // Return it.
18
17
  return {
19
18
  status: 'ok',
@@ -139,7 +139,7 @@ export const reportDeletionForm = async (
139
139
  const query: Record<string, string> = {
140
140
  reports: lines.join('\n'),
141
141
  intro: anyDeletable ? intro : emptyIntro,
142
- disabled: anyDeletable ? '' : ' disabled'
142
+ disabled: anyDeletable ? '' : 'disabled'
143
143
  };
144
144
  // Return the populated page.
145
145
  return {
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>__description__ test request received | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>Test request | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -5,14 +5,13 @@
5
5
 
6
6
  // IMPORTS
7
7
 
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
8
+ import {populateTemplate} from '../../util.ts';
10
9
 
11
10
  // FUNCTIONS
12
11
 
13
12
  export const answer = async (): Promise<{status: string; answerPage: string}> => {
14
13
  // Get the test request form template.
15
- const answerPage = await fs.readFile(path.join(import.meta.dirname, 'index.html'), 'utf8');
14
+ const answerPage = await populateTemplate(import.meta.dirname, {});
16
15
  // Return it.
17
16
  return {
18
17
  status: 'ok',
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>__target__ retest request received | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>
@@ -1,14 +1,9 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta name="publisher" content="Jonathan Robert Pool">
7
- <meta name="creator" content="Jonathan Robert Pool">
4
+ __head__
8
5
  <meta name="keywords" content="report,accessibility,a11y">
9
6
  <title>__target__ retest recommendation | Kilotest</title>
10
- <link rel="icon" href="/favicon.ico">
11
- <link rel="stylesheet" href="/style.css">
12
7
  </head>
13
8
  <body>
14
9
  <main>