diff --git a/.prettierignore b/.prettierignore index 85868a3350..ecdac9bcb1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ # Build Artefacts dist +mockDist target # Release body template should not be auto-formatted, as the word wrap does not really looks good in the GitHub UI. diff --git a/Cargo.lock b/Cargo.lock index 0cfcccce79..2a7fb9eb72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1211,8 +1211,6 @@ dependencies = [ "dirs", "enso-build-base", "enso-build-macros-lib", - "enso-enso-font", - "enso-font", "enso-install-config", "futures", "glob", @@ -1313,23 +1311,6 @@ dependencies = [ "serde", ] -[[package]] -name = "enso-enso-font" -version = "0.1.0" -dependencies = [ - "enso-font", - "ide-ci", - "owned_ttf_parser", -] - -[[package]] -name = "enso-font" -version = "0.1.0" -dependencies = [ - "derive_more", - "owned_ttf_parser", -] - [[package]] name = "enso-formatter" version = "0.1.0" @@ -2858,15 +2839,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "owned_ttf_parser" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e6affeb1632d6ff6a23d2cd40ffed138e82f1532571a26f527c8a284bb2fbb" -dependencies = [ - "ttf-parser", -] - [[package]] name = "parking" version = "2.2.0" @@ -4349,12 +4321,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "ttf-parser" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" - [[package]] name = "tuikit" version = "0.5.0" diff --git a/app/gui/.gitignore b/app/gui/.gitignore index 4dfa7178b5..7275eab1af 100644 --- a/app/gui/.gitignore +++ b/app/gui/.gitignore @@ -26,11 +26,5 @@ mockDist test-results/ playwright-report/ -public/font-dejavu/ -public/font-enso/ -public/font-mplus1/ -src/project-view/assets/font-dejavu.css -src/project-view/assets/font-enso.css -src/project-view/assets/font-mplus1.css src/project-view/util/iconList.json src/project-view/util/iconName.ts diff --git a/app/gui/package.json b/app/gui/package.json index 87fa24bcaa..e910ac51e2 100644 --- a/app/gui/package.json +++ b/app/gui/package.json @@ -29,11 +29,10 @@ "test-dev:unit": "vitest", "test:e2e": "cross-env NODE_ENV=production playwright test", "test-dev:e2e": "cross-env NODE_ENV=production playwright test --ui", - "preinstall": "corepack pnpm run generate-metadata && corepack pnpm run download-fonts", + "preinstall": "corepack pnpm run generate-metadata", "postinstall": "playwright install", "build-rust-ffi": "wasm-pack build ./rust-ffi --release --target web && wasm-pack build ./rust-ffi --out-dir node-pkg --target nodejs", - "generate-metadata": "node scripts/generateIconMetadata.js", - "download-fonts": "node scripts/downloadFonts.js" + "generate-metadata": "node scripts/generateIconMetadata.js" }, "dependencies": { "@aws-amplify/auth": "5.6.5", @@ -166,7 +165,6 @@ "@types/mapbox-gl": "^2.7.13", "@types/shuffle-seed": "^1.1.0", "@types/tar": "^6.1.4", - "@types/unbzip2-stream": "^1.4.3", "@types/wicg-file-system-access": "^2023.10.2", "@types/ws": "^8.5.5", "@vitejs/plugin-vue": "^5.0.4", @@ -188,7 +186,6 @@ "sql-formatter": "^13.0.0", "tar": "^6.2.1", "tsx": "^4.7.1", - "unbzip2-stream": "^1.4.3", "vite-plugin-vue-devtools": "7.3.7", "vite-plugin-wasm": "^3.3.0", "vue-react-wrapper": "^0.3.1", diff --git a/app/gui/public/font-dejavu/DejaVuSansMono-Bold.ttf b/app/gui/public/font-dejavu/DejaVuSansMono-Bold.ttf index 9cb0a5e795..8184ced8cf 100644 Binary files a/app/gui/public/font-dejavu/DejaVuSansMono-Bold.ttf and b/app/gui/public/font-dejavu/DejaVuSansMono-Bold.ttf differ diff --git a/app/gui/scripts/downloadFonts.js b/app/gui/scripts/downloadFonts.js deleted file mode 100644 index da1eaf88a6..0000000000 --- a/app/gui/scripts/downloadFonts.js +++ /dev/null @@ -1,217 +0,0 @@ -/** - * @file ⚠️⚠️⚠️ THIS SCRIPT IS PROVIDED ONLY FOR CONVENIENCE. ⚠️⚠️⚠️ - * The sources of truth are at `build/build/src/project/gui.rs` and - * `build/build/src/ide/web/fonts.rs`. - */ - -import * as fsSync from 'node:fs' -import * as fs from 'node:fs/promises' -import * as http from 'node:http' -import * as https from 'node:https' -import * as process from 'node:process' -import tar from 'tar' -import bz2 from 'unbzip2-stream' - -if (process.env.CI === '1') process.exit(0) - -const WARNING_MESSAGE = - '⚠️⚠️⚠️ Please use the buildscript (`./run`) to download fonts instead. ⚠️⚠️⚠️' -let warningMessageAlreadyShown = false -let exitCode = 0 - -const ENSO_FONT_URL = 'https://github.com/enso-org/font/releases/download/1.0/enso-font-1.0.tar.gz' -const MPLUS1_FONT_URL = - 'https://github.com/coz-m/MPLUS_FONTS/raw/71d438c798d063cc6fdae8d2864bc48f2d3d06ad/fonts/ttf/MPLUS1%5Bwght%5D.ttf' -const DEJAVU_SANS_MONO_FONT_URL = - 'https://sourceforge.net/projects/dejavu/files/dejavu/2.37/dejavu-fonts-ttf-2.37.tar.bz2' - -/** - * @param {string | https.RequestOptions | URL} options - * @param {((res: import('node:http').IncomingMessage) => void) | undefined} [callback] - */ -function get(options, callback) { - const protocol = - typeof options === 'string' ? new URL(options).protocol : options.protocol ?? 'https:' - /** @type {{ get: typeof http['get'] }} */ - let httpModule = https - switch (protocol) { - case 'http:': { - httpModule = http - break - } - } - return httpModule.get(options, (response) => { - const location = response.headers.location - if (location) { - get( - typeof options === 'string' || options instanceof URL ? - location - : { ...options, ...new URL(location) }, - callback, - ) - } else { - callback?.(response) - } - }) -} - -/** @param {unknown} error */ -function errorCode(error) { - return ( - typeof error === 'object' && - error != null && - 'code' in error && - typeof error.code === 'string' - ) ? - error.code - : undefined -} - -/** @param {unknown} error */ -function isFileNotFoundError(error) { - return errorCode(error) === 'ENOENT' -} - -const ENSO_FONT_VARIANTS = [ - { variant: 'Thin', weight: 100 }, - { variant: 'ExtraLight', weight: 200 }, - { variant: 'Light', weight: 300 }, - { variant: 'Regular', weight: 400 }, - { variant: 'Medium', weight: 500 }, - { variant: 'SemiBold', weight: 600 }, - { variant: 'Bold', weight: 700 }, - { variant: 'ExtraBold', weight: 800 }, - { variant: 'Black', weight: 900 }, -].map((variant) => ({ font: 'Enso', ...variant })) - -const DEJAVU_FONT_VARIANTS = [ - { variant: 'DejaVuSansMono', weight: 400 }, - { variant: 'DejaVuSansMono-Bold', weight: 700 }, -].map((variant) => ({ font: 'DejaVu Sans Mono', ...variant })) - -try { - await fs.access(`./src/project-view/assets/font-enso.css`) - for (const { variant } of ENSO_FONT_VARIANTS) { - await fs.access(`./public/font-enso/Enso-${variant}.ttf`) - } - console.info('Enso font already downloaded, skipping...') -} catch (error) { - if (!isFileNotFoundError(error)) { - console.error('Unexpected error occurred when checking for Enso font:') - console.error(error) - exitCode = 1 - } else { - if (!warningMessageAlreadyShown) console.warn(WARNING_MESSAGE) - warningMessageAlreadyShown = true - console.info('Downloading Enso font...') - await fs.rm('./public/font-enso/', { recursive: true, force: true }) - await fs.mkdir('./public/font-enso/', { recursive: true }) - await new Promise((resolve, reject) => { - get(ENSO_FONT_URL, (response) => { - response.pipe( - tar.extract({ - cwd: './public/font-enso/', - strip: 1, - filter(path) { - // Reject files starting with `.`. - return !/[\\/][.]/.test(path) - }, - }), - ) - response.on('end', resolve) - response.on('error', reject) - }) - }) - /** @type {string[]} */ - let css = [] - for (const { font, variant, weight } of ENSO_FONT_VARIANTS) { - css.push(`\ -@font-face { - font-family: '${font}'; - src: url('/font-enso/Enso-${variant}.ttf'); - font-weight: ${weight}; -} -`) - } - await fs.writeFile('./src/project-view/assets/font-enso.css', css.join('\n')) - } -} -try { - await fs.access(`./src/project-view/assets/font-mplus1.css`) - await fs.access(`./public/font-mplus1/MPLUS1[wght].ttf`) - console.info('M PLUS 1 font already downloaded, skipping...') -} catch (error) { - if (!isFileNotFoundError(error)) { - console.error('Unexpected error occurred when checking for M PLUS 1 font:') - console.error(error) - exitCode = 1 - } else { - if (!warningMessageAlreadyShown) console.warn(WARNING_MESSAGE) - warningMessageAlreadyShown = true - console.info('Downloading M PLUS 1 font...') - await fs.rm('./public/font-mplus1/', { recursive: true, force: true }) - await fs.mkdir('./public/font-mplus1/', { recursive: true }) - await new Promise((resolve, reject) => { - get(MPLUS1_FONT_URL, (response) => { - response.pipe(fsSync.createWriteStream('./public/font-mplus1/MPLUS1[wght].ttf')) - response.on('end', resolve) - response.on('error', reject) - }) - }) - const css = `\ -@font-face { - font-family: 'M PLUS 1'; - src: url('/font-mplus1/MPLUS1[wght].ttf'); -} -` - await fs.writeFile('./src/project-view/assets/font-mplus1.css', css) - } -} -try { - await fs.access(`./src/project-view/assets/font-dejavu.css`) - for (const variant of ['', '-Bold']) { - await fs.access(`./public/font-dejavu/DejaVuSansMono${variant}.ttf`) - } - console.info('DejaVu Sans Mono font already downloaded, skipping...') -} catch (error) { - if (!isFileNotFoundError(error)) { - console.error('Unexpected error occurred when checking for DejaVu Sans Mono font:') - console.error(error) - exitCode = 1 - } else { - if (!warningMessageAlreadyShown) console.warn(WARNING_MESSAGE) - warningMessageAlreadyShown = true - console.info('Downloading DejaVu Sans Mono font...') - await fs.rm('./public/font-dejavu/', { recursive: true, force: true }) - await fs.mkdir('./public/font-dejavu/', { recursive: true }) - await new Promise((resolve, reject) => { - get(DEJAVU_SANS_MONO_FONT_URL, (response) => { - response.pipe(bz2()).pipe( - tar.extract({ - cwd: './public/font-dejavu/', - strip: 2, - filter(path) { - return /[\\/]DejaVuSansMono/.test(path) && !/Oblique[.]ttf$/.test(path) - }, - }), - ) - response.on('end', resolve) - response.on('error', reject) - }) - }) - /** @type {string[]} */ - let css = [] - for (const { font, variant, weight } of DEJAVU_FONT_VARIANTS) { - css.push(`\ -@font-face { - font-family: '${font}'; - src: url('/font-dejavu/${variant}.ttf'); - font-weight: ${weight}; -} -`) - } - await fs.writeFile('./src/project-view/assets/font-dejavu.css', css.join('\n')) - } -} -console.info('Done.') -process.exit(exitCode) diff --git a/app/gui/src/project-view/assets/font-dejavu.css b/app/gui/src/project-view/assets/font-dejavu.css new file mode 100644 index 0000000000..e070d086f6 --- /dev/null +++ b/app/gui/src/project-view/assets/font-dejavu.css @@ -0,0 +1,12 @@ +@font-face { + font-family: 'DejaVu Sans Mono'; + src: url('/font-dejavu/DejaVuSansMono.ttf'); + font-weight: 400; +} + +@font-face { + font-family: 'DejaVu Sans Mono'; + src: url('/font-dejavu/DejaVuSansMono-Bold.ttf'); + font-weight: 700; +} + diff --git a/app/gui/src/project-view/assets/font-enso.css b/app/gui/src/project-view/assets/font-enso.css new file mode 100644 index 0000000000..d65196d180 --- /dev/null +++ b/app/gui/src/project-view/assets/font-enso.css @@ -0,0 +1,54 @@ +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-Thin.ttf'); + font-weight: 100; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-ExtraLight.ttf'); + font-weight: 200; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-Light.ttf'); + font-weight: 300; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-Regular.ttf'); + font-weight: 400; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-Medium.ttf'); + font-weight: 500; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-SemiBold.ttf'); + font-weight: 600; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-Bold.ttf'); + font-weight: 700; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-ExtraBold.ttf'); + font-weight: 800; +} + +@font-face { + font-family: 'Enso'; + src: url('/font-enso/Enso-Black.ttf'); + font-weight: 900; +} + diff --git a/app/gui/src/project-view/assets/font-mplus1.css b/app/gui/src/project-view/assets/font-mplus1.css new file mode 100644 index 0000000000..b2a98be0bf --- /dev/null +++ b/app/gui/src/project-view/assets/font-mplus1.css @@ -0,0 +1,5 @@ +@font-face { + font-family: 'M PLUS 1'; + src: url('/font-mplus1/MPLUS1[wght].ttf'); +} + diff --git a/app/gui/src/project-view/util/iconList.json b/app/gui/src/project-view/util/iconList.json deleted file mode 100644 index 5f235947ed..0000000000 --- a/app/gui/src/project-view/util/iconList.json +++ /dev/null @@ -1,213 +0,0 @@ -[ - "3_dot_menu", - "accessed_by_projects", - "accessed_data", - "add", - "add_to_graph_editor", - "array_new", - "array_new2", - "arrow_left", - "arrow_right", - "arrow_right_head_only", - "auto_replay", - "bell", - "bold", - "bookmark", - "bottom_panel", - "braces", - "brush", - "bullet-list", - "calendar", - "camera", - "chat", - "chat_gpt", - "chat_gpt2", - "chat_gpt_mod", - "chat_gpt_mod2", - "check", - "check-list", - "clone", - "close", - "cloud", - "cloud_from", - "code", - "collection", - "column_add", - "columns_increasing", - "command", - "command2", - "command3", - "command4", - "command5", - "comment", - "compass", - "compliance", - "compliance2", - "connector", - "connector_add", - "convert", - "copy", - "copy2", - "credit_card", - "data_download", - "data_input", - "data_output", - "data_upload", - "datetime", - "docs", - "drive", - "duplicate", - "edit", - "enso_logo", - "enter_node", - "error", - "exclamation", - "exit_fullscreen", - "expanded_node", - "eye", - "find", - "folder", - "folder_add", - "folder_closed", - "folder_opened", - "fullscreen", - "fullscreen2", - "fullscreen3", - "geo_map_distance", - "geo_map_pin", - "ghost", - "google", - "google_color", - "graph", - "graph2", - "graph_editor", - "graph_editor", - "group", - "header1", - "header2", - "header3", - "heart", - "heatmap", - "help", - "home", - "home2", - "icon/lock", - "icon/skip", - "image", - "in_out", - "in_out2", - "input_number", - "italic", - "join", - "join-1", - "join2", - "join2-1", - "key", - "key_cmd", - "key_ctrl", - "key_option", - "keyboard_shortcuts", - "lab", - "lab2", - "lab3", - "libraries", - "local_scope", - "local_scope2", - "local_scope3", - "local_scope4", - "location", - "location2", - "log", - "log_cloud", - "make_node_def_local_copy", - "map_row", - "marketplace", - "math", - "metadata", - "microphone", - "minus", - "mixed", - "no_auto_replay", - "not_cloud", - "not_exclamation", - "not_paragraph", - "numbered-list", - "open", - "open_count", - "operators", - "order", - "paint", - "paint_palette", - "panic", - "paragraph", - "parse", - "parse2", - "parse3", - "parse4", - "path2", - "people", - "people_settings", - "points", - "predict", - "preparation", - "quote", - "random", - "recent", - "record", - "record_once", - "redo", - "refresh", - "remove-textstyle", - "restore", - "right_panel", - "right_side_panel", - "robot", - "root", - "row_add", - "scissors", - "select", - "select_column", - "select_row", - "settings", - "settings1", - "settings2", - "shift_key", - "shortcut", - "shortcut2", - "shortcut3", - "show_all", - "sort", - "sort_ascending", - "sort_descending", - "split", - "star", - "strike-through", - "system", - "table", - "table_clean", - "table_edit", - "table_from_columns", - "table_from_rows", - "tag", - "temp", - "text", - "text2", - "text3", - "text_input", - "time", - "time2", - "transform", - "transform2", - "transform3", - "transform4", - "trash", - "trash2", - "undo", - "union", - "unstable", - "unstable2", - "vector_add", - "warning", - "workflow_play", - "zoom" -] diff --git a/build/build/Cargo.toml b/build/build/Cargo.toml index f2062292d8..d582be606c 100644 --- a/build/build/Cargo.toml +++ b/build/build/Cargo.toml @@ -21,8 +21,6 @@ futures = { workspace = true } glob = "0.3.0" handlebars = "4.3.5" enso-build-base = { path = "../base" } -enso-enso-font = { path = "../../lib/rust/enso-font" } -enso-font = { path = "../../lib/rust/font" } enso-install-config = { path = "../install/config" } ide-ci = { path = "../ci_utils" } mime = { workspace = true } diff --git a/build/build/src/ide/web.rs b/build/build/src/ide/web.rs index 547d58d55d..2de3d38a40 100644 --- a/build/build/src/ide/web.rs +++ b/build/build/src/ide/web.rs @@ -21,13 +21,6 @@ use tempfile::TempDir; // === Export === // ============== -pub mod dejavu_font; -pub mod enso_font; -pub mod fonts; -pub mod google_font; - - - lazy_static! { /// Path to the file with build information that is consumed by the JS part of the IDE. /// diff --git a/build/build/src/ide/web/dejavu_font.rs b/build/build/src/ide/web/dejavu_font.rs deleted file mode 100644 index 747bf1aa4d..0000000000 --- a/build/build/src/ide/web/dejavu_font.rs +++ /dev/null @@ -1,134 +0,0 @@ -//! Definitions for DejaVu fonts, and functions for downloading and installing them. - -use crate::prelude::*; - -use enso_font as font; -use enso_font::NonVariableDefinition; -use enso_font::NonVariableFaceHeader; -use ide_ci::cache::Cache; - - - -// ================= -// === Constants === -// ================= - -pub const PACKAGE_URL: &str = "https://github.com/dejavu-fonts/dejavu-fonts/releases/download/version_2_37/dejavu-fonts-ttf-2.37.zip"; - -const FONT_FAMILY: &str = "DejaVu Sans Mono"; - -const FILE_PREFIX: &str = "DejaVu"; - -const FILE_SANS_MONO_PREFIX: &str = "SansMono"; - -const SANS_MONO_FONT_FAMILY_FONTS: &[(&str, font::Weight)] = - &[("-Bold", font::Weight::Bold), ("", font::Weight::Normal)]; - - - -// =================== -// === DejaVu Font === -// =================== - -/// Internal helper function to download the DejaVu Sans Mono font. Exposed via thin wrapper -/// functions. -async fn install_sans_mono_internal( - cache: &Cache, - octocrab: &Octocrab, - output_path: impl AsRef, - css_output_info: Option<(&str, impl AsRef)>, -) -> Result { - let output_path = output_path.as_ref(); - let font = font(); - let faces = faces(); - let font = crate::ide::web::fonts::filter_font(&font, &faces); - let package = download(cache, octocrab).await?; - let get_font_files = extract_fonts(&font, package, output_path); - let make_css_file = crate::ide::web::fonts::write_css_file_if_required( - FONT_FAMILY, - &font, - &faces, - css_output_info, - ); - try_join!(get_font_files, make_css_file)?; - Ok(()) -} - -/// Install DejaVu Sans Mono, without an auto-generated CSS file. -pub async fn install_sans_mono( - cache: &Cache, - octocrab: &Octocrab, - output_path: impl AsRef, -) -> Result { - install_sans_mono_internal(cache, octocrab, output_path, None::<(&str, &str)>).await -} - -/// Install DejaVu Sans Mono, including an auto-generated CSS file. -pub async fn install_sans_mono_with_css( - cache: &Cache, - octocrab: &Octocrab, - css_basepath: &str, - output_path: impl AsRef, - css_output_path: impl AsRef, -) -> Result { - install_sans_mono_internal(cache, octocrab, output_path, Some((css_basepath, css_output_path))) - .await -} - -/// The DejaVu Sans Mono Font. -pub fn font() -> NonVariableDefinition { - SANS_MONO_FONT_FAMILY_FONTS - .iter() - .map(|(name, weight)| { - let file = format!("{FILE_PREFIX}{FILE_SANS_MONO_PREFIX}{name}.ttf"); - let header = NonVariableFaceHeader { - weight: *weight, - width: font::Width::Normal, - style: font::Style::Normal, - }; - (header, file) - }) - .collect() -} - -/// All font faces contained in this font. -pub fn faces() -> [NonVariableFaceHeader; 2] { - [NonVariableFaceHeader { weight: font::Weight::Normal, ..default() }, NonVariableFaceHeader { - weight: font::Weight::Bold, - ..default() - }] -} - -/// Extract the fonts from the given archive file, and write them in the given directory. -pub async fn extract_fonts( - fonts: &NonVariableDefinition, - package: impl AsRef, - out_dir: impl AsRef, -) -> Result { - let mut archive = ide_ci::archive::zip::open(&package)?; - crate::ide::web::fonts::extract_fonts(&mut archive, fonts, package, out_dir, &mut |path| { - let mut iter = path.iter(); - for _ in iter.by_ref().take(2) {} - Box::from(iter.as_str()) - }) - .await -} - -/// Download the DejaVu Font package, with caching and GitHub authentication. -pub async fn download(cache: &Cache, octocrab: &Octocrab) -> Result> { - Ok(cache - .get(ide_ci::cache::download::DownloadFile { - client: octocrab.client.clone(), - key: ide_ci::cache::download::Key { - url: PACKAGE_URL.parse().unwrap(), - additional_headers: reqwest::header::HeaderMap::from_iter([( - reqwest::header::ACCEPT, - reqwest::header::HeaderValue::from_static( - mime::APPLICATION_OCTET_STREAM.as_ref(), - ), - )]), - }, - }) - .await? - .into_boxed_path()) -} diff --git a/build/build/src/ide/web/enso_font.rs b/build/build/src/ide/web/enso_font.rs deleted file mode 100644 index 4c5a3c3061..0000000000 --- a/build/build/src/ide/web/enso_font.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! Definitions for Enso Font, and functions for downloading and installing them. - -use crate::prelude::*; - -use enso_enso_font::ttf; -use enso_font::NonVariableFaceHeader; -use ide_ci::cache::Cache; - - - -// ================= -// === Constants === -// ================= - -const FONT_FAMILY: &str = "Enso"; - - - -// ================= -// === Enso Font === -// ================= - -pub async fn install_for_html( - cache: &Cache, - octocrab: &Octocrab, - output_path: impl AsRef, -) -> Result { - let output_path = output_path.as_ref(); - let html_fonts: HashMap<_, _> = [ - (NonVariableFaceHeader { weight: ttf::Weight::Normal, ..default() }, "Regular"), - (NonVariableFaceHeader { weight: ttf::Weight::ExtraBold, ..default() }, "Bold"), - ] - .into_iter() - .collect(); - let html_font_definitions = enso_enso_font::font() - .variations() - .filter(|v| html_fonts.contains_key(&v.header)) - .collect(); - let get_font_files = async { - let package = download(cache, octocrab).await?; - enso_enso_font::extract_fonts(&html_font_definitions, package, output_path).await - }; - let make_css_file = async { - let mut css = String::new(); - let url = "."; - for (header, variant) in html_fonts { - use std::fmt::Write; - let def = html_font_definitions.get(header); - let def = def.ok_or_else(|| { - anyhow!( - "Required font not found in Enso Font package. \ - Expected a font matching: {header:?}." - ) - })?; - let file = &def.file; - // Note that this cannot use `generate_css_file`, as it specifies a different font - // family for each variant. - writeln!(&mut css, "@font-face {{")?; - writeln!(&mut css, " font-family: '{FONT_FAMILY}{variant}';")?; - writeln!(&mut css, " src: url('{url}/{file}');")?; - writeln!(&mut css, " font-weight: normal;")?; - writeln!(&mut css, " font-style: normal;")?; - writeln!(&mut css, "}}")?; - } - let css_path = output_path.join("ensoFont.css"); - ide_ci::fs::tokio::write(css_path, css).await?; - Ok(()) - }; - try_join!(get_font_files, make_css_file)?; - Ok(()) -} - -pub async fn install_with_css( - cache: &Cache, - octocrab: &Octocrab, - css_basepath: &str, - output_path: impl AsRef, - css_output_path: impl AsRef, -) -> Result { - let output_path = output_path.as_ref(); - let font = enso_enso_font::font(); - let faces = enso_enso_font::faces(); - let font = crate::ide::web::fonts::filter_font(&font, &faces); - let package = download(cache, octocrab).await?; - let get_font_files = enso_enso_font::extract_fonts(&font, package, output_path); - let css_output_info = Some((css_basepath, css_output_path)); - let make_css_file = crate::ide::web::fonts::write_css_file_if_required( - FONT_FAMILY, - &font, - &faces, - css_output_info, - ); - try_join!(get_font_files, make_css_file)?; - Ok(()) -} - -/// Download the Enso Font package, with caching and GitHub authentication. -pub async fn download(cache: &Cache, octocrab: &Octocrab) -> Result> { - Ok(cache - .get(ide_ci::cache::download::DownloadFile { - client: octocrab.client.clone(), - key: ide_ci::cache::download::Key { - url: enso_enso_font::PACKAGE_URL.parse().unwrap(), - additional_headers: reqwest::header::HeaderMap::from_iter([( - reqwest::header::ACCEPT, - reqwest::header::HeaderValue::from_static( - mime::APPLICATION_OCTET_STREAM.as_ref(), - ), - )]), - }, - }) - .await? - .into_boxed_path()) -} diff --git a/build/build/src/ide/web/fonts.rs b/build/build/src/ide/web/fonts.rs deleted file mode 100644 index 1340bd91cf..0000000000 --- a/build/build/src/ide/web/fonts.rs +++ /dev/null @@ -1,192 +0,0 @@ -use crate::prelude::*; - -use enso_font::NonVariableDefinition; -use enso_font::NonVariableFaceHeader; -use ide_ci::archive::extract_files::ExtractFiles; -use ide_ci::cache::Cache; - - - -// ========================= -// === HTML Font Support === -// ========================= - -pub async fn install_html_fonts( - cache: &Cache, - octocrab: &Octocrab, - output_path: impl AsRef, -) -> Result { - let output_path = output_path.as_ref(); - crate::ide::web::google_font::install(cache, octocrab, "mplus1", output_path).await?; - crate::ide::web::enso_font::install_for_html(cache, octocrab, output_path).await?; - Ok(()) -} - -/// A CSS font style that is displayed as a CSS [`@font-face`] [`font-style`] value. -/// -/// [`@font-face`]: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face -/// [`font-style`]: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-style -#[derive(Debug, Display, Copy, Clone)] -pub enum FontStyle { - #[display("normal")] - Normal, - #[display("italic")] - Italic, - #[display("oblique")] - Oblique, - /// Angle is in degrees, between -90 and 90. - #[display("oblique {_0}deg")] - ObliqueWithAngle(f64), - /// Angles are in degrees, between -90 and 90. - #[display("oblique {_0}deg {_1}deg")] - ObliqueWithAngleRange(f64, f64), -} - -/// A CSS font face that is displayed as a CSS [`@font-face`] declaration. -/// -/// [`@font-face`]: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face -#[derive(Debug, Clone)] -pub struct FontFace<'a> { - family: Cow<'a, str>, - path: Cow<'a, str>, - weight: Option, - style: Option, -} - -impl Display for FontFace<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let family = &self.family; - let path = &self.path; - writeln!(f, "@font-face {{")?; - writeln!(f, " font-family: '{family}';")?; - writeln!(f, " src: url('{path}');")?; - if let Some(weight) = self.weight { - writeln!(f, " font-weight: {weight};")?; - } - if let Some(style) = self.style { - writeln!(f, " font-style: {style};")?; - } - writeln!(f, "}}")?; - Ok(()) - } -} - -/// Generate a CSS file containing the given font files. Does not include font-weight, so use this -/// only if the font weights are not known - prefer [`generate_css_file`] in all other cases. -pub fn generate_css_file_from_paths( - basepath: &str, - family: &str, - paths: impl Iterator, -) -> Result -where - AsRefStr: AsRef, -{ - let mut css = String::new(); - for path in paths { - use std::fmt::Write; - let path = format!("{basepath}/{}", path.as_ref()); - let font_face = FontFace { - family: Cow::Borrowed(family), - path: Cow::Borrowed(path.as_str()), - weight: None, - style: None, - }; - writeln!(&mut css, "{font_face}")?; - } - Ok(css) -} - -/// Generate a CSS file containing the given font family, including only the given font variations. -pub fn generate_css_file<'a>( - basepath: &str, - family: &str, - definitions: &NonVariableDefinition, - fonts: impl Iterator, -) -> Result { - let mut css = String::new(); - for header in fonts { - use std::fmt::Write; - let def = definitions.get(*header); - let def = def.ok_or_else(|| { - anyhow!( - "Required font not found in {family} Font package. \ - Expected a font matching: {header:?}." - ) - })?; - let path = format!("{basepath}/{}", def.file); - let weight = def.header.weight.to_number(); - let font_face = FontFace { - family: Cow::Borrowed(family), - path: Cow::Borrowed(path.as_str()), - weight: Some(weight), - style: None, - }; - writeln!(&mut css, "{font_face}")?; - } - Ok(css) -} - - - -// =================== -// === Filter Font === -// =================== - -pub fn filter_font( - font: &NonVariableDefinition, - faces: &[NonVariableFaceHeader], -) -> NonVariableDefinition { - font.variations().filter(|v| faces.contains(&v.header)).collect() -} - - - -// ===================== -// === Make CSS File === -// ===================== - -pub async fn write_css_file_if_required( - font_family: &str, - font: &NonVariableDefinition, - faces: &[NonVariableFaceHeader], - css_output_info: Option<(&str, impl AsRef)>, -) -> Result { - if let Some((css_basepath, css_output_path)) = css_output_info { - let contents = generate_css_file(css_basepath, font_family, font, faces.iter())?; - ide_ci::fs::tokio::write(css_output_path, contents).await?; - Ok(()) - } else { - Ok(()) - } -} - - - -// ===================== -// === Extract Fonts === -// ===================== - -/// Extract the fonts from the given archive file, and write them in the given directory. -#[context("Failed to extract fonts from archive {}", package.as_ref().display())] -pub async fn extract_fonts( - archive: impl ExtractFiles, - fonts: &NonVariableDefinition, - package: impl AsRef, - out_dir: impl AsRef, - normalize_path: &mut impl FnMut(&Path) -> Box, -) -> Result { - ide_ci::fs::tokio::create_dir_if_missing(out_dir.as_ref()).await?; - let mut files_expected: HashSet<_> = fonts.files().collect(); - archive - .extract_files(|path_in_archive| { - let stripped_path = normalize_path(path_in_archive); - if files_expected.remove(stripped_path.as_ref()) { - Some(out_dir.as_ref().join(stripped_path.as_ref())) - } else { - None - } - }) - .await?; - ensure!(files_expected.is_empty(), "Required fonts not found in archive: {files_expected:?}."); - Ok(()) -} diff --git a/build/build/src/ide/web/google_font.rs b/build/build/src/ide/web/google_font.rs deleted file mode 100644 index 4706eac688..0000000000 --- a/build/build/src/ide/web/google_font.rs +++ /dev/null @@ -1,196 +0,0 @@ -//! Functions for downloading and installing Google fonts. - -use crate::prelude::*; - -use ide_ci::cache::Cache; -use ide_ci::cache::Storable; -use ide_ci::github; -use ide_ci::github::RepoRef; -use octocrab::models::repos; - - - -// ================= -// === Constants === -// ================= - -/// Google Fonts repository. -pub const REPOSITORY: RepoRef = RepoRef { owner: "google", name: "fonts" }; - -/// Path to the directory on the Google Fonts repository where we get the fonts from. -/// -/// The directory name denotes the license of the fonts. In our case this is SIL OPEN FONT LICENSE -/// Version 1.1, commonly known as OFL. -pub const DIRECTORY: &str = "ofl"; - -/// We keep dependency to a fixed commit, so we can safely cache it. -/// -/// There are no known reasons not to bump this. -pub const COMMIT_SHA1: &str = "ea893a43af7c5ab5ccee189fc2720788d99887ed"; - - -// ============== -// === Family === -// ============== - -/// Identifies uniquely a source of font family download. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Family { - /// Remote repository with fonts. - pub repo: github::Repo, - /// Which commit we want to be downloaded. - pub r#ref: String, - /// Font family. It corresponds to the subdirectories names (under the top-level - /// license-denoting directories). - pub name: String, -} - -impl Family { - /// List content items in the repository that contain TTF files for the given font family. - pub async fn list_ttf( - &self, - handle: github::repo::Handle, - ) -> Result> { - let path = format!("{DIRECTORY}/{}", self.name); - let files = handle.repos().get_content().r#ref(&self.r#ref).path(path).send().await?; - Ok(files.items.into_iter().filter(|file| file.name.ends_with(".ttf")).collect()) - } -} - - -// ==================== -// === DownloadFont === -// ==================== - -/// Description of the job to download the fonts. -#[derive(Clone)] -#[derive_where(Debug)] -pub struct DownloadFont { - pub family: Family, - /// Possible authentication to GitHub (to get bigger rate limit). - #[derive_where(skip)] - pub octocrab: Octocrab, -} - -impl DownloadFont { - /// Get a handle to the remote repository with the fonts. - pub fn handle(&self) -> github::repo::Handle { - self.family.repo.handle(&self.octocrab) - } - - /// Download the font family to the given directory. They will be placed in the output - /// directory. The function returns relative paths to the downloaded files. - pub async fn download(&self, output_path: impl AsRef) -> Result> { - let files = self.family.list_ttf(self.handle()).await?; - let mut ret = Vec::new(); - for file in &files { - let destination_file = output_path.as_ref().join(&file.name); - let url = file.download_url.as_ref().context("Missing 'download_url' in the reply.")?; - let reply = ide_ci::io::web::client::download(&self.octocrab.client, url).await?; - ide_ci::io::web::stream_to_file(reply, &destination_file).await?; - ret.push(file.name.as_str().into()); - } - Ok(ret) - } -} - -impl Storable for DownloadFont { - /// In metadata form we just store paths relative to the store. - type Metadata = Vec; - /// Here paths are absolute. - type Output = Vec; - type Key = Family; - - fn generate( - &self, - _cache: Cache, - store: PathBuf, - ) -> BoxFuture<'static, Result> { - let this = self.clone(); - async move { - let fonts = this.download(&store).await?; - Ok(fonts) - } - .boxed() - } - - fn adapt( - &self, - cache: PathBuf, - mut metadata: Self::Metadata, - ) -> BoxFuture<'static, Result> { - async move { - for font in &mut metadata { - *font = cache.join(&*font); - } - Ok(metadata) - } - .boxed() - } - - fn key(&self) -> Self::Key { - self.family.clone() - } -} - -// =================== -// === Entry Point === -// =================== - -/// Install a Google font, without an auto-generated CSS file. -pub async fn install( - cache: &Cache, - octocrab: &Octocrab, - family: &str, - output_path: impl AsRef, -) -> Result> { - let family = - Family { repo: REPOSITORY.into(), r#ref: COMMIT_SHA1.into(), name: family.into() }; - let font = DownloadFont { family, octocrab: octocrab.clone() }; - let cached_fonts = cache.get(font).await?; - let copy_futures = - cached_fonts.into_iter().map(|font| ide_ci::fs::tokio::copy_to(font, &output_path)); - let result = futures::future::join_all(copy_futures).await.into_iter().try_collect()?; - Ok(result) -} - -/// Install a Google font, including an auto-generated CSS file. -pub async fn install_with_css( - cache: &Cache, - octocrab: &Octocrab, - family: &str, - css_family: &str, - css_basepath: &str, - output_path: impl AsRef, - css_output_path: impl AsRef, -) -> Result> { - let paths = install(cache, octocrab, family, output_path).await?; - let css = crate::ide::web::fonts::generate_css_file_from_paths( - css_basepath, - css_family, - paths.iter().flat_map(|path| path.try_file_name().map(|name| name.as_str())), - )?; - ide_ci::fs::tokio::write(css_output_path, css).await?; - Ok(paths) -} - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - #[ignore] - async fn new_download() -> Result { - setup_logging().ok(); - let path = r"C:\temp\google_fonts2"; - let octocrab = github::setup_octocrab().await?; - let cache = Cache::new_default().await?; - let aaa = install(&cache, &octocrab, "mplus1", path).await?; - dbg!(aaa); - Ok(()) - } -} diff --git a/build/build/src/project/gui.rs b/build/build/src/project/gui.rs index 5f4bb6d815..a2639fbf48 100644 --- a/build/build/src/project/gui.rs +++ b/build/build/src/project/gui.rs @@ -64,32 +64,6 @@ impl IsTarget for Gui { let WithDestination { inner: _, destination } = job; async move { let repo_root = &context.repo_root; - crate::ide::web::google_font::install_with_css( - &context.cache, - &context.octocrab, - "mplus1", - "M PLUS 1", - "/font-mplus1", - &repo_root.app.gui.public.font_mplus_1, - &repo_root.app.gui.src.project_view.assets.font_mplus_1_css, - ) - .await?; - crate::ide::web::dejavu_font::install_sans_mono_with_css( - &context.cache, - &context.octocrab, - "/font-dejavu", - &repo_root.app.gui.public.font_dejavu, - &repo_root.app.gui.src.project_view.assets.font_dejavu_css, - ) - .await?; - crate::ide::web::enso_font::install_with_css( - &context.cache, - &context.octocrab, - "/font-enso", - &repo_root.app.gui.public.font_enso, - &repo_root.app.gui.src.project_view.assets.font_enso_css, - ) - .await?; crate::web::install(repo_root).await?; crate::web::run_script(repo_root, crate::web::Script::Build).await?; ide_ci::fs::mirror_directory( diff --git a/eslint.config.mjs b/eslint.config.mjs index 750be22a6e..d51443827f 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -191,6 +191,7 @@ export default [ '**/.cache/**', '**/playwright-report', '**/dist', + '**/mockDist', '**/build.mjs', '**/*.timestamp-*.mjs', '**/node_modules', diff --git a/lib/rust/enso-font/Cargo.toml b/lib/rust/enso-font/Cargo.toml deleted file mode 100644 index 1dd074275a..0000000000 --- a/lib/rust/enso-font/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "enso-enso-font" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2021" - -[dependencies] -enso-font = { path = "../font" } -ide-ci = { path = "../../../build/ci_utils" } -owned_ttf_parser = { workspace = true } - -[lints] -workspace = true diff --git a/lib/rust/enso-font/src/lib.rs b/lib/rust/enso-font/src/lib.rs deleted file mode 100644 index bb59c252a8..0000000000 --- a/lib/rust/enso-font/src/lib.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! The Enso Font. This crate supports downloading and unpacking the font family, as well as -//! constructing a reduced font family from a subset of the fonts. - -// === Non-Standard Linter Configuration === -#![deny(unconditional_recursion)] -#![warn(missing_docs)] -#![warn(trivial_casts)] - -use ide_ci::prelude::*; - -use enso_font::NonVariableDefinition; -use enso_font::NonVariableFaceHeader; - - -// ============== -// === Export === -// ============== - -pub use owned_ttf_parser as ttf; - - - -// ================= -// === Constants === -// ================= - -/// The name of the Enso font family. -pub const FONT_FAMILY: &str = "enso"; - -const FONTS: &[(&str, ttf::Weight)] = &[ - ("Black", ttf::Weight::Black), - ("Bold", ttf::Weight::Bold), - ("ExtraBold", ttf::Weight::ExtraBold), - ("ExtraLight", ttf::Weight::ExtraLight), - ("Light", ttf::Weight::Light), - ("Medium", ttf::Weight::Medium), - ("Regular", ttf::Weight::Normal), - ("SemiBold", ttf::Weight::SemiBold), - ("Thin", ttf::Weight::Thin), -]; - -/// The URL for the Enso Font package. -pub const PACKAGE_URL: &str = - "https://github.com/enso-org/font/releases/download/1.0/enso-font-1.0.tar.gz"; -const PACKAGE_FONTS_PREFIX: &str = "ttf"; - -/// Font features. -pub mod feature { - /// The flag identifying the ligature feature in this font. - pub const LIGATURES: &str = "liga"; -} - - - -// ================= -// === Enso Font === -// ================= - -/// The Enso Font. -pub fn font() -> NonVariableDefinition { - FONTS - .iter() - .map(|(name, weight)| { - let file = format!("Enso-{name}.ttf"); - let header = NonVariableFaceHeader { - weight: *weight, - width: ttf::Width::Normal, - style: ttf::Style::Normal, - }; - (header, file) - }) - .collect() -} - -/// All font faces contained in this font. -pub fn faces() -> [NonVariableFaceHeader; 9] { - [ - NonVariableFaceHeader { weight: ttf::Weight::Thin, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::ExtraLight, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::Light, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::Normal, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::Medium, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::SemiBold, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::Bold, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::ExtraBold, ..default() }, - NonVariableFaceHeader { weight: ttf::Weight::Black, ..default() }, - ] -} - -/// Extract the fonts from the given archive file, and write them in the given directory. -#[context("Failed to extract fonts from archive {}", package.as_ref().display())] -pub async fn extract_fonts( - fonts: &NonVariableDefinition, - package: impl AsRef, - out_dir: impl AsRef, -) -> Result { - use ide_ci::archive::extract_files::ExtractFiles; - ide_ci::fs::tokio::create_dir_if_missing(out_dir.as_ref()).await?; - let mut files_expected: HashSet<_> = fonts.files().collect(); - ide_ci::archive::tar::Archive::open_tar_gz(&package) - .await? - .extract_files(|path_in_archive| { - path_in_archive - .strip_prefix(PACKAGE_FONTS_PREFIX) - .ok() - .filter(|path| path.to_str().map_or(false, |path| files_expected.remove(path))) - .map(|path| out_dir.as_ref().join(path)) - }) - .await?; - ensure!(files_expected.is_empty(), "Required fonts not found in archive: {files_expected:?}."); - Ok(()) -} diff --git a/lib/rust/font/Cargo.toml b/lib/rust/font/Cargo.toml deleted file mode 100644 index 7841f92f33..0000000000 --- a/lib/rust/font/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "enso-font" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2021" - -[dependencies] -owned_ttf_parser = { workspace = true } -derive_more = { workspace = true } - -[lib] -crate-type = ["cdylib", "rlib"] - -[lints] -workspace = true diff --git a/lib/rust/font/src/lib.rs b/lib/rust/font/src/lib.rs deleted file mode 100644 index 993bc28254..0000000000 --- a/lib/rust/font/src/lib.rs +++ /dev/null @@ -1,203 +0,0 @@ -//! Definition of a font family, a set of related font faces. -//! -//! # One font face per file -//! The implementation of this library has an important limitation that should not cause any -//! problems, however, it is important to be aware of it. In case of non-variable fonts, only one -//! font face is supported per file. A font face is identified by (width, weight, style) triple (see -//! [`NonVariableFaceHeader`]) to learn more. If you want to use font faces defined in the same -//! file (e.g. ".ttf" file), you have to split them into multiple files first. All major browsers -//! have the same limitation. For example, you are unable to define in CSS a new font family by -//! loading different faces from the same file with the `@font-face` rule -//! (https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face). - -// === Non-Standard Linter Configuration === -#![deny(unconditional_recursion)] -#![warn(missing_docs)] -#![warn(trivial_casts)] -#![warn(unused_qualifications)] - -use derive_more::Deref; -use derive_more::Display; - - -// ============== -// === Export === -// ============== - -pub use owned_ttf_parser::Style; -pub use owned_ttf_parser::Weight; -pub use owned_ttf_parser::Width; - - - -// ============ -// === Name === -// ============ - -/// A name of a font. The name is normalized to case-insensitive form during construction to -/// eliminate accidental mistakes, the same way as it's done in CSS: -/// https://stackoverflow.com/questions/17967371/are-property-values-in-css-case-sensitive -#[allow(missing_docs)] -#[derive(Clone, Debug, Deref, Display, Hash, PartialEq, Eq)] -pub struct Name { - pub normalized: String, -} - -impl From<&Name> for Name { - fn from(name: &Name) -> Self { - name.clone() - } -} - -impl From<&str> for Name { - fn from(name: &str) -> Self { - let normalized = name.to_lowercase(); - Name { normalized } - } -} - -impl From<&String> for Name { - fn from(name: &String) -> Self { - name.as_str().into() - } -} - -impl From for Name { - fn from(name: String) -> Self { - (&name).into() - } -} - - - -// =================== -// === Font Family === -// =================== - -/// Definition of a font family. Font family consist of one font face in case of variable fonts or -/// multiple font faces in case of non-variable ones. -#[allow(missing_docs)] -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum FontFamily { - Variable(VariableDefinition), - NonVariable(NonVariableDefinition), -} - - - -// ========================== -// === VariableDefinition === -// ========================== - -/// Definition of a variable font family. See the following link to learn more about variable fonts: -/// https://docs.microsoft.com/en-us/windows/win32/directwrite/opentype-variable-fonts -#[allow(missing_docs)] -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct VariableDefinition { - /// Name of the file that the font data was read from. It contains the file extension, for - /// example `MPLUS1[wght].ttf`. - pub file_name: String, -} - -impl VariableDefinition { - /// Constructor. - pub fn new(file_name: impl Into) -> Self { - let file_name = file_name.into(); - Self { file_name } - } -} - - - -// ============================= -// === NonVariableDefinition === -// ============================= - -/// Definition of a non-variable font family. Contains mapping between (width, weight, style) triple -/// (see [`NonVariableFaceHeader`]) to learn more) and file names. -#[allow(missing_docs)] -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct NonVariableDefinition { - variations: std::collections::HashMap, -} - -impl NonVariableDefinition { - /// All weights defined in this font family. - pub fn possible_weights(&self) -> Vec { - let mut weights: Vec<_> = self.variations().map(|var| var.header.weight).collect(); - weights.sort_unstable_by_key(|w| w.to_number()); - weights.dedup(); - weights - } - - /// Return an iterator over the filenames associated with fonts in this family. - pub fn files(&self) -> impl Iterator { - self.variations().map(|v| v.file) - } - - /// Return an iterator over the fonts in this family. - pub fn variations(&self) -> impl Iterator { - self.variations - .iter() - .map(|(header, file)| NonVariableVariation { header: *header, file: file.as_str() }) - } - - /// Return the font in this family that exactly matches the given parameters, if any. - pub fn get(&self, header: NonVariableFaceHeader) -> Option { - self.variations.get(&header).map(|file| NonVariableVariation { header, file }) - } -} - -impl FromIterator<(NonVariableFaceHeader, String)> for NonVariableDefinition { - fn from_iter(iter: T) -> Self - where T: IntoIterator { - let map = iter.into_iter().collect(); - Self { variations: map } - } -} - -impl<'a> FromIterator> for NonVariableDefinition { - fn from_iter(iter: T) -> Self - where T: IntoIterator> { - let map = iter.into_iter().map(|v| (v.header, v.file.to_owned())).collect(); - Self { variations: map } - } -} - - - -// ============================ -// === NonVariableVariation === -// ============================ - -/// The parameters of a font, and the filename where it should be found. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct NonVariableVariation<'a> { - /// The parameters of the font. - pub header: NonVariableFaceHeader, - /// The filename for the font. - pub file: &'a str, -} - - - -// ============================= -// === NonVariableFaceHeader === -// ============================= - -/// Combination of all information allowing mapping the font face to a font file for non-variable -/// fonts. For variable fonts, there is just one definition for any combination of the parameters. -#[allow(missing_docs)] -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Hash)] -pub struct NonVariableFaceHeader { - pub width: Width, - pub weight: Weight, - pub style: Style, -} - -impl NonVariableFaceHeader { - /// Constructor. - pub const fn new(width: Width, weight: Weight, style: Style) -> Self { - Self { width, weight, style } - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3d0ad2305f..825cb52635 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -428,9 +428,6 @@ importers: '@types/tar': specifier: ^6.1.4 version: 6.1.13 - '@types/unbzip2-stream': - specifier: ^1.4.3 - version: 1.4.3 '@types/validator': specifier: ^13.11.7 version: 13.12.0 @@ -524,9 +521,6 @@ importers: typescript: specifier: ^5.5.3 version: 5.5.3 - unbzip2-stream: - specifier: ^1.4.3 - version: 1.4.3 vite: specifier: ^5.3.5 version: 5.3.5(@types/node@20.11.21)(lightningcss@1.25.1) @@ -3065,18 +3059,12 @@ packages: '@types/tar@6.1.13': resolution: {integrity: sha512-IznnlmU5f4WcGTh2ltRu/Ijpmk8wiWXfF0VA4s+HPjHZgvFggk1YaIkbo5krX/zUCzWF8N/l4+W/LNxnvAJ8nw==} - '@types/through@0.0.33': - resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} - '@types/to-ico@1.1.3': resolution: {integrity: sha512-3Ew8Hsz/qiDGzwvz75pjRU+6Ocfvrit6hHfirauEdJXxdro73MTe5XdcANh4GZ2wdJqWw9BIuHwWgKAfjUXoGw==} '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/unbzip2-stream@1.4.3': - resolution: {integrity: sha512-D8X5uuJRISqc8YtwL8jNW2FpPdUOCYXbfD6zNROCTbVXK9nawucxh10tVXE3MPjnHdRA1LvB0zDxVya/lBsnYw==} - '@types/validator@13.12.0': resolution: {integrity: sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==} @@ -6960,9 +6948,6 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -7121,9 +7106,6 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - unbzip2-stream@1.4.3: - resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} - undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -10504,20 +10486,12 @@ snapshots: '@types/node': 20.11.21 minipass: 4.2.8 - '@types/through@0.0.33': - dependencies: - '@types/node': 20.11.21 - '@types/to-ico@1.1.3': dependencies: '@types/node': 20.11.21 '@types/tough-cookie@4.0.5': {} - '@types/unbzip2-stream@1.4.3': - dependencies: - '@types/through': 0.0.33 - '@types/validator@13.12.0': {} '@types/verror@1.10.10': @@ -15079,8 +15053,6 @@ snapshots: dependencies: any-promise: 1.3.0 - through@2.3.8: {} - tiny-invariant@1.3.3: {} tinybench@2.8.0: {} @@ -15238,11 +15210,6 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - unbzip2-stream@1.4.3: - dependencies: - buffer: 5.7.1 - through: 2.3.8 - undici-types@5.26.5: {} undici@6.13.0: {}