Repository navigation
v3.2.0
3.2.0
-
Fix: a false boolean attribute set as a property turned it on.
resolveAttributeValueresolves a false boolean
attribute tonull(no attribute), whichsetAttributetakes as a bare (true) attribute for the ones set as
properties: everyselected="false"option (also$option(selected: false)) was selected, so a<select>showed
its last option;hidden="false",multiple="false"andinert="false"turned those on too.DOMGenerator.setAttributesnow sets each resolved value with the newsetResolvedAttribute.
resolveAttributeValueandsetResolvedAttributetake 2 required named defaults for an attribute without a
value:booleanDefault(a boolean attribute: on or off) andvalueDefault(any other: that value, or
removed whennull);setAttributespassesfalseandnull. A false boolean attribute resolves tonull
(off). NewDOMGenerator.resolveAttributeDefaultsreturns an attribute's value or its default.
booleanDefaultholds for every boolean attribute (checked,disabled… too), not only the ones set as
properties.
setAttributekeepsnullas a bare attribute (true). The web generator'ssetElementAttributetakes
booleanDefaulttoo (defaulttrue)._parseAttributeBoolValuetakes thenullvalue as a named
defaultValue(web anddart:htmlgenerators).- Breaking for a class extending
DOMGeneratordirectly:setResolvedAttributeis abstract, and must be
implemented (a fallback tosetAttributewould turn every false boolean attribute on); a caller or override of
resolveAttributeValuemust pass or take the 2 new required parameters. The package's generators (web,
dart:html, delegate, dummy, none) implement them; subclasses of them are unaffected. - A
nullselectedormultipleon an element without that property now removes the attribute (it threw).
-
Fix: one rule for every boolean attribute value,
DOMAttribute.parseBooleanValue: on fortrue, bare,"", the
attribute's own name (checked="checked",selected="selected": XHTML form, any case) andon/yes/1; off
otherwise ("false","off","no","0": dom_builder reads boolean values, and templates rely on it). Used by
DOMAttribute.from,setValueon an existing attribute,resolveAttributeValue(template values too) and the
generators'setAttribute/setResolvedAttribute. Before, each read them its own way:checked="checked"and the other own-name forms were off;- a boolean attribute with a template value (
checked="{{:on}}true{{?}}false{{/}}",disabled="{{d}}") was not a
boolean:"false"was set aschecked="false"/disabled="false", on in a browser; "false"viasetResolvedAttribute/setAttributeturnedchecked/disabledon, while""or the own name
turnedselected/hiddenoff;setAttribute('checked', 'checked')on an element that already had it turned it off.
-
Fix: the generators set a boolean attribute both as the attribute (present when on, removed when off: the
element's default state) and, where it stops following it, as the property (option.selected,input.checked,
media.muted).selectedwas only a property, sooption[selected]matched nothing and a form reset selected the
first option;checkedwas only an attribute, so a re-render didn't change a checkbox the user had toggled.
setAttributetakesnullas a bare attribute (on) for every boolean attribute (it removedchecked/disabled). -
Fix:
hidden="until-found"(hidden, but found by find-in-page and fragment navigation) is kept as the value: it was
read as a boolean, false, so the element was shown.DOMAttribute.booleanAttributeKeywordlists such keywords. -
Fix: an empty value is a value:
data-x="", a valuelessdata-xandvalue=""are kept ([data-x]selectors,
dataset.x == ""); they were dropped from the HTML and the DOM.DOMAttributeValueStringkeeps''apart from
null(no value), andDOMElement.buildHTMLwritesname="". Behaviour change:DOMAttribute.from('title', '')
now buildstitle=""(it built nothing); an emptyclassorstyleis still left out.
DOMElement.hasAttributeValueis true for an empty value too (onlynull, absent or a false boolean attribute,
is false), as its doc said ("if attribute exists").- Regression tests (
dom_builder_web_regression_test.dart).
- Regression tests (
-
Fix: templates (
DOMTemplateVariable):- A
Setin the context is checked for membership ({{:tags.vip}}), givingtrueorfalse: it was converted
to aListfirst and indexed, so its membership branch never ran. - A
Function(Object?)value is called with any context: it also matchedFunction(Map?), checked first, which
cast the context toMap?and threw for a non-Mapone. AFunction(Map?)getsnullfor a non-Mapcontext. - A
Set(or any otherIterable) value works as a condition and a loop ({{:tags}},{{*:tags}}): it threw.
- A
-
Fix: an empty string value equals
''(and notnull):DOMAttributeValueString('').equalsAttributeValue('')was
false. -
Tests for the boolean attributes (
checked,hidden,disabled,selected,multiple,inert,autoplay,
controls,muted):dom_builder_boolean_attributes_test.dart(VM):DOMAttributeparsing, HTML output (a false one is left out),
templates,resolveAttributeValue, andsetAttributessetting every resolved value withsetResolvedAttribute
(also throughDOMGeneratorDelegateandDOMGeneratorDummy).dom_builder_web_boolean_attributes_test.dart(browser): each one on its element's property,"true", bare,
"false"and absent, from parsed HTML and$tagattributes;selectedoptions (parsed,$option, a multiple
select, a template's language select);setAttribute,setResolvedAttribute(on and off,booleanDefault)
andsetElementAttribute.
-
Coverage tests (VM):
dom_builder_base_coverage_test.dart,dom_builder_css_coverage_test.dart,
dom_builder_template_coverage_test.dart,dom_builder_helpers_attribute_coverage_test.dartand
dom_builder_generator_coverage_test.dart(generator, runtime, tree map): VM line coverage ~85% -> 97.4%. Suspected
bugs found are reproduced as skipped tests (skip: 'Bug: …'). -
README: Codecov badge.