mirror of
https://github.com/servo/servo
synced 2026-05-09 08:32:31 +02:00
Servo has a lot of comments like this: ```rust // https://example-spec.com/#do-the-thing fn do_the_thing() {} ``` and I keep turning these into doc comments whenever I'm working close to one of them. Doing so allows me to hover over a function call in an IDE and open its specification without having to jump to the function definition first. This change fixes all of these comments at once. This was done using `find components -name '*.rs' -exec perl -i -0777 -pe 's|^([ \t]*)// (https?://.*)\n\1(fn )|\1/// <$2>\n\1$3|mg' {} +`. Note that these comments should be doc comments even within trait `impl` blocks, because rustdoc will use them as fallback documentation when the method definition on the trait does not have documentation. Testing: Comments only, no testing required Preparation for https://github.com/servo/servo/pull/39552 --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
600 lines
21 KiB
Rust
600 lines
21 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||
|
||
use std::cell::Cell;
|
||
|
||
use dom_struct::dom_struct;
|
||
use html5ever::{LocalName, Prefix, QualName, local_name, ns};
|
||
use js::rust::HandleObject;
|
||
use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_unsigned_integer};
|
||
use style::color::AbsoluteColor;
|
||
|
||
use crate::dom::attr::Attr;
|
||
use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
|
||
use crate::dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods;
|
||
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
|
||
use crate::dom::bindings::inheritance::Castable;
|
||
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
|
||
use crate::dom::bindings::str::DOMString;
|
||
use crate::dom::document::Document;
|
||
use crate::dom::element::{
|
||
AttributeMutation, CustomElementCreationMode, Element, ElementCreator, LayoutElementHelpers,
|
||
};
|
||
use crate::dom::html::htmlcollection::{CollectionFilter, HTMLCollection};
|
||
use crate::dom::html::htmlelement::HTMLElement;
|
||
use crate::dom::html::htmltablecaptionelement::HTMLTableCaptionElement;
|
||
use crate::dom::html::htmltablecolelement::HTMLTableColElement;
|
||
use crate::dom::html::htmltablerowelement::HTMLTableRowElement;
|
||
use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
|
||
use crate::dom::node::{Node, NodeTraits};
|
||
use crate::dom::virtualmethods::VirtualMethods;
|
||
use crate::script_runtime::CanGc;
|
||
|
||
#[dom_struct]
|
||
pub(crate) struct HTMLTableElement {
|
||
htmlelement: HTMLElement,
|
||
border: Cell<Option<u32>>,
|
||
cellpadding: Cell<Option<u32>>,
|
||
cellspacing: Cell<Option<u32>>,
|
||
tbodies: MutNullableDom<HTMLCollection>,
|
||
}
|
||
|
||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||
#[derive(JSTraceable, MallocSizeOf)]
|
||
struct TableRowFilter {
|
||
sections: Vec<Dom<Node>>,
|
||
}
|
||
|
||
impl CollectionFilter for TableRowFilter {
|
||
fn filter(&self, elem: &Element, root: &Node) -> bool {
|
||
elem.is::<HTMLTableRowElement>() &&
|
||
(root.is_parent_of(elem.upcast()) ||
|
||
self.sections
|
||
.iter()
|
||
.any(|section| section.is_parent_of(elem.upcast())))
|
||
}
|
||
}
|
||
|
||
impl HTMLTableElement {
|
||
fn new_inherited(
|
||
local_name: LocalName,
|
||
prefix: Option<Prefix>,
|
||
document: &Document,
|
||
) -> HTMLTableElement {
|
||
HTMLTableElement {
|
||
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
||
border: Cell::new(None),
|
||
cellpadding: Cell::new(None),
|
||
cellspacing: Cell::new(None),
|
||
tbodies: Default::default(),
|
||
}
|
||
}
|
||
|
||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||
pub(crate) fn new(
|
||
local_name: LocalName,
|
||
prefix: Option<Prefix>,
|
||
document: &Document,
|
||
proto: Option<HandleObject>,
|
||
can_gc: CanGc,
|
||
) -> DomRoot<HTMLTableElement> {
|
||
let n = Node::reflect_node_with_proto(
|
||
Box::new(HTMLTableElement::new_inherited(
|
||
local_name, prefix, document,
|
||
)),
|
||
document,
|
||
proto,
|
||
can_gc,
|
||
);
|
||
|
||
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||
n
|
||
}
|
||
|
||
pub(crate) fn get_border(&self) -> Option<u32> {
|
||
self.border.get()
|
||
}
|
||
|
||
// https://html.spec.whatwg.org/multipage/#dom-table-thead
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-tfoot>
|
||
fn get_first_section_of_type(
|
||
&self,
|
||
atom: &LocalName,
|
||
) -> Option<DomRoot<HTMLTableSectionElement>> {
|
||
self.upcast::<Node>()
|
||
.child_elements()
|
||
.find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == atom)
|
||
.and_then(|n| n.downcast().map(DomRoot::from_ref))
|
||
}
|
||
|
||
// https://html.spec.whatwg.org/multipage/#dom-table-thead
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-tfoot>
|
||
fn set_first_section_of_type<P>(
|
||
&self,
|
||
atom: &LocalName,
|
||
section: Option<&HTMLTableSectionElement>,
|
||
reference_predicate: P,
|
||
can_gc: CanGc,
|
||
) -> ErrorResult
|
||
where
|
||
P: FnMut(&DomRoot<Element>) -> bool,
|
||
{
|
||
if let Some(e) = section {
|
||
if e.upcast::<Element>().local_name() != atom {
|
||
return Err(Error::HierarchyRequest);
|
||
}
|
||
}
|
||
|
||
self.delete_first_section_of_type(atom, can_gc);
|
||
|
||
let node = self.upcast::<Node>();
|
||
|
||
if let Some(section) = section {
|
||
let reference_element = node.child_elements().find(reference_predicate);
|
||
let reference_node = reference_element.as_ref().map(|e| e.upcast());
|
||
|
||
node.InsertBefore(section.upcast(), reference_node, can_gc)?;
|
||
}
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-createthead>
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-createtfoot>
|
||
fn create_section_of_type(
|
||
&self,
|
||
atom: &LocalName,
|
||
can_gc: CanGc,
|
||
) -> DomRoot<HTMLTableSectionElement> {
|
||
if let Some(section) = self.get_first_section_of_type(atom) {
|
||
return section;
|
||
}
|
||
|
||
let section = Element::create(
|
||
QualName::new(None, ns!(html), atom.clone()),
|
||
None,
|
||
&self.owner_document(),
|
||
ElementCreator::ScriptCreated,
|
||
CustomElementCreationMode::Asynchronous,
|
||
None,
|
||
can_gc,
|
||
);
|
||
|
||
let section = DomRoot::downcast::<HTMLTableSectionElement>(section).unwrap();
|
||
|
||
match *atom {
|
||
local_name!("thead") => self.SetTHead(Some(§ion)),
|
||
local_name!("tfoot") => self.SetTFoot(Some(§ion)),
|
||
_ => unreachable!("unexpected section type"),
|
||
}
|
||
.expect("unexpected section type");
|
||
|
||
section
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-deletethead>
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot>
|
||
fn delete_first_section_of_type(&self, atom: &LocalName, can_gc: CanGc) {
|
||
if let Some(thead) = self.get_first_section_of_type(atom) {
|
||
thead.upcast::<Node>().remove_self(can_gc);
|
||
}
|
||
}
|
||
|
||
fn get_rows(&self) -> TableRowFilter {
|
||
TableRowFilter {
|
||
sections: self
|
||
.upcast::<Node>()
|
||
.children()
|
||
.filter_map(|ref node| {
|
||
node.downcast::<HTMLTableSectionElement>()
|
||
.map(|_| Dom::from_ref(&**node))
|
||
})
|
||
.collect(),
|
||
}
|
||
}
|
||
}
|
||
|
||
impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-rows>
|
||
fn Rows(&self) -> DomRoot<HTMLCollection> {
|
||
let filter = self.get_rows();
|
||
HTMLCollection::new(
|
||
&self.owner_window(),
|
||
self.upcast(),
|
||
Box::new(filter),
|
||
CanGc::note(),
|
||
)
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-caption>
|
||
fn GetCaption(&self) -> Option<DomRoot<HTMLTableCaptionElement>> {
|
||
self.upcast::<Node>()
|
||
.children()
|
||
.filter_map(DomRoot::downcast)
|
||
.next()
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-caption>
|
||
fn SetCaption(&self, new_caption: Option<&HTMLTableCaptionElement>) -> Fallible<()> {
|
||
if let Some(ref caption) = self.GetCaption() {
|
||
caption.upcast::<Node>().remove_self(CanGc::note());
|
||
}
|
||
|
||
if let Some(caption) = new_caption {
|
||
let node = self.upcast::<Node>();
|
||
node.InsertBefore(
|
||
caption.upcast(),
|
||
node.GetFirstChild().as_deref(),
|
||
CanGc::note(),
|
||
)?;
|
||
}
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-createcaption>
|
||
fn CreateCaption(&self, can_gc: CanGc) -> DomRoot<HTMLTableCaptionElement> {
|
||
match self.GetCaption() {
|
||
Some(caption) => caption,
|
||
None => {
|
||
let caption = Element::create(
|
||
QualName::new(None, ns!(html), local_name!("caption")),
|
||
None,
|
||
&self.owner_document(),
|
||
ElementCreator::ScriptCreated,
|
||
CustomElementCreationMode::Asynchronous,
|
||
None,
|
||
can_gc,
|
||
);
|
||
let caption = DomRoot::downcast::<HTMLTableCaptionElement>(caption).unwrap();
|
||
|
||
self.SetCaption(Some(&caption))
|
||
.expect("Generated caption is invalid");
|
||
caption
|
||
},
|
||
}
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-deletecaption>
|
||
fn DeleteCaption(&self) {
|
||
if let Some(caption) = self.GetCaption() {
|
||
caption.upcast::<Node>().remove_self(CanGc::note());
|
||
}
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-thead>
|
||
fn GetTHead(&self) -> Option<DomRoot<HTMLTableSectionElement>> {
|
||
self.get_first_section_of_type(&local_name!("thead"))
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-thead>
|
||
fn SetTHead(&self, thead: Option<&HTMLTableSectionElement>) -> ErrorResult {
|
||
self.set_first_section_of_type(
|
||
&local_name!("thead"),
|
||
thead,
|
||
|n| !n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>(),
|
||
CanGc::note(),
|
||
)
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-createthead>
|
||
fn CreateTHead(&self, can_gc: CanGc) -> DomRoot<HTMLTableSectionElement> {
|
||
self.create_section_of_type(&local_name!("thead"), can_gc)
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-deletethead>
|
||
fn DeleteTHead(&self) {
|
||
self.delete_first_section_of_type(&local_name!("thead"), CanGc::note())
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-tfoot>
|
||
fn GetTFoot(&self) -> Option<DomRoot<HTMLTableSectionElement>> {
|
||
self.get_first_section_of_type(&local_name!("tfoot"))
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-tfoot>
|
||
fn SetTFoot(&self, tfoot: Option<&HTMLTableSectionElement>) -> ErrorResult {
|
||
self.set_first_section_of_type(
|
||
&local_name!("tfoot"),
|
||
tfoot,
|
||
|n| {
|
||
if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() {
|
||
return false;
|
||
}
|
||
|
||
if n.is::<HTMLTableSectionElement>() {
|
||
let name = n.local_name();
|
||
if name == &local_name!("thead") || name == &local_name!("tbody") {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
true
|
||
},
|
||
CanGc::note(),
|
||
)
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-createtfoot>
|
||
fn CreateTFoot(&self, can_gc: CanGc) -> DomRoot<HTMLTableSectionElement> {
|
||
self.create_section_of_type(&local_name!("tfoot"), can_gc)
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot>
|
||
fn DeleteTFoot(&self) {
|
||
self.delete_first_section_of_type(&local_name!("tfoot"), CanGc::note())
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-tbodies>
|
||
fn TBodies(&self) -> DomRoot<HTMLCollection> {
|
||
self.tbodies.or_init(|| {
|
||
HTMLCollection::new_with_filter_fn(
|
||
&self.owner_window(),
|
||
self.upcast(),
|
||
|element, root| {
|
||
element.is::<HTMLTableSectionElement>() &&
|
||
element.local_name() == &local_name!("tbody") &&
|
||
element.upcast::<Node>().GetParentNode().as_deref() == Some(root)
|
||
},
|
||
CanGc::note(),
|
||
)
|
||
})
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-createtbody>
|
||
fn CreateTBody(&self, can_gc: CanGc) -> DomRoot<HTMLTableSectionElement> {
|
||
let tbody = Element::create(
|
||
QualName::new(None, ns!(html), local_name!("tbody")),
|
||
None,
|
||
&self.owner_document(),
|
||
ElementCreator::ScriptCreated,
|
||
CustomElementCreationMode::Asynchronous,
|
||
None,
|
||
can_gc,
|
||
);
|
||
let tbody = DomRoot::downcast::<HTMLTableSectionElement>(tbody).unwrap();
|
||
let node = self.upcast::<Node>();
|
||
let last_tbody = node
|
||
.rev_children()
|
||
.filter_map(DomRoot::downcast::<Element>)
|
||
.find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == &local_name!("tbody"));
|
||
let reference_element = last_tbody.and_then(|t| t.upcast::<Node>().GetNextSibling());
|
||
|
||
node.InsertBefore(tbody.upcast(), reference_element.as_deref(), can_gc)
|
||
.expect("Insertion failed");
|
||
tbody
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-insertrow>
|
||
fn InsertRow(&self, index: i32, can_gc: CanGc) -> Fallible<DomRoot<HTMLTableRowElement>> {
|
||
let rows = self.Rows();
|
||
let number_of_row_elements = rows.Length();
|
||
|
||
if index < -1 || index > number_of_row_elements as i32 {
|
||
return Err(Error::IndexSize);
|
||
}
|
||
|
||
let new_row = Element::create(
|
||
QualName::new(None, ns!(html), local_name!("tr")),
|
||
None,
|
||
&self.owner_document(),
|
||
ElementCreator::ScriptCreated,
|
||
CustomElementCreationMode::Asynchronous,
|
||
None,
|
||
can_gc,
|
||
);
|
||
let new_row = DomRoot::downcast::<HTMLTableRowElement>(new_row).unwrap();
|
||
let node = self.upcast::<Node>();
|
||
|
||
if number_of_row_elements == 0 {
|
||
// append new row to last or new tbody in table
|
||
if let Some(last_tbody) = node
|
||
.rev_children()
|
||
.filter_map(DomRoot::downcast::<Element>)
|
||
.find(|n| {
|
||
n.is::<HTMLTableSectionElement>() && n.local_name() == &local_name!("tbody")
|
||
})
|
||
{
|
||
last_tbody
|
||
.upcast::<Node>()
|
||
.AppendChild(new_row.upcast::<Node>(), can_gc)
|
||
.expect("InsertRow failed to append first row.");
|
||
} else {
|
||
let tbody = self.CreateTBody(can_gc);
|
||
node.AppendChild(tbody.upcast(), can_gc)
|
||
.expect("InsertRow failed to append new tbody.");
|
||
|
||
tbody
|
||
.upcast::<Node>()
|
||
.AppendChild(new_row.upcast::<Node>(), can_gc)
|
||
.expect("InsertRow failed to append first row.");
|
||
}
|
||
} else if index == number_of_row_elements as i32 || index == -1 {
|
||
// append new row to parent of last row in table
|
||
let last_row = rows
|
||
.Item(number_of_row_elements - 1)
|
||
.expect("InsertRow failed to find last row in table.");
|
||
|
||
let last_row_parent = last_row
|
||
.upcast::<Node>()
|
||
.GetParentNode()
|
||
.expect("InsertRow failed to find parent of last row in table.");
|
||
|
||
last_row_parent
|
||
.upcast::<Node>()
|
||
.AppendChild(new_row.upcast::<Node>(), can_gc)
|
||
.expect("InsertRow failed to append last row.");
|
||
} else {
|
||
// insert new row before the index-th row in rows using the same parent
|
||
let ith_row = rows
|
||
.Item(index as u32)
|
||
.expect("InsertRow failed to find a row in table.");
|
||
|
||
let ith_row_parent = ith_row
|
||
.upcast::<Node>()
|
||
.GetParentNode()
|
||
.expect("InsertRow failed to find parent of a row in table.");
|
||
|
||
ith_row_parent
|
||
.upcast::<Node>()
|
||
.InsertBefore(
|
||
new_row.upcast::<Node>(),
|
||
Some(ith_row.upcast::<Node>()),
|
||
can_gc,
|
||
)
|
||
.expect("InsertRow failed to append row");
|
||
}
|
||
|
||
Ok(new_row)
|
||
}
|
||
|
||
/// <https://html.spec.whatwg.org/multipage/#dom-table-deleterow>
|
||
fn DeleteRow(&self, mut index: i32) -> Fallible<()> {
|
||
let rows = self.Rows();
|
||
let num_rows = rows.Length() as i32;
|
||
|
||
// Step 1: If index is less than −1 or greater than or equal to the number of elements
|
||
// in the rows collection, then throw an "IndexSizeError".
|
||
if !(-1..num_rows).contains(&index) {
|
||
return Err(Error::IndexSize);
|
||
}
|
||
|
||
let num_rows = rows.Length() as i32;
|
||
|
||
// Step 2: If index is −1, then remove the last element in the rows collection from its
|
||
// parent, or do nothing if the rows collection is empty.
|
||
if index == -1 {
|
||
index = num_rows - 1;
|
||
}
|
||
|
||
if num_rows == 0 {
|
||
return Ok(());
|
||
}
|
||
|
||
// Step 3: Otherwise, remove the indexth element in the rows collection from its parent.
|
||
DomRoot::upcast::<Node>(rows.Item(index as u32).unwrap()).remove_self(CanGc::note());
|
||
|
||
Ok(())
|
||
}
|
||
|
||
// https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
|
||
make_getter!(BgColor, "bgcolor");
|
||
|
||
// https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
|
||
make_legacy_color_setter!(SetBgColor, "bgcolor");
|
||
|
||
// <https://html.spec.whatwg.org/multipage/#dom-table-width>
|
||
make_getter!(Width, "width");
|
||
|
||
// <https://html.spec.whatwg.org/multipage/#dom-table-width>
|
||
make_nonzero_dimension_setter!(SetWidth, "width");
|
||
}
|
||
|
||
pub(crate) trait HTMLTableElementLayoutHelpers {
|
||
fn get_background_color(self) -> Option<AbsoluteColor>;
|
||
fn get_border(self) -> Option<u32>;
|
||
fn get_cellpadding(self) -> Option<u32>;
|
||
fn get_cellspacing(self) -> Option<u32>;
|
||
fn get_width(self) -> LengthOrPercentageOrAuto;
|
||
fn get_height(self) -> LengthOrPercentageOrAuto;
|
||
}
|
||
|
||
impl HTMLTableElementLayoutHelpers for LayoutDom<'_, HTMLTableElement> {
|
||
fn get_background_color(self) -> Option<AbsoluteColor> {
|
||
self.upcast::<Element>()
|
||
.get_attr_for_layout(&ns!(), &local_name!("bgcolor"))
|
||
.and_then(AttrValue::as_color)
|
||
.cloned()
|
||
}
|
||
|
||
fn get_border(self) -> Option<u32> {
|
||
(self.unsafe_get()).border.get()
|
||
}
|
||
|
||
fn get_cellpadding(self) -> Option<u32> {
|
||
(self.unsafe_get()).cellpadding.get()
|
||
}
|
||
|
||
fn get_cellspacing(self) -> Option<u32> {
|
||
(self.unsafe_get()).cellspacing.get()
|
||
}
|
||
|
||
fn get_width(self) -> LengthOrPercentageOrAuto {
|
||
self.upcast::<Element>()
|
||
.get_attr_for_layout(&ns!(), &local_name!("width"))
|
||
.map(AttrValue::as_dimension)
|
||
.cloned()
|
||
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
||
}
|
||
|
||
fn get_height(self) -> LengthOrPercentageOrAuto {
|
||
self.upcast::<Element>()
|
||
.get_attr_for_layout(&ns!(), &local_name!("height"))
|
||
.map(AttrValue::as_dimension)
|
||
.cloned()
|
||
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
||
}
|
||
}
|
||
|
||
impl VirtualMethods for HTMLTableElement {
|
||
fn super_type(&self) -> Option<&dyn VirtualMethods> {
|
||
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
|
||
}
|
||
|
||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
|
||
self.super_type()
|
||
.unwrap()
|
||
.attribute_mutated(attr, mutation, can_gc);
|
||
match *attr.local_name() {
|
||
local_name!("border") => {
|
||
// According to HTML5 § 14.3.9, invalid values map to 1px.
|
||
self.border.set(
|
||
mutation
|
||
.new_value(attr)
|
||
.map(|value| parse_unsigned_integer(value.chars()).unwrap_or(1)),
|
||
);
|
||
},
|
||
local_name!("cellpadding") => {
|
||
self.cellpadding.set(
|
||
mutation
|
||
.new_value(attr)
|
||
.and_then(|value| parse_unsigned_integer(value.chars()).ok()),
|
||
);
|
||
},
|
||
local_name!("cellspacing") => {
|
||
self.cellspacing.set(
|
||
mutation
|
||
.new_value(attr)
|
||
.and_then(|value| parse_unsigned_integer(value.chars()).ok()),
|
||
);
|
||
},
|
||
_ => {},
|
||
}
|
||
}
|
||
|
||
fn attribute_affects_presentational_hints(&self, attr: &Attr) -> bool {
|
||
match attr.local_name() {
|
||
&local_name!("width") | &local_name!("height") => true,
|
||
_ => self
|
||
.super_type()
|
||
.unwrap()
|
||
.attribute_affects_presentational_hints(attr),
|
||
}
|
||
}
|
||
|
||
fn parse_plain_attribute(&self, local_name: &LocalName, value: DOMString) -> AttrValue {
|
||
match *local_name {
|
||
local_name!("border") => AttrValue::from_u32(value.into(), 1),
|
||
local_name!("width") => AttrValue::from_nonzero_dimension(value.into()),
|
||
local_name!("height") => AttrValue::from_dimension(value.into()),
|
||
local_name!("bgcolor") => AttrValue::from_legacy_color(value.into()),
|
||
_ => self
|
||
.super_type()
|
||
.unwrap()
|
||
.parse_plain_attribute(local_name, value),
|
||
}
|
||
}
|
||
}
|