Use lazy_static instead of phf due to phf incompatibility with latest Rust versions
This commit is contained in:
parent
fba2dd965d
commit
2a010088fa
|
@ -16,7 +16,7 @@ include = ["/src/**/*", "/Cargo.toml", "/LICENSE", "/README.md"]
|
|||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[dependencies]
|
||||
phf = { version = "0.8.0", features = ["macros"] }
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[profile.release]
|
||||
panic = 'abort'
|
||||
|
|
77
gen/attrs.ts
77
gen/attrs.ts
|
@ -48,12 +48,7 @@ const rsTagAttr = ({
|
|||
defaultValue,
|
||||
collapseAndTrim,
|
||||
boolean,
|
||||
}: AttrConfig) => `AttributeMinification {
|
||||
boolean: ${boolean},
|
||||
redundant_if_empty: ${redundantIfEmpty},
|
||||
collapse_and_trim: ${collapseAndTrim},
|
||||
default_value: ${defaultValue == undefined ? 'None' : `Some(b"${defaultValue}")`},
|
||||
}`;
|
||||
}: AttrConfig) => `AttributeMinification { boolean: ${boolean}, redundant_if_empty: ${redundantIfEmpty}, collapse_and_trim: ${collapseAndTrim}, default_value: ${defaultValue == undefined ? 'None' : `Some(b"${defaultValue}")`} }`;
|
||||
|
||||
const processReactTypeDeclarations = (source: SourceFile) => {
|
||||
const nodes: Node[] = [source];
|
||||
|
@ -127,7 +122,9 @@ const processReactTypeDeclarations = (source: SourceFile) => {
|
|||
}
|
||||
|
||||
let code = `
|
||||
use crate::spec::tag::ns::Namespace;
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashMap;
|
||||
use crate::spec::tag::ns::Namespace;
|
||||
|
||||
pub struct AttributeMinification {
|
||||
pub boolean: bool,
|
||||
|
@ -138,29 +135,28 @@ pub struct AttributeMinification {
|
|||
|
||||
pub enum AttrMapEntry {
|
||||
AllNamespaceElements(AttributeMinification),
|
||||
SpecificNamespaceElements(phf::Map<&'static [u8], AttributeMinification>),
|
||||
SpecificNamespaceElements(HashMap<&'static [u8], AttributeMinification>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ByNamespace {
|
||||
// Make pub so this struct can be statically created in gen/attrs.rs.
|
||||
pub html: Option<&'static AttrMapEntry>,
|
||||
pub svg: Option<&'static AttrMapEntry>,
|
||||
pub html: Option<AttrMapEntry>,
|
||||
pub svg: Option<AttrMapEntry>,
|
||||
}
|
||||
|
||||
impl ByNamespace {
|
||||
fn get(&self, ns: Namespace) -> Option<&'static AttrMapEntry> {
|
||||
fn get(&self, ns: Namespace) -> Option<&AttrMapEntry> {
|
||||
match ns {
|
||||
Namespace::Html => self.html,
|
||||
Namespace::Svg => self.svg,
|
||||
Namespace::Html => self.html.as_ref(),
|
||||
Namespace::Svg => self.svg.as_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AttrMap(phf::Map<&'static [u8], ByNamespace>);
|
||||
pub struct AttrMap(HashMap<&'static [u8], ByNamespace>);
|
||||
|
||||
impl AttrMap {
|
||||
pub const fn new(map: phf::Map<&'static [u8], ByNamespace>) -> AttrMap {
|
||||
pub const fn new(map: HashMap<&'static [u8], ByNamespace>) -> AttrMap {
|
||||
AttrMap(map)
|
||||
}
|
||||
|
||||
|
@ -174,35 +170,32 @@ impl AttrMap {
|
|||
|
||||
`;
|
||||
|
||||
for (const [attrName, namespaces] of attributes) {
|
||||
let byNsCode = '';
|
||||
byNsCode += `static ${attrName.toUpperCase()}_ATTR: ByNamespace = ByNamespace {\n`;
|
||||
for (const ns of ['html', 'svg'] as const) {
|
||||
byNsCode += `\t${ns}: `;
|
||||
const tagsMap = namespaces.get(ns);
|
||||
if (!tagsMap) {
|
||||
byNsCode += 'None';
|
||||
} else {
|
||||
code += `
|
||||
lazy_static! {
|
||||
pub static ref ATTRS: AttrMap = {
|
||||
let mut m = HashMap::<&'static [u8], ByNamespace>::new();
|
||||
${[...attributes].map(([attr_name, namespaces]) => ` m.insert(b\"${attr_name}\", ByNamespace {
|
||||
${(['html', 'svg'] as const).map(ns => ` ${ns}: ` + (() => {
|
||||
const tagsMap = namespaces.get(ns);
|
||||
if (!tagsMap) {
|
||||
return 'None';
|
||||
}
|
||||
const globalAttr = tagsMap.get('*');
|
||||
if (globalAttr) {
|
||||
code += `static ${ns.toUpperCase()}_${attrName.toUpperCase()}_ATTR: &AttrMapEntry = &AttrMapEntry::AllNamespaceElements(${rsTagAttr(globalAttr)});\n\n`;
|
||||
} else {
|
||||
code += `static ${ns.toUpperCase()}_${attrName.toUpperCase()}_ATTR: &AttrMapEntry = &AttrMapEntry::SpecificNamespaceElements(phf::phf_map! {\n${
|
||||
[...tagsMap].map(([tagName, tagAttr]) => `b\"${tagName}\" => ${rsTagAttr(tagAttr)}`).join(',\n')
|
||||
}\n});\n\n`;
|
||||
return `Some(AttrMapEntry::AllNamespaceElements(${rsTagAttr(globalAttr)}))`;
|
||||
}
|
||||
byNsCode += `Some(${ns.toUpperCase()}_${attrName.toUpperCase()}_ATTR)`;
|
||||
}
|
||||
byNsCode += ',\n';
|
||||
}
|
||||
byNsCode += '};\n\n';
|
||||
code += byNsCode;
|
||||
}
|
||||
code += 'pub static ATTRS: AttrMap = AttrMap::new(phf::phf_map! {\n';
|
||||
for (const attr_name of attributes.keys()) {
|
||||
code += `\tb\"${attr_name}\" => ${attr_name.toUpperCase()}_ATTR,\n`;
|
||||
}
|
||||
code += '});\n\n';
|
||||
return `Some({
|
||||
let mut m = HashMap::<&'static [u8], AttributeMinification>::new();
|
||||
${[...tagsMap].map(([tagName, tagAttr]) => ` m.insert(b\"${tagName}\", ${rsTagAttr(tagAttr)});`).join('\n')}
|
||||
AttrMapEntry::SpecificNamespaceElements(m)
|
||||
})`;
|
||||
})() + ',').join('\n')}
|
||||
});
|
||||
|
||||
`).join('')}
|
||||
AttrMap::new(m)
|
||||
};
|
||||
}`;
|
||||
return code;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use phf::{Map, phf_map, phf_set, Set};
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::{HashSet, HashMap};
|
||||
|
||||
// Rules sourced from https://html.spec.whatwg.org/multipage/syntax.html#syntax-tag-omission.
|
||||
// TODO html, head, body
|
||||
|
@ -10,12 +11,12 @@ pub enum ClosingTagOmissionRuleIfLast {
|
|||
// Closing tag can never be omitted if it's the last node of its parent's children.
|
||||
Never,
|
||||
// Closing tag can be omitted if it's the last node of its parent's children and the parent tag name is not one of these.
|
||||
ParentIsNot(Set<&'static [u8]>),
|
||||
ParentIsNot(HashSet<&'static [u8]>),
|
||||
}
|
||||
|
||||
pub struct ClosingTagOmissionRule {
|
||||
// Closing tag can be omitted if immediately followed by an element node with one of these tag names.
|
||||
followed_by: Set<&'static [u8]>,
|
||||
followed_by: HashSet<&'static [u8]>,
|
||||
// Closing tag can be omitted if it's the last node of its parent's children.
|
||||
is_last: ClosingTagOmissionRuleIfLast,
|
||||
}
|
||||
|
@ -37,128 +38,218 @@ impl ClosingTagOmissionRule {
|
|||
}
|
||||
}
|
||||
|
||||
static LI_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"li"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref LI_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"li");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static DT_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"dt", b"dd"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Never,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref DT_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"dt");
|
||||
s.insert(b"dd");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Never,
|
||||
};
|
||||
}
|
||||
|
||||
static DD_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"dd", b"dt"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref DD_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"dd");
|
||||
s.insert(b"dt");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static P_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(
|
||||
b"address",
|
||||
b"article",
|
||||
b"aside",
|
||||
b"blockquote",
|
||||
b"details",
|
||||
b"div",
|
||||
b"dl",
|
||||
b"fieldset",
|
||||
b"figcaption",
|
||||
b"figure",
|
||||
b"footer",
|
||||
b"form",
|
||||
b"h1",
|
||||
b"h2",
|
||||
b"h3",
|
||||
b"h4",
|
||||
b"h5",
|
||||
b"h6",
|
||||
b"header",
|
||||
b"hgroup",
|
||||
b"hr",
|
||||
b"main",
|
||||
b"menu",
|
||||
b"nav",
|
||||
b"ol",
|
||||
b"p",
|
||||
b"pre",
|
||||
b"section",
|
||||
b"table",
|
||||
b"ul",
|
||||
),
|
||||
is_last: ClosingTagOmissionRuleIfLast::ParentIsNot(phf_set!(
|
||||
b"a",
|
||||
b"audio",
|
||||
b"del",
|
||||
b"ins",
|
||||
b"map",
|
||||
b"noscript",
|
||||
b"video",
|
||||
)),
|
||||
};
|
||||
lazy_static! {
|
||||
static ref P_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = {
|
||||
let mut followed_by = HashSet::<&'static [u8]>::new();
|
||||
followed_by.insert(b"address");
|
||||
followed_by.insert(b"article");
|
||||
followed_by.insert(b"aside");
|
||||
followed_by.insert(b"blockquote");
|
||||
followed_by.insert(b"details");
|
||||
followed_by.insert(b"div");
|
||||
followed_by.insert(b"dl");
|
||||
followed_by.insert(b"fieldset");
|
||||
followed_by.insert(b"figcaption");
|
||||
followed_by.insert(b"figure");
|
||||
followed_by.insert(b"footer");
|
||||
followed_by.insert(b"form");
|
||||
followed_by.insert(b"h1");
|
||||
followed_by.insert(b"h2");
|
||||
followed_by.insert(b"h3");
|
||||
followed_by.insert(b"h4");
|
||||
followed_by.insert(b"h5");
|
||||
followed_by.insert(b"h6");
|
||||
followed_by.insert(b"header");
|
||||
followed_by.insert(b"hgroup");
|
||||
followed_by.insert(b"hr");
|
||||
followed_by.insert(b"main");
|
||||
followed_by.insert(b"menu");
|
||||
followed_by.insert(b"nav");
|
||||
followed_by.insert(b"ol");
|
||||
followed_by.insert(b"p");
|
||||
followed_by.insert(b"pre");
|
||||
followed_by.insert(b"section");
|
||||
followed_by.insert(b"table");
|
||||
followed_by.insert(b"ul");
|
||||
|
||||
static RT_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"rt", b"rp"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
let mut is_last_tags = HashSet::<&'static [u8]>::new();
|
||||
is_last_tags.insert(b"a");
|
||||
is_last_tags.insert(b"audio");
|
||||
is_last_tags.insert(b"del");
|
||||
is_last_tags.insert(b"ins");
|
||||
is_last_tags.insert(b"map");
|
||||
is_last_tags.insert(b"noscript");
|
||||
is_last_tags.insert(b"video");
|
||||
|
||||
static RP_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"rt", b"rp"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
ClosingTagOmissionRule { followed_by, is_last: ClosingTagOmissionRuleIfLast::ParentIsNot(is_last_tags) }
|
||||
};
|
||||
}
|
||||
|
||||
static OPTGROUP_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"optgroup"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref RT_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"rt");
|
||||
s.insert(b"rp");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static OPTION_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"option", b"optgroup"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref RP_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"rt");
|
||||
s.insert(b"rp");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static THEAD_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"tbody", b"tfoot"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Never,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref OPTGROUP_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"optgroup");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static TBODY_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"tbody", b"tfoot"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref OPTION_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"option");
|
||||
s.insert(b"optgroup");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static TFOOT_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref THEAD_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"tbody");
|
||||
s.insert(b"tfoot");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Never,
|
||||
};
|
||||
}
|
||||
|
||||
static TR_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"tr"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref TBODY_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"tbody");
|
||||
s.insert(b"tfoot");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static TD_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"td", b"th"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref TFOOT_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: HashSet::<&'static [u8]>::new(),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
static TH_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule {
|
||||
followed_by: phf_set!(b"td", b"th"),
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref TR_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"tr");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
pub static CLOSING_TAG_OMISSION_RULES: Map<&'static [u8], &ClosingTagOmissionRule> = phf_map! {
|
||||
b"li" => LI_CLOSING_TAG_OMISSION_RULE,
|
||||
b"dt" => DT_CLOSING_TAG_OMISSION_RULE,
|
||||
b"dd" => DD_CLOSING_TAG_OMISSION_RULE,
|
||||
b"p" => P_CLOSING_TAG_OMISSION_RULE,
|
||||
b"rt" => RT_CLOSING_TAG_OMISSION_RULE,
|
||||
b"rp" => RP_CLOSING_TAG_OMISSION_RULE,
|
||||
b"optgroup" => OPTGROUP_CLOSING_TAG_OMISSION_RULE,
|
||||
b"option" => OPTION_CLOSING_TAG_OMISSION_RULE,
|
||||
b"thead" => THEAD_CLOSING_TAG_OMISSION_RULE,
|
||||
b"tbody" => TBODY_CLOSING_TAG_OMISSION_RULE,
|
||||
b"tfoot" => TFOOT_CLOSING_TAG_OMISSION_RULE,
|
||||
b"tr" => TR_CLOSING_TAG_OMISSION_RULE,
|
||||
b"td" => TD_CLOSING_TAG_OMISSION_RULE,
|
||||
b"th" => TH_CLOSING_TAG_OMISSION_RULE,
|
||||
};
|
||||
lazy_static! {
|
||||
static ref TD_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"td");
|
||||
s.insert(b"th");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref TH_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
|
||||
followed_by: {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"td");
|
||||
s.insert(b"th");
|
||||
s
|
||||
},
|
||||
is_last: ClosingTagOmissionRuleIfLast::Always,
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref CLOSING_TAG_OMISSION_RULES: HashMap<&'static [u8], &'static ClosingTagOmissionRule> = {
|
||||
let mut m = HashMap::<&'static [u8], &'static ClosingTagOmissionRule>::new();
|
||||
m.insert(b"li", &LI_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"dt", &DT_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"dd", &DD_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"p", &P_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"rt", &RT_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"rp", &RP_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"optgroup", &OPTGROUP_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"option", &OPTION_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"thead", &THEAD_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"tbody", &TBODY_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"tfoot", &TFOOT_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"tr", &TR_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"td", &TD_CLOSING_TAG_OMISSION_RULE);
|
||||
m.insert(b"th", &TH_CLOSING_TAG_OMISSION_RULE);
|
||||
m
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
use phf::{phf_set, Set};
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub static VOID_TAGS: Set<&'static [u8]> = phf_set! {
|
||||
b"area",
|
||||
b"base",
|
||||
b"br",
|
||||
b"col",
|
||||
b"embed",
|
||||
b"hr",
|
||||
b"img",
|
||||
b"input",
|
||||
b"keygen",
|
||||
b"link",
|
||||
b"meta",
|
||||
b"param",
|
||||
b"source",
|
||||
b"track",
|
||||
b"wbr",
|
||||
};
|
||||
lazy_static! {
|
||||
pub static ref VOID_TAGS: HashSet<&'static [u8]> = {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"area");
|
||||
s.insert(b"base");
|
||||
s.insert(b"br");
|
||||
s.insert(b"col");
|
||||
s.insert(b"embed");
|
||||
s.insert(b"hr");
|
||||
s.insert(b"img");
|
||||
s.insert(b"input");
|
||||
s.insert(b"keygen");
|
||||
s.insert(b"link");
|
||||
s.insert(b"meta");
|
||||
s.insert(b"param");
|
||||
s.insert(b"source");
|
||||
s.insert(b"track");
|
||||
s.insert(b"wbr");
|
||||
s
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use phf::{Map, phf_map};
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct WhitespaceMinification {
|
||||
pub collapse: bool,
|
||||
|
@ -48,116 +49,121 @@ static DEFAULT: &WhitespaceMinification = &WhitespaceMinification {
|
|||
trim: false,
|
||||
};
|
||||
|
||||
static TAG_WHITESPACE_MINIFICATION: Map<&'static [u8], &'static WhitespaceMinification> = phf_map! {
|
||||
// Content tags.
|
||||
b"address" => CONTENT,
|
||||
b"audio" => CONTENT,
|
||||
b"button" => CONTENT,
|
||||
b"canvas" => CONTENT,
|
||||
b"caption" => CONTENT,
|
||||
b"figcaption" => CONTENT,
|
||||
b"h1" => CONTENT,
|
||||
b"h2" => CONTENT,
|
||||
b"h3" => CONTENT,
|
||||
b"h4" => CONTENT,
|
||||
b"h5" => CONTENT,
|
||||
b"h6" => CONTENT,
|
||||
b"legend" => CONTENT,
|
||||
b"meter" => CONTENT,
|
||||
b"object" => CONTENT,
|
||||
b"option" => CONTENT,
|
||||
b"p" => CONTENT,
|
||||
b"summary" => CONTENT,
|
||||
b"textarea" => CONTENT,
|
||||
b"video" => CONTENT,
|
||||
lazy_static! {
|
||||
static ref TAG_WHITESPACE_MINIFICATION: HashMap<&'static [u8], &'static WhitespaceMinification> = {
|
||||
let mut m = HashMap::<&'static [u8], &'static WhitespaceMinification>::new();
|
||||
// Content tags.
|
||||
m.insert(b"address", CONTENT);
|
||||
m.insert(b"audio", CONTENT);
|
||||
m.insert(b"button", CONTENT);
|
||||
m.insert(b"canvas", CONTENT);
|
||||
m.insert(b"caption", CONTENT);
|
||||
m.insert(b"figcaption", CONTENT);
|
||||
m.insert(b"h1", CONTENT);
|
||||
m.insert(b"h2", CONTENT);
|
||||
m.insert(b"h3", CONTENT);
|
||||
m.insert(b"h4", CONTENT);
|
||||
m.insert(b"h5", CONTENT);
|
||||
m.insert(b"h6", CONTENT);
|
||||
m.insert(b"legend", CONTENT);
|
||||
m.insert(b"meter", CONTENT);
|
||||
m.insert(b"object", CONTENT);
|
||||
m.insert(b"option", CONTENT);
|
||||
m.insert(b"p", CONTENT);
|
||||
m.insert(b"summary", CONTENT);
|
||||
m.insert(b"textarea", CONTENT);
|
||||
m.insert(b"video", CONTENT);
|
||||
|
||||
// Content-first tags.
|
||||
b"dd" => CONTENT_FIRST,
|
||||
b"details" => CONTENT_FIRST,
|
||||
b"dt" => CONTENT_FIRST,
|
||||
b"iframe" => CONTENT_FIRST,
|
||||
b"label" => CONTENT_FIRST,
|
||||
b"li" => CONTENT_FIRST,
|
||||
b"noscript" => CONTENT_FIRST,
|
||||
b"output" => CONTENT_FIRST,
|
||||
b"progress" => CONTENT_FIRST,
|
||||
b"slot" => CONTENT_FIRST,
|
||||
b"td" => CONTENT_FIRST,
|
||||
b"template" => CONTENT_FIRST,
|
||||
b"th" => CONTENT_FIRST,
|
||||
// Content-first tags.
|
||||
m.insert(b"dd", CONTENT_FIRST);
|
||||
m.insert(b"details", CONTENT_FIRST);
|
||||
m.insert(b"dt", CONTENT_FIRST);
|
||||
m.insert(b"iframe", CONTENT_FIRST);
|
||||
m.insert(b"label", CONTENT_FIRST);
|
||||
m.insert(b"li", CONTENT_FIRST);
|
||||
m.insert(b"noscript", CONTENT_FIRST);
|
||||
m.insert(b"output", CONTENT_FIRST);
|
||||
m.insert(b"progress", CONTENT_FIRST);
|
||||
m.insert(b"slot", CONTENT_FIRST);
|
||||
m.insert(b"td", CONTENT_FIRST);
|
||||
m.insert(b"template", CONTENT_FIRST);
|
||||
m.insert(b"th", CONTENT_FIRST);
|
||||
|
||||
// Formatting tags.
|
||||
// Sourced from https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Inline_text_semantics.
|
||||
// Differences to tags listed in table at above URL: -br, +del, +ins.
|
||||
b"a" => FORMATTING,
|
||||
b"abbr" => FORMATTING,
|
||||
b"b" => FORMATTING,
|
||||
b"bdi" => FORMATTING,
|
||||
b"bdo" => FORMATTING,
|
||||
b"cite" => FORMATTING,
|
||||
b"data" => FORMATTING,
|
||||
b"del" => FORMATTING,
|
||||
b"dfn" => FORMATTING,
|
||||
b"em" => FORMATTING,
|
||||
b"i" => FORMATTING,
|
||||
b"ins" => FORMATTING,
|
||||
b"kbd" => FORMATTING,
|
||||
b"mark" => FORMATTING,
|
||||
b"q" => FORMATTING,
|
||||
b"rp" => FORMATTING,
|
||||
b"rt" => FORMATTING,
|
||||
b"rtc" => FORMATTING,
|
||||
b"ruby" => FORMATTING,
|
||||
b"s" => FORMATTING,
|
||||
b"samp" => FORMATTING,
|
||||
b"small" => FORMATTING,
|
||||
b"span" => FORMATTING,
|
||||
b"strong" => FORMATTING,
|
||||
b"sub" => FORMATTING,
|
||||
b"sup" => FORMATTING,
|
||||
b"time" => FORMATTING,
|
||||
b"u" => FORMATTING,
|
||||
b"var" => FORMATTING,
|
||||
b"wbr" => FORMATTING,
|
||||
// Formatting tags.
|
||||
// Sourced from https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Inline_text_semantics.
|
||||
// Differences to tags listed in table at above URL: -br, +del, +ins.
|
||||
m.insert(b"a", FORMATTING);
|
||||
m.insert(b"abbr", FORMATTING);
|
||||
m.insert(b"b", FORMATTING);
|
||||
m.insert(b"bdi", FORMATTING);
|
||||
m.insert(b"bdo", FORMATTING);
|
||||
m.insert(b"cite", FORMATTING);
|
||||
m.insert(b"data", FORMATTING);
|
||||
m.insert(b"del", FORMATTING);
|
||||
m.insert(b"dfn", FORMATTING);
|
||||
m.insert(b"em", FORMATTING);
|
||||
m.insert(b"i", FORMATTING);
|
||||
m.insert(b"ins", FORMATTING);
|
||||
m.insert(b"kbd", FORMATTING);
|
||||
m.insert(b"mark", FORMATTING);
|
||||
m.insert(b"q", FORMATTING);
|
||||
m.insert(b"rp", FORMATTING);
|
||||
m.insert(b"rt", FORMATTING);
|
||||
m.insert(b"rtc", FORMATTING);
|
||||
m.insert(b"ruby", FORMATTING);
|
||||
m.insert(b"s", FORMATTING);
|
||||
m.insert(b"samp", FORMATTING);
|
||||
m.insert(b"small", FORMATTING);
|
||||
m.insert(b"span", FORMATTING);
|
||||
m.insert(b"strong", FORMATTING);
|
||||
m.insert(b"sub", FORMATTING);
|
||||
m.insert(b"sup", FORMATTING);
|
||||
m.insert(b"time", FORMATTING);
|
||||
m.insert(b"u", FORMATTING);
|
||||
m.insert(b"var", FORMATTING);
|
||||
m.insert(b"wbr", FORMATTING);
|
||||
|
||||
// Layout tags.
|
||||
b"article" => LAYOUT,
|
||||
b"aside" => LAYOUT,
|
||||
b"blockquote" => LAYOUT,
|
||||
b"body" => LAYOUT,
|
||||
b"colgroup" => LAYOUT,
|
||||
b"datalist" => LAYOUT,
|
||||
b"dialog" => LAYOUT,
|
||||
b"div" => LAYOUT,
|
||||
b"dl" => LAYOUT,
|
||||
b"fieldset" => LAYOUT,
|
||||
b"figure" => LAYOUT,
|
||||
b"footer" => LAYOUT,
|
||||
b"form" => LAYOUT,
|
||||
b"head" => LAYOUT,
|
||||
b"header" => LAYOUT,
|
||||
b"hgroup" => LAYOUT,
|
||||
b"html" => LAYOUT,
|
||||
b"main" => LAYOUT,
|
||||
b"map" => LAYOUT,
|
||||
b"menu" => LAYOUT,
|
||||
b"nav" => LAYOUT,
|
||||
b"ol" => LAYOUT,
|
||||
b"optgroup" => LAYOUT,
|
||||
b"picture" => LAYOUT,
|
||||
b"section" => LAYOUT,
|
||||
b"select" => LAYOUT,
|
||||
b"table" => LAYOUT,
|
||||
b"tbody" => LAYOUT,
|
||||
b"tfoot" => LAYOUT,
|
||||
b"thead" => LAYOUT,
|
||||
b"tr" => LAYOUT,
|
||||
b"ul" => LAYOUT,
|
||||
// Layout tags.
|
||||
m.insert(b"article", LAYOUT);
|
||||
m.insert(b"aside", LAYOUT);
|
||||
m.insert(b"blockquote", LAYOUT);
|
||||
m.insert(b"body", LAYOUT);
|
||||
m.insert(b"colgroup", LAYOUT);
|
||||
m.insert(b"datalist", LAYOUT);
|
||||
m.insert(b"dialog", LAYOUT);
|
||||
m.insert(b"div", LAYOUT);
|
||||
m.insert(b"dl", LAYOUT);
|
||||
m.insert(b"fieldset", LAYOUT);
|
||||
m.insert(b"figure", LAYOUT);
|
||||
m.insert(b"footer", LAYOUT);
|
||||
m.insert(b"form", LAYOUT);
|
||||
m.insert(b"head", LAYOUT);
|
||||
m.insert(b"header", LAYOUT);
|
||||
m.insert(b"hgroup", LAYOUT);
|
||||
m.insert(b"html", LAYOUT);
|
||||
m.insert(b"main", LAYOUT);
|
||||
m.insert(b"map", LAYOUT);
|
||||
m.insert(b"menu", LAYOUT);
|
||||
m.insert(b"nav", LAYOUT);
|
||||
m.insert(b"ol", LAYOUT);
|
||||
m.insert(b"optgroup", LAYOUT);
|
||||
m.insert(b"picture", LAYOUT);
|
||||
m.insert(b"section", LAYOUT);
|
||||
m.insert(b"select", LAYOUT);
|
||||
m.insert(b"table", LAYOUT);
|
||||
m.insert(b"tbody", LAYOUT);
|
||||
m.insert(b"tfoot", LAYOUT);
|
||||
m.insert(b"thead", LAYOUT);
|
||||
m.insert(b"tr", LAYOUT);
|
||||
m.insert(b"ul", LAYOUT);
|
||||
|
||||
// Whitespace-sensitive tags.
|
||||
b"code" => WHITESPACE_SENSITIVE,
|
||||
b"pre" => WHITESPACE_SENSITIVE,
|
||||
};
|
||||
// Whitespace-sensitive tags.
|
||||
m.insert(b"code", WHITESPACE_SENSITIVE);
|
||||
m.insert(b"pre", WHITESPACE_SENSITIVE);
|
||||
|
||||
m
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_whitespace_minification_for_tag(tag_name: Option<&[u8]>) -> &'static WhitespaceMinification {
|
||||
match tag_name {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use phf::{Map, phf_map};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashMap;
|
||||
use crate::err::ProcessingResult;
|
||||
use crate::proc::checkpoint::Checkpoint;
|
||||
use crate::proc::MatchAction::*;
|
||||
|
@ -40,17 +40,21 @@ fn entity_requires_semicolon(next_char: u8) -> bool {
|
|||
}
|
||||
|
||||
// See comment in `process_attr_value` for full description of why these intentionally do not have semicolons.
|
||||
static ENCODED: Map<u8, &'static [u8]> = phf_map! {
|
||||
b'\'' => b"'",
|
||||
b'"' => b""",
|
||||
b'>' => b">",
|
||||
// Whitespace characters as defined by spec in crate::spec::codepoint::is_whitespace.
|
||||
b'\x09' => b"	",
|
||||
b'\x0a' => b"
",
|
||||
b'\x0c' => b"",
|
||||
b'\x0d' => b"
",
|
||||
b'\x20' => b" ",
|
||||
};
|
||||
lazy_static! {
|
||||
static ref ENCODED: HashMap<u8, &'static [u8]> = {
|
||||
let mut m = HashMap::<u8, &'static [u8]>::new();
|
||||
m.insert(b'\'', b"'");
|
||||
m.insert(b'"', b""");
|
||||
m.insert(b'>', b">");
|
||||
// Whitespace characters as defined by spec in crate::spec::codepoint::is_whitespace.
|
||||
m.insert(b'\x09', b"	");
|
||||
m.insert(b'\x0a', b"
");
|
||||
m.insert(b'\x0c', b"");
|
||||
m.insert(b'\x0d', b"
");
|
||||
m.insert(b'\x20', b" ");
|
||||
m
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum CharType {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use phf::{phf_set, Set};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashSet;
|
||||
use crate::err::{ErrorType, ProcessingResult};
|
||||
use crate::proc::checkpoint::Checkpoint;
|
||||
use crate::proc::MatchAction::*;
|
||||
|
@ -16,24 +16,28 @@ use crate::unit::style::process_style;
|
|||
use crate::gen::attrs::{ATTRS, AttributeMinification};
|
||||
use crate::spec::tag::ns::Namespace;
|
||||
|
||||
pub static JAVASCRIPT_MIME_TYPES: Set<&'static [u8]> = phf_set! {
|
||||
b"application/ecmascript",
|
||||
b"application/javascript",
|
||||
b"application/x-ecmascript",
|
||||
b"application/x-javascript",
|
||||
b"text/ecmascript",
|
||||
b"text/javascript",
|
||||
b"text/javascript1.0",
|
||||
b"text/javascript1.1",
|
||||
b"text/javascript1.2",
|
||||
b"text/javascript1.3",
|
||||
b"text/javascript1.4",
|
||||
b"text/javascript1.5",
|
||||
b"text/jscript",
|
||||
b"text/livescript",
|
||||
b"text/x-ecmascript",
|
||||
b"text/x-javascript",
|
||||
};
|
||||
lazy_static! {
|
||||
pub static ref JAVASCRIPT_MIME_TYPES: HashSet<&'static [u8]> = {
|
||||
let mut s = HashSet::<&'static [u8]>::new();
|
||||
s.insert(b"application/ecmascript");
|
||||
s.insert(b"application/javascript");
|
||||
s.insert(b"application/x-ecmascript");
|
||||
s.insert(b"application/x-javascript");
|
||||
s.insert(b"text/ecmascript");
|
||||
s.insert(b"text/javascript");
|
||||
s.insert(b"text/javascript1.0");
|
||||
s.insert(b"text/javascript1.1");
|
||||
s.insert(b"text/javascript1.2");
|
||||
s.insert(b"text/javascript1.3");
|
||||
s.insert(b"text/javascript1.4");
|
||||
s.insert(b"text/javascript1.5");
|
||||
s.insert(b"text/jscript");
|
||||
s.insert(b"text/livescript");
|
||||
s.insert(b"text/x-ecmascript");
|
||||
s.insert(b"text/x-javascript");
|
||||
s
|
||||
};
|
||||
}
|
||||
|
||||
// Tag names may only use ASCII alphanumerics. However, some people also use `:` and `-`.
|
||||
// See https://html.spec.whatwg.org/multipage/syntax.html#syntax-tag-name for spec.
|
||||
|
|
Loading…
Reference in New Issue