Use lazy_static instead of phf due to phf incompatibility with latest Rust versions

This commit is contained in:
Wilson Lin 2020-07-03 17:32:09 +10:00
parent fba2dd965d
commit 2a010088fa
7 changed files with 418 additions and 315 deletions

View File

@ -16,7 +16,7 @@ include = ["/src/**/*", "/Cargo.toml", "/LICENSE", "/README.md"]
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }
[dependencies] [dependencies]
phf = { version = "0.8.0", features = ["macros"] } lazy_static = "1.4.0"
[profile.release] [profile.release]
panic = 'abort' panic = 'abort'

View File

@ -48,12 +48,7 @@ const rsTagAttr = ({
defaultValue, defaultValue,
collapseAndTrim, collapseAndTrim,
boolean, boolean,
}: AttrConfig) => `AttributeMinification { }: AttrConfig) => `AttributeMinification { boolean: ${boolean}, redundant_if_empty: ${redundantIfEmpty}, collapse_and_trim: ${collapseAndTrim}, default_value: ${defaultValue == undefined ? 'None' : `Some(b"${defaultValue}")`} }`;
boolean: ${boolean},
redundant_if_empty: ${redundantIfEmpty},
collapse_and_trim: ${collapseAndTrim},
default_value: ${defaultValue == undefined ? 'None' : `Some(b"${defaultValue}")`},
}`;
const processReactTypeDeclarations = (source: SourceFile) => { const processReactTypeDeclarations = (source: SourceFile) => {
const nodes: Node[] = [source]; const nodes: Node[] = [source];
@ -127,7 +122,9 @@ const processReactTypeDeclarations = (source: SourceFile) => {
} }
let code = ` 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 struct AttributeMinification {
pub boolean: bool, pub boolean: bool,
@ -138,29 +135,28 @@ pub struct AttributeMinification {
pub enum AttrMapEntry { pub enum AttrMapEntry {
AllNamespaceElements(AttributeMinification), AllNamespaceElements(AttributeMinification),
SpecificNamespaceElements(phf::Map<&'static [u8], AttributeMinification>), SpecificNamespaceElements(HashMap<&'static [u8], AttributeMinification>),
} }
#[derive(Clone, Copy)]
pub struct ByNamespace { pub struct ByNamespace {
// Make pub so this struct can be statically created in gen/attrs.rs. // Make pub so this struct can be statically created in gen/attrs.rs.
pub html: Option<&'static AttrMapEntry>, pub html: Option<AttrMapEntry>,
pub svg: Option<&'static AttrMapEntry>, pub svg: Option<AttrMapEntry>,
} }
impl ByNamespace { impl ByNamespace {
fn get(&self, ns: Namespace) -> Option<&'static AttrMapEntry> { fn get(&self, ns: Namespace) -> Option<&AttrMapEntry> {
match ns { match ns {
Namespace::Html => self.html, Namespace::Html => self.html.as_ref(),
Namespace::Svg => self.svg, Namespace::Svg => self.svg.as_ref(),
} }
} }
} }
pub struct AttrMap(phf::Map<&'static [u8], ByNamespace>); pub struct AttrMap(HashMap<&'static [u8], ByNamespace>);
impl AttrMap { 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) AttrMap(map)
} }
@ -174,35 +170,32 @@ impl AttrMap {
`; `;
for (const [attrName, namespaces] of attributes) { code += `
let byNsCode = ''; lazy_static! {
byNsCode += `static ${attrName.toUpperCase()}_ATTR: ByNamespace = ByNamespace {\n`; pub static ref ATTRS: AttrMap = {
for (const ns of ['html', 'svg'] as const) { let mut m = HashMap::<&'static [u8], ByNamespace>::new();
byNsCode += `\t${ns}: `; ${[...attributes].map(([attr_name, namespaces]) => ` m.insert(b\"${attr_name}\", ByNamespace {
const tagsMap = namespaces.get(ns); ${(['html', 'svg'] as const).map(ns => ` ${ns}: ` + (() => {
if (!tagsMap) { const tagsMap = namespaces.get(ns);
byNsCode += 'None'; if (!tagsMap) {
} else { return 'None';
}
const globalAttr = tagsMap.get('*'); const globalAttr = tagsMap.get('*');
if (globalAttr) { if (globalAttr) {
code += `static ${ns.toUpperCase()}_${attrName.toUpperCase()}_ATTR: &AttrMapEntry = &AttrMapEntry::AllNamespaceElements(${rsTagAttr(globalAttr)});\n\n`; return `Some(AttrMapEntry::AllNamespaceElements(${rsTagAttr(globalAttr)}))`;
} 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`;
} }
byNsCode += `Some(${ns.toUpperCase()}_${attrName.toUpperCase()}_ATTR)`; return `Some({
} let mut m = HashMap::<&'static [u8], AttributeMinification>::new();
byNsCode += ',\n'; ${[...tagsMap].map(([tagName, tagAttr]) => ` m.insert(b\"${tagName}\", ${rsTagAttr(tagAttr)});`).join('\n')}
} AttrMapEntry::SpecificNamespaceElements(m)
byNsCode += '};\n\n'; })`;
code += byNsCode; })() + ',').join('\n')}
} });
code += 'pub static ATTRS: AttrMap = AttrMap::new(phf::phf_map! {\n';
for (const attr_name of attributes.keys()) { `).join('')}
code += `\tb\"${attr_name}\" => ${attr_name.toUpperCase()}_ATTR,\n`; AttrMap::new(m)
} };
code += '});\n\n'; }`;
return code; return code;
}; };

View File

@ -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. // Rules sourced from https://html.spec.whatwg.org/multipage/syntax.html#syntax-tag-omission.
// TODO html, head, body // 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. // Closing tag can never be omitted if it's the last node of its parent's children.
Never, 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. // 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 { pub struct ClosingTagOmissionRule {
// Closing tag can be omitted if immediately followed by an element node with one of these tag names. // 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. // Closing tag can be omitted if it's the last node of its parent's children.
is_last: ClosingTagOmissionRuleIfLast, is_last: ClosingTagOmissionRuleIfLast,
} }
@ -37,128 +38,218 @@ impl ClosingTagOmissionRule {
} }
} }
static LI_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule { lazy_static! {
followed_by: phf_set!(b"li"), static ref LI_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { lazy_static! {
followed_by: phf_set!(b"dt", b"dd"), static ref DT_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Never, 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 { lazy_static! {
followed_by: phf_set!(b"dd", b"dt"), static ref DD_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { lazy_static! {
followed_by: phf_set!( static ref P_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = {
b"address", let mut followed_by = HashSet::<&'static [u8]>::new();
b"article", followed_by.insert(b"address");
b"aside", followed_by.insert(b"article");
b"blockquote", followed_by.insert(b"aside");
b"details", followed_by.insert(b"blockquote");
b"div", followed_by.insert(b"details");
b"dl", followed_by.insert(b"div");
b"fieldset", followed_by.insert(b"dl");
b"figcaption", followed_by.insert(b"fieldset");
b"figure", followed_by.insert(b"figcaption");
b"footer", followed_by.insert(b"figure");
b"form", followed_by.insert(b"footer");
b"h1", followed_by.insert(b"form");
b"h2", followed_by.insert(b"h1");
b"h3", followed_by.insert(b"h2");
b"h4", followed_by.insert(b"h3");
b"h5", followed_by.insert(b"h4");
b"h6", followed_by.insert(b"h5");
b"header", followed_by.insert(b"h6");
b"hgroup", followed_by.insert(b"header");
b"hr", followed_by.insert(b"hgroup");
b"main", followed_by.insert(b"hr");
b"menu", followed_by.insert(b"main");
b"nav", followed_by.insert(b"menu");
b"ol", followed_by.insert(b"nav");
b"p", followed_by.insert(b"ol");
b"pre", followed_by.insert(b"p");
b"section", followed_by.insert(b"pre");
b"table", followed_by.insert(b"section");
b"ul", followed_by.insert(b"table");
), followed_by.insert(b"ul");
is_last: ClosingTagOmissionRuleIfLast::ParentIsNot(phf_set!(
b"a",
b"audio",
b"del",
b"ins",
b"map",
b"noscript",
b"video",
)),
};
static RT_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule { let mut is_last_tags = HashSet::<&'static [u8]>::new();
followed_by: phf_set!(b"rt", b"rp"), is_last_tags.insert(b"a");
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { ClosingTagOmissionRule { followed_by, is_last: ClosingTagOmissionRuleIfLast::ParentIsNot(is_last_tags) }
followed_by: phf_set!(b"rt", b"rp"), };
is_last: ClosingTagOmissionRuleIfLast::Always, }
};
static OPTGROUP_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule { lazy_static! {
followed_by: phf_set!(b"optgroup"), static ref RT_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { lazy_static! {
followed_by: phf_set!(b"option", b"optgroup"), static ref RP_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { lazy_static! {
followed_by: phf_set!(b"tbody", b"tfoot"), static ref OPTGROUP_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Never, 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 { lazy_static! {
followed_by: phf_set!(b"tbody", b"tfoot"), static ref OPTION_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { lazy_static! {
followed_by: phf_set!(), static ref THEAD_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { lazy_static! {
followed_by: phf_set!(b"tr"), static ref TBODY_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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 { lazy_static! {
followed_by: phf_set!(b"td", b"th"), static ref TFOOT_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, followed_by: HashSet::<&'static [u8]>::new(),
}; is_last: ClosingTagOmissionRuleIfLast::Always,
};
}
static TH_CLOSING_TAG_OMISSION_RULE: &ClosingTagOmissionRule = &ClosingTagOmissionRule { lazy_static! {
followed_by: phf_set!(b"td", b"th"), static ref TR_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
is_last: ClosingTagOmissionRuleIfLast::Always, 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! { lazy_static! {
b"li" => LI_CLOSING_TAG_OMISSION_RULE, static ref TD_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
b"dt" => DT_CLOSING_TAG_OMISSION_RULE, followed_by: {
b"dd" => DD_CLOSING_TAG_OMISSION_RULE, let mut s = HashSet::<&'static [u8]>::new();
b"p" => P_CLOSING_TAG_OMISSION_RULE, s.insert(b"td");
b"rt" => RT_CLOSING_TAG_OMISSION_RULE, s.insert(b"th");
b"rp" => RP_CLOSING_TAG_OMISSION_RULE, s
b"optgroup" => OPTGROUP_CLOSING_TAG_OMISSION_RULE, },
b"option" => OPTION_CLOSING_TAG_OMISSION_RULE, is_last: ClosingTagOmissionRuleIfLast::Always,
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, lazy_static! {
b"td" => TD_CLOSING_TAG_OMISSION_RULE, static ref TH_CLOSING_TAG_OMISSION_RULE: ClosingTagOmissionRule = ClosingTagOmissionRule {
b"th" => TH_CLOSING_TAG_OMISSION_RULE, 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
};
}

View File

@ -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! { lazy_static! {
b"area", pub static ref VOID_TAGS: HashSet<&'static [u8]> = {
b"base", let mut s = HashSet::<&'static [u8]>::new();
b"br", s.insert(b"area");
b"col", s.insert(b"base");
b"embed", s.insert(b"br");
b"hr", s.insert(b"col");
b"img", s.insert(b"embed");
b"input", s.insert(b"hr");
b"keygen", s.insert(b"img");
b"link", s.insert(b"input");
b"meta", s.insert(b"keygen");
b"param", s.insert(b"link");
b"source", s.insert(b"meta");
b"track", s.insert(b"param");
b"wbr", s.insert(b"source");
}; s.insert(b"track");
s.insert(b"wbr");
s
};
}

View File

@ -1,4 +1,5 @@
use phf::{Map, phf_map}; use lazy_static::lazy_static;
use std::collections::HashMap;
pub struct WhitespaceMinification { pub struct WhitespaceMinification {
pub collapse: bool, pub collapse: bool,
@ -48,116 +49,121 @@ static DEFAULT: &WhitespaceMinification = &WhitespaceMinification {
trim: false, trim: false,
}; };
static TAG_WHITESPACE_MINIFICATION: Map<&'static [u8], &'static WhitespaceMinification> = phf_map! { lazy_static! {
// Content tags. static ref TAG_WHITESPACE_MINIFICATION: HashMap<&'static [u8], &'static WhitespaceMinification> = {
b"address" => CONTENT, let mut m = HashMap::<&'static [u8], &'static WhitespaceMinification>::new();
b"audio" => CONTENT, // Content tags.
b"button" => CONTENT, m.insert(b"address", CONTENT);
b"canvas" => CONTENT, m.insert(b"audio", CONTENT);
b"caption" => CONTENT, m.insert(b"button", CONTENT);
b"figcaption" => CONTENT, m.insert(b"canvas", CONTENT);
b"h1" => CONTENT, m.insert(b"caption", CONTENT);
b"h2" => CONTENT, m.insert(b"figcaption", CONTENT);
b"h3" => CONTENT, m.insert(b"h1", CONTENT);
b"h4" => CONTENT, m.insert(b"h2", CONTENT);
b"h5" => CONTENT, m.insert(b"h3", CONTENT);
b"h6" => CONTENT, m.insert(b"h4", CONTENT);
b"legend" => CONTENT, m.insert(b"h5", CONTENT);
b"meter" => CONTENT, m.insert(b"h6", CONTENT);
b"object" => CONTENT, m.insert(b"legend", CONTENT);
b"option" => CONTENT, m.insert(b"meter", CONTENT);
b"p" => CONTENT, m.insert(b"object", CONTENT);
b"summary" => CONTENT, m.insert(b"option", CONTENT);
b"textarea" => CONTENT, m.insert(b"p", CONTENT);
b"video" => CONTENT, m.insert(b"summary", CONTENT);
m.insert(b"textarea", CONTENT);
m.insert(b"video", CONTENT);
// Content-first tags. // Content-first tags.
b"dd" => CONTENT_FIRST, m.insert(b"dd", CONTENT_FIRST);
b"details" => CONTENT_FIRST, m.insert(b"details", CONTENT_FIRST);
b"dt" => CONTENT_FIRST, m.insert(b"dt", CONTENT_FIRST);
b"iframe" => CONTENT_FIRST, m.insert(b"iframe", CONTENT_FIRST);
b"label" => CONTENT_FIRST, m.insert(b"label", CONTENT_FIRST);
b"li" => CONTENT_FIRST, m.insert(b"li", CONTENT_FIRST);
b"noscript" => CONTENT_FIRST, m.insert(b"noscript", CONTENT_FIRST);
b"output" => CONTENT_FIRST, m.insert(b"output", CONTENT_FIRST);
b"progress" => CONTENT_FIRST, m.insert(b"progress", CONTENT_FIRST);
b"slot" => CONTENT_FIRST, m.insert(b"slot", CONTENT_FIRST);
b"td" => CONTENT_FIRST, m.insert(b"td", CONTENT_FIRST);
b"template" => CONTENT_FIRST, m.insert(b"template", CONTENT_FIRST);
b"th" => CONTENT_FIRST, m.insert(b"th", CONTENT_FIRST);
// Formatting tags. // Formatting tags.
// Sourced from https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Inline_text_semantics. // 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. // Differences to tags listed in table at above URL: -br, +del, +ins.
b"a" => FORMATTING, m.insert(b"a", FORMATTING);
b"abbr" => FORMATTING, m.insert(b"abbr", FORMATTING);
b"b" => FORMATTING, m.insert(b"b", FORMATTING);
b"bdi" => FORMATTING, m.insert(b"bdi", FORMATTING);
b"bdo" => FORMATTING, m.insert(b"bdo", FORMATTING);
b"cite" => FORMATTING, m.insert(b"cite", FORMATTING);
b"data" => FORMATTING, m.insert(b"data", FORMATTING);
b"del" => FORMATTING, m.insert(b"del", FORMATTING);
b"dfn" => FORMATTING, m.insert(b"dfn", FORMATTING);
b"em" => FORMATTING, m.insert(b"em", FORMATTING);
b"i" => FORMATTING, m.insert(b"i", FORMATTING);
b"ins" => FORMATTING, m.insert(b"ins", FORMATTING);
b"kbd" => FORMATTING, m.insert(b"kbd", FORMATTING);
b"mark" => FORMATTING, m.insert(b"mark", FORMATTING);
b"q" => FORMATTING, m.insert(b"q", FORMATTING);
b"rp" => FORMATTING, m.insert(b"rp", FORMATTING);
b"rt" => FORMATTING, m.insert(b"rt", FORMATTING);
b"rtc" => FORMATTING, m.insert(b"rtc", FORMATTING);
b"ruby" => FORMATTING, m.insert(b"ruby", FORMATTING);
b"s" => FORMATTING, m.insert(b"s", FORMATTING);
b"samp" => FORMATTING, m.insert(b"samp", FORMATTING);
b"small" => FORMATTING, m.insert(b"small", FORMATTING);
b"span" => FORMATTING, m.insert(b"span", FORMATTING);
b"strong" => FORMATTING, m.insert(b"strong", FORMATTING);
b"sub" => FORMATTING, m.insert(b"sub", FORMATTING);
b"sup" => FORMATTING, m.insert(b"sup", FORMATTING);
b"time" => FORMATTING, m.insert(b"time", FORMATTING);
b"u" => FORMATTING, m.insert(b"u", FORMATTING);
b"var" => FORMATTING, m.insert(b"var", FORMATTING);
b"wbr" => FORMATTING, m.insert(b"wbr", FORMATTING);
// Layout tags. // Layout tags.
b"article" => LAYOUT, m.insert(b"article", LAYOUT);
b"aside" => LAYOUT, m.insert(b"aside", LAYOUT);
b"blockquote" => LAYOUT, m.insert(b"blockquote", LAYOUT);
b"body" => LAYOUT, m.insert(b"body", LAYOUT);
b"colgroup" => LAYOUT, m.insert(b"colgroup", LAYOUT);
b"datalist" => LAYOUT, m.insert(b"datalist", LAYOUT);
b"dialog" => LAYOUT, m.insert(b"dialog", LAYOUT);
b"div" => LAYOUT, m.insert(b"div", LAYOUT);
b"dl" => LAYOUT, m.insert(b"dl", LAYOUT);
b"fieldset" => LAYOUT, m.insert(b"fieldset", LAYOUT);
b"figure" => LAYOUT, m.insert(b"figure", LAYOUT);
b"footer" => LAYOUT, m.insert(b"footer", LAYOUT);
b"form" => LAYOUT, m.insert(b"form", LAYOUT);
b"head" => LAYOUT, m.insert(b"head", LAYOUT);
b"header" => LAYOUT, m.insert(b"header", LAYOUT);
b"hgroup" => LAYOUT, m.insert(b"hgroup", LAYOUT);
b"html" => LAYOUT, m.insert(b"html", LAYOUT);
b"main" => LAYOUT, m.insert(b"main", LAYOUT);
b"map" => LAYOUT, m.insert(b"map", LAYOUT);
b"menu" => LAYOUT, m.insert(b"menu", LAYOUT);
b"nav" => LAYOUT, m.insert(b"nav", LAYOUT);
b"ol" => LAYOUT, m.insert(b"ol", LAYOUT);
b"optgroup" => LAYOUT, m.insert(b"optgroup", LAYOUT);
b"picture" => LAYOUT, m.insert(b"picture", LAYOUT);
b"section" => LAYOUT, m.insert(b"section", LAYOUT);
b"select" => LAYOUT, m.insert(b"select", LAYOUT);
b"table" => LAYOUT, m.insert(b"table", LAYOUT);
b"tbody" => LAYOUT, m.insert(b"tbody", LAYOUT);
b"tfoot" => LAYOUT, m.insert(b"tfoot", LAYOUT);
b"thead" => LAYOUT, m.insert(b"thead", LAYOUT);
b"tr" => LAYOUT, m.insert(b"tr", LAYOUT);
b"ul" => LAYOUT, m.insert(b"ul", LAYOUT);
// Whitespace-sensitive tags. // Whitespace-sensitive tags.
b"code" => WHITESPACE_SENSITIVE, m.insert(b"code", WHITESPACE_SENSITIVE);
b"pre" => WHITESPACE_SENSITIVE, m.insert(b"pre", WHITESPACE_SENSITIVE);
};
m
};
}
pub fn get_whitespace_minification_for_tag(tag_name: Option<&[u8]>) -> &'static WhitespaceMinification { pub fn get_whitespace_minification_for_tag(tag_name: Option<&[u8]>) -> &'static WhitespaceMinification {
match tag_name { match tag_name {

View File

@ -1,5 +1,5 @@
use phf::{Map, phf_map}; use lazy_static::lazy_static;
use std::collections::HashMap;
use crate::err::ProcessingResult; use crate::err::ProcessingResult;
use crate::proc::checkpoint::Checkpoint; use crate::proc::checkpoint::Checkpoint;
use crate::proc::MatchAction::*; 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. // 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! { lazy_static! {
b'\'' => b"&#39", static ref ENCODED: HashMap<u8, &'static [u8]> = {
b'"' => b"&#34", let mut m = HashMap::<u8, &'static [u8]>::new();
b'>' => b"&gt", m.insert(b'\'', b"&#39");
// Whitespace characters as defined by spec in crate::spec::codepoint::is_whitespace. m.insert(b'"', b"&#34");
b'\x09' => b"&#9", m.insert(b'>', b"&gt");
b'\x0a' => b"&#10", // Whitespace characters as defined by spec in crate::spec::codepoint::is_whitespace.
b'\x0c' => b"&#12", m.insert(b'\x09', b"&#9");
b'\x0d' => b"&#13", m.insert(b'\x0a', b"&#10");
b'\x20' => b"&#32", m.insert(b'\x0c', b"&#12");
}; m.insert(b'\x0d', b"&#13");
m.insert(b'\x20', b"&#32");
m
};
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum CharType { enum CharType {

View File

@ -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::err::{ErrorType, ProcessingResult};
use crate::proc::checkpoint::Checkpoint; use crate::proc::checkpoint::Checkpoint;
use crate::proc::MatchAction::*; use crate::proc::MatchAction::*;
@ -16,24 +16,28 @@ use crate::unit::style::process_style;
use crate::gen::attrs::{ATTRS, AttributeMinification}; use crate::gen::attrs::{ATTRS, AttributeMinification};
use crate::spec::tag::ns::Namespace; use crate::spec::tag::ns::Namespace;
pub static JAVASCRIPT_MIME_TYPES: Set<&'static [u8]> = phf_set! { lazy_static! {
b"application/ecmascript", pub static ref JAVASCRIPT_MIME_TYPES: HashSet<&'static [u8]> = {
b"application/javascript", let mut s = HashSet::<&'static [u8]>::new();
b"application/x-ecmascript", s.insert(b"application/ecmascript");
b"application/x-javascript", s.insert(b"application/javascript");
b"text/ecmascript", s.insert(b"application/x-ecmascript");
b"text/javascript", s.insert(b"application/x-javascript");
b"text/javascript1.0", s.insert(b"text/ecmascript");
b"text/javascript1.1", s.insert(b"text/javascript");
b"text/javascript1.2", s.insert(b"text/javascript1.0");
b"text/javascript1.3", s.insert(b"text/javascript1.1");
b"text/javascript1.4", s.insert(b"text/javascript1.2");
b"text/javascript1.5", s.insert(b"text/javascript1.3");
b"text/jscript", s.insert(b"text/javascript1.4");
b"text/livescript", s.insert(b"text/javascript1.5");
b"text/x-ecmascript", s.insert(b"text/jscript");
b"text/x-javascript", 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 `-`. // 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. // See https://html.spec.whatwg.org/multipage/syntax.html#syntax-tag-name for spec.