@burger-editor/frozen-patty 4.0.0-alpha.7 → 4.0.0-alpha.70

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/dist/set-value.js CHANGED
@@ -25,7 +25,6 @@ export function setValue(el, name, datum, attr = 'field', filter, xssSanitize =
25
25
  if (filter) {
26
26
  datum = filter(datum);
27
27
  }
28
- // console.log({ name, field, fieldName, propName, datum, el: el.innerHTML });
29
28
  if (!propName) {
30
29
  setContent(el, datum, undefined, xssSanitize);
31
30
  return;
@@ -74,6 +73,53 @@ export function setValue(el, name, datum, attr = 'field', filter, xssSanitize =
74
73
  }
75
74
  el.setAttribute(propName, `${datum}`);
76
75
  }
76
+ /**
77
+ * Set a boolean attribute on an element via its DOM property.
78
+ * Empty string is treated as true (HTML boolean attribute convention).
79
+ * Falls back to setAttribute if the element doesn't match any of the expected types.
80
+ * @param el
81
+ * @param datum
82
+ * @param types
83
+ * @param prop
84
+ * @param emptyIsTrue
85
+ * @returns true if handled
86
+ */
87
+ function setBooleanAttr(el, datum, types, prop, emptyIsTrue = true) {
88
+ if (types.some((T) => el instanceof T)) {
89
+ // SAFETY: prop is always a hardcoded string literal from setBooleanAttrByName
90
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
+ el[prop] = emptyIsTrue ? (datum === '' ? true : !!datum) : !!datum;
92
+ return true;
93
+ }
94
+ return false;
95
+ }
96
+ /**
97
+ * Set an integer attribute on an element via its DOM property.
98
+ * Removes the attribute if the parsed value is NaN.
99
+ * Falls back to setAttribute if the element doesn't match any of the expected types.
100
+ * @param el
101
+ * @param name
102
+ * @param datum
103
+ * @param types
104
+ * @param prop
105
+ * @param floor
106
+ * @returns true if handled
107
+ */
108
+ function setIntegerAttr(el, name, datum, types, prop, floor = false) {
109
+ if (types.some((T) => el instanceof T)) {
110
+ const val = toInt(datum);
111
+ if (Number.isNaN(val)) {
112
+ el.removeAttribute(name);
113
+ }
114
+ else {
115
+ // SAFETY: prop is always a hardcoded string literal from setIntegerAttrByName
116
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
+ el[prop] = floor ? Math.floor(val) : val;
118
+ }
119
+ return true;
120
+ }
121
+ return false;
122
+ }
77
123
  /**
78
124
  *
79
125
  * @param el
@@ -121,6 +167,11 @@ function set(el, prefix, name, datum, xssSanitize = true) {
121
167
  el.removeAttribute(name);
122
168
  return;
123
169
  }
170
+ // Custom elements
171
+ if (el.localName.includes('-')) {
172
+ el.setAttribute(name, `${datum}`);
173
+ return;
174
+ }
124
175
  if (!name.startsWith('data-') && !propInElement(el, name)) {
125
176
  const dataAttr = `data-${prefix}-${kebabCase(name)}`;
126
177
  if (el.hasAttribute(dataAttr)) {
@@ -128,6 +179,25 @@ function set(el, prefix, name, datum, xssSanitize = true) {
128
179
  }
129
180
  return;
130
181
  }
182
+ if (setSpecialAttr(el, name, datum)) {
183
+ return;
184
+ }
185
+ if (setBooleanAttrByName(el, name, datum)) {
186
+ return;
187
+ }
188
+ if (setIntegerAttrByName(el, name, datum)) {
189
+ return;
190
+ }
191
+ el.setAttribute(name, `${datum}`);
192
+ }
193
+ /**
194
+ * Handle attributes with unique logic that doesn't fit boolean/integer patterns.
195
+ * @param el
196
+ * @param name
197
+ * @param datum
198
+ * @returns true if handled
199
+ */
200
+ function setSpecialAttr(el, name, datum) {
131
201
  switch (name) {
132
202
  case 'contenteditable': {
133
203
  switch (datum) {
@@ -141,7 +211,7 @@ function set(el, prefix, name, datum, xssSanitize = true) {
141
211
  el.removeAttribute(name);
142
212
  }
143
213
  }
144
- return;
214
+ return true;
145
215
  }
146
216
  case 'dir': {
147
217
  switch (datum) {
@@ -150,45 +220,45 @@ function set(el, prefix, name, datum, xssSanitize = true) {
150
220
  el.dir = datum;
151
221
  break;
152
222
  }
153
- // case 'auto':
154
223
  default: {
155
224
  el.removeAttribute(name);
156
225
  }
157
226
  }
158
- return;
227
+ return true;
159
228
  }
160
229
  case 'draggable': {
161
230
  if (typeof datum === 'boolean') {
162
231
  el.draggable = datum;
163
- break;
164
232
  }
165
- switch (datum) {
166
- case 'true': {
167
- el.draggable = true;
168
- break;
169
- }
170
- case 'false': {
171
- el.draggable = false;
172
- break;
173
- }
174
- // case 'auto':
175
- default: {
176
- el.removeAttribute(name);
233
+ else {
234
+ switch (datum) {
235
+ case 'true': {
236
+ el.draggable = true;
237
+ break;
238
+ }
239
+ case 'false': {
240
+ el.draggable = false;
241
+ break;
242
+ }
243
+ default: {
244
+ el.removeAttribute(name);
245
+ }
177
246
  }
178
247
  }
179
- return;
248
+ return true;
180
249
  }
181
250
  case 'hidden': {
182
251
  if (datum === 'until-found') {
183
252
  el.setAttribute(name, datum);
184
- return;
185
253
  }
186
- el.hidden = !!datum;
187
- return;
254
+ else {
255
+ el.hidden = !!datum;
256
+ }
257
+ return true;
188
258
  }
189
259
  case 'spellcheck': {
190
260
  el.spellcheck = !!datum;
191
- return;
261
+ return true;
192
262
  }
193
263
  case 'tabindex': {
194
264
  let i;
@@ -199,501 +269,224 @@ function set(el, prefix, name, datum, xssSanitize = true) {
199
269
  i = Number.parseInt(datum, 10);
200
270
  }
201
271
  else {
202
- i = datum;
272
+ i = datum ?? -1;
203
273
  }
204
274
  el.tabIndex = Number.isNaN(i) ? -1 : Math.floor(i);
205
- return;
206
- }
207
- case 'async': {
208
- if (el instanceof HTMLScriptElement) {
209
- el.async = !!datum;
210
- }
211
- else {
212
- el.setAttribute(name, `${datum}`);
213
- }
214
- return;
275
+ return true;
215
276
  }
216
277
  case 'autocomplete': {
217
278
  if (el instanceof HTMLInputElement || el instanceof HTMLFormElement) {
218
- // @ts-ignore
219
- el.autocomplete = datum ? `${datum}` : 'off';
279
+ el.setAttribute(name, datum ? `${datum}` : 'off');
220
280
  }
221
281
  else {
222
282
  el.setAttribute(name, `${datum}`);
223
283
  }
224
- return;
284
+ return true;
225
285
  }
226
- case 'autofocus': {
227
- if (el instanceof HTMLButtonElement ||
228
- el instanceof HTMLInputElement ||
229
- el instanceof HTMLSelectElement ||
230
- el instanceof HTMLTextAreaElement) {
231
- el.autofocus = datum === '' ? true : !!datum;
286
+ case 'download': {
287
+ if (el instanceof HTMLAnchorElement) {
288
+ if (datum || datum === '') {
289
+ el.download = `${datum}`;
290
+ }
291
+ else {
292
+ el.removeAttribute(name);
293
+ }
232
294
  }
233
295
  else {
234
296
  el.setAttribute(name, `${datum}`);
235
297
  }
236
- return;
298
+ return true;
237
299
  }
238
- case 'autoplay': {
300
+ case 'preload': {
239
301
  if (el instanceof HTMLAudioElement || el instanceof HTMLVideoElement) {
240
- el.autoplay = datum === '' ? true : !!datum;
302
+ switch (datum) {
303
+ case '':
304
+ case 'auto':
305
+ case 'metadata': {
306
+ el.preload = datum;
307
+ break;
308
+ }
309
+ default: {
310
+ el.preload = 'none';
311
+ }
312
+ }
241
313
  }
242
314
  else {
243
315
  el.setAttribute(name, `${datum}`);
244
316
  }
245
- return;
317
+ return true;
246
318
  }
247
- case 'checked': {
319
+ case 'step': {
248
320
  if (el instanceof HTMLInputElement) {
249
- el.checked = datum === '' ? true : !!datum;
250
- }
251
- else {
252
- el.setAttribute(name, `${datum}`);
253
- }
254
- return;
255
- }
256
- case 'cols': {
257
- if (el instanceof HTMLTextAreaElement) {
258
- const cols = toInt(datum);
259
- if (Number.isNaN(cols)) {
260
- el.removeAttribute(name);
321
+ if (datum === 'any') {
322
+ el.step = datum;
261
323
  }
262
324
  else {
263
- el.cols = cols;
325
+ const step = toNum(datum);
326
+ if (Number.isNaN(step)) {
327
+ el.removeAttribute(name);
328
+ }
329
+ else {
330
+ el.step = step.toString(10);
331
+ }
264
332
  }
265
333
  }
266
334
  else {
267
335
  el.setAttribute(name, `${datum}`);
268
336
  }
269
- return;
337
+ return true;
270
338
  }
271
- case 'colspan': {
272
- if (el instanceof HTMLTableCellElement) {
273
- const colSpan = toInt(datum);
274
- if (Number.isNaN(colSpan)) {
275
- el.removeAttribute(name);
339
+ case 'target': {
340
+ if (el instanceof HTMLAnchorElement ||
341
+ el instanceof HTMLAreaElement ||
342
+ el instanceof HTMLFormElement) {
343
+ if (datum) {
344
+ el.target = `${datum}`;
276
345
  }
277
346
  else {
278
- el.colSpan = colSpan;
347
+ el.removeAttribute(name);
279
348
  }
280
349
  }
281
350
  else {
282
351
  el.setAttribute(name, `${datum}`);
283
352
  }
284
- return;
353
+ return true;
354
+ }
355
+ default: {
356
+ return false;
357
+ }
358
+ }
359
+ }
360
+ /**
361
+ * Handle boolean HTML attributes via their DOM properties.
362
+ * @param el
363
+ * @param name
364
+ * @param datum
365
+ * @returns true if handled
366
+ */
367
+ function setBooleanAttrByName(el, name, datum) {
368
+ switch (name) {
369
+ case 'async': {
370
+ return setBooleanAttr(el, datum, [HTMLScriptElement], 'async', false);
371
+ }
372
+ case 'autofocus': {
373
+ return setBooleanAttr(el, datum, [HTMLButtonElement, HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement], 'autofocus');
374
+ }
375
+ case 'autoplay': {
376
+ return setBooleanAttr(el, datum, [HTMLAudioElement, HTMLVideoElement], 'autoplay');
377
+ }
378
+ case 'checked': {
379
+ return setBooleanAttr(el, datum, [HTMLInputElement], 'checked');
285
380
  }
286
381
  case 'controls': {
287
- if (el instanceof HTMLAudioElement || el instanceof HTMLVideoElement) {
288
- el.controls = datum === '' ? true : !!datum;
289
- }
290
- else {
291
- el.setAttribute(name, `${datum}`);
292
- }
293
- return;
382
+ return setBooleanAttr(el, datum, [HTMLAudioElement, HTMLVideoElement], 'controls');
294
383
  }
295
384
  case 'default': {
296
- if (el instanceof HTMLTrackElement) {
297
- el.default = datum === '' ? true : !!datum;
298
- }
299
- else {
300
- el.setAttribute(name, `${datum}`);
301
- }
302
- return;
385
+ return setBooleanAttr(el, datum, [HTMLTrackElement], 'default');
303
386
  }
304
387
  case 'defer': {
305
- if (el instanceof HTMLScriptElement) {
306
- el.defer = !!datum;
307
- }
308
- else {
309
- el.setAttribute(name, `${datum}`);
310
- }
311
- return;
388
+ return setBooleanAttr(el, datum, [HTMLScriptElement], 'defer', false);
312
389
  }
313
390
  case 'disabled': {
314
- if (el instanceof HTMLButtonElement ||
315
- el instanceof HTMLFieldSetElement ||
316
- el instanceof HTMLInputElement ||
317
- el instanceof HTMLOptGroupElement ||
318
- el instanceof HTMLOptionElement ||
319
- el instanceof HTMLSelectElement ||
320
- el instanceof HTMLTextAreaElement) {
321
- el.disabled = datum === '' ? true : !!datum;
322
- }
323
- else {
324
- el.setAttribute(name, `${datum}`);
325
- }
326
- return;
327
- }
328
- case 'download': {
329
- if (el instanceof HTMLAnchorElement) {
330
- if (datum || datum === '') {
331
- el.download = `${datum}`;
332
- }
333
- else {
334
- el.removeAttribute(name);
335
- }
336
- }
337
- else {
338
- el.setAttribute(name, `${datum}`);
339
- }
340
- return;
341
- }
342
- case 'high': {
343
- if (el instanceof HTMLMeterElement) {
344
- const high = toInt(datum);
345
- if (Number.isNaN(high)) {
346
- el.removeAttribute(name);
347
- }
348
- else {
349
- el.high = high;
350
- }
351
- }
352
- else {
353
- el.setAttribute(name, `${datum}`);
354
- }
355
- return;
391
+ return setBooleanAttr(el, datum, [
392
+ HTMLButtonElement,
393
+ HTMLFieldSetElement,
394
+ HTMLInputElement,
395
+ HTMLOptGroupElement,
396
+ HTMLOptionElement,
397
+ HTMLSelectElement,
398
+ HTMLTextAreaElement,
399
+ ], 'disabled');
356
400
  }
357
401
  case 'ismap': {
358
- if (el instanceof HTMLImageElement) {
359
- el.isMap = datum === '' ? true : !!datum;
360
- }
361
- else {
362
- el.setAttribute(name, `${datum}`);
363
- }
364
- return;
402
+ return setBooleanAttr(el, datum, [HTMLImageElement], 'isMap');
365
403
  }
366
404
  case 'loop': {
367
- if (el instanceof HTMLAudioElement || el instanceof HTMLVideoElement) {
368
- el.loop = datum === '' ? true : !!datum;
369
- }
370
- else {
371
- el.setAttribute(name, `${datum}`);
372
- }
373
- return;
374
- }
375
- case 'low': {
376
- if (el instanceof HTMLMeterElement) {
377
- const low = toInt(datum);
378
- if (Number.isNaN(low)) {
379
- el.removeAttribute(name);
380
- }
381
- else {
382
- el.low = low;
383
- }
384
- }
385
- else {
386
- el.setAttribute(name, `${datum}`);
387
- }
388
- return;
389
- }
390
- case 'max': {
391
- if (el instanceof HTMLInputElement ||
392
- el instanceof HTMLMeterElement ||
393
- el instanceof HTMLProgressElement) {
394
- const max = toInt(datum);
395
- if (Number.isNaN(max)) {
396
- el.removeAttribute(name);
397
- }
398
- else {
399
- el.max = max;
400
- }
401
- }
402
- else {
403
- el.setAttribute(name, `${datum}`);
404
- }
405
- return;
406
- }
407
- case 'maxlength': {
408
- if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
409
- const maxLength = toInt(datum);
410
- if (Number.isNaN(maxLength)) {
411
- el.removeAttribute(name);
412
- }
413
- else {
414
- el.maxLength = Math.floor(maxLength);
415
- }
416
- }
417
- else {
418
- el.setAttribute(name, `${datum}`);
419
- }
420
- return;
421
- }
422
- case 'min': {
423
- if (el instanceof HTMLInputElement || el instanceof HTMLMeterElement) {
424
- const min = toInt(datum);
425
- if (Number.isNaN(min)) {
426
- el.removeAttribute(name);
427
- }
428
- else {
429
- el.min = min;
430
- }
431
- }
432
- else {
433
- el.setAttribute(name, `${datum}`);
434
- }
435
- return;
405
+ return setBooleanAttr(el, datum, [HTMLAudioElement, HTMLVideoElement], 'loop');
436
406
  }
437
407
  case 'multiple': {
438
- if (el instanceof HTMLInputElement || el instanceof HTMLSelectElement) {
439
- el.multiple = datum === '' ? true : !!datum;
440
- }
441
- else {
442
- el.setAttribute(name, `${datum}`);
443
- }
444
- return;
408
+ return setBooleanAttr(el, datum, [HTMLInputElement, HTMLSelectElement], 'multiple');
445
409
  }
446
410
  case 'novalidate': {
447
- if (el instanceof HTMLFormElement) {
448
- el.noValidate = datum === '' ? true : !!datum;
449
- }
450
- else {
451
- el.setAttribute(name, `${datum}`);
452
- }
453
- return;
411
+ return setBooleanAttr(el, datum, [HTMLFormElement], 'noValidate');
454
412
  }
455
413
  case 'open': {
456
- if (el instanceof HTMLDetailsElement) {
457
- el.open = datum === '' ? true : !!datum;
458
- }
459
- else {
460
- el.setAttribute(name, `${datum}`);
461
- }
462
- break;
463
- }
464
- case 'optimum': {
465
- if (el instanceof HTMLMeterElement) {
466
- const optimum = toInt(datum);
467
- if (Number.isNaN(optimum)) {
468
- el.removeAttribute(name);
469
- }
470
- else {
471
- el.optimum = Math.floor(optimum);
472
- }
473
- }
474
- else {
475
- el.setAttribute(name, `${datum}`);
476
- }
477
- return;
478
- }
479
- case 'preload': {
480
- if (el instanceof HTMLAudioElement || el instanceof HTMLVideoElement) {
481
- switch (datum) {
482
- case '':
483
- case 'auto':
484
- case 'metadata': {
485
- el.preload = datum;
486
- break;
487
- }
488
- default: {
489
- el.preload = 'none';
490
- }
491
- }
492
- }
493
- else {
494
- el.setAttribute(name, `${datum}`);
495
- }
496
- return;
414
+ return setBooleanAttr(el, datum, [HTMLDetailsElement], 'open');
497
415
  }
498
416
  case 'readonly': {
499
- if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
500
- el.readOnly = datum === '' ? true : !!datum;
501
- }
502
- else {
503
- el.setAttribute(name, `${datum}`);
504
- }
505
- return;
417
+ return setBooleanAttr(el, datum, [HTMLInputElement, HTMLTextAreaElement], 'readOnly');
506
418
  }
507
419
  case 'required': {
508
- if (el instanceof HTMLInputElement ||
509
- el instanceof HTMLSelectElement ||
510
- el instanceof HTMLTextAreaElement) {
511
- el.required = datum === '' ? true : !!datum;
512
- }
513
- else {
514
- el.setAttribute(name, `${datum}`);
515
- }
516
- return;
420
+ return setBooleanAttr(el, datum, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement], 'required');
517
421
  }
518
422
  case 'reversed': {
519
- if (el instanceof HTMLOListElement) {
520
- el.reversed = datum === '' ? true : !!datum;
521
- }
522
- else {
523
- el.setAttribute(name, `${datum}`);
524
- }
525
- return;
423
+ return setBooleanAttr(el, datum, [HTMLOListElement], 'reversed');
424
+ }
425
+ default: {
426
+ return false;
427
+ }
428
+ }
429
+ }
430
+ /**
431
+ * Handle integer HTML attributes via their DOM properties.
432
+ * @param el
433
+ * @param name
434
+ * @param datum
435
+ * @returns true if handled
436
+ */
437
+ function setIntegerAttrByName(el, name, datum) {
438
+ switch (name) {
439
+ case 'cols': {
440
+ return setIntegerAttr(el, name, datum, [HTMLTextAreaElement], 'cols');
441
+ }
442
+ case 'colspan': {
443
+ return setIntegerAttr(el, name, datum, [HTMLTableCellElement], 'colSpan');
444
+ }
445
+ case 'high': {
446
+ return setIntegerAttr(el, name, datum, [HTMLMeterElement], 'high');
447
+ }
448
+ case 'low': {
449
+ return setIntegerAttr(el, name, datum, [HTMLMeterElement], 'low');
450
+ }
451
+ case 'max': {
452
+ return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLMeterElement, HTMLProgressElement], 'max');
453
+ }
454
+ case 'maxlength': {
455
+ return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLTextAreaElement], 'maxLength', true);
456
+ }
457
+ case 'min': {
458
+ return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLMeterElement], 'min');
459
+ }
460
+ case 'optimum': {
461
+ return setIntegerAttr(el, name, datum, [HTMLMeterElement], 'optimum', true);
526
462
  }
527
463
  case 'rows': {
528
- if (el instanceof HTMLTextAreaElement) {
529
- const rows = toInt(datum);
530
- if (Number.isNaN(rows)) {
531
- el.removeAttribute(name);
532
- }
533
- else {
534
- el.rows = Math.floor(rows);
535
- }
536
- }
537
- else {
538
- el.setAttribute(name, `${datum}`);
539
- }
540
- return;
464
+ return setIntegerAttr(el, name, datum, [HTMLTextAreaElement], 'rows', true);
541
465
  }
542
466
  case 'rowspan': {
543
- if (el instanceof HTMLTableCellElement) {
544
- const rowSpan = toInt(datum);
545
- if (Number.isNaN(rowSpan)) {
546
- el.removeAttribute(name);
547
- }
548
- else {
549
- el.rowSpan = Math.floor(rowSpan);
550
- }
551
- }
552
- else {
553
- el.setAttribute(name, `${datum}`);
554
- }
555
- return;
467
+ return setIntegerAttr(el, name, datum, [HTMLTableCellElement], 'rowSpan', true);
556
468
  }
557
469
  case 'size': {
558
- if (el instanceof HTMLInputElement || el instanceof HTMLSelectElement) {
559
- const size = toInt(datum);
560
- if (Number.isNaN(size)) {
561
- el.removeAttribute(name);
562
- }
563
- else {
564
- el.size = size;
565
- }
566
- }
567
- else {
568
- el.setAttribute(name, `${datum}`);
569
- }
570
- return;
470
+ return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLSelectElement], 'size');
571
471
  }
572
472
  case 'span': {
573
- if (el instanceof HTMLTableColElement) {
574
- const span = toInt(datum);
575
- if (Number.isNaN(span)) {
576
- el.removeAttribute(name);
577
- }
578
- else {
579
- el.span = span;
580
- }
581
- }
582
- else {
583
- el.setAttribute(name, `${datum}`);
584
- }
585
- return;
473
+ return setIntegerAttr(el, name, datum, [HTMLTableColElement], 'span');
586
474
  }
587
475
  case 'start': {
588
- if (el instanceof HTMLOListElement) {
589
- const start = toInt(datum);
590
- if (Number.isNaN(start)) {
591
- el.removeAttribute(name);
592
- }
593
- else {
594
- el.start = start;
595
- }
596
- }
597
- else {
598
- el.setAttribute(name, `${datum}`);
599
- }
600
- return;
601
- }
602
- case 'step': {
603
- if (el instanceof HTMLInputElement) {
604
- if (datum === 'any') {
605
- el.step = datum;
606
- break;
607
- }
608
- const step = toNum(datum);
609
- if (Number.isNaN(step)) {
610
- el.removeAttribute(name);
611
- }
612
- else {
613
- el.step = step.toString(10);
614
- }
615
- }
616
- else {
617
- el.setAttribute(name, `${datum}`);
618
- }
619
- return;
620
- }
621
- case 'target': {
622
- if (el instanceof HTMLAnchorElement ||
623
- el instanceof HTMLAreaElement ||
624
- el instanceof HTMLFormElement) {
625
- if (datum) {
626
- el.target = `${datum}`;
627
- }
628
- else {
629
- el.removeAttribute(name);
630
- }
631
- }
632
- else {
633
- el.setAttribute(name, `${datum}`);
634
- }
635
- return;
476
+ return setIntegerAttr(el, name, datum, [HTMLOListElement], 'start');
636
477
  }
637
- // case 'accesskey':
638
- // case 'class':
639
- // case 'contextmenu':
640
- // case 'dropzone': // breakable support
641
- // case 'id':
642
- // case 'itemid':
643
- // case 'itemprop':
644
- // case 'itemref':
645
- // case 'itemscope':
646
- // case 'itemtype':
647
- // case 'lang':
648
- // case 'slot': // breakable support
649
- // case 'style':
650
- // case 'title':
651
- // case 'translate': // breakable support
652
- // case 'accept':
653
- // case 'accept-charset':
654
- // case 'action':
655
- // case 'align':
656
- // case 'alt':
657
- // case 'cite':
658
- // case 'coords':
659
- // case 'datetime':
660
- // case 'enctype':
661
- // case 'for':
662
- // case 'headers':
663
- // case 'href':
664
- // case 'hreflang':
665
- // case 'kind':
666
- // case 'label':
667
- // case 'list':
668
- // case 'media':
669
- // case 'method':
670
- // case 'name':
671
- // case 'pattern':
672
- // case 'placeholder':
673
- // case 'poster':
674
- // case 'pubdate':
675
- // case 'rel':
676
- // case 'sandbox':
677
- // case 'src':
678
- // case 'srcdoc':
679
- // case 'srclang':
680
- // case 'summary':
681
- // case 'type':
682
- // case 'usemap':
683
- // case 'value':
684
- // case 'wrap':
685
- // and Data-* attributes
686
478
  default: {
687
- el.setAttribute(name, `${datum}`);
479
+ return false;
688
480
  }
689
481
  }
690
482
  }
691
483
  /**
692
- *
693
- * @param el
694
- * @param datum
695
- * @param asHtml
696
- * @param xssSanitize
484
+ * Set content value on a form element or general element.
485
+ * Handles checkbox/radio checked state, input values, and innerHTML/textContent.
486
+ * @param el - The target element
487
+ * @param datum - The value to set
488
+ * @param asHtml - Whether to set as innerHTML (true) or textContent (false)
489
+ * @param xssSanitize - Whether to sanitize HTML content for XSS protection
697
490
  */
698
491
  export function setContent(el, datum, asHtml = true, xssSanitize = true) {
699
492
  if (el instanceof HTMLInputElement ||
@@ -702,11 +495,27 @@ export function setContent(el, datum, asHtml = true, xssSanitize = true) {
702
495
  el instanceof HTMLOutputElement) {
703
496
  if (el instanceof HTMLInputElement &&
704
497
  (el.type === 'radio' || el.type === 'checkbox')) {
498
+ // Boolean values are always set directly regardless of value attribute
705
499
  if (typeof datum === 'boolean') {
706
500
  el.checked = datum;
707
501
  return;
708
502
  }
709
- el.checked = el.value === `${datum}`;
503
+ // Checkbox/radio with value attribute: traditional value comparison
504
+ if (el.hasAttribute('value')) {
505
+ el.checked = el.value === `${datum}`;
506
+ return;
507
+ }
508
+ // Checkbox without value attribute: switch-like behavior (string boolean processing)
509
+ if (datum === 'true') {
510
+ el.checked = true;
511
+ return;
512
+ }
513
+ if (datum === 'false') {
514
+ el.checked = false;
515
+ return;
516
+ }
517
+ // Other values default to false
518
+ el.checked = false;
710
519
  return;
711
520
  }
712
521
  el.value = `${datum}`;