1 // Copyright 2014-2017 The html5ever Project Developers. See the
2 // COPYRIGHT file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10 extern crate phf_codegen;
11 extern crate string_cache_codegen;
12
13 use std::collections::HashMap;
14 use std::env;
15 use std::fs::File;
16 use std::io::{BufRead, BufReader, BufWriter, Write};
17 use std::path::Path;
18
19 mod entities;
20
21 static NAMESPACES: &[(&str, &str)] = &[
22 ("", ""),
23 ("*", "*"),
24 ("html", "http://www.w3.org/1999/xhtml"),
25 ("xml", "http://www.w3.org/XML/1998/namespace"),
26 ("xmlns", "http://www.w3.org/2000/xmlns/"),
27 ("xlink", "http://www.w3.org/1999/xlink"),
28 ("svg", "http://www.w3.org/2000/svg"),
29 ("mathml", "http://www.w3.org/1998/Math/MathML"),
30 ];
31
main()32 fn main() {
33 let generated = Path::new(&env::var("OUT_DIR").unwrap()).join("generated.rs");
34 let mut generated = BufWriter::new(File::create(&generated).unwrap());
35
36 named_entities_to_phf(&Path::new(&env::var("OUT_DIR").unwrap()).join("named_entities.rs"));
37
38 // Create a string cache for local names
39 let local_names = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("local_names.txt");
40 let mut local_names_atom = string_cache_codegen::AtomType::new("LocalName", "local_name!");
41 for line in BufReader::new(File::open(&local_names).unwrap()).lines() {
42 let local_name = line.unwrap();
43 local_names_atom.atom(&local_name);
44 local_names_atom.atom(&local_name.to_ascii_lowercase());
45 }
46 local_names_atom
47 .with_macro_doc("Takes a local name as a string and returns its key in the string cache.")
48 .write_to(&mut generated)
49 .unwrap();
50
51 // Create a string cache for namespace prefixes
52 string_cache_codegen::AtomType::new("Prefix", "namespace_prefix!")
53 .with_macro_doc("Takes a namespace prefix string and returns its key in a string cache.")
54 .atoms(NAMESPACES.iter().map(|&(prefix, _url)| prefix))
55 .write_to(&mut generated)
56 .unwrap();
57
58 // Create a string cache for namespace urls
59 string_cache_codegen::AtomType::new("Namespace", "namespace_url!")
60 .with_macro_doc("Takes a namespace url string and returns its key in a string cache.")
61 .atoms(NAMESPACES.iter().map(|&(_prefix, url)| url))
62 .write_to(&mut generated)
63 .unwrap();
64
65 writeln!(
66 generated,
67 r#"
68 /// Maps the input of [`namespace_prefix!`](macro.namespace_prefix.html) to
69 /// the output of [`namespace_url!`](macro.namespace_url.html).
70 ///
71 #[macro_export] macro_rules! ns {{
72 "#
73 )
74 .unwrap();
75 for &(prefix, url) in NAMESPACES {
76 writeln!(
77 generated,
78 "({}) => {{ namespace_url!({:?}) }};",
79 prefix, url
80 )
81 .unwrap();
82 }
83 writeln!(generated, "}}").unwrap();
84 }
85
named_entities_to_phf(to: &Path)86 fn named_entities_to_phf(to: &Path) {
87 let mut entities: HashMap<&str, (u32, u32)> = entities::NAMED_ENTITIES
88 .iter()
89 .map(|(name, cp1, cp2)| {
90 assert!(name.starts_with('&'));
91 (&name[1..], (*cp1, *cp2))
92 })
93 .collect();
94
95 // Add every missing prefix of those keys, mapping to NULL characters.
96 for key in entities.keys().cloned().collect::<Vec<_>>() {
97 for n in 1..key.len() {
98 entities.entry(&key[..n]).or_insert((0, 0));
99 }
100 }
101 entities.insert("", (0, 0));
102
103 let mut phf_map = phf_codegen::Map::new();
104 for (key, value) in entities {
105 phf_map.entry(key, &format!("{:?}", value));
106 }
107
108 let mut file = File::create(to).unwrap();
109 writeln!(
110 &mut file,
111 r#"
112 /// A map of entity names to their codepoints. The second codepoint will
113 /// be 0 if the entity contains a single codepoint. Entities have their preceeding '&' removed.
114 ///
115 /// # Examples
116 ///
117 /// ```
118 /// use markup5ever::data::NAMED_ENTITIES;
119 ///
120 /// assert_eq!(NAMED_ENTITIES.get("gt;").unwrap(), &(62, 0));
121 /// ```
122 "#
123 )
124 .unwrap();
125 writeln!(
126 &mut file,
127 "pub static NAMED_ENTITIES: Map<&'static str, (u32, u32)> = {};",
128 phf_map.build(),
129 )
130 .unwrap();
131 }
132