Fix/BOOK-529 new icon * fix(BOOK-529): add new icon, remove scroll again * fix(BOOK-529): remove divider when no saved card Approved-by: Joakim Jäderberg
354 lines
7.0 KiB
TypeScript
354 lines
7.0 KiB
TypeScript
import crypto from "node:crypto";
|
|
import { createWriteStream } from "node:fs";
|
|
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { join, resolve } from "node:path";
|
|
import { Readable } from "node:stream";
|
|
import { pipeline } from "node:stream/promises";
|
|
|
|
import stringify from "json-stable-stringify-without-jsonify";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = resolve(__filename, "..");
|
|
|
|
// Defines where the font lives
|
|
const FONT_DIR = resolve(__dirname, "../shared/fonts/material-symbols");
|
|
|
|
// Defines the settings for the font
|
|
const FONT_BASE_URL = `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0..1,0`;
|
|
|
|
// Defines the subset of icons for the font
|
|
const icons = [
|
|
"accessibility",
|
|
"accessible",
|
|
"add_circle",
|
|
"add",
|
|
"air_purifier_gen",
|
|
"air",
|
|
"airline_seat_recline_normal",
|
|
"airplane_ticket",
|
|
"apartment",
|
|
"apparel",
|
|
"arrow_back_ios",
|
|
"arrow_back",
|
|
"arrow_forward_ios",
|
|
"arrow_forward",
|
|
"arrow_right",
|
|
"arrow_upward",
|
|
"assistant_navigation",
|
|
"asterisk",
|
|
"attractions",
|
|
"award_star",
|
|
"bakery_dining",
|
|
"balcony",
|
|
"bathroom",
|
|
"bathtub",
|
|
"beach_access",
|
|
"bed",
|
|
"bedroom_parent",
|
|
"box",
|
|
"brunch_dining",
|
|
"business_center",
|
|
"calendar_add_on",
|
|
"calendar_clock",
|
|
"calendar_month",
|
|
"calendar_today",
|
|
"call_quality",
|
|
"call",
|
|
"camera",
|
|
"cancel",
|
|
"chair",
|
|
"charging_station",
|
|
"check_box",
|
|
"check_circle",
|
|
"check",
|
|
"checked_bag",
|
|
"checkroom",
|
|
"chevron_left",
|
|
"chevron_right",
|
|
"close",
|
|
"coffee_maker",
|
|
"coffee",
|
|
"compare_arrows",
|
|
"computer",
|
|
"concierge",
|
|
"confirmation_number",
|
|
"connected_tv",
|
|
"content_copy",
|
|
"contract",
|
|
"cool_to_dry",
|
|
"countertops",
|
|
"credit_card_heart",
|
|
"credit_card",
|
|
"credit_score",
|
|
"curtains_closed",
|
|
"curtains",
|
|
"deck",
|
|
"delete",
|
|
"desk",
|
|
"device_thermostat",
|
|
"diamond",
|
|
"dining",
|
|
"directions_run",
|
|
"directions_subway",
|
|
"directions",
|
|
"downhill_skiing",
|
|
"download",
|
|
"dresser",
|
|
"edit_calendar",
|
|
"edit_square",
|
|
"edit",
|
|
"electric_bike",
|
|
"electric_car",
|
|
"elevator",
|
|
"emoji_transportation",
|
|
"error_circle_rounded",
|
|
"error",
|
|
"exercise",
|
|
"family_restroom",
|
|
"fastfood",
|
|
"favorite",
|
|
"fax",
|
|
"featured_seasonal_and_gifts",
|
|
"festival",
|
|
"filter_alt",
|
|
"filter",
|
|
"format_list_bulleted",
|
|
"floor_lamp",
|
|
"forest",
|
|
"garage",
|
|
"globe",
|
|
"golf_course",
|
|
"groups",
|
|
"health_and_beauty",
|
|
"heat",
|
|
"hiking",
|
|
"home",
|
|
"hot_tub",
|
|
"houseboat",
|
|
"hvac",
|
|
"id_card",
|
|
"imagesmode",
|
|
"info",
|
|
"iron",
|
|
"kayaking",
|
|
"kettle",
|
|
"keyboard_arrow_down",
|
|
"keyboard_arrow_right",
|
|
"keyboard_arrow_up",
|
|
"king_bed",
|
|
"kitchen",
|
|
"landscape",
|
|
"laundry",
|
|
"link",
|
|
"liquor",
|
|
"live_tv",
|
|
"local_bar",
|
|
"local_cafe",
|
|
"local_convenience_store",
|
|
"local_drink",
|
|
"local_laundry_service",
|
|
"local_parking",
|
|
"location_city",
|
|
"location_on",
|
|
"lock",
|
|
"lock_clock",
|
|
"loyalty",
|
|
"luggage",
|
|
"mail",
|
|
"map",
|
|
"meeting_room",
|
|
"microwave",
|
|
"mode_fan",
|
|
"museum",
|
|
"music_cast",
|
|
"music_note",
|
|
"nature",
|
|
"night_shelter",
|
|
"nightlife",
|
|
"open_in_new",
|
|
"pan_zoom",
|
|
"panorama",
|
|
"pause",
|
|
"pedal_bike",
|
|
"person",
|
|
"pets",
|
|
"phone",
|
|
"photo_camera",
|
|
"play_arrow",
|
|
"pool",
|
|
"print",
|
|
"radio",
|
|
"recommend",
|
|
"redeem",
|
|
"refresh",
|
|
"remove",
|
|
"restaurant",
|
|
"room_service",
|
|
"router",
|
|
"sailing",
|
|
"sauna",
|
|
"scene",
|
|
"search",
|
|
"sell",
|
|
"shopping_bag",
|
|
"shower",
|
|
"single_bed",
|
|
"skateboarding",
|
|
"smoke_free",
|
|
"smoking_rooms",
|
|
"spa",
|
|
"sports_esports",
|
|
"sports_golf",
|
|
"sports_handball",
|
|
"sports_tennis",
|
|
"stairs",
|
|
"star",
|
|
"straighten",
|
|
"styler",
|
|
"support_agent",
|
|
"swipe",
|
|
"sync_saved_locally",
|
|
"table_bar",
|
|
"theater_comedy",
|
|
"things_to_do",
|
|
"train",
|
|
"tram",
|
|
"transit_ticket",
|
|
"travel_luggage_and_bags",
|
|
"travel",
|
|
"trophy",
|
|
"tv_guide",
|
|
"tv_remote",
|
|
"upload",
|
|
"visibility_off",
|
|
"visibility",
|
|
"volume_off",
|
|
"volume_up",
|
|
"ward",
|
|
"warning",
|
|
"water_full",
|
|
"wifi",
|
|
"yard",
|
|
].sort();
|
|
|
|
function createHash(value: unknown) {
|
|
const stringified = stringify(value);
|
|
const hash = crypto.createHash("sha256");
|
|
hash.update(stringified);
|
|
return hash.digest("hex");
|
|
}
|
|
|
|
const hash = createHash(icons).substring(0, 8);
|
|
|
|
async function fetchIconUrl(url: string) {
|
|
const response = await fetch(url, {
|
|
headers: {
|
|
Accept:
|
|
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
"User-Agent":
|
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
|
|
},
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.error(`Unable to fetch woff2 for ${url}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const text = await response.text();
|
|
|
|
const isWoff2 = /format\('woff2'\)/.test(text);
|
|
if (!isWoff2) {
|
|
console.error(`Unable to identify woff2 font in response`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const srcUrl = text.match(/src: url\(([^)]+)\)/);
|
|
|
|
if (srcUrl && srcUrl[1]) {
|
|
return srcUrl[1];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
async function download(url: string, destFolder: string) {
|
|
const dest = resolve(join(destFolder, `/rounded-${hash}.woff2`));
|
|
|
|
try {
|
|
const response = await fetch(url);
|
|
|
|
if (!response.ok) {
|
|
console.error(`Unable to fetch ${url}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (!response.body) {
|
|
console.error(`Bad response from ${url}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const fileStream = createWriteStream(dest);
|
|
|
|
// @ts-expect-error: type mismatch
|
|
const readableNodeStream = Readable.fromWeb(response.body);
|
|
|
|
await pipeline(readableNodeStream, fileStream);
|
|
} catch (error) {
|
|
console.error(`Error downloading file from ${url}:`, error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
async function cleanFontDirs() {
|
|
await rm(FONT_DIR, { recursive: true, force: true });
|
|
await mkdir(FONT_DIR, { recursive: true });
|
|
await writeFile(
|
|
join(FONT_DIR, ".auto-generated"),
|
|
`Auto-generated, do not edit. Use scripts/material-symbols-update.mts to update.\nhash=${hash}\ncreated=${new Date().toISOString()}\n`,
|
|
{ encoding: "utf-8" }
|
|
);
|
|
}
|
|
|
|
async function updateFontCSS() {
|
|
const file = resolve(__dirname, "../packages/design-system/lib/fonts.css");
|
|
|
|
const css = await readFile(file, {
|
|
encoding: "utf-8",
|
|
});
|
|
|
|
await writeFile(
|
|
file,
|
|
css.replace(
|
|
/url\(\/_static\/shared\/fonts\/material-symbols\/rounded[^)]+\)/,
|
|
`url(/_static/shared/fonts/material-symbols/rounded-${hash}.woff2)`
|
|
),
|
|
{
|
|
encoding: "utf-8",
|
|
}
|
|
);
|
|
}
|
|
|
|
async function main() {
|
|
const fontUrl = `${FONT_BASE_URL}&icon_names=${icons.join(",")}&display=block`;
|
|
|
|
const iconUrl = await fetchIconUrl(fontUrl);
|
|
|
|
if (iconUrl) {
|
|
await cleanFontDirs();
|
|
|
|
await download(iconUrl, FONT_DIR);
|
|
|
|
await updateFontCSS();
|
|
|
|
console.log("Successfully updated icons!");
|
|
process.exit(0);
|
|
} else {
|
|
console.error(
|
|
`Unable to find the icon font src URL in CSS response from Google Fonts at ${fontUrl}`
|
|
);
|
|
}
|
|
}
|
|
|
|
main();
|