@govtechsg/oobee 0.10.85 → 0.10.87

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 (62) hide show
  1. package/.github/workflows/publish.yml +10 -0
  2. package/DETAILS.md +29 -0
  3. package/dist/cli.js +18 -5
  4. package/dist/combine.js +3 -1
  5. package/dist/constants/cliFunctions.js +2 -2
  6. package/dist/constants/common.js +70 -17
  7. package/dist/constants/constants.js +604 -1
  8. package/dist/crawlers/commonCrawlerFunc.js +3 -2
  9. package/dist/crawlers/crawlDomain.js +38 -13
  10. package/dist/crawlers/crawlIntelligentSitemap.js +62 -30
  11. package/dist/crawlers/crawlSitemap.js +141 -84
  12. package/dist/crawlers/custom/utils.js +218 -71
  13. package/dist/crawlers/guards/urlGuard.js +8 -15
  14. package/dist/crawlers/runCustom.js +18 -11
  15. package/dist/generateHtmlReport.js +18 -11
  16. package/dist/generateOobeeClientScanner.js +570 -0
  17. package/dist/mergeAxeResults/itemReferences.js +60 -25
  18. package/dist/mergeAxeResults/sentryTelemetry.js +4 -1
  19. package/dist/mergeAxeResults.js +23 -13
  20. package/dist/npmIndex.js +10 -2
  21. package/dist/proxyService.js +18 -3
  22. package/dist/services/s3Uploader.js +21 -10
  23. package/dist/static/ejs/partials/scripts/decodeUnzipParse.ejs +6 -3
  24. package/dist/static/ejs/partials/scripts/header/aboutScanModal/ScanConfiguration.ejs +2 -2
  25. package/dist/static/ejs/partials/scripts/ruleModal/constants.ejs +1 -761
  26. package/dist/static/ejs/partials/scripts/ruleModal/itemCardRenderer.ejs +38 -2
  27. package/dist/static/ejs/partials/scripts/ruleModal/pageAccordionBuilder.ejs +1 -1
  28. package/dist/static/ejs/partials/scripts/ruleModal/ruleOffcanvas.ejs +4 -4
  29. package/dist/static/ejs/summary.ejs +19 -8
  30. package/dist/utils.js +4 -3
  31. package/fix-summary-html-oom-pr.md +62 -0
  32. package/oobee-client-scanner.js +34992 -0
  33. package/package.json +5 -5
  34. package/src/cli.ts +19 -5
  35. package/src/combine.ts +5 -1
  36. package/src/constants/cliFunctions.ts +2 -2
  37. package/src/constants/common.ts +87 -22
  38. package/src/constants/constants.ts +602 -1
  39. package/src/crawlers/commonCrawlerFunc.ts +4 -3
  40. package/src/crawlers/crawlDomain.ts +39 -13
  41. package/src/crawlers/crawlIntelligentSitemap.ts +63 -30
  42. package/src/crawlers/crawlSitemap.ts +165 -100
  43. package/src/crawlers/custom/utils.ts +241 -80
  44. package/src/crawlers/guards/urlGuard.ts +24 -31
  45. package/src/crawlers/runCustom.ts +29 -11
  46. package/src/generateHtmlReport.ts +21 -11
  47. package/src/generateOobeeClientScanner.ts +591 -0
  48. package/src/mergeAxeResults/itemReferences.ts +70 -26
  49. package/src/mergeAxeResults/sentryTelemetry.ts +4 -1
  50. package/src/mergeAxeResults.ts +26 -14
  51. package/src/npmIndex.ts +12 -2
  52. package/src/proxyService.ts +25 -4
  53. package/src/services/s3Uploader.ts +23 -11
  54. package/src/static/ejs/partials/scripts/decodeUnzipParse.ejs +6 -3
  55. package/src/static/ejs/partials/scripts/header/aboutScanModal/ScanConfiguration.ejs +2 -2
  56. package/src/static/ejs/partials/scripts/ruleModal/constants.ejs +1 -761
  57. package/src/static/ejs/partials/scripts/ruleModal/itemCardRenderer.ejs +38 -2
  58. package/src/static/ejs/partials/scripts/ruleModal/pageAccordionBuilder.ejs +1 -1
  59. package/src/static/ejs/partials/scripts/ruleModal/ruleOffcanvas.ejs +4 -4
  60. package/src/static/ejs/summary.ejs +19 -8
  61. package/src/utils.ts +4 -3
  62. package/testStaticJSScanner.html +534 -0
@@ -1,10 +1,44 @@
1
1
  <script>
2
2
  /**
3
- * Resolves item references (composite "html\x00xpath" strings) to full item data using htmlGroups.
3
+ * Rebuilds the item list for a page from pre-computed htmlGroups when the light report omits page.items.
4
+ */
5
+ function buildItemsFromHtmlGroupsForPage(page, ruleInCategory) {
6
+ const htmlGroups = ruleInCategory.htmlGroups || {};
7
+ const resolvedItems = [];
8
+
9
+ Object.values(htmlGroups).forEach(groupData => {
10
+ if (!Array.isArray(groupData.pageUrls) || !groupData.pageUrls.includes(page.url)) {
11
+ return;
12
+ }
13
+
14
+ resolvedItems.push({
15
+ html: groupData.html,
16
+ xpath: groupData.xpath,
17
+ message: groupData.message,
18
+ screenshotPath: groupData.screenshotPath,
19
+ displayNeedsReview: groupData.displayNeedsReview,
20
+ pageUrl: page.url,
21
+ pageTitle: page.pageTitle || page.metadata
22
+ });
23
+ });
24
+
25
+ return resolvedItems;
26
+ }
27
+
28
+ /**
29
+ * The embedded report payload now omits page.items and rebuilds occurrences from
30
+ * htmlGroups + page metadata. Keep the older page.items resolution logic below
31
+ * commented for an easy rollback if we need to restore mixed payload support.
4
32
  */
5
33
  function resolveItemReferencesForPage(page, ruleInCategory) {
34
+ return buildItemsFromHtmlGroupsForPage(page, ruleInCategory);
35
+
36
+ /*
6
37
  const items = page.items || [];
7
- if (items.length === 0) return [];
38
+
39
+ if (items.length === 0) {
40
+ return buildItemsFromHtmlGroupsForPage(page, ruleInCategory);
41
+ }
8
42
 
9
43
  const isReference = typeof items[0] === 'string';
10
44
 
@@ -27,6 +61,7 @@
27
61
  pageTitle: page.pageTitle || page.metadata
28
62
  };
29
63
  }
64
+
30
65
  // Fallback: parse composite key
31
66
  const nullByteIndex = compositeKey.indexOf('\x00');
32
67
  const html = nullByteIndex !== -1 ? compositeKey.slice(0, nullByteIndex) : compositeKey;
@@ -40,6 +75,7 @@
40
75
  pageTitle: page.pageTitle || page.metadata
41
76
  };
42
77
  });
78
+ */
43
79
  }
44
80
 
45
81
  function buildItemCardsWithPagination(accordionId, category, ruleInCategory, page, index) {
@@ -86,7 +86,7 @@
86
86
  // Use pre-computed htmlGroups for count if available, otherwise use pages
87
87
  const count = isHtmlGrouping && selectedCategory.htmlGroups
88
88
  ? Object.keys(selectedCategory.htmlGroups).length
89
- : selectedCategory.pagesAffected.length;
89
+ : (selectedCategory.pagesAffectedCount || selectedCategory.pagesAffected.length);
90
90
  if (isHtmlGrouping) {
91
91
  dropdownTitle.innerText = `HTML elements affected by this issue (${count})`;
92
92
  } else {
@@ -270,8 +270,8 @@ include('./pageAccordionBuilder') %> <%- include('./constants') %>
270
270
  if (!Array.isArray(rule.pagesAffected)) return;
271
271
 
272
272
  rule.pagesAffected.sort((a, b) => {
273
- const lenA = Array.isArray(a.items) ? a.items.length : 0;
274
- const lenB = Array.isArray(b.items) ? b.items.length : 0;
273
+ const lenA = Array.isArray(a.items) ? a.items.length : a.itemsCount || 0;
274
+ const lenB = Array.isArray(b.items) ? b.items.length : b.itemsCount || 0;
275
275
  return lenB - lenA; // DESC
276
276
  });
277
277
  });
@@ -295,10 +295,10 @@ include('./pageAccordionBuilder') %> <%- include('./constants') %>
295
295
  dropdownToggle.innerText = `${ruleInCategory.totalItems} Total occ.`;
296
296
  dropdownToggle.setAttribute('aria-label', occurrencesText);
297
297
  document.getElementById('expandedRuleDropdownTitle').innerText =
298
- `Pages affected by this issue (${ruleInCategory.pagesAffected.length})`;
298
+ `Pages affected by this issue (${(ruleInCategory.pagesAffectedCount || ruleInCategory.pagesAffected.length)})`;
299
299
  buildExpandedRuleCategoryContent(category, ruleInCategory);
300
300
  document.getElementById('expandedRulePageContent').innerText =
301
- `Total ${ruleInCategory.pagesAffected.length} affected pages`;
301
+ `Total ${(ruleInCategory.pagesAffectedCount || ruleInCategory.pagesAffected.length)} affected pages`;
302
302
  }
303
303
  }
304
304
  });
@@ -21,14 +21,25 @@
21
21
  %>
22
22
  <script>
23
23
  const scanItems = <%- JSON.stringify(
24
- {
25
- ...items,
26
- passed: {
27
- rules: items.passed.rules.map(r => delete r.pagesAffected),
28
- ...items.passed
29
- },
30
- }
31
- ) %>
24
+ ['mustFix','goodToFix','needsReview','passed'].reduce((acc, cat) => {
25
+ if (items[cat]) {
26
+ acc[cat] = {
27
+ description: items[cat].description,
28
+ totalItems: items[cat].totalItems,
29
+ totalRuleIssues: items[cat].totalRuleIssues,
30
+ rules: (items[cat].rules || []).map(rule => ({
31
+ rule: rule.rule,
32
+ description: rule.description,
33
+ helpUrl: rule.helpUrl,
34
+ conformance: rule.conformance,
35
+ totalItems: rule.totalItems,
36
+ pagesAffected: { length: (rule.pagesAffected || []).length },
37
+ })),
38
+ };
39
+ }
40
+ return acc;
41
+ }, {})
42
+ ).replace(/<\//g, '<\\/') %>
32
43
  </script>
33
44
  <%- include('partials/scripts/summaryTable') %>
34
45
  <script>
package/src/utils.ts CHANGED
@@ -5,6 +5,7 @@ import fs from 'fs-extra';
5
5
  import axe, { Rule } from 'axe-core';
6
6
  import { v4 as uuidv4 } from 'uuid';
7
7
  import { getDomain } from 'tldts';
8
+ import { normalizeUrl } from '@apify/utilities';
8
9
  import constants, {
9
10
  BrowserTypes,
10
11
  destinationPath,
@@ -1078,13 +1079,13 @@ export const randomThreeDigitNumberString = () => {
1078
1079
  return String(threeDigitNumber);
1079
1080
  };
1080
1081
 
1082
+ export const normUrl = (u: string): string => (u ? normalizeUrl(u) || u : '');
1083
+
1081
1084
  export const isFollowStrategy = (link1: string, link2: string, rule: string): boolean => {
1085
+ if (rule === 'all') return true;
1082
1086
  try {
1083
1087
  const parsedLink1 = new URL(link1);
1084
1088
  const parsedLink2 = new URL(link2);
1085
- if (rule === 'all') {
1086
- return true;
1087
- }
1088
1089
  if (rule === 'same-origin') {
1089
1090
  return parsedLink1.origin === parsedLink2.origin;
1090
1091
  }