shadscan-vue 0.2.0 → 0.3.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0](https://github.com/vinayakkulkarni/shadscan-vue/compare/v0.2.1...v0.3.0) (2026-07-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * **scan:** skip illustrative directories ([50fec75](https://github.com/vinayakkulkarni/shadscan-vue/commit/50fec753c75378e5dede5ce65bf69e09aed41c39))
9
+
10
+
11
+ ### Documentation
12
+
13
+ * reference the action by its moving major tag ([0ee2d7d](https://github.com/vinayakkulkarni/shadscan-vue/commit/0ee2d7d0d503cb3d68312f5172a53da00bbf19c6))
14
+
15
+ ## [0.2.1](https://github.com/vinayakkulkarni/shadscan-vue/compare/v0.2.0...v0.2.1) (2026-07-26)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **rules:** treat slot-projected content as an accessible name ([4dc2cc0](https://github.com/vinayakkulkarni/shadscan-vue/commit/4dc2cc0413b28f76783c85035f4ca83b46feaa39))
21
+
3
22
  ## [0.2.0](https://github.com/vinayakkulkarni/shadscan-vue/compare/v0.1.2...v0.2.0) (2026-07-26)
4
23
 
5
24
 
package/README.md CHANGED
@@ -88,7 +88,7 @@ There is also a composite action, which writes the score and every failing
88
88
  rule to the job summary:
89
89
 
90
90
  ```yaml
91
- - uses: vinayakkulkarni/shadscan-vue@v0.2.0
91
+ - uses: vinayakkulkarni/shadscan-vue@v0
92
92
  with:
93
93
  fail-under: 70
94
94
  ```
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  import { cac } from "cac";
5
5
  import { glob } from "tinyglobby";
6
6
  import { parse } from "@vue/compiler-sfc";
7
- import { NodeTypes } from "@vue/compiler-dom";
7
+ import { ElementTypes, NodeTypes } from "@vue/compiler-dom";
8
8
  import ts from "typescript";
9
9
  import { parse as parse$1 } from "jsonc-parser";
10
10
  import pc from "picocolors";
@@ -64,6 +64,12 @@ const IGNORE_PATTERNS = [
64
64
  "**/fixtures/**",
65
65
  "**/__tests__/**",
66
66
  "**/__mocks__/**",
67
+ "**/__registry__/**",
68
+ "**/demo/**",
69
+ "**/demos/**",
70
+ "**/example/**",
71
+ "**/examples/**",
72
+ "**/_*/**",
67
73
  "**/*.spec.*",
68
74
  "**/*.test.*",
69
75
  "**/*.stories.*",
@@ -736,6 +742,19 @@ const collectText = (children) => {
736
742
  };
737
743
  const visibleText = (element) => collectText(element.children).trim();
738
744
  /**
745
+ * True when the element projects caller-supplied content through a `<slot>`.
746
+ * The name then lives at the call site, so the component itself cannot be
747
+ * judged nameless — `<a><slot /></a>` is a wrapper, not an anonymous link.
748
+ */
749
+ const projectsSlotContent = (element) => {
750
+ for (const child of element.children) {
751
+ if (child.type !== NodeTypes.ELEMENT) continue;
752
+ if (child.tagType === ElementTypes.SLOT) return true;
753
+ if (projectsSlotContent(child)) return true;
754
+ }
755
+ return false;
756
+ };
757
+ /**
739
758
  * True when the element carries an explicit accessible name via ARIA,
740
759
  * a title, or visually-hidden text.
741
760
  */
@@ -1234,7 +1253,7 @@ const iconButtonsHaveLabels = {
1234
1253
  const children = elementChildren(element);
1235
1254
  if (!(children.length > 0 && children.every((child) => isIconTag$1(child.tag)) || findAttribute(element, "size")?.static === "icon")) return;
1236
1255
  if (visibleText(element).length > 0) return;
1237
- if (hasAriaName(element) || hasScreenReaderText(element)) return;
1256
+ if (hasAriaName(element) || hasScreenReaderText(element) || projectsSlotContent(element)) return;
1238
1257
  findings.push({
1239
1258
  message: `Icon-only <${element.tag}> has no accessible name.`,
1240
1259
  evidence: [{
@@ -1439,7 +1458,7 @@ const linksHaveAccessibleNames = {
1439
1458
  if (!LINK_TAGS$2.has(element.tag)) return;
1440
1459
  if (visibleText(element).length > 0) return;
1441
1460
  if (hasAriaName(element) || hasScreenReaderText(element)) return;
1442
- if (hasLabelledImage(element)) return;
1461
+ if (hasLabelledImage(element) || projectsSlotContent(element)) return;
1443
1462
  findings.push({
1444
1463
  message: `<${element.tag}> has no accessible name.`,
1445
1464
  evidence: [{