Skip to content

Commit 8390919

Browse files
committed
Add WASM target
1 parent 9da264f commit 8390919

File tree

11 files changed

+147
-15
lines changed

11 files changed

+147
-15
lines changed

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ members = [
55
"fontspector-cli",
66
"fontspector-checkapi",
77
"profile-universal", "profile-testplugin", "profile-googlefonts",
8+
"fontspector-web",
89
]
910

11+
default-members = [ "fontspector-cli" ]
12+
1013
[workspace.dependencies]
1114
pluginator = "1.0.1"
1215

fontspector-checkapi/Cargo.toml

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ name = "fontspector-checkapi"
33
version = "0.1.0"
44
edition = "2021"
55

6+
[lib]
7+
crate-type = ["cdylib", "rlib"]
8+
9+
[target.'cfg(not(target_family = "wasm"))'.dependencies]
10+
# Plugin architecture
11+
pluginator = {workspace = true}
12+
613
[dependencies]
714
read-fonts = {workspace = true}
815
skrifa = {workspace = true}
@@ -14,9 +21,6 @@ glob="0.3.1"
1421
# Needed so that we can refer to status codes on the command line
1522
clap = {version = "3.2.5", features = ["derive"]}
1623

17-
# Plugin architecture
18-
pluginator = {workspace = true}
19-
2024
# Serializing and deserializing profiles
2125
toml = "0.8.14"
2226
serde = { workspace = true }

fontspector-checkapi/src/font.rs

+37-10
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,30 @@ pub struct TestFont {
1818
pub const TTF: FileType = FileType { pattern: "*.ttf" };
1919

2020
impl<'a> FileTypeConvert<TestFont> for FileType<'a> {
21+
#[cfg(not(target_family = "wasm"))]
2122
fn from_testable(&self, t: &Testable) -> Option<TestFont> {
2223
self.applies(t)
2324
.then(|| TestFont::new(&t.filename))
2425
.transpose()
2526
.unwrap_or(None)
2627
}
28+
29+
#[cfg(target_family = "wasm")]
30+
fn from_testable(&self, t: &Testable) -> Option<TestFont> {
31+
self.applies(t)
32+
.then(|| TestFont::new_from_data(&t.filename, t.contents.clone()))
33+
.transpose()
34+
.unwrap_or(None)
35+
}
2736
}
2837

2938
impl TestFont {
3039
pub fn new(filename: &str) -> std::io::Result<TestFont> {
3140
let font_data = std::fs::read(filename)?;
41+
TestFont::new_from_data(filename, font_data)
42+
}
43+
44+
pub fn new_from_data(filename: &str, font_data: Vec<u8>) -> std::io::Result<TestFont> {
3245
let mut fnt = TestFont {
3346
filename: filename.to_string(),
3447
font_data,
@@ -41,9 +54,23 @@ impl TestFont {
4154
.mappings()
4255
.map(|(u, _gid)| u)
4356
.collect();
44-
fnt._sibling_filenames = {
57+
58+
fnt.find_siblings()?;
59+
60+
if FontRef::new(&fnt.font_data).is_err() {
61+
return Err(std::io::Error::new(
62+
ErrorKind::InvalidData,
63+
"Can't parse font",
64+
));
65+
}
66+
Ok(fnt)
67+
}
68+
69+
#[cfg(not(target_family = "wasm"))]
70+
fn find_siblings(&mut self) -> std::io::Result<()> {
71+
self._sibling_filenames = {
4572
// All other TTF files in same directory
46-
let directory = Path::new(&fnt.filename)
73+
let directory = Path::new(&self.filename)
4774
.parent()
4875
.ok_or(std::io::Error::new(
4976
ErrorKind::NotFound,
@@ -59,19 +86,19 @@ impl TestFont {
5986
paths
6087
.flatten()
6188
.filter(|x| x.path().extension().map_or(false, |ext| ext == "ttf"))
62-
.filter(|x| x.path().to_string_lossy() != fnt.filename)
89+
.filter(|x| x.path().to_string_lossy() != self.filename)
6390
.map(|x| x.path().to_string_lossy().to_string())
6491
.collect()
6592
};
93+
Ok(())
94+
}
6695

67-
if FontRef::new(&fnt.font_data).is_err() {
68-
return Err(std::io::Error::new(
69-
ErrorKind::InvalidData,
70-
"Can't parse font",
71-
));
72-
}
73-
Ok(fnt)
96+
#[cfg(target_family = "wasm")]
97+
fn find_siblings(&mut self) -> std::io::Result<()> {
98+
self._sibling_filenames = vec![];
99+
Ok(())
74100
}
101+
75102
pub fn font(&self) -> FontRef {
76103
#[allow(clippy::expect_used)] // We just tested for it in the initializer
77104
FontRef::new(&self.font_data).expect("Can't happen")

fontspector-checkapi/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ pub mod prelude {
2626
Status, StatusList, Testable, TTF,
2727
};
2828
}
29+
2930
pub trait Plugin {
3031
fn register(&self, cr: &mut Registry) -> Result<(), String>;
3132
}
3233

34+
#[cfg(not(target_family = "wasm"))]
3335
pluginator::plugin_trait!(Plugin);

fontspector-checkapi/src/registry.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl<'a> Registry<'a> {
2020
self.checks.values()
2121
}
2222

23+
#[cfg(not(target_family = "wasm"))]
2324
pub fn load_plugin(&mut self, plugin_path: &str) -> Result<(), String> {
2425
let plugin = unsafe { crate::load_plugin(plugin_path) }.unwrap_or_else(|e| {
2526
panic!("Could not load plugin {:?}: {:?}", plugin_path, e);

fontspector-checkapi/src/testable.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22
pub struct Testable {
33
pub filename: String,
44
pub source: Option<String>,
5+
#[cfg(target_family = "wasm")]
6+
pub contents: Vec<u8>,
57
}
68

79
impl Testable {
10+
#[cfg(not(target_family = "wasm"))]
811
pub fn new(filename: &str) -> Self {
912
Self {
1013
filename: filename.to_owned(),
1114
source: None,
1215
}
1316
}
1417

18+
#[cfg(not(target_family = "wasm"))]
1519
pub fn new_with_source(filename: &str, source: &str) -> Self {
1620
Self {
1721
filename: filename.to_owned(),

fontspector-web/Cargo.toml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "fontspector-web"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
wasm-bindgen = { version = "0.2.63" }
8+
console_error_panic_hook = { version = "0.1.6" }
9+
js-sys = { version = "0.3.68" }
10+
fontspector-checkapi = { path = "../fontspector-checkapi" }
11+
profile-universal = { path = "../profile-universal" }
12+
profile-googlefonts = { path = "../profile-googlefonts" }
13+
serde_json = { version = "1.0.96", features = ["preserve_order"] }
14+
15+
[lib]
16+
crate-type = ["cdylib", "rlib"]
17+
path = "src/lib.rs"

fontspector-web/src/lib.rs

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use wasm_bindgen::prelude::*;
2+
extern crate console_error_panic_hook;
3+
use fontspector_checkapi::{Check, CheckResult, Context, Plugin, Registry, Testable};
4+
use profile_googlefonts::GoogleFonts;
5+
use profile_universal::Universal;
6+
7+
#[wasm_bindgen]
8+
pub fn test(font_a: &[u8]) -> String {
9+
let mut registry = Registry::new();
10+
Universal
11+
.register(&mut registry)
12+
.expect("Couldn't register universal profile, fontspector bug");
13+
GoogleFonts
14+
.register(&mut registry)
15+
.expect("Couldn't register googlefonts profile, fontspector bug");
16+
let testable: Testable = Testable {
17+
filename: "font.ttf".to_string(),
18+
source: None,
19+
contents: font_a.to_vec(),
20+
};
21+
let testables = vec![testable];
22+
let profile = registry.get_profile("googlefonts").unwrap();
23+
let context = Context {
24+
skip_network: true,
25+
network_timeout: None,
26+
configuration: serde_json::Map::new(),
27+
};
28+
29+
let checkorder: Vec<(String, &Testable, &Check, Context)> = profile
30+
.sections
31+
.iter()
32+
.flat_map(|(sectionname, checknames)| {
33+
#[allow(clippy::unwrap_used)] // We previously ensured the check exists in the registry
34+
checknames
35+
.iter()
36+
// .filter(|checkname| included_excluded(checkname, &args))
37+
.map(|checkname| {
38+
(
39+
sectionname.clone(),
40+
registry.checks.get(checkname).unwrap(),
41+
context.clone(),
42+
)
43+
})
44+
})
45+
.flat_map(|(sectionname, check, context): (String, &Check, Context)| {
46+
testables
47+
.iter()
48+
.filter(|testable| check.applies(testable, &registry))
49+
.map(move |testable| (sectionname.clone(), testable, check, context.clone()))
50+
})
51+
.collect();
52+
53+
let results: Vec<CheckResult> = checkorder
54+
.iter()
55+
.map(|(sectionname, testable, check, context)| {
56+
(
57+
testable,
58+
check,
59+
check.run_one(testable, context, sectionname),
60+
)
61+
})
62+
.flat_map(|(_, _, result)| result)
63+
.collect();
64+
serde_json::to_string(&results).unwrap_or("Couldn't do it".to_string())
65+
}

fontspector-web/test.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const fs = require('fs');
2+
const fontspector = require('./pkg');
3+
const data = fs.readFileSync('../Nunito[wght].ttf')
4+
console.log(fontspector.test(data))

profile-testplugin/Cargo.toml

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ version = "0.1.0"
44
edition = "2021"
55

66
[lib]
7-
crate-type=["dylib"]
7+
crate-type=["cdylib"]
88

99
[dependencies]
1010
fontspector-checkapi = { path = "../fontspector-checkapi" }
11-
pluginator = "1.0.1"
1211
toml = "0.8.14"
12+
13+
[target.'cfg(not(target_family = "wasm"))'.dependencies]
14+
# Plugin architecture
15+
pluginator = {workspace = true}

profile-testplugin/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,6 @@ impl fontspector_checkapi::Plugin for Test {
5353
cr.register_simple_profile("test", vec![VALIDATE_TOML, SAY_HELLO])
5454
}
5555
}
56+
57+
#[cfg(not(target_family = "wasm"))]
5658
pluginator::plugin_implementation!(fontspector_checkapi::Plugin, Test);

0 commit comments

Comments
 (0)