@govtechsg/oobee 0.10.20

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 (123) hide show
  1. package/.dockerignore +22 -0
  2. package/.github/pull_request_template.md +11 -0
  3. package/.github/workflows/docker-test.yml +54 -0
  4. package/.github/workflows/image.yml +107 -0
  5. package/.github/workflows/publish.yml +18 -0
  6. package/.idea/modules.xml +8 -0
  7. package/.idea/purple-a11y.iml +9 -0
  8. package/.idea/vcs.xml +6 -0
  9. package/.prettierrc.json +12 -0
  10. package/.vscode/extensions.json +5 -0
  11. package/.vscode/settings.json +10 -0
  12. package/CODE_OF_CONDUCT.md +128 -0
  13. package/DETAILS.md +163 -0
  14. package/Dockerfile +60 -0
  15. package/INSTALLATION.md +146 -0
  16. package/INTEGRATION.md +785 -0
  17. package/LICENSE +22 -0
  18. package/README.md +587 -0
  19. package/SECURITY.md +5 -0
  20. package/__mocks__/mock-report.html +1431 -0
  21. package/__mocks__/mockFunctions.ts +32 -0
  22. package/__mocks__/mockIssues.ts +64 -0
  23. package/__mocks__/mock_all_issues/000000001.json +64 -0
  24. package/__mocks__/mock_all_issues/000000002.json +53 -0
  25. package/__mocks__/mock_all_issues/fake-file.txt +0 -0
  26. package/__tests__/logs.test.ts +25 -0
  27. package/__tests__/mergeAxeResults.test.ts +278 -0
  28. package/__tests__/utils.test.ts +118 -0
  29. package/a11y-scan-results.zip +0 -0
  30. package/eslint.config.js +53 -0
  31. package/exclusions.txt +2 -0
  32. package/gitlab-pipeline-template.yml +54 -0
  33. package/jest.config.js +1 -0
  34. package/package.json +96 -0
  35. package/scripts/copyFiles.js +44 -0
  36. package/scripts/install_oobee_dependencies.cmd +13 -0
  37. package/scripts/install_oobee_dependencies.command +101 -0
  38. package/scripts/install_oobee_dependencies.ps1 +110 -0
  39. package/scripts/oobee_shell.cmd +13 -0
  40. package/scripts/oobee_shell.command +11 -0
  41. package/scripts/oobee_shell.sh +55 -0
  42. package/scripts/oobee_shell_ps.ps1 +54 -0
  43. package/src/cli.ts +401 -0
  44. package/src/combine.ts +240 -0
  45. package/src/constants/__tests__/common.test.ts +44 -0
  46. package/src/constants/cliFunctions.ts +305 -0
  47. package/src/constants/common.ts +1840 -0
  48. package/src/constants/constants.ts +443 -0
  49. package/src/constants/errorMeta.json +319 -0
  50. package/src/constants/itemTypeDescription.ts +11 -0
  51. package/src/constants/oobeeAi.ts +141 -0
  52. package/src/constants/questions.ts +181 -0
  53. package/src/constants/sampleData.ts +187 -0
  54. package/src/crawlers/__tests__/commonCrawlerFunc.test.ts +51 -0
  55. package/src/crawlers/commonCrawlerFunc.ts +656 -0
  56. package/src/crawlers/crawlDomain.ts +877 -0
  57. package/src/crawlers/crawlIntelligentSitemap.ts +156 -0
  58. package/src/crawlers/crawlLocalFile.ts +193 -0
  59. package/src/crawlers/crawlSitemap.ts +356 -0
  60. package/src/crawlers/custom/extractAndGradeText.ts +57 -0
  61. package/src/crawlers/custom/flagUnlabelledClickableElements.ts +964 -0
  62. package/src/crawlers/custom/utils.ts +486 -0
  63. package/src/crawlers/customAxeFunctions.ts +82 -0
  64. package/src/crawlers/pdfScanFunc.ts +468 -0
  65. package/src/crawlers/runCustom.ts +117 -0
  66. package/src/index.ts +173 -0
  67. package/src/logs.ts +66 -0
  68. package/src/mergeAxeResults.ts +964 -0
  69. package/src/npmIndex.ts +284 -0
  70. package/src/screenshotFunc/htmlScreenshotFunc.ts +411 -0
  71. package/src/screenshotFunc/pdfScreenshotFunc.ts +762 -0
  72. package/src/static/ejs/partials/components/categorySelector.ejs +4 -0
  73. package/src/static/ejs/partials/components/categorySelectorDropdown.ejs +57 -0
  74. package/src/static/ejs/partials/components/pagesScannedModal.ejs +70 -0
  75. package/src/static/ejs/partials/components/reportSearch.ejs +47 -0
  76. package/src/static/ejs/partials/components/ruleOffcanvas.ejs +105 -0
  77. package/src/static/ejs/partials/components/scanAbout.ejs +263 -0
  78. package/src/static/ejs/partials/components/screenshotLightbox.ejs +13 -0
  79. package/src/static/ejs/partials/components/summaryScanAbout.ejs +141 -0
  80. package/src/static/ejs/partials/components/summaryScanResults.ejs +16 -0
  81. package/src/static/ejs/partials/components/summaryTable.ejs +20 -0
  82. package/src/static/ejs/partials/components/summaryWcagCompliance.ejs +94 -0
  83. package/src/static/ejs/partials/components/topFive.ejs +6 -0
  84. package/src/static/ejs/partials/components/wcagCompliance.ejs +70 -0
  85. package/src/static/ejs/partials/footer.ejs +21 -0
  86. package/src/static/ejs/partials/header.ejs +230 -0
  87. package/src/static/ejs/partials/main.ejs +40 -0
  88. package/src/static/ejs/partials/scripts/bootstrap.ejs +8 -0
  89. package/src/static/ejs/partials/scripts/categorySelectorDropdownScript.ejs +190 -0
  90. package/src/static/ejs/partials/scripts/categorySummary.ejs +141 -0
  91. package/src/static/ejs/partials/scripts/highlightjs.ejs +335 -0
  92. package/src/static/ejs/partials/scripts/popper.ejs +7 -0
  93. package/src/static/ejs/partials/scripts/reportSearch.ejs +248 -0
  94. package/src/static/ejs/partials/scripts/ruleOffcanvas.ejs +801 -0
  95. package/src/static/ejs/partials/scripts/screenshotLightbox.ejs +71 -0
  96. package/src/static/ejs/partials/scripts/summaryScanResults.ejs +14 -0
  97. package/src/static/ejs/partials/scripts/summaryTable.ejs +78 -0
  98. package/src/static/ejs/partials/scripts/utils.ejs +441 -0
  99. package/src/static/ejs/partials/styles/bootstrap.ejs +12375 -0
  100. package/src/static/ejs/partials/styles/highlightjs.ejs +54 -0
  101. package/src/static/ejs/partials/styles/styles.ejs +1843 -0
  102. package/src/static/ejs/partials/styles/summaryBootstrap.ejs +12458 -0
  103. package/src/static/ejs/partials/summaryHeader.ejs +70 -0
  104. package/src/static/ejs/partials/summaryMain.ejs +75 -0
  105. package/src/static/ejs/report.ejs +420 -0
  106. package/src/static/ejs/summary.ejs +47 -0
  107. package/src/static/mustache/.prettierrc +4 -0
  108. package/src/static/mustache/Attention Deficit.mustache +11 -0
  109. package/src/static/mustache/Blind.mustache +11 -0
  110. package/src/static/mustache/Cognitive.mustache +7 -0
  111. package/src/static/mustache/Colorblindness.mustache +20 -0
  112. package/src/static/mustache/Deaf.mustache +12 -0
  113. package/src/static/mustache/Deafblind.mustache +7 -0
  114. package/src/static/mustache/Dyslexia.mustache +14 -0
  115. package/src/static/mustache/Low Vision.mustache +7 -0
  116. package/src/static/mustache/Mobility.mustache +15 -0
  117. package/src/static/mustache/Sighted Keyboard Users.mustache +42 -0
  118. package/src/static/mustache/report.mustache +1709 -0
  119. package/src/types/print-message.d.ts +28 -0
  120. package/src/types/types.ts +46 -0
  121. package/src/types/xpath-to-css.d.ts +3 -0
  122. package/src/utils.ts +332 -0
  123. package/tsconfig.json +15 -0
package/.dockerignore ADDED
@@ -0,0 +1,22 @@
1
+ # Node
2
+ **/node_modules/
3
+ **/dist
4
+ .git
5
+ npm-debug.log
6
+ .coverage
7
+ .coverage.*
8
+ .env
9
+ .aws
10
+
11
+ #MacOS
12
+ **/.DS_Store
13
+ **/thumbs.db
14
+
15
+ # App-specific
16
+ .github
17
+ screenshots/
18
+ logs/
19
+ results/
20
+ ImageMagick-*/
21
+ errors.txt
22
+ oobee-scan-results.zip
@@ -0,0 +1,11 @@
1
+ This PR adds... <!-- A brief description of what your PR does -->
2
+
3
+ <!-- This checklist is just a guideline.-->
4
+ <!-- If any of the following does not apply to your PR, please leave them unchecked and explain in the PR -->
5
+
6
+ - [ ] I've kept this PR as small as possible (~500 lines) by splitting it into PRs with manageable chunks of code
7
+ - [ ] I've requested reviews from 1 reviewer
8
+ - [ ] I've tested existing features (website scan, sitemap, custom flow) in both node index and cli
9
+ - [ ] I've synced this fork with GovTechSG repo
10
+ - [ ] I've added/updated unit tests
11
+ - [ ] I've added/updated any necessary dependencies in `package[-lock].json` `npm audit`, portable installation on GitHub Actions
@@ -0,0 +1,54 @@
1
+ name: Build Run and Test Docker Container
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ tags:
7
+ - '*.*.*'
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: Checkout code
15
+ uses: actions/checkout@v2
16
+
17
+ - name: Build and run Docker container
18
+ run: |
19
+ # Build your Docker image (replace 'oobee' and 'Dockerfile' with your image name and Dockerfile path)
20
+ docker build -t oobee .
21
+ # Run the Docker container (adjust any options as needed)
22
+ docker run -dit --name oobee-container oobee
23
+ # Ensure the Docker container is running before running the next step
24
+ continue-on-error: true
25
+
26
+ - name: Run Node CLI command inside the Docker container
27
+ run: |
28
+ # Execute a webisite crawl
29
+ docker exec oobee-container npm run cli -- -u "${{ vars.OOBEE_SCAN_URL }}" -c 2 -p "${{ vars.OOBEE_SCAN_MAX_NUM_PAGES }}" -t "${{ vars.OOBEE_SCAN_MAX_CONCURRENCY }}" -k "${{ github.actor }}:${{ github.actor }}@users.noreply.github.com" -b chromium || true
30
+
31
+ - name: Print errors
32
+ run: |
33
+ docker exec oobee-container cat errors.txt || true
34
+
35
+ - name: Print logs
36
+ run: |
37
+ docker exec oobee-container cat logs/*/*.txt || true
38
+ - name: Copy Results from Docker Container
39
+ run: docker cp oobee-container:/app/results ./results
40
+
41
+ - name: Zip Results
42
+ run: zip -r results.zip ./results
43
+
44
+ - name: Upload Zip File
45
+ uses: actions/upload-artifact@v4
46
+ with:
47
+ name: results
48
+ path: results.zip
49
+
50
+ - name: Cleanup Docker container
51
+ run: |
52
+ # Stop and remove the Docker container
53
+ docker stop oobee-container
54
+ docker rm oobee-container
@@ -0,0 +1,107 @@
1
+ name: Push installation image
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ release:
6
+ types: [published]
7
+
8
+ jobs:
9
+ windows-install-oobee:
10
+ runs-on: windows-latest
11
+
12
+ steps:
13
+ - name: Check out repository code
14
+ uses: actions/checkout@v3
15
+ with:
16
+ path: oobee
17
+
18
+ - name: Copy scripts to parent directory
19
+ run: |
20
+ cp ${{github.workspace}}/oobee/scripts/*.ps1 ${{github.workspace}}
21
+ cp ${{github.workspace}}/oobee/scripts/*.cmd ${{github.workspace}}
22
+ cp ${{github.workspace}}/oobee/scripts/*.xml ${{github.workspace}}
23
+
24
+ - name: Install Purple dependencies for Windows
25
+ shell: pwsh
26
+ run: powershell.exe -NoProfile -ExecutionPolicy Bypass "& ${{github.workspace}}\install_oobee_dependencies.ps1"
27
+ working-directory: ${{github.workspace}}
28
+
29
+ - name: Zip entire Purple folder (Windows)
30
+ shell: pwsh
31
+ run: Compress-Archive -Path ${{github.workspace}}/* -DestinationPath oobee-portable-windows.zip
32
+
33
+ - name: Upload Windows artifact
34
+ uses: actions/upload-artifact@v4
35
+ with:
36
+ name: oobee-portable-windows
37
+ path: ./oobee-portable-windows.zip
38
+
39
+ - name: Release Windows artifact
40
+ uses: softprops/action-gh-release@v1
41
+ if: startsWith(github.ref, 'refs/tags/')
42
+ with:
43
+ files: |
44
+ oobee-portable-windows.zip
45
+
46
+ mac-install-oobee:
47
+ runs-on: self-hosted
48
+ environment: macos
49
+
50
+ steps:
51
+ - name: Clean Workspace Folder
52
+ run: |
53
+ rm -rf ./* || true
54
+ rm -rf ./.??* || true
55
+
56
+ - name: Check out repository code
57
+ uses: actions/checkout@v3
58
+ with:
59
+ path: oobee
60
+
61
+ - name: Grant execute permissions for user
62
+ run: chmod ugo+rwx ./scripts/*.command ./scripts/*.sh
63
+ working-directory: oobee
64
+
65
+ - name: Copy scripts to parent directory
66
+ run: |
67
+ cp ./oobee/scripts/{*.command,*.sh,*.xml} ${{ github.workspace }}
68
+
69
+ - name: Install Purple dependencies for MacOS
70
+ run: |
71
+ ./install_oobee_dependencies.command
72
+
73
+ - name: Sign required binaries for MacOS
74
+ run: |
75
+ # Find a valid code signing certificate in your keychain for distribution outside Mac App Store
76
+ CERTIFICATE=$(security find-identity -v -p codesigning -s - | tail -n +2 | grep -o '"Developer ID Application:[^"]*"' | sed 's/"//g')
77
+
78
+ # Paths to the binaries you want to sign only ending with .node
79
+ BINARIES=($(find . -type f \( -name "*.node" -o -name "*.sh" -o -name "*.command" \) ! -path "*.framework/*" ! -path "*.dSYM/*"))
80
+
81
+ # Loop through the binary paths and sign each one with a secure timestamp
82
+ for binary in "${BINARIES[@]}"; do
83
+ # Check if the binary is already signed
84
+ codesign --timestamp -f -s "$CERTIFICATE" "$binary"
85
+ if [ $? -eq 0 ]; then
86
+ echo "Successfully signed (with secure timestamp): $binary"
87
+ else
88
+ echo "Failed to sign: $binary"
89
+ fi
90
+ done
91
+
92
+ - name: Zip entire Purple folder (Mac)
93
+ run: |
94
+ zip oobee-portable-mac.zip -y -r ./
95
+
96
+ - name: Upload Mac artifact
97
+ uses: actions/upload-artifact@v4
98
+ with:
99
+ name: oobee-portable-mac
100
+ path: ./oobee-portable-mac.zip
101
+
102
+ - name: Release Mac artifact
103
+ uses: softprops/action-gh-release@v1
104
+ if: startsWith(github.ref, 'refs/tags/')
105
+ with:
106
+ files: |
107
+ oobee-portable-mac.zip
@@ -0,0 +1,18 @@
1
+ name: Publish Package to npmjs
2
+ on:
3
+ workflow_dispatch:
4
+ release:
5
+ types: [published]
6
+ jobs:
7
+ build:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v3
11
+ # Setup .npmrc file to publish to npm
12
+ - uses: actions/setup-node@v3
13
+ with:
14
+ node-version: '16.x'
15
+ registry-url: 'https://registry.npmjs.org'
16
+ - run: npm publish
17
+ env:
18
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/purple-a11y.iml" filepath="$PROJECT_DIR$/.idea/purple-a11y.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="JAVA_MODULE" version="4">
3
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
4
+ <exclude-output />
5
+ <content url="file://$MODULE_DIR$" />
6
+ <orderEntry type="inheritedJdk" />
7
+ <orderEntry type="sourceFolder" forTests="false" />
8
+ </component>
9
+ </module>
package/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,12 @@
1
+ {
2
+ "printWidth": 100,
3
+ "tabWidth": 2,
4
+ "useTabs": false,
5
+ "semi": true,
6
+ "singleQuote": true,
7
+ "trailingComma": "all",
8
+ "bracketSpacing": true,
9
+ "jsxBracketSameLine": false,
10
+ "arrowParens": "avoid",
11
+ "endOfLine": "auto"
12
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "recommendations": [
3
+ "dbaeumer.vscode-eslint"
4
+ ]
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "editor.codeActionsOnSave": {
3
+ "source.fixAll.eslint": "explicit"
4
+ },
5
+ "eslint.validate": [
6
+ "javascript",
7
+ "typescript",
8
+ ],
9
+ "editor.formatOnSave": true,
10
+ }
@@ -0,0 +1,128 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or
31
+ advances of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email
35
+ address, without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ accessibility [at] tech.gov.sg.
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series
86
+ of actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or
93
+ permanent ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within
113
+ the community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.0, available at
119
+ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120
+
121
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct
122
+ enforcement ladder](https://github.com/mozilla/diversity).
123
+
124
+ [homepage]: https://www.contributor-covenant.org
125
+
126
+ For answers to common questions about this code of conduct, see the FAQ at
127
+ https://www.contributor-covenant.org/faq. Translations are available at
128
+ https://www.contributor-covenant.org/translations.
package/DETAILS.md ADDED
@@ -0,0 +1,163 @@
1
+ # Scan Issue Details
2
+
3
+ Details of each issue and severity rating provided by the current scan engine.
4
+
5
+ ## Table Of Contents
6
+
7
+ 1. [Conformance Covered](#conformance-covered)
8
+ 2. [WCAG 2.0 Level A](#wcag-20-level-a)
9
+ 3. [WCAG 2.0 Level AA](#wcag-20-level-aa)
10
+ 4. [WCAG 2.1 Level AA](#wcag-21-level-aa)
11
+ 5. [WCAG 2.2 Level AA](#wcag-22-level-aa)
12
+ 5. [WCAG 2.x Level AAA](#wcag-2x-level-aaa)
13
+ 6. [Best Practice](#best-practice)
14
+
15
+ ## Conformance Covered
16
+
17
+ | Conformance |
18
+ | ----------- |
19
+ | WCAG 1.1.1 |
20
+ | WCAG 1.2.2 |
21
+ | WCAG 1.3.1 |
22
+ | WCAG 1.3.5 |
23
+ | WCAG 1.4.1 |
24
+ | WCAG 1.4.12 |
25
+ | WCAG 1.4.2 |
26
+ | WCAG 1.4.3 |
27
+ | WCAG 1.4.4 |
28
+ | WCAG 1.4.6 |
29
+ | WCAG 2.1.1 |
30
+ | WCAG 2.2.1 |
31
+ | WCAG 2.2.2 |
32
+ | WCAG 2.2.4 |
33
+ | WCAG 2.4.1 |
34
+ | WCAG 2.4.2 |
35
+ | WCAG 2.4.4 |
36
+ | WCAG 2.4.9 |
37
+ | WCAG 3.1.1 |
38
+ | WCAG 3.1.2 |
39
+ | WCAG 3.3.2 |
40
+ | WCAG 3.2.5 |
41
+ | WCAG 4.1.2 |
42
+
43
+ ## WCAG 2.0 Level A
44
+
45
+ | Issue ID | Issue Description | Severity | Conformance |
46
+ | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ---------------------- |
47
+ | area-alt | Ensures `<area>` elements of image maps have alternate text | Must Fix | WCAG 2.4.4, WCAG 4.1.2 |
48
+ | aria-allowed-attr | Ensures an element's role supports its ARIA attributes | Must Fix | WCAG 4.1.2 |
49
+ | aria-braille-equivalent | Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent | Must Fix | WCAG 4.1.2 |
50
+ | aria-command-name | Ensures every ARIA button, link and menuitem has an accessible name | Must Fix | WCAG 4.1.2 |
51
+ | aria-conditional-attr | Ensures ARIA attributes are used as described in the specification of the element's role | Must Fix | WCAG 4.1.2 |
52
+ | aria-deprecated-role | Ensures elements do not use deprecated roles | Good To Fix | WCAG 4.1.2 |
53
+ | aria-hidden-body | Ensures aria-hidden="true" is not present on the document body. | Must Fix | WCAG 4.1.2 |
54
+ | aria-hidden-focus | Ensures aria-hidden elements are not focusable nor contain focusable elements | Must Fix | WCAG 4.1.2 |
55
+ | aria-input-field-name | Ensures every ARIA input field has an accessible name | Must Fix | WCAG 4.1.2 |
56
+ | aria-meter-name | Ensures every ARIA meter node has an accessible name | Must Fix | WCAG 1.1.1 |
57
+ | aria-progressbar-name | Ensures every ARIA progressbar node has an accessible name | Must Fix | WCAG 1.1.1 |
58
+ | aria-prohibited-attr | Ensures ARIA attributes are not prohibited for an element's rolessible name | Must Fix | WCAG 4.1.2 |
59
+ | aria-required-attr | Ensures elements with ARIA roles have all required ARIA attributes | Must Fix | WCAG 4.1.2 |
60
+ | aria-required-children | Ensures elements with an ARIA role that require child roles contain them | Must Fix | WCAG 1.3.1 |
61
+ | aria-required-parent | Ensures elements with an ARIA role that require parent roles are contained by them | Must Fix | WCAG 1.3.1 |
62
+ | aria-roles | Ensures all elements with a role attribute use a valid value | Must Fix | WCAG 4.1.2 |
63
+ | aria-toggle-field-name | Ensures every ARIA toggle field has an accessible name | Must Fix | WCAG 4.1.2 |
64
+ | aria-tooltip-name | Ensures every ARIA tooltip node has an accessible name | Must Fix | WCAG 4.1.2 |
65
+ | aria-valid-attr-value | Ensures all ARIA attributes have valid values | Must Fix | WCAG 4.1.2 |
66
+ | aria-valid-attr | Ensures attributes that begin with aria- are valid ARIA attributes | Must Fix | WCAG 4.1.2 |
67
+ | blink | Ensures `<blink>` elements are not used | Must Fix | WCAG 2.2.2 |
68
+ | button-name | Ensures buttons have discernible text | Must Fix | WCAG 4.1.2 |
69
+ | bypass | Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content | Must Fix | WCAG 2.4.1 |
70
+ | definition-list | Ensures `<dl>` elements are structured correctly | Must Fix | WCAG 1.3.1 |
71
+ | dlitem | Ensures `<dt>` and `<dd>` elements are contained by a `<dl>` | Must Fix | WCAG 1.3.1 |
72
+ | document-title | Ensures each HTML document contains a non-empty `<title>` element | Must Fix | WCAG 2.4.2 |
73
+ | duplicate-id-aria | Ensures every id attribute value used in ARIA and in labels is unique | Must Fix | WCAG 4.1.2 |
74
+ | form-field-multiple-labels | Ensures form field does not have multiple label elements | Good to Fix | WCAG 3.3.2 |
75
+ | frame-focusable-content | Ensures `<frame>` and `<iframe>` elements with focusable content do not have tabindex=-1 | Must Fix | WCAG 2.1.1 |
76
+ | frame-title-unique | Ensures `<iframe>` and `<frame>` elements contain a unique title attribute | Must Fix | WCAG 4.1.2 |
77
+ | frame-title | Ensures `<iframe>` and `<frame>` elements have an accessible name | Must Fix | WCAG 4.1.2 |
78
+ | html-has-lang | Ensures every HTML document has a lang attribute | Must Fix | WCAG 3.1.1 |
79
+ | html-lang-valid | Ensures the lang attribute of the `<html>` element has a valid value | Must Fix | WCAG 3.1.1 |
80
+ | html-xml-lang-mismatch | Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page | Good to Fix | WCAG 3.1.1 |
81
+ | image-alt | Ensures `<img>` elements have alternate text or a role of none or presentation | Must Fix | WCAG 1.1.1 |
82
+ | input-button-name | Ensures input buttons have discernible text | Must Fix | WCAG 4.1.2 |
83
+ | input-image-alt | Ensures `<input type="image">` elements have alternate text | Must Fix | WCAG 1.1.1, WCAG 4.1.2 |
84
+ | label | Ensures every form element has a label | Must Fix | WCAG 4.1.2 |
85
+ | link-in-text-block | Ensure links are distinguished from surrounding text in a way that does not rely on color | Must Fix | WCAG 1.4.1 |
86
+ | link-name | Ensures links have discernible text | Must Fix | WCAG 2.4.4, WCAG 4.1.2 |
87
+ | list | Ensures that lists are structured correctly | Must Fix | WCAG 1.3.1 |
88
+ | listitem | Ensures `<li>` elements are used semantically | Must Fix | WCAG 1.3.1 |
89
+ | marquee | Ensures `<marquee>` elements are not used | Must Fix | WCAG 2.2.2 |
90
+ | meta-refresh | Ensures `<meta http-equiv="refresh">` is not used for delayed refresh | Must Fix | WCAG 2.2.1 |
91
+ | nested-interactive | Ensures interactive controls are not nested as they are not always announced by screen readers or can cause focus problems for assistive technologies | Must Fix | WCAG 4.1.2 |
92
+ | no-autoplay-audio | Ensures `<video>` or `<audio>` elements do not autoplay audio for more than 3 seconds without a control mechanism to stop or mute the audio | Good to Fix | WCAG 1.4.2 |
93
+ | object-alt | Ensures `<object>` elements have alternate text | Must Fix | WCAG 1.1.1 |
94
+ | role-img-alt | Ensures [role="img"] elements have alternate text | Must Fix | WCAG 1.1.1 |
95
+ | scrollable-region-focusable | Ensure elements that have scrollable content are accessible by keyboard | Must Fix | WCAG 2.1.1 |
96
+ | select-name | Ensures select element has an accessible name | Must Fix | WCAG 4.1.2 |
97
+ | server-side-image-map | Ensures that server-side image maps are not used | Good to Fix | WCAG 2.1.1 |
98
+ | svg-img-alt | Ensures `<svg>` elements with an img, graphics-document or graphics-symbol role have an accessible text | Must Fix | WCAG 1.1.1 |
99
+ | td-headers-attr | Ensure that each cell in a table that uses the headers attribute refers only to other cells in that table | Must Fix | WCAG 1.3.1 |
100
+ | th-has-data-cells | Ensure that `<th>` elements and elements with role=columnheader/rowheader have data cells they describe | Must Fix | WCAG 1.3.1 |
101
+ | video-caption | Ensures `<video>` elements have captions | Must Fix | WCAG 1.2.2 |
102
+
103
+ ## WCAG 2.0 Level AA
104
+
105
+ | Issue ID | Issue Description | Severity | Conformance |
106
+ | -------------- | --------------------------------------------------------------------------------------------------------------- | -------- | ----------- |
107
+ | color-contrast | Ensures the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds | Must Fix | WCAG 1.4.3 |
108
+ | meta-viewport | Ensures `<meta name="viewport">` does not disable text scaling and zooming | Must Fix | WCAG 1.4.4 |
109
+ | valid-lang | Ensures lang attributes have valid values | Must Fix | WCAG 3.1.2 |
110
+
111
+ ## WCAG 2.1 Level AA
112
+
113
+ | Issue ID | Issue Description | Severity | Conformance |
114
+ | -------------------- | --------------------------------------------------------------------------------------------- | -------- | ----------- |
115
+ | autocomplete-valid | Ensure the autocomplete attribute is correct and suitable for the form field | Must Fix | WCAG 1.3.5 |
116
+ | avoid-inline-spacing | Ensure that text spacing set through style attributes can be adjusted with custom stylesheets | Must Fix | WCAG 1.4.12 |
117
+
118
+ ## WCAG 2.2 Level AA
119
+
120
+ | Issue ID | Issue Description | Severity | Conformance |
121
+ | ----------- | -------------------------------------------------- | -------- | ----------- |
122
+ | target-size | Ensure touch target have sufficient size and space | Must Fix | WCAG 2.5.8 |
123
+
124
+ ## WCAG 2.x Level AAA
125
+
126
+ | Issue ID | Issue Description | Severity | Conformance |
127
+ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------- | ---------------------- |
128
+ | color-contrast-enhanced | Ensure the contrast between foreground and background colors meets WCAG 2 AAA enhanced contrast ratio thresholds | Must Fix | WCAG 1.4.6 |
129
+ | identical-links-same-purpose | Ensure that links with the same accessible name serve a similar purpose | Good to Fix | WCAG 2.4.9 |
130
+ | meta-refresh-no-exceptions | Ensure <meta http-equiv="refresh"> is not used for delayed refresh | Good to Fix | WCAG 2.2.4, WCAG 3.2.5 |
131
+
132
+ ## Best Practice
133
+
134
+ | Issue ID | Issue Description | Severity |
135
+ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
136
+ | accesskeys | Ensures every accesskey attribute value is unique | Must Fix |
137
+ | aria-allowed-role | Ensures role attribute has an appropriate value for the element | Good to Fix |
138
+ | aria-dialog-name | Ensures every ARIA dialog and alertdialog node has an accessible name | Must Fix |
139
+ | aria-text | Ensures role="text" is used on elements with no focusable descendants | Must Fix |
140
+ | aria-treeitem-name | Ensures every ARIA treeitem node has an accessible name | Must Fix |
141
+ | empty-heading | Ensures headings have discernible text | Good to Fix |
142
+ | empty-table-header | Ensures table headers have discernible text | Good to Fix |
143
+ | frame-tested | Ensures `<iframe>` and `<frame>` elements contain the axe-core script | Must Fix |
144
+ | heading-order | Ensures the order of headings is semantically correct | Good to Fix |
145
+ | image-redundant-alt | Ensure image alternative is not repeated as text | Good to Fix |
146
+ | label-title-only | Ensures that every form element has a visible label and is not solely labeled using hidden labels, or the title or aria-describedby attributes | Must Fix |
147
+ | landmark-banner-is-top-level | Ensures the banner landmark is at top level | Good to Fix |
148
+ | landmark-complementary-is-top-level | Ensures the complementary landmark or aside is at top level | Good to Fix |
149
+ | landmark-contentinfo-is-top-level | Ensures the contentinfo landmark is at top level | Good to Fix |
150
+ | landmark-main-is-top-level | Ensures the main landmark is at top level | Good to Fix |
151
+ | landmark-no-duplicate-banner | Ensures the document has at most one banner landmark | Good to Fix |
152
+ | landmark-no-duplicate-contentinfo | Ensures the document has at most one contentinfo landmark | Good to Fix |
153
+ | landmark-no-duplicate-main | Ensures the document has at most one main landmark | Good to Fix |
154
+ | landmark-one-main | Ensures the document has a main landmark | Good to Fix |
155
+ | landmark-unique | Landmarks should have a unique role or role/label/title (i.e. accessible name) combination | Good to Fix |
156
+ | meta-viewport-large | Ensures `<meta name="viewport">` can scale a significant amount | Good to Fix |
157
+ | page-has-heading-one | Ensure that the page, or at least one of its frames contains a level-one heading | Good to Fix |
158
+ | presentation-role-conflict | Elements marked as presentational should not have global ARIA or tabindex to ensure all screen readers ignore them | Good to Fix |
159
+ | region | Ensures all page content is contained by landmarks | Good to Fix |
160
+ | scope-attr-valid | Ensures the scope attribute is used correctly on tables | Good to Fix |
161
+ | skip-link | Ensure all skip links have a focusable target | Good to Fix |
162
+ | tabindex | Ensures tabindex attribute values are not greater than 0 | Must Fix |
163
+ | table-duplicate-name | Ensure the `<caption>` element does not contain the same text as the summary attribute | Good to Fix |
package/Dockerfile ADDED
@@ -0,0 +1,60 @@
1
+ # Use Node LTS alpine distribution
2
+ FROM node:lts-alpine3.18
3
+
4
+ # Installation of packages for oobee and chromium
5
+ RUN apk add build-base gcompat g++ make python3 zip bash git chromium openjdk11-jre
6
+
7
+ # Installation of VeraPDF
8
+ RUN echo $'<?xml version="1.0" encoding="UTF-8" standalone="no"?> \n\
9
+ <AutomatedInstallation langpack="eng"> \n\
10
+ <com.izforge.izpack.panels.htmlhello.HTMLHelloPanel id="welcome"/> \n\
11
+ <com.izforge.izpack.panels.target.TargetPanel id="install_dir"> \n\
12
+ <installpath>/opt/verapdf</installpath> \n\
13
+ </com.izforge.izpack.panels.target.TargetPanel> \n\
14
+ <com.izforge.izpack.panels.packs.PacksPanel id="sdk_pack_select"> \n\
15
+ <pack index="0" name="veraPDF GUI" selected="true"/> \n\
16
+ <pack index="1" name="veraPDF Batch files" selected="true"/> \n\
17
+ <pack index="2" name="veraPDF Validation model" selected="false"/> \n\
18
+ <pack index="3" name="veraPDF Documentation" selected="false"/> \n\
19
+ <pack index="4" name="veraPDF Sample Plugins" selected="false"/> \n\
20
+ </com.izforge.izpack.panels.packs.PacksPanel> \n\
21
+ <com.izforge.izpack.panels.install.InstallPanel id="install"/> \n\
22
+ <com.izforge.izpack.panels.finish.FinishPanel id="finish"/> \n\
23
+ </AutomatedInstallation> ' >> /opt/verapdf-auto-install-docker.xml
24
+
25
+ RUN wget "https://github.com/GovTechSG/oobee/releases/download/cache/verapdf-installer.zip" -P /opt
26
+ RUN unzip /opt/verapdf-installer.zip -d /opt
27
+ RUN latest_version=$(ls -d /opt/verapdf-greenfield-* | sort -V | tail -n 1) && [ -n "$latest_version" ] && \
28
+ "$latest_version/verapdf-install" "/opt/verapdf-auto-install-docker.xml"
29
+ RUN rm -rf /opt/verapdf-installer.zip /opt/verapdf-greenfield-*
30
+
31
+ # Set oobee directory
32
+ WORKDIR /app
33
+
34
+ # Copy package.json to working directory, perform npm install before copying the remaining files
35
+ COPY package*.json ./
36
+
37
+ # Environment variables for node and Playwright
38
+ ENV NODE_ENV=production
39
+ ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD="true"
40
+ ENV PLAYWRIGHT_BROWSERS_PATH="/opt/ms-playwright"
41
+ ENV PATH="/opt/verapdf:${PATH}"
42
+
43
+ # Install dependencies
44
+ RUN npm install --force --omit=dev
45
+
46
+ # Install Playwright browsers
47
+ RUN npx playwright install chromium webkit
48
+
49
+ # Add non-privileged user
50
+ RUN addgroup -S oobee && adduser -S -G oobee oobee
51
+ RUN chown -R oobee:oobee ./
52
+
53
+ # Run everything after as non-privileged user.
54
+ USER oobee
55
+
56
+ # Copy application and support files
57
+ COPY . .
58
+
59
+ # Compile TypeScript
60
+ RUN npm run build || true # true exits with code 0 - temp workaround until errors are resolved