]> code.delx.au - gnu-emacs-elpa/blob - web-forms.rnc
Emit error for empty form-control `name` attr.
[gnu-emacs-elpa] / web-forms.rnc
1 datatypes w = "http://whattf.org/datatype-draft"
2
3 # #####################################################################
4 ## RELAX NG Schema for HTML 5: Web Forms 1.0 markup #
5 # #####################################################################
6
7 ## Shared attributes for form controls
8
9 common-form.attrs =
10 ( common-form.attrs.name?
11 & common-form.attrs.disabled?
12 )
13
14 common-form.attrs.name =
15 attribute name {
16 form.data.nonemptystring
17 }
18
19 common-form.attrs.disabled =
20 attribute disabled {
21 w:string "disabled" | w:string ""
22 }
23
24 shared-form.attrs.readonly =
25 attribute readonly {
26 w:string "readonly" | w:string ""
27 }
28
29 shared-form.attrs.maxlength =
30 attribute maxlength {
31 common.data.integer.non-negative
32 }
33
34 shared-form.attrs.size =
35 attribute size {
36 common.data.integer.positive
37 }
38
39 # REVISIT tabindex goes in common.attrs
40
41 ## Shared attributes for <input>
42
43 input.attrs.checked =
44 attribute checked {
45 w:string "checked" | w:string ""
46 }
47
48 ## Text Field: <input type='text'>
49
50 input.text.elem =
51 element input { input.text.attrs }
52 input.text.attrs =
53 ( common.attrs
54 & common-form.attrs
55 & input.text.attrs.type?
56 & shared-form.attrs.maxlength?
57 & shared-form.attrs.readonly?
58 & shared-form.attrs.size?
59 & input.text.attrs.value?
60 & ( common.attrs.aria.implicit.textbox
61 | common.attrs.aria.implicit.combobox
62 | common.attrs.aria.role.textbox
63 | common.attrs.aria.role.combobox
64 )?
65 )
66 input.text.attrs.type =
67 attribute type {
68 w:string "text"
69 }
70 input.text.attrs.value =
71 attribute value {
72 form.data.stringwithoutlinebreaks
73 }
74
75 input.elem = input.text.elem
76
77 ## Password Field: <input type='password'>
78
79 input.password.elem =
80 element input { input.password.attrs }
81 input.password.attrs =
82 ( common.attrs
83 & common-form.attrs
84 & input.password.attrs.type
85 & shared-form.attrs.maxlength?
86 & shared-form.attrs.readonly?
87 & shared-form.attrs.size?
88 & input.password.attrs.value?
89 & ( common.attrs.aria.implicit.textbox
90 | common.attrs.aria.role.textbox
91 )?
92 )
93 input.password.attrs.type =
94 attribute type {
95 w:string "password"
96 }
97 input.password.attrs.value =
98 attribute value {
99 form.data.stringwithoutlinebreaks
100 }
101
102 input.elem |= input.password.elem
103
104 ## Checkbox: <input type='checkbox'>
105
106 input.checkbox.elem =
107 element input { input.checkbox.attrs }
108 input.checkbox.attrs =
109 ( common.attrs
110 & common-form.attrs
111 & input.checkbox.attrs.type
112 & input.attrs.checked?
113 & input.checkbox.attrs.value?
114 & ( common.attrs.aria.implicit.checkbox
115 | common.attrs.aria.role.checkbox
116 | common.attrs.aria.role.menuitemcheckbox
117 )?
118 )
119 input.checkbox.attrs.type =
120 attribute type {
121 w:string "checkbox"
122 }
123 input.checkbox.attrs.value =
124 attribute value {
125 string #REVISIT require non-empty value?
126 }
127
128 input.elem |= input.checkbox.elem
129
130 ## Radiobutton: <input type='radio'>
131
132 input.radio.elem =
133 element input { input.radio.attrs }
134 input.radio.attrs =
135 ( common.attrs
136 & common-form.attrs
137 & input.radio.attrs.type
138 & input.attrs.checked?
139 & input.radio.attrs.value?
140 & ( common.attrs.aria.implicit.radio
141 | common.attrs.aria.role.radio
142 | common.attrs.aria.role.menuitemradio
143 )?
144 )
145 input.radio.attrs.type =
146 attribute type {
147 w:string "radio"
148 }
149 input.radio.attrs.value =
150 attribute value {
151 string #REVISIT require non-empty value?
152 }
153
154 input.elem |= input.radio.elem
155
156 ## Scripting Hook Button: <input type='button'>
157
158 input.button.elem =
159 element input { input.button.attrs }
160 input.button.attrs =
161 ( common.attrs
162 & common-form.attrs
163 & input.button.attrs.type
164 & input.button.attrs.value?
165 & ( common.attrs.aria.implicit.button
166 | common.attrs.aria.role.button
167 | common.attrs.aria.role.link
168 | common.attrs.aria.role.menuitem
169 | common.attrs.aria.role.menuitemcheckbox
170 | common.attrs.aria.role.menuitemradio
171 | common.attrs.aria.role.radio
172 )?
173 )
174 input.button.attrs.type =
175 attribute type {
176 w:string "button"
177 }
178 input.button.attrs.value =
179 attribute value {
180 string #REVISIT require non-empty value?
181 }
182
183 input.elem |= input.button.elem
184 #REVISIT should this be enabled by a scripting module only?
185
186 ## Submit Button: <input type='submit'>
187
188 input.submit.elem =
189 element input { input.submit.attrs }
190 input.submit.attrs =
191 ( common.attrs
192 & common-form.attrs
193 & input.submit.attrs.type
194 & input.submit.attrs.value?
195 & ( common.attrs.aria.implicit.button
196 | common.attrs.aria.role.button
197 )?
198 )
199 input.submit.attrs.type =
200 attribute type {
201 w:string "submit"
202 }
203 input.submit.attrs.value =
204 attribute value {
205 string #REVISIT require non-empty value?
206 }
207
208 input.elem |= input.submit.elem
209
210 ## Reset Button: <input type='reset'>
211
212 input.reset.elem =
213 element input { input.reset.attrs }
214 input.reset.attrs =
215 ( common.attrs
216 & common-form.attrs
217 & input.reset.attrs.type
218 & input.reset.attrs.value?
219 & ( common.attrs.aria.implicit.button
220 | common.attrs.aria.role.button
221 )?
222 )
223 input.reset.attrs.type =
224 attribute type {
225 w:string "reset"
226 }
227 input.reset.attrs.value =
228 attribute value {
229 string #REVISIT require non-empty value?
230 }
231
232 input.elem |= input.reset.elem
233 # REVISIT does reset make sense outside a form?
234
235 ## File Upload: <input type='file'>
236
237 input.file.elem =
238 element input { input.file.attrs }
239 input.file.attrs =
240 ( common.attrs
241 & common-form.attrs
242 & input.file.attrs.type
243 & input.file.attrs.accept?
244 & common.attrs.aria?
245 )
246 input.file.attrs.type =
247 attribute type {
248 w:string "file"
249 }
250 input.file.attrs.accept =
251 attribute accept {
252 form.data.mimetypelist
253 }
254
255 input.elem |= input.file.elem
256
257 ## Hidden String: <input type='hidden'>
258
259 input.hidden.elem =
260 element input { input.hidden.attrs }
261 input.hidden.attrs =
262 ( common.attrs
263 & common-form.attrs
264 & input.hidden.attrs.type
265 & input.hidden.attrs.value?
266 & common.attrs.aria?
267 )
268 input.hidden.attrs.type =
269 attribute type {
270 w:string "hidden"
271 }
272 input.hidden.attrs.value =
273 attribute value {
274 string
275 }
276
277 input.elem |= input.hidden.elem
278
279 ## Image Submit Button: <input type='image'>
280
281 input.image.elem =
282 element input { input.image.attrs }
283 input.image.attrs =
284 ( common.attrs
285 & common-form.attrs
286 & input.image.attrs.type
287 & input.image.attrs.alt
288 & input.image.attrs.src?
289 & ( common.attrs.aria.implicit.button
290 | common.attrs.aria.role.button
291 | common.attrs.aria.role.link
292 | common.attrs.aria.role.menuitem
293 | common.attrs.aria.role.menuitemcheckbox
294 | common.attrs.aria.role.menuitemradio
295 | common.attrs.aria.role.radio
296 )?
297 )
298 input.image.attrs.type =
299 attribute type {
300 w:string "image"
301 }
302 input.image.attrs.alt =
303 attribute alt {
304 form.data.nonemptystring
305 }
306 input.image.attrs.src =
307 attribute src {
308 common.data.uri.non-empty
309 }
310
311 input.elem |= input.image.elem
312
313 common.elem.phrasing |= input.elem
314
315 ## Text Area: <textarea>
316
317 textarea.elem =
318 element textarea { textarea.inner & textarea.attrs }
319 textarea.attrs =
320 ( common.attrs
321 & common-form.attrs
322 & shared-form.attrs.readonly?
323 & textarea.attrs.rows-and-cols-wf1
324 & ( common.attrs.aria.implicit.textbox
325 | common.attrs.aria.role.presentation
326 | common.attrs.aria.role.menuitem
327 | common.attrs.aria.role.textbox
328 )?
329 #FIXME onfocus, onblur, onselect,onchange
330 )
331 # This is ugly.
332 textarea.attrs.rows-and-cols-wf1 =
333 textarea.attrs.rows-and-cols-wf1.inner
334 textarea.attrs.rows-and-cols-wf1.inner =
335 ( textarea.attrs.cols
336 & textarea.attrs.rows
337 )
338 textarea.attrs.cols =
339 attribute cols {
340 common.data.integer.positive
341 }
342 textarea.attrs.rows =
343 attribute rows {
344 common.data.integer.positive
345 }
346 textarea.inner =
347 ( text )
348
349 common.elem.phrasing |= textarea.elem
350
351 # Due to limitations with interleave, handling single/multiple selection
352 # enforcement in RELAX NG seems to be possible but really awkward.
353 # Tried it. Leaving it to Schematron.
354
355 ## Select menu option: <option selected>
356
357 option.elem =
358 element option { option.inner & option.attrs }
359 option.attrs =
360 ( common.attrs
361 & common-form.attrs.disabled?
362 & option.attrs.selected?
363 & option.attrs.label?
364 & option.attrs.value?
365 & ( common.attrs.aria.implicit.option
366 | common.attrs.aria.role.option
367 | common.attrs.aria.role.menuitem
368 | common.attrs.aria.role.menuitemradio
369 | common.attrs.aria.role.menuitemcheckbox
370 | common.attrs.aria.role.presentation
371 )?
372 )
373 option.attrs.selected =
374 attribute selected {
375 w:string "selected" | w:string ""
376 }
377 option.attrs.label =
378 attribute label {
379 form.data.nonemptystring
380 }
381 option.attrs.value =
382 attribute value {
383 string
384 }
385 option.inner =
386 ( text )
387
388 ## Option Group: <optgroup>
389
390 optgroup.elem =
391 element optgroup { optgroup.inner & optgroup.attrs }
392 optgroup.attrs =
393 ( common.attrs
394 & optgroup.attrs.label
395 & common-form.attrs.disabled?
396 & ( common.attrs.aria.role.presentation
397 | common.attrs.aria.role.menuitem
398 )?
399 )
400 optgroup.attrs.label =
401 attribute label {
402 string
403 }
404 optgroup.inner =
405 ( option.elem*
406 & common.elem.script-supporting*
407 )
408
409 ## Selection Menu: <select>
410
411 select.elem =
412 element select { select.inner & select.attrs }
413 select.attrs =
414 ( common.attrs
415 & common-form.attrs
416 & select.attrs.size?
417 & select.attrs.multiple?
418 # FIXME onfocus, onblur, onchange
419 & ( common.attrs.aria.implicit.listbox
420 | common.attrs.aria.role.listbox # aria-multiselectable depends on "multiple" value; check in assertions
421 | common.attrs.aria.role.menu
422 | common.attrs.aria.role.presentation
423 | common.attrs.aria.role.menuitem
424 )?
425 )
426 select.attrs.size =
427 attribute size {
428 common.data.integer.positive
429 }
430 select.attrs.multiple =
431 attribute multiple {
432 w:string "multiple" | w:string ""
433 }
434 select.inner =
435 ( optgroup.elem*
436 & option.elem*
437 & common.elem.script-supporting*
438 )
439
440 common.elem.phrasing |= select.elem
441
442 ## Shared Definitions for Complex Button
443
444 button.attrs.value =
445 attribute value {
446 string
447 }
448 button.inner =
449 ( common.inner.phrasing )
450
451 ## Complex Submit Button: <button type='submit'>
452
453 button.submit.elem =
454 element button { button.inner & button.submit.attrs }
455 button.submit.attrs =
456 ( common.attrs
457 & common-form.attrs
458 & button.submit.attrs.type?
459 & button.attrs.value?
460 & ( common.attrs.aria.implicit.button
461 | common.attrs.aria.role.button
462 | common.attrs.aria.role.link
463 | common.attrs.aria.role.menuitem
464 | common.attrs.aria.role.menuitemcheckbox
465 | common.attrs.aria.role.menuitemradio
466 | common.attrs.aria.role.radio
467 )?
468 )
469 button.submit.attrs.type =
470 attribute type {
471 w:string "submit"
472 }
473
474 button.elem = button.submit.elem
475
476 ## Complex Reset Button: <button type='reset'>
477
478 button.reset.elem =
479 element button { button.inner & button.reset.attrs }
480 button.reset.attrs =
481 ( common.attrs
482 & common-form.attrs
483 & button.reset.attrs.type
484 & button.attrs.value? #REVISIT I guess this still affects the DOM
485 & ( common.attrs.aria.implicit.button
486 | common.attrs.aria.role.button
487 | common.attrs.aria.role.link
488 | common.attrs.aria.role.menuitem
489 | common.attrs.aria.role.menuitemcheckbox
490 | common.attrs.aria.role.menuitemradio
491 | common.attrs.aria.role.radio
492 )?
493 )
494 button.reset.attrs.type =
495 attribute type {
496 w:string "reset"
497 }
498
499 button.elem |= button.reset.elem
500
501 ## Complex Push Button: <button type='button'>
502
503 button.button.elem =
504 element button { button.inner & button.button.attrs }
505 button.button.attrs =
506 ( common.attrs
507 & common-form.attrs
508 & button.button.attrs.type
509 & button.attrs.value? #REVISIT I guess this still affects the DOM
510 & ( common.attrs.aria.implicit.button
511 | common.attrs.aria.role.button
512 | common.attrs.aria.role.link
513 | common.attrs.aria.role.menuitem
514 | common.attrs.aria.role.menuitemcheckbox
515 | common.attrs.aria.role.menuitemradio
516 | common.attrs.aria.role.radio
517 )?
518 )
519 button.button.attrs.type =
520 attribute type {
521 w:string "button"
522 }
523
524 button.elem |= button.button.elem
525
526 common.elem.phrasing |= button.elem
527
528 ## Form: <form>
529
530 form.elem =
531 element form { form.inner & form.attrs }
532 form.attrs =
533 ( common.attrs
534 & form.attrs.action? #REVISIT Should this be required anyway?
535 & form.attrs.method?
536 & form.attrs.enctype?
537 & common-form.attrs.name?
538 & form.attrs.accept-charset?
539 & common.attrs.aria?
540 )
541 form.attrs.action =
542 attribute action {
543 common.data.uri.non-empty
544 }
545 form.attrs.method =
546 attribute method {
547 form.attrs.method.data
548 }
549 form.attrs.method.data =
550 ( w:string "get" | w:string "post" )
551 form.attrs.enctype =
552 attribute enctype {
553 form.attrs.enctype.data
554 }
555 form.attrs.enctype.data =
556 ( w:string "application/x-www-form-urlencoded"
557 | w:string "multipart/form-data"
558 )
559 form.attrs.accept-charset =
560 attribute accept-charset {
561 form.data.charsetlist
562 }
563 form.inner =
564 ( common.inner.flow )
565
566 common.elem.flow |= form.elem
567
568 ## Fieldset: <fieldset>
569
570 fieldset.elem =
571 element fieldset { fieldset.inner & fieldset.attrs }
572 fieldset.attrs =
573 ( common.attrs
574 & ( common.attrs.aria.implicit.group
575 | common.attrs.aria
576 )?
577 )
578 fieldset.inner =
579 ( legend.elem? #REVISIT should this be required?
580 , common.inner.flow
581 )
582
583 common.elem.flow |= fieldset.elem
584
585 ## Label: <label>
586
587 label.elem =
588 element label { label.inner & label.attrs }
589 label.attrs =
590 ( common.attrs
591 & label.attrs.for?
592 & ( common.attrs.aria.role.presentation
593 | common.attrs.aria.role.menuitem
594 )?
595 )
596 label.attrs.for =
597 attribute for {
598 common.data.idref
599 }
600 label.inner =
601 ( common.inner.phrasing ) #REVISIT making obvious guess
602
603 common.elem.phrasing |= label.elem
604