Skip to content

Commit affd6e4

Browse files
committed
Jsx: handle data- and aria- props for all components
`aria-` props are type-checked against their specification [0], and enums are provided where necessary (see `react.jsx.AriaAttributes`). They are enabled by default for both html elements and react components. You can disable `aria-` props entirely with `-D react_jsx_no_aria`, or only disable it for react components with `-D react_jsx_no_aria_for_components`. `data-` props are enabled by default for react components (all unknown props are already accepted for html elements), with a type of `Dynamic`. They can be disabled with `-D react_jsx_no_data_for_components`. [0]: https://www.w3.org/TR/wai-aria-1.1/#state_prop_def
1 parent 796ec00 commit affd6e4

File tree

2 files changed

+145
-1
lines changed

2 files changed

+145
-1
lines changed

src/lib/react/ReactMacro.hx

+26-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import haxe.macro.TypeTools;
99
import tink.hxx.Node;
1010
import tink.hxx.Parser;
1111
import tink.hxx.StringAt;
12+
import react.jsx.AriaAttributes;
1213
import react.jsx.HtmlEntities;
1314
import react.jsx.JsxStaticMacro;
1415
import react.macro.MacroUtil;
@@ -180,6 +181,18 @@ class ReactMacro
180181
return value;
181182

182183
default:
184+
#if !react_jsx_no_data_for_components
185+
// Always allow data- props
186+
if (StringTools.startsWith(field, "data-")) return value;
187+
#end
188+
189+
#if (!react_jsx_no_aria || !react_jsx_no_aria_for_components)
190+
// Always allow valid aria- attributes
191+
if (StringTools.startsWith(field, "aria-")) {
192+
var ct = AriaAttributes.map[field];
193+
if (ct != null) return macro @:pos(value.pos) (${value} :$ct);
194+
}
195+
#end
183196
}
184197
}
185198
}
@@ -241,7 +254,19 @@ class ReactMacro
241254
}
242255

243256
return isHtml
244-
? function(_, e:Expr) return e
257+
? function(name:StringAt, value:Expr) {
258+
#if !react_jsx_no_aria
259+
// Type valid aria- attributes
260+
// TODO: consider displaying warning for unknown `aria-` props
261+
var field = name.value;
262+
if (StringTools.startsWith(field, "aria-")) {
263+
var ct = AriaAttributes.map[field];
264+
if (ct != null) return macro @:pos(value.pos) (${value} :$ct);
265+
}
266+
#end
267+
268+
return value;
269+
}
245270
: switch (t) {
246271
case TFun(args, _):
247272
switch (args) {

src/lib/react/jsx/AriaAttributes.hx

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package react.jsx;
2+
3+
#if macro
4+
import haxe.macro.Expr.ComplexType;
5+
#end
6+
7+
class AriaAttributes {
8+
#if macro
9+
static public var map:Map<String, ComplexType> = [
10+
"aria-activedescendant" => macro :react.jsx.AriaAttributes.IdReference,
11+
"aria-atomic" => macro :Bool,
12+
"aria-autocomplete" => macro :react.jsx.AriaAttributes.AriaAutoComplete,
13+
"aria-busy" => macro :Bool,
14+
"aria-checked" => macro :react.jsx.AriaAttributes.TriState,
15+
"aria-colcount" => macro :Int,
16+
"aria-colindex" => macro :Int,
17+
"aria-colspan" => macro :Int,
18+
"aria-controls" => macro :react.jsx.AriaAttributes.IdReferenceList,
19+
"aria-current" => macro :react.jsx.AriaAttributes.AriaCurrent,
20+
"aria-describedby" => macro:react.jsx.AriaAttributes.IdReferenceList,
21+
"aria-details" => macro :react.jsx.AriaAttributes.IdReference,
22+
"aria-disabled" => macro :Bool,
23+
"aria-errormessage" => macro :react.jsx.AriaAttributes.IdReference,
24+
"aria-expanded" => macro :Bool,
25+
"aria-flowto" => macro :react.jsx.AriaAttributes.IdReferenceList,
26+
"aria-haspopup" => macro :react.jsx.AriaAttributes.AriaHasPopup,
27+
"aria-hidden" => macro :Bool,
28+
"aria-invalid" => macro :react.jsx.AriaAttributes.AriaInvalid,
29+
"aria-keyshortcuts" => macro :String,
30+
"aria-label" => macro :String,
31+
"aria-labelledby" => macro :react.jsx.AriaAttributes.IdReferenceList,
32+
"aria-level" => macro :Int,
33+
"aria-live" => macro :react.jsx.AriaAttributes.AriaLive,
34+
"aria-modal" => macro :Bool,
35+
"aria-multiline" => macro :Bool,
36+
"aria-multiselectable" => macro :Bool,
37+
"aria-orientation" => macro :react.jsx.AriaAttributes.AriaOrientation,
38+
"aria-owns" => macro :react.jsx.AriaAttributes.IdReferenceList,
39+
"aria-placeholder" => macro :String,
40+
"aria-posinset" => macro :Int,
41+
"aria-pressed" => macro :react.jsx.AriaAttributes.TriState,
42+
"aria-readonly" => macro :Bool,
43+
"aria-relevant" => macro :react.jsx.AriaAttributes.AriaRelevant,
44+
"aria-required" => macro :Bool,
45+
"aria-roledescription" => macro :String,
46+
"aria-rowcount" => macro :Int,
47+
"aria-rowindex" => macro :Int,
48+
"aria-rowspan" => macro :Int,
49+
"aria-selected" => macro :Bool,
50+
"aria-setsize" => macro :Int,
51+
"aria-sort" => macro :react.jsx.AriaAttributes.AriaSort,
52+
"aria-valuemax" => macro :Float,
53+
"aria-valuemin" => macro :Float,
54+
"aria-valuenow" => macro :Float,
55+
"aria-valuetext" => macro :String
56+
];
57+
#end
58+
}
59+
60+
typedef IdReference = String;
61+
typedef IdReferenceList = String;
62+
63+
@:enum abstract TriState(Dynamic) from Bool {
64+
var Mixed = "mixed";
65+
}
66+
67+
@:enum abstract AriaAutoComplete(String) {
68+
var Inline = "inline";
69+
var List = "list";
70+
var Both = "both";
71+
var None = "none";
72+
}
73+
74+
@:enum abstract AriaCurrent(Dynamic) from Bool {
75+
var Page = "page";
76+
var Step = "step";
77+
var Location = "location";
78+
var Date = "date";
79+
var Time = "time";
80+
}
81+
82+
@:enum abstract AriaHasPopup(Dynamic) from Bool {
83+
var Menu = "menu";
84+
var Listbox = "listbox";
85+
var Tree = "tree";
86+
var Grid = "grid";
87+
var Dialog = "dialog";
88+
}
89+
90+
@:enum abstract AriaInvalid(Dynamic) from Bool {
91+
var Grammar = "grammar";
92+
var Spelling = "spelling";
93+
}
94+
95+
@:enum abstract AriaLive(String) {
96+
var Assertive = "assertive";
97+
var Off = "off";
98+
var Polite = "polite";
99+
}
100+
101+
@:enum abstract AriaOrientation(String) {
102+
var Horizontal = "horizontal";
103+
var Vertical = "vertical";
104+
}
105+
106+
@:enum abstract AriaRelevant(String) {
107+
var Additions = "additions";
108+
var AdditionsText = "additions text";
109+
var All = "all";
110+
var Removals = "removals";
111+
var Text = "text";
112+
}
113+
114+
@:enum abstract AriaSort(String) {
115+
var Ascending = "ascending";
116+
var Descending = "descending";
117+
var None = "none";
118+
var Other = "other";
119+
}

0 commit comments

Comments
 (0)