From a3a513dc2434b643c46f16322d614b9e1b50f37b Mon Sep 17 00:00:00 2001 From: Mia Zbikowski Date: Mon, 9 Jun 2025 14:54:54 -0400 Subject: [PATCH] Add DeprecatedFonts theme check --- .changeset/rich-tigers-fail.md | 5 + .../deprecated-fonts-data.ts | 1337 +++++++++++++++++ .../index.spec.ts | 613 ++++++++ .../index.ts | 284 ++++ .../theme-check-common/src/checks/index.ts | 2 + .../src/types/schemas/section.ts | 10 +- packages/theme-check-node/configs/all.yml | 3 + .../theme-check-node/configs/recommended.yml | 3 + 8 files changed, 2253 insertions(+), 4 deletions(-) create mode 100644 .changeset/rich-tigers-fail.md create mode 100644 packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts create mode 100644 packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts create mode 100644 packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts diff --git a/.changeset/rich-tigers-fail.md b/.changeset/rich-tigers-fail.md new file mode 100644 index 000000000..2c6b9a8b4 --- /dev/null +++ b/.changeset/rich-tigers-fail.md @@ -0,0 +1,5 @@ +--- +'@shopify/theme-check-common': minor +--- + +Introduce new DeprecatedFontsOnSectionsAndBlocks check diff --git a/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts b/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts new file mode 100644 index 000000000..fc0afb2e9 --- /dev/null +++ b/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/deprecated-fonts-data.ts @@ -0,0 +1,1337 @@ +export const DEPRECATED_FONT_HANDLES = new Set([ + 'agmena_i3', + 'agmena_i4', + 'agmena_i6', + 'agmena_i7', + 'agmena_n3', + 'agmena_n4', + 'agmena_n6', + 'agmena_n7', + 'akko_i2', + 'akko_i3', + 'akko_i4', + 'akko_i5', + 'akko_i7', + 'akko_i9', + 'akko_n2', + 'akko_n3', + 'akko_n4', + 'akko_n5', + 'akko_n7', + 'akko_n9', + 'alfie_n4', + 'americana_i4', + 'americana_n4', + 'americana_n7', + 'americana_n8', + 'antique_olive_i4', + 'antique_olive_n3', + 'antique_olive_n4', + 'antique_olive_n7', + 'antique_olive_n9', + 'armata_n4', + 'avenir_next_i1', + 'avenir_next_i2', + 'avenir_next_i3', + 'avenir_next_i4', + 'avenir_next_i5', + 'avenir_next_i6', + 'avenir_next_i7', + 'avenir_next_i8', + 'avenir_next_n1', + 'avenir_next_n2', + 'avenir_next_n3', + 'avenir_next_n4', + 'avenir_next_n5', + 'avenir_next_n6', + 'avenir_next_n7', + 'avenir_next_n8', + 'avenir_next_rounded_i4', + 'avenir_next_rounded_i5', + 'avenir_next_rounded_i6', + 'avenir_next_rounded_i7', + 'avenir_next_rounded_n4', + 'avenir_next_rounded_n5', + 'avenir_next_rounded_n6', + 'avenir_next_rounded_n7', + 'azbuka_i3', + 'azbuka_i4', + 'azbuka_i5', + 'azbuka_i6', + 'azbuka_i7', + 'azbuka_n2', + 'azbuka_n3', + 'azbuka_n4', + 'azbuka_n5', + 'azbuka_n6', + 'azbuka_n7', + 'azbuka_n8', + 'azbuka_n9', + 'basic_commercial_i3', + 'basic_commercial_i4', + 'basic_commercial_i7', + 'basic_commercial_i8', + 'basic_commercial_n3', + 'basic_commercial_n4', + 'basic_commercial_n7', + 'basic_commercial_n8', + 'basic_commercial_soft_rounded_n4', + 'basic_commercial_soft_rounded_n7', + 'basic_commercial_soft_rounded_n9', + 'baskerville_no_2_i4', + 'baskerville_no_2_i7', + 'baskerville_no_2_n4', + 'baskerville_no_2_n7', + 'bauer_bodoni_i4', + 'bauer_bodoni_i7', + 'bauer_bodoni_i9', + 'bauer_bodoni_n4', + 'bauer_bodoni_n7', + 'bauer_bodoni_n9', + 'beefcakes_i4', + 'beefcakes_n4', + 'bembo_book_i4', + 'bembo_book_i7', + 'bembo_book_n4', + 'bembo_book_n7', + 'bernhard_modern_i4', + 'bernhard_modern_i7', + 'bernhard_modern_n4', + 'bernhard_modern_n7', + 'bio_rhyme_n2', + 'bio_rhyme_n3', + 'bio_rhyme_n4', + 'bio_rhyme_n7', + 'bio_rhyme_n8', + 'bodoni_poster_i9', + 'bodoni_poster_n9', + 'burlingame_i1', + 'burlingame_i2', + 'burlingame_i3', + 'burlingame_i4', + 'burlingame_i5', + 'burlingame_i6', + 'burlingame_i7', + 'burlingame_i8', + 'burlingame_i9', + 'burlingame_n1', + 'burlingame_n2', + 'burlingame_n3', + 'burlingame_n4', + 'burlingame_n5', + 'burlingame_n6', + 'burlingame_n7', + 'burlingame_n8', + 'burlingame_n9', + 'cachet_i1', + 'cachet_i2', + 'cachet_i3', + 'cachet_i4', + 'cachet_i5', + 'cachet_i6', + 'cachet_i7', + 'cachet_i8', + 'cachet_n1', + 'cachet_n2', + 'cachet_n3', + 'cachet_n4', + 'cachet_n5', + 'cachet_n6', + 'cachet_n7', + 'cachet_n8', + 'cardamon_i4', + 'cardamon_i5', + 'cardamon_i6', + 'cardamon_i7', + 'cardamon_n4', + 'cardamon_n5', + 'cardamon_n6', + 'cardamon_n7', + 'carter_sans_i4', + 'carter_sans_i5', + 'carter_sans_i6', + 'carter_sans_i7', + 'carter_sans_n4', + 'carter_sans_n5', + 'carter_sans_n6', + 'carter_sans_n7', + 'caslon_bold_i4', + 'caslon_bold_n4', + 'caslon_old_face_i4', + 'caslon_old_face_n4', + 'caslon_old_face_n7', + 'centaur_i4', + 'centaur_i7', + 'centaur_n4', + 'centaur_n7', + 'century_gothic_i4', + 'century_gothic_i7', + 'century_gothic_n4', + 'century_gothic_n7', + 'chong_modern_i3', + 'chong_modern_i4', + 'chong_modern_i7', + 'chong_modern_n3', + 'chong_modern_n4', + 'chong_modern_n7', + 'claire_news_n3', + 'claire_news_n7', + 'cooper_bt_i2', + 'cooper_bt_i5', + 'cooper_bt_i7', + 'cooper_bt_i9', + 'cooper_bt_n2', + 'cooper_bt_n5', + 'cooper_bt_n7', + 'cooper_bt_n9', + 'daytona_i2', + 'daytona_i3', + 'daytona_i4', + 'daytona_i6', + 'daytona_i7', + 'daytona_n2', + 'daytona_n3', + 'daytona_n4', + 'daytona_n6', + 'daytona_n7', + 'din_neuzeit_grotesk_n3', + 'din_neuzeit_grotesk_n7', + 'din_next_i2', + 'din_next_i3', + 'din_next_i4', + 'din_next_i5', + 'din_next_i7', + 'din_next_i8', + 'din_next_i9', + 'din_next_n2', + 'din_next_n3', + 'din_next_n4', + 'din_next_n5', + 'din_next_n7', + 'din_next_n8', + 'din_next_n9', + 'din_next_slab_i2', + 'din_next_slab_i3', + 'din_next_slab_i4', + 'din_next_slab_i5', + 'din_next_slab_i7', + 'din_next_slab_i8', + 'din_next_slab_i9', + 'din_next_slab_n2', + 'din_next_slab_n3', + 'din_next_slab_n4', + 'din_next_slab_n5', + 'din_next_slab_n7', + 'din_next_slab_n8', + 'din_next_slab_n9', + 'electra_i4', + 'electra_i7', + 'electra_n4', + 'electra_n7', + 'eurostile_next_i2', + 'eurostile_next_i3', + 'eurostile_next_i4', + 'eurostile_next_i6', + 'eurostile_next_i7', + 'eurostile_next_n2', + 'eurostile_next_n3', + 'eurostile_next_n4', + 'eurostile_next_n6', + 'eurostile_next_n7', + 'fette_gotisch_n4', + 'ff_meta_i1', + 'ff_meta_i2', + 'ff_meta_i3', + 'ff_meta_i4', + 'ff_meta_i5', + 'ff_meta_i6', + 'ff_meta_i7', + 'ff_meta_i9', + 'ff_meta_n1', + 'ff_meta_n2', + 'ff_meta_n3', + 'ff_meta_n4', + 'ff_meta_n5', + 'ff_meta_n6', + 'ff_meta_n7', + 'ff_meta_n9', + 'ff_meta_serif_i3', + 'ff_meta_serif_i4', + 'ff_meta_serif_i5', + 'ff_meta_serif_i7', + 'ff_meta_serif_i8', + 'ff_meta_serif_i9', + 'ff_meta_serif_n3', + 'ff_meta_serif_n4', + 'ff_meta_serif_n5', + 'ff_meta_serif_n7', + 'ff_meta_serif_n8', + 'ff_meta_serif_n9', + 'ff_tisa_i2', + 'ff_tisa_i3', + 'ff_tisa_i4', + 'ff_tisa_i5', + 'ff_tisa_i7', + 'ff_tisa_i8', + 'ff_tisa_i9', + 'ff_tisa_n2', + 'ff_tisa_n3', + 'ff_tisa_n4', + 'ff_tisa_n5', + 'ff_tisa_n7', + 'ff_tisa_n8', + 'ff_tisa_n9', + 'ff_tisa_sans_i2', + 'ff_tisa_sans_i3', + 'ff_tisa_sans_i4', + 'ff_tisa_sans_i5', + 'ff_tisa_sans_i7', + 'ff_tisa_sans_i8', + 'ff_tisa_sans_i9', + 'ff_tisa_sans_n2', + 'ff_tisa_sans_n3', + 'ff_tisa_sans_n4', + 'ff_tisa_sans_n5', + 'ff_tisa_sans_n7', + 'ff_tisa_sans_n8', + 'ff_tisa_sans_n9', + 'ff_unit_i2', + 'ff_unit_i3', + 'ff_unit_i4', + 'ff_unit_i5', + 'ff_unit_i7', + 'ff_unit_i8', + 'ff_unit_i9', + 'ff_unit_n2', + 'ff_unit_n3', + 'ff_unit_n4', + 'ff_unit_n5', + 'ff_unit_n7', + 'ff_unit_n8', + 'ff_unit_n9', + 'ff_unit_rounded_i3', + 'ff_unit_rounded_i4', + 'ff_unit_rounded_i5', + 'ff_unit_rounded_i7', + 'ff_unit_rounded_i8', + 'ff_unit_rounded_i9', + 'ff_unit_rounded_n3', + 'ff_unit_rounded_n4', + 'ff_unit_rounded_n5', + 'ff_unit_rounded_n7', + 'ff_unit_rounded_n8', + 'ff_unit_rounded_n9', + 'ff_unit_slab_i2', + 'ff_unit_slab_i3', + 'ff_unit_slab_i4', + 'ff_unit_slab_i5', + 'ff_unit_slab_i7', + 'ff_unit_slab_i8', + 'ff_unit_slab_i9', + 'ff_unit_slab_n2', + 'ff_unit_slab_n3', + 'ff_unit_slab_n4', + 'ff_unit_slab_n5', + 'ff_unit_slab_n7', + 'ff_unit_slab_n8', + 'ff_unit_slab_n9', + 'friz_quadrata_i4', + 'friz_quadrata_i7', + 'friz_quadrata_n4', + 'friz_quadrata_n7', + 'frutiger_serif_i3', + 'frutiger_serif_i4', + 'frutiger_serif_i5', + 'frutiger_serif_i7', + 'frutiger_serif_i8', + 'frutiger_serif_n3', + 'frutiger_serif_n4', + 'frutiger_serif_n5', + 'frutiger_serif_n7', + 'frutiger_serif_n8', + 'fs_kim_i4', + 'fs_kim_i5', + 'fs_kim_i7', + 'fs_kim_i8', + 'fs_kim_i9', + 'fs_kim_n4', + 'fs_kim_n5', + 'fs_kim_n7', + 'fs_kim_n8', + 'fs_kim_n9', + 'fs_koopman_i1', + 'fs_koopman_i3', + 'fs_koopman_i4', + 'fs_koopman_i5', + 'fs_koopman_i7', + 'fs_koopman_i8', + 'fs_koopman_i9', + 'fs_koopman_n1', + 'fs_koopman_n3', + 'fs_koopman_n4', + 'fs_koopman_n5', + 'fs_koopman_n7', + 'fs_koopman_n8', + 'fs_koopman_n9', + 'fs_siena_i1', + 'fs_siena_i2', + 'fs_siena_i3', + 'fs_siena_i4', + 'fs_siena_i5', + 'fs_siena_i6', + 'fs_siena_i7', + 'fs_siena_n1', + 'fs_siena_n2', + 'fs_siena_n3', + 'fs_siena_n4', + 'fs_siena_n5', + 'fs_siena_n6', + 'fs_siena_n7', + 'futura_black_n4', + 'futura_n3', + 'futura_n4', + 'futura_n5', + 'futura_n6', + 'futura_n7', + 'futura_n8', + 'futura_n9', + 'futura_o3', + 'futura_o4', + 'futura_o5', + 'futura_o6', + 'futura_o7', + 'futura_o8', + 'geometric_415_i4', + 'geometric_415_i6', + 'geometric_415_i7', + 'geometric_415_n4', + 'geometric_415_n6', + 'geometric_415_n7', + 'georgia_pro_i3', + 'georgia_pro_i4', + 'georgia_pro_i6', + 'georgia_pro_i7', + 'georgia_pro_i9', + 'georgia_pro_n3', + 'georgia_pro_n4', + 'georgia_pro_n6', + 'georgia_pro_n7', + 'georgia_pro_n9', + 'gill_sans_nova_i1', + 'gill_sans_nova_i2', + 'gill_sans_nova_i3', + 'gill_sans_nova_i4', + 'gill_sans_nova_i5', + 'gill_sans_nova_i6', + 'gill_sans_nova_i7', + 'gill_sans_nova_n1', + 'gill_sans_nova_n2', + 'gill_sans_nova_n3', + 'gill_sans_nova_n4', + 'gill_sans_nova_n5', + 'gill_sans_nova_n6', + 'gill_sans_nova_n7', + 'gill_sans_nova_n8', + 'gill_sans_nova_n9', + 'glegoo_n4', + 'glegoo_n7', + 'goudy_old_style_i4', + 'goudy_old_style_i7', + 'goudy_old_style_n4', + 'goudy_old_style_n7', + 'goudy_old_style_n8', + 'harmonia_sans_i3', + 'harmonia_sans_i4', + 'harmonia_sans_i6', + 'harmonia_sans_i7', + 'harmonia_sans_i9', + 'harmonia_sans_n3', + 'harmonia_sans_n4', + 'harmonia_sans_n6', + 'harmonia_sans_n7', + 'harmonia_sans_n9', + 'helvetica_n3', + 'helvetica_n4', + 'helvetica_n7', + 'helvetica_n9', + 'helvetica_o3', + 'helvetica_o4', + 'helvetica_o7', + 'helvetica_o9', + 'hope_sans_i1', + 'hope_sans_i2', + 'hope_sans_i3', + 'hope_sans_i4', + 'hope_sans_i6', + 'hope_sans_i7', + 'hope_sans_n1', + 'hope_sans_n2', + 'hope_sans_n3', + 'hope_sans_n4', + 'hope_sans_n6', + 'hope_sans_n7', + 'humanist_521_i2', + 'humanist_521_i4', + 'humanist_521_i7', + 'humanist_521_n2', + 'humanist_521_n4', + 'humanist_521_n7', + 'humanist_521_n8', + 'humanist_521_n9', + 'itc_avant_garde_gothic_n2', + 'itc_avant_garde_gothic_n4', + 'itc_avant_garde_gothic_n5', + 'itc_avant_garde_gothic_n6', + 'itc_avant_garde_gothic_n7', + 'itc_avant_garde_gothic_o2', + 'itc_avant_garde_gothic_o4', + 'itc_avant_garde_gothic_o5', + 'itc_avant_garde_gothic_o6', + 'itc_avant_garde_gothic_o7', + 'itc_benguiat_i4', + 'itc_benguiat_i5', + 'itc_benguiat_i7', + 'itc_benguiat_n4', + 'itc_benguiat_n5', + 'itc_benguiat_n7', + 'itc_berkeley_old_style_i4', + 'itc_berkeley_old_style_i5', + 'itc_berkeley_old_style_i7', + 'itc_berkeley_old_style_i9', + 'itc_berkeley_old_style_n4', + 'itc_berkeley_old_style_n5', + 'itc_berkeley_old_style_n7', + 'itc_berkeley_old_style_n9', + 'itc_bodoni_seventytwo_i4', + 'itc_bodoni_seventytwo_i7', + 'itc_bodoni_seventytwo_n4', + 'itc_bodoni_seventytwo_n7', + 'itc_bodoni_twelve_i4', + 'itc_bodoni_twelve_i7', + 'itc_bodoni_twelve_n4', + 'itc_bodoni_twelve_n7', + 'itc_caslon_no_224_i4', + 'itc_caslon_no_224_i5', + 'itc_caslon_no_224_i7', + 'itc_caslon_no_224_i9', + 'itc_caslon_no_224_n4', + 'itc_caslon_no_224_n5', + 'itc_caslon_no_224_n7', + 'itc_caslon_no_224_n9', + 'itc_charter_i4', + 'itc_charter_i7', + 'itc_charter_i9', + 'itc_charter_n4', + 'itc_charter_n7', + 'itc_charter_n9', + 'itc_cheltenham_i3', + 'itc_cheltenham_i4', + 'itc_cheltenham_i7', + 'itc_cheltenham_i9', + 'itc_cheltenham_n3', + 'itc_cheltenham_n4', + 'itc_cheltenham_n7', + 'itc_cheltenham_n9', + 'itc_clearface_i4', + 'itc_clearface_i7', + 'itc_clearface_i8', + 'itc_clearface_i9', + 'itc_clearface_n4', + 'itc_clearface_n7', + 'itc_clearface_n8', + 'itc_clearface_n9', + 'itc_conduit_i2', + 'itc_conduit_i3', + 'itc_conduit_i4', + 'itc_conduit_i5', + 'itc_conduit_i7', + 'itc_conduit_i8', + 'itc_conduit_i9', + 'itc_conduit_n2', + 'itc_conduit_n3', + 'itc_conduit_n4', + 'itc_conduit_n5', + 'itc_conduit_n7', + 'itc_conduit_n8', + 'itc_conduit_n9', + 'itc_esprit_i4', + 'itc_esprit_i5', + 'itc_esprit_i7', + 'itc_esprit_i9', + 'itc_esprit_n4', + 'itc_esprit_n5', + 'itc_esprit_n7', + 'itc_esprit_n9', + 'itc_founders_caslon_i4', + 'itc_founders_caslon_n4', + 'itc_franklin_gothic_i4', + 'itc_franklin_gothic_i5', + 'itc_franklin_gothic_i7', + 'itc_franklin_gothic_i9', + 'itc_franklin_gothic_n4', + 'itc_franklin_gothic_n5', + 'itc_franklin_gothic_n7', + 'itc_franklin_gothic_n9', + 'itc_galliard_i4', + 'itc_galliard_i7', + 'itc_galliard_i8', + 'itc_galliard_i9', + 'itc_galliard_n4', + 'itc_galliard_n7', + 'itc_galliard_n8', + 'itc_galliard_n9', + 'itc_gamma_i4', + 'itc_gamma_i5', + 'itc_gamma_i7', + 'itc_gamma_i8', + 'itc_gamma_n4', + 'itc_gamma_n5', + 'itc_gamma_n7', + 'itc_gamma_n8', + 'itc_goudy_sans_i4', + 'itc_goudy_sans_i5', + 'itc_goudy_sans_i7', + 'itc_goudy_sans_i9', + 'itc_goudy_sans_n4', + 'itc_goudy_sans_n5', + 'itc_goudy_sans_n7', + 'itc_goudy_sans_n9', + 'itc_johnston_i3', + 'itc_johnston_i5', + 'itc_johnston_i7', + 'itc_johnston_n3', + 'itc_johnston_n5', + 'itc_johnston_n7', + 'itc_mendoza_roman_i4', + 'itc_mendoza_roman_i5', + 'itc_mendoza_roman_i7', + 'itc_mendoza_roman_n4', + 'itc_mendoza_roman_n5', + 'itc_mendoza_roman_n7', + 'itc_modern_no_216_i3', + 'itc_modern_no_216_i5', + 'itc_modern_no_216_i7', + 'itc_modern_no_216_i8', + 'itc_modern_no_216_n3', + 'itc_modern_no_216_n5', + 'itc_modern_no_216_n7', + 'itc_modern_no_216_n8', + 'itc_new_baskerville_i4', + 'itc_new_baskerville_i6', + 'itc_new_baskerville_i7', + 'itc_new_baskerville_i9', + 'itc_new_baskerville_n4', + 'itc_new_baskerville_n6', + 'itc_new_baskerville_n7', + 'itc_new_baskerville_n9', + 'itc_new_esprit_i4', + 'itc_new_esprit_i5', + 'itc_new_esprit_i7', + 'itc_new_esprit_i8', + 'itc_new_esprit_n4', + 'itc_new_esprit_n5', + 'itc_new_esprit_n7', + 'itc_new_esprit_n8', + 'itc_new_veljovic_i3', + 'itc_new_veljovic_i4', + 'itc_new_veljovic_i5', + 'itc_new_veljovic_i7', + 'itc_new_veljovic_i9', + 'itc_new_veljovic_n3', + 'itc_new_veljovic_n4', + 'itc_new_veljovic_n5', + 'itc_new_veljovic_n7', + 'itc_new_veljovic_n9', + 'itc_novarese_i4', + 'itc_novarese_i5', + 'itc_novarese_i7', + 'itc_novarese_n4', + 'itc_novarese_n5', + 'itc_novarese_n7', + 'itc_novarese_n9', + 'itc_officina_sans_i4', + 'itc_officina_sans_i5', + 'itc_officina_sans_i7', + 'itc_officina_sans_i8', + 'itc_officina_sans_i9', + 'itc_officina_sans_n4', + 'itc_officina_sans_n5', + 'itc_officina_sans_n7', + 'itc_officina_sans_n8', + 'itc_officina_sans_n9', + 'itc_officina_serif_i4', + 'itc_officina_serif_i5', + 'itc_officina_serif_i7', + 'itc_officina_serif_i8', + 'itc_officina_serif_i9', + 'itc_officina_serif_n4', + 'itc_officina_serif_n5', + 'itc_officina_serif_n7', + 'itc_officina_serif_n8', + 'itc_officina_serif_n9', + 'itc_stepp_i3', + 'itc_stepp_i5', + 'itc_stepp_i7', + 'itc_stepp_i9', + 'itc_stepp_n3', + 'itc_stepp_n4', + 'itc_stepp_n7', + 'itc_stepp_n9', + 'itc_stone_humanist_i5', + 'itc_stone_humanist_i6', + 'itc_stone_humanist_i7', + 'itc_stone_humanist_n5', + 'itc_stone_humanist_n6', + 'itc_stone_humanist_n7', + 'itc_stone_informal_i4', + 'itc_stone_informal_i6', + 'itc_stone_informal_i7', + 'itc_stone_informal_n4', + 'itc_stone_informal_n6', + 'itc_stone_informal_n7', + 'itc_stone_sans_ii_i3', + 'itc_stone_sans_ii_i4', + 'itc_stone_sans_ii_i5', + 'itc_stone_sans_ii_i6', + 'itc_stone_sans_ii_i7', + 'itc_stone_sans_ii_i8', + 'itc_stone_sans_ii_n3', + 'itc_stone_sans_ii_n4', + 'itc_stone_sans_ii_n5', + 'itc_stone_sans_ii_n6', + 'itc_stone_sans_ii_n7', + 'itc_stone_sans_ii_n8', + 'itc_stone_serif_i4', + 'itc_stone_serif_i6', + 'itc_stone_serif_i7', + 'itc_stone_serif_n4', + 'itc_stone_serif_n6', + 'itc_stone_serif_n7', + 'itc_tapioca_n5', + 'joanna_nova_i1', + 'joanna_nova_i2', + 'joanna_nova_i3', + 'joanna_nova_i4', + 'joanna_nova_i5', + 'joanna_nova_i6', + 'joanna_nova_i7', + 'joanna_nova_i8', + 'joanna_nova_i9', + 'joanna_nova_n1', + 'joanna_nova_n2', + 'joanna_nova_n3', + 'joanna_nova_n4', + 'joanna_nova_n5', + 'joanna_nova_n6', + 'joanna_nova_n7', + 'joanna_nova_n8', + 'joanna_nova_n9', + 'joanna_sans_nova_i1', + 'joanna_sans_nova_i2', + 'joanna_sans_nova_i3', + 'joanna_sans_nova_i4', + 'joanna_sans_nova_i5', + 'joanna_sans_nova_i7', + 'joanna_sans_nova_i8', + 'joanna_sans_nova_i9', + 'joanna_sans_nova_n1', + 'joanna_sans_nova_n2', + 'joanna_sans_nova_n3', + 'joanna_sans_nova_n4', + 'joanna_sans_nova_n5', + 'joanna_sans_nova_n7', + 'joanna_sans_nova_n8', + 'joanna_sans_nova_n9', + 'kairos_i1', + 'kairos_i2', + 'kairos_i3', + 'kairos_i4', + 'kairos_i5', + 'kairos_i7', + 'kairos_i8', + 'kairos_i9', + 'kairos_n1', + 'kairos_n2', + 'kairos_n3', + 'kairos_n4', + 'kairos_n5', + 'kairos_n7', + 'kairos_n8', + 'kairos_n9', + 'laurentian_i4', + 'laurentian_i6', + 'laurentian_n4', + 'laurentian_n6', + 'laurentian_n7', + 'libelle_n4', + 'linotype_didot_i4', + 'linotype_didot_i7', + 'linotype_didot_n4', + 'linotype_didot_n7', + 'linotype_gianotten_i3', + 'linotype_gianotten_i4', + 'linotype_gianotten_i5', + 'linotype_gianotten_i7', + 'linotype_gianotten_i8', + 'linotype_gianotten_n3', + 'linotype_gianotten_n4', + 'linotype_gianotten_n5', + 'linotype_gianotten_n7', + 'linotype_gianotten_n8', + 'linotype_gianotten_n9', + 'linotype_really_i5', + 'linotype_really_i6', + 'linotype_really_n5', + 'linotype_really_n6', + 'linotype_syntax_serif_i3', + 'linotype_syntax_serif_i4', + 'linotype_syntax_serif_i5', + 'linotype_syntax_serif_i7', + 'linotype_syntax_serif_i8', + 'linotype_syntax_serif_i9', + 'linotype_syntax_serif_n3', + 'linotype_syntax_serif_n4', + 'linotype_syntax_serif_n5', + 'linotype_syntax_serif_n7', + 'linotype_syntax_serif_n8', + 'linotype_syntax_serif_n9', + 'lobster_n4', + 'lucia_n4', + 'luthersche_fraktur_n4', + 'madera_i1', + 'madera_i2', + 'madera_i3', + 'madera_i4', + 'madera_i5', + 'madera_i6', + 'madera_i7', + 'madera_i8', + 'madera_n1', + 'madera_n2', + 'madera_n3', + 'madera_n4', + 'madera_n5', + 'madera_n6', + 'madera_n7', + 'madera_n8', + 'malabar_i4', + 'malabar_i7', + 'malabar_i9', + 'malabar_n4', + 'malabar_n7', + 'malabar_n9', + 'mariposa_sans_i4', + 'mariposa_sans_n4', + 'mariposa_sans_n5', + 'mariposa_sans_n7', + 'mariposa_sans_n9', + 'megrim_n4', + 'melior_i4', + 'melior_i7', + 'melior_n4', + 'melior_n7', + 'memphis_i3', + 'memphis_i5', + 'memphis_i7', + 'memphis_n3', + 'memphis_n5', + 'memphis_n7', + 'memphis_n8', + 'memphis_soft_rounded_n5', + 'memphis_soft_rounded_n7', + 'memphis_soft_rounded_n8', + 'mentor_sans_i3', + 'mentor_sans_i4', + 'mentor_sans_i7', + 'mentor_sans_i9', + 'mentor_sans_n3', + 'mentor_sans_n4', + 'mentor_sans_n7', + 'mentor_sans_n9', + 'metro_nova_i2', + 'metro_nova_i3', + 'metro_nova_i4', + 'metro_nova_i5', + 'metro_nova_i7', + 'metro_nova_i8', + 'metro_nova_i9', + 'metro_nova_n2', + 'metro_nova_n3', + 'metro_nova_n4', + 'metro_nova_n5', + 'metro_nova_n7', + 'metro_nova_n8', + 'metro_nova_n9', + 'modern_no_20_i4', + 'modern_no_20_n4', + 'monotype_baskerville_i4', + 'monotype_baskerville_i6', + 'monotype_baskerville_i7', + 'monotype_baskerville_n4', + 'monotype_baskerville_n6', + 'monotype_baskerville_n7', + 'monotype_bodoni_i4', + 'monotype_bodoni_i5', + 'monotype_bodoni_i7', + 'monotype_bodoni_i8', + 'monotype_bodoni_i9', + 'monotype_bodoni_n4', + 'monotype_bodoni_n5', + 'monotype_bodoni_n7', + 'monotype_bodoni_n8', + 'monotype_bodoni_n9', + 'monotype_century_old_style_i5', + 'monotype_century_old_style_i7', + 'monotype_century_old_style_n5', + 'monotype_century_old_style_n7', + 'monotype_goudy_i4', + 'monotype_goudy_i7', + 'monotype_goudy_modern_i4', + 'monotype_goudy_modern_i7', + 'monotype_goudy_modern_n4', + 'monotype_goudy_modern_n7', + 'monotype_goudy_n4', + 'monotype_goudy_n7', + 'monotype_goudy_n8', + 'monotype_italian_old_style_i4', + 'monotype_italian_old_style_i7', + 'monotype_italian_old_style_n4', + 'monotype_italian_old_style_n7', + 'monotype_new_clarendon_n5', + 'monotype_new_clarendon_n7', + 'monotype_news_gothic_i4', + 'monotype_news_gothic_i7', + 'monotype_news_gothic_n4', + 'monotype_news_gothic_n7', + 'monotype_sabon_i4', + 'monotype_sabon_i6', + 'monotype_sabon_n4', + 'monotype_sabon_n6', + 'mouse_memoirs_n4', + 'mundo_sans_i2', + 'mundo_sans_i3', + 'mundo_sans_i4', + 'mundo_sans_i5', + 'mundo_sans_i7', + 'mundo_sans_i8', + 'mundo_sans_i9', + 'mundo_sans_n2', + 'mundo_sans_n3', + 'mundo_sans_n4', + 'mundo_sans_n5', + 'mundo_sans_n7', + 'mundo_sans_n8', + 'mundo_sans_n9', + 'neo_sans_i3', + 'neo_sans_i4', + 'neo_sans_i5', + 'neo_sans_i7', + 'neo_sans_i8', + 'neo_sans_i9', + 'neo_sans_n3', + 'neo_sans_n4', + 'neo_sans_n5', + 'neo_sans_n7', + 'neo_sans_n8', + 'neo_sans_n9', + 'neue_aachen_i1', + 'neue_aachen_i2', + 'neue_aachen_i3', + 'neue_aachen_i4', + 'neue_aachen_i5', + 'neue_aachen_i6', + 'neue_aachen_i7', + 'neue_aachen_i8', + 'neue_aachen_i9', + 'neue_aachen_n1', + 'neue_aachen_n2', + 'neue_aachen_n3', + 'neue_aachen_n4', + 'neue_aachen_n5', + 'neue_aachen_n6', + 'neue_aachen_n7', + 'neue_aachen_n8', + 'neue_aachen_n9', + 'neue_frutiger_1450_i3', + 'neue_frutiger_1450_i4', + 'neue_frutiger_1450_i6', + 'neue_frutiger_1450_i7', + 'neue_frutiger_1450_n3', + 'neue_frutiger_1450_n4', + 'neue_frutiger_1450_n6', + 'neue_frutiger_1450_n7', + 'neue_haas_unica_i1', + 'neue_haas_unica_i2', + 'neue_haas_unica_i3', + 'neue_haas_unica_i4', + 'neue_haas_unica_i5', + 'neue_haas_unica_i6', + 'neue_haas_unica_i7', + 'neue_haas_unica_i8', + 'neue_haas_unica_i9', + 'neue_haas_unica_n1', + 'neue_haas_unica_n2', + 'neue_haas_unica_n3', + 'neue_haas_unica_n4', + 'neue_haas_unica_n5', + 'neue_haas_unica_n6', + 'neue_haas_unica_n7', + 'neue_haas_unica_n8', + 'neue_haas_unica_n9', + 'neue_plak_i2', + 'neue_plak_i3', + 'neue_plak_i4', + 'neue_plak_i6', + 'neue_plak_i7', + 'neue_plak_i9', + 'neue_plak_n2', + 'neue_plak_n3', + 'neue_plak_n4', + 'neue_plak_n6', + 'neue_plak_n7', + 'neue_plak_n9', + 'neue_swift_i3', + 'neue_swift_i4', + 'neue_swift_i5', + 'neue_swift_i6', + 'neue_swift_i7', + 'neue_swift_n3', + 'neue_swift_n4', + 'neue_swift_n5', + 'neue_swift_n6', + 'neue_swift_n7', + 'neuzeit_office_i4', + 'neuzeit_office_i7', + 'neuzeit_office_n4', + 'neuzeit_office_n7', + 'neuzeit_office_soft_rounded_n4', + 'neuzeit_office_soft_rounded_n7', + 'neuzeit_s_n4', + 'neuzeit_s_n9', + 'new_century_schoolbook_i4', + 'new_century_schoolbook_i7', + 'new_century_schoolbook_n4', + 'new_century_schoolbook_n7', + 'news_702_i4', + 'news_702_i7', + 'news_702_n4', + 'news_702_n7', + 'news_705_i4', + 'news_705_i7', + 'news_705_n4', + 'news_705_n7', + 'news_cycle_n4', + 'news_cycle_n7', + 'news_gothic_no_2_i2', + 'news_gothic_no_2_i3', + 'news_gothic_no_2_i4', + 'news_gothic_no_2_i5', + 'news_gothic_no_2_i7', + 'news_gothic_no_2_i8', + 'news_gothic_no_2_n2', + 'news_gothic_no_2_n3', + 'news_gothic_no_2_n4', + 'news_gothic_no_2_n5', + 'news_gothic_no_2_n7', + 'news_gothic_no_2_n8', + 'news_plantin_i4', + 'news_plantin_i7', + 'news_plantin_n4', + 'news_plantin_n7', + 'noticia_text_i4', + 'noticia_text_i7', + 'noticia_text_n4', + 'noticia_text_n7', + 'optima_nova_i3', + 'optima_nova_i4', + 'optima_nova_i5', + 'optima_nova_i6', + 'optima_nova_i7', + 'optima_nova_i8', + 'optima_nova_i9', + 'optima_nova_n3', + 'optima_nova_n4', + 'optima_nova_n5', + 'optima_nova_n6', + 'optima_nova_n7', + 'optima_nova_n8', + 'optima_nova_n9', + 'oxygen_n3', + 'oxygen_n4', + 'oxygen_n7', + 'parma_i4', + 'parma_n4', + 'parma_n7', + 'perpetua_i4', + 'perpetua_i7', + 'perpetua_n4', + 'perpetua_n7', + 'plantin_i3', + 'plantin_i4', + 'plantin_i6', + 'plantin_i7', + 'plantin_n3', + 'plantin_n4', + 'plantin_n6', + 'plantin_n7', + 'pmn_caecilia_i3', + 'pmn_caecilia_i4', + 'pmn_caecilia_i7', + 'pmn_caecilia_i9', + 'pmn_caecilia_n3', + 'pmn_caecilia_n4', + 'pmn_caecilia_n7', + 'pmn_caecilia_n9', + 'prata_n4', + 'pt_mono_n4', + 'pt_sans_narrow_n4', + 'pt_sans_narrow_n7', + 'quattrocento_n4', + 'quattrocento_n7', + 'quire_sans_i1', + 'quire_sans_i2', + 'quire_sans_i3', + 'quire_sans_i4', + 'quire_sans_i5', + 'quire_sans_i6', + 'quire_sans_i7', + 'quire_sans_i8', + 'quire_sans_i9', + 'quire_sans_n1', + 'quire_sans_n2', + 'quire_sans_n3', + 'quire_sans_n4', + 'quire_sans_n5', + 'quire_sans_n6', + 'quire_sans_n7', + 'quire_sans_n8', + 'quire_sans_n9', + 'really_no_2_i3', + 'really_no_2_i4', + 'really_no_2_i5', + 'really_no_2_i6', + 'really_no_2_i7', + 'really_no_2_i8', + 'really_no_2_i9', + 'really_no_2_n3', + 'really_no_2_n4', + 'really_no_2_n5', + 'really_no_2_n6', + 'really_no_2_n7', + 'really_no_2_n8', + 'really_no_2_n9', + 'righteous_n4', + 'rockwell_i4', + 'rockwell_i7', + 'rockwell_n4', + 'rockwell_n7', + 'rockwell_n8', + 'sabon_next_i4', + 'sabon_next_i6', + 'sabon_next_i7', + 'sabon_next_i8', + 'sabon_next_i9', + 'sabon_next_n4', + 'sabon_next_n6', + 'sabon_next_n7', + 'sabon_next_n8', + 'sabon_next_n9', + 'sackers_square_gothic_n4', + 'sagrantino_n4', + 'scene_i3', + 'scene_i4', + 'scene_i5', + 'scene_i7', + 'scene_i8', + 'scene_i9', + 'scene_n3', + 'scene_n4', + 'scene_n5', + 'scene_n7', + 'scene_n8', + 'scene_n9', + 'scherzo_i4', + 'scherzo_i6', + 'scherzo_i7', + 'scherzo_n4', + 'scherzo_n6', + 'scherzo_n7', + 'slabo_13px_n4', + 'slate_i2', + 'slate_i3', + 'slate_i4', + 'slate_i5', + 'slate_i7', + 'slate_i9', + 'slate_n2', + 'slate_n3', + 'slate_n4', + 'slate_n5', + 'slate_n7', + 'slate_n9', + 'soho_gothic_i2', + 'soho_gothic_i3', + 'soho_gothic_i4', + 'soho_gothic_i5', + 'soho_gothic_i7', + 'soho_gothic_i8', + 'soho_gothic_i9', + 'soho_gothic_n2', + 'soho_gothic_n3', + 'soho_gothic_n4', + 'soho_gothic_n5', + 'soho_gothic_n7', + 'soho_gothic_n8', + 'soho_gothic_n9', + 'soho_i1', + 'soho_i2', + 'soho_i3', + 'soho_i4', + 'soho_i5', + 'soho_i6', + 'soho_i7', + 'soho_i8', + 'soho_i9', + 'soho_n1', + 'soho_n2', + 'soho_n3', + 'soho_n4', + 'soho_n5', + 'soho_n6', + 'soho_n7', + 'soho_n8', + 'soho_n9', + 'stempel_schneidler_i3', + 'stempel_schneidler_i4', + 'stempel_schneidler_i5', + 'stempel_schneidler_i7', + 'stempel_schneidler_i8', + 'stempel_schneidler_n3', + 'stempel_schneidler_n4', + 'stempel_schneidler_n5', + 'stempel_schneidler_n7', + 'stempel_schneidler_n8', + 'swiss_721_i1', + 'swiss_721_i2', + 'swiss_721_i4', + 'swiss_721_i5', + 'swiss_721_i7', + 'swiss_721_i8', + 'swiss_721_i9', + 'swiss_721_n1', + 'swiss_721_n2', + 'swiss_721_n4', + 'swiss_721_n5', + 'swiss_721_n7', + 'swiss_721_n8', + 'swiss_721_n9', + 'swiss_721_rounded_n7', + 'swiss_721_rounded_n9', + 'tiemann_n3', + 'tiemann_n4', + 'tinos_i4', + 'tinos_i7', + 'tinos_n4', + 'tinos_n7', + 'trade_gothic_n3', + 'trade_gothic_n4', + 'trade_gothic_n7', + 'trade_gothic_next_i3', + 'trade_gothic_next_i4', + 'trade_gothic_next_i7', + 'trade_gothic_next_i8', + 'trade_gothic_next_n3', + 'trade_gothic_next_n4', + 'trade_gothic_next_n7', + 'trade_gothic_next_n8', + 'trade_gothic_o3', + 'trade_gothic_o4', + 'trade_gothic_o7', + 'twentieth_century_i3', + 'twentieth_century_i5', + 'twentieth_century_i7', + 'twentieth_century_i8', + 'twentieth_century_i9', + 'twentieth_century_n3', + 'twentieth_century_n4', + 'twentieth_century_n5', + 'twentieth_century_n6', + 'twentieth_century_n7', + 'twentieth_century_n8', + 'twentieth_century_n9', + 'univers_next_i1', + 'univers_next_i2', + 'univers_next_i3', + 'univers_next_i4', + 'univers_next_i5', + 'univers_next_i6', + 'univers_next_i7', + 'univers_next_i8', + 'univers_next_i9', + 'univers_next_n1', + 'univers_next_n2', + 'univers_next_n3', + 'univers_next_n4', + 'univers_next_n5', + 'univers_next_n6', + 'univers_next_n7', + 'univers_next_n8', + 'univers_next_n9', + 'univers_next_typewriter_i4', + 'univers_next_typewriter_i7', + 'univers_next_typewriter_n4', + 'univers_next_typewriter_n7', + 'unna_i4', + 'unna_i7', + 'unna_n4', + 'unna_n7', + 'vala_n4', + 'varela_n4', + 'varela_round_n4', + 'verdana_pro_i3', + 'verdana_pro_i4', + 'verdana_pro_i6', + 'verdana_pro_i7', + 'verdana_pro_i9', + 'verdana_pro_n3', + 'verdana_pro_n4', + 'verdana_pro_n6', + 'verdana_pro_n7', + 'verdana_pro_n9', + 'vidaloka_n4', + 'volkhov_i4', + 'volkhov_i7', + 'volkhov_n4', + 'volkhov_n7', + 'vollkorn_i4', + 'vollkorn_i6', + 'vollkorn_i7', + 'vollkorn_i9', + 'vollkorn_n4', + 'vollkorn_n6', + 'vollkorn_n7', + 'vollkorn_n9', + 'waza_n4', + 'wola_n4', + 'ysobel_i3', + 'ysobel_i4', + 'ysobel_i6', + 'ysobel_i7', + 'ysobel_n3', + 'ysobel_n4', + 'ysobel_n6', + 'ysobel_n7', + 'zurich_extended_n4', + 'zurich_extended_n7', + 'zurich_extended_n8', + 'zurich_extended_n9', + 'zurich_i3', + 'zurich_i4', + 'zurich_i7', + 'zurich_i8', + 'zurich_n3', + 'zurich_n4', + 'zurich_n7', + 'zurich_n8', + 'zurich_n9', +]); diff --git a/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts b/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts new file mode 100644 index 000000000..fa8b10f18 --- /dev/null +++ b/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.spec.ts @@ -0,0 +1,613 @@ +import { expect, describe, it } from 'vitest'; +import { highlightedOffenses, runLiquidCheck, check, MockTheme } from '../../test'; +import { DeprecatedFontsOnSectionsAndBlocks } from './index'; + +const DEFAULT_FILE_NAME = 'sections/file.liquid'; + +describe('Module: DeprecatedFonts', () => { + it('reports no warning when the setting has a non-deprecated font as default value', async () => { + const sourceCode = ` + {% schema %} + { + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font", + "default": "alegreya_n4" + } + ] + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(0); + }); + + it('reports a warning when setting has a deprecated font as default value', async () => { + const sourceCode = ` + {% schema %} + { + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font", + "default": "helvetica_n4" + } + ] + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + + const highlights = highlightedOffenses({ [DEFAULT_FILE_NAME]: sourceCode }, offenses); + expect(highlights).toHaveLength(1); + }); + + it('reports a warning when multiple settings have a deprecated font as default value', async () => { + const sourceCode = ` + {% schema %} + { + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font", + "default": "helvetica_n4" + }, + { + "type": "font_picker", + "id": "footer_font", + "label": "Footer font", + "default": "helvetica_n4" + } + ] + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(2); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + expect(offenses[1].message).toEqual( + "setting 'footer_font' is using deprecated font 'helvetica_n4'", + ); + }); + + it('does not report a warning when the local block setting has no deprecated font', async () => { + const sourceCode = ` + {% schema %} + { + "blocks": [{ + "type": "my-local-block", + "name": "My Local Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font", + "default": "alegreya_n4" + } + ] + }] + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(0); + }); + + it('reports a warning when the local block setting has a deprecated font', async () => { + const sourceCode = ` + {% schema %} + { + "blocks": [{ + "type": "my-local-block", + "name": "My Local Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font", + "default": "helvetica_n4" + } + ] + }] + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + + const highlights = highlightedOffenses({ [DEFAULT_FILE_NAME]: sourceCode }, offenses); + expect(highlights).toHaveLength(1); + }); + + it('reports no warning when the preset settings do not use deprecated fonts', async () => { + const sourceCode = ` + {% schema %} + { + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font", + "default": "alegreya_n4" + } + ], + "presets": [ + { + "name": "Preset 1", + "settings": { + "heading_font": "alegreya_n4" + } + } + ] + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(0); + }); + + it('reports a warning when the preset setting has a deprecated font as default value', async () => { + const sourceCode = ` + {% schema %} + { + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font", + "default": "alegreya_n4" + } + ], + "presets": [ + { + "name": "Preset 1", + "settings": { + "heading_font": "helvetica_n4" + } + } + ] + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + + const highlights = highlightedOffenses({ [DEFAULT_FILE_NAME]: sourceCode }, offenses); + expect(highlights).toHaveLength(1); + }); + + it('reports no warning when the preset block setting has no deprecated fonts (blocks as a hash)', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "presets": [ + { + "name": "Preset 1", + "blocks": { + "text-1": { + "type": "text", + "settings": { + "heading_font": "alegreya_n4" + } + } + } + } + ] + } + {% endschema %}`, + 'blocks/text.liquid': ` + {% schema %} + { + "name": "Text Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(0); + }); + + it('reports a warning when the preset block setting has a deprecated font (blocks as a hash)', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "presets": [ + { + "name": "Preset 1", + "blocks": { + "text-1": { + "type": "text", + "settings": { + "heading_font": "helvetica_n4" + } + } + } + } + ] + } + {% endschema %}`, + 'blocks/text.liquid': ` + {% schema %} + { + "name": "Text Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + }); + + it('reports a warning when the preset block setting has a deprecated font in a nested block (blocks as a hash)', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "presets": [ + { + "name": "Preset 1", + "blocks": { + "text-1": { + "type": "text", + "blocks": { + "text-2": { + "type": "text", + "settings": { "heading_font": "helvetica_n4" } + } + } + } + } + } + ] + } + {% endschema %}`, + 'blocks/text.liquid': ` + {% schema %} + { + "name": "Text Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + }); + + it('reports no warning when the preset block setting has no deprecated fonts (blocks as an array)', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "presets": [ + { + "name": "Preset 1", + "blocks": [ + { + "type": "text", + "settings": { "heading_font": "alegreya_n4" } + } + ] + } + ] + } + {% endschema %}`, + 'blocks/text.liquid': ` + {% schema %} + { + "name": "Text Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(0); + }); + + it('reports a warning when the preset block setting has a deprecated font (blocks as an array)', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "presets": [ + { + "name": "Preset 1", + "blocks": [ + { + "type": "text", + "settings": { "heading_font": "helvetica_n4" } + } + ] + } + ] + } + {% endschema %}`, + 'blocks/text.liquid': ` + {% schema %} + { + "name": "Text Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + }); + + it('reports a warning when the preset nested block setting has a deprecated fonts (blocks as an array)', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "presets": [ + { + "name": "Preset 1", + "blocks": [ + { + "type": "text", + "blocks": [ + { + "type": "text", + "settings": { "heading_font": "helvetica_n4" } + } + ] + } + ] + } + ] + } + {% endschema %}`, + 'blocks/text.liquid': ` + {% schema %} + { + "name": "Text Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + }); + + it('reports no warning when the section default setting has no deprecated fonts', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + "defaults": { + "settings": { + "heading_font": "alegreya_n4" + } + } + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(0); + }); + + it('reports a warning when the section default setting has a deprecated font', async () => { + const sourceCode = ` + {% schema %} + { + "name": "Section 1", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + "default": { + "settings": { + "heading_font": "helvetica_n4" + } + } + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + + const highlights = highlightedOffenses({ [DEFAULT_FILE_NAME]: sourceCode }, offenses); + expect(highlights).toHaveLength(1); + }); + + it('reports no warning when the section default block setting has no deprecated fonts', async () => { + const theme: MockTheme = { + 'sections/section-1.liquid': ` + {% schema %} + { + "name": "Section 1", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ], + "blocks": [ + { + "type": "text" + } + ], + "defaults": { + "blocks": { + "type": "text", + "settings": { + "heading_font": "alegreya_n4" + } + } + } + } + {% endschema %}`, + }; + + const offenses = await check(theme, [DeprecatedFontsOnSectionsAndBlocks]); + expect(offenses).toHaveLength(0); + }); + + it('reports a warning when the section default block setting has a deprecated font', async () => { + const sourceCode = ` + {% schema %} + { + "name": "Section 1", + "blocks": [ + { + "type": "text", + "name": "Local Text Block", + "settings": [ + { + "type": "font_picker", + "id": "heading_font", + "label": "Heading font" + } + ] + } + ], + "default": { + "blocks": [{ + "type": "text", + "settings": { + "heading_font": "helvetica_n4" + } + }] + } + } + {% endschema %}`; + + const offenses = await runLiquidCheck( + DeprecatedFontsOnSectionsAndBlocks, + sourceCode, + DEFAULT_FILE_NAME, + ); + expect(offenses).toHaveLength(1); + expect(offenses[0].message).toEqual( + "setting 'heading_font' is using deprecated font 'helvetica_n4'", + ); + + const highlights = highlightedOffenses({ [DEFAULT_FILE_NAME]: sourceCode }, offenses); + expect(highlights).toHaveLength(1); + }); +}); diff --git a/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts b/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts new file mode 100644 index 000000000..0323653dd --- /dev/null +++ b/packages/theme-check-common/src/checks/deprecated-fonts-on-sections-and-blocks/index.ts @@ -0,0 +1,284 @@ +import { getSchema } from '../../to-schema'; +import { + JSONNode, + LiquidCheckDefinition, + Section, + Severity, + Setting, + Preset, + SourceCodeType, + ThemeBlock, + Context, + ArrayNode, +} from '../../types'; +import { getLocEnd, getLocStart, nodeAtPath } from '../../json'; +import { DEPRECATED_FONT_HANDLES } from './deprecated-fonts-data'; + +export const DeprecatedFontsOnSectionsAndBlocks: LiquidCheckDefinition = { + meta: { + code: 'DeprecatedFontsOnSectionsAndBlocks', + name: 'Check for deprecated fonts in section and block schema settings values', + docs: { + description: 'Warns on deprecated fonts in section and block schema settings values.', + recommended: true, + url: 'https://shopify.dev/docs/themes/tools/theme-check/checks/deprecated-fonts-on-sections-and-blocks', + }, + type: SourceCodeType.LiquidHtml, + severity: Severity.WARNING, + schema: {}, + targets: [], + }, + + create(context) { + return { + async LiquidRawTag(node) { + if (node.name !== 'schema' || node.body.kind !== 'json') { + return; + } + + const schema = await getSchema(context); + const { validSchema, ast } = schema ?? {}; + if (!validSchema || validSchema instanceof Error) return; + if (!ast || ast instanceof Error) return; + + const offset = node.blockStartPosition.end; + + // 1st: check schema settings for deprecated fonts + checkSchemaSettingsForDeprecatedFonts(validSchema, offset, ast, context); + + // 2nd: check local blocks settings for deprecated fonts + checkLocalBlocksSettingsForDeprecatedFonts(validSchema, offset, ast, context); + + // 3rd: check preset settings for deprecated fonts + await checkPresetsForDeprecatedFonts(validSchema, offset, ast, context); + + // 4th: check schema default (sections only) for deprecated fonts + if ('default' in validSchema) { + await checkSchemaDefaultForDeprecatedFonts( + validSchema as Section.Schema, + offset, + ast, + context, + ); + } + }, + }; + }, +}; + +function checkSchemaSettingsForDeprecatedFonts( + schema: ThemeBlock.Schema | Section.Schema, + offset: number, + ast: JSONNode, + context: Context, +) { + const settings = schema.settings; + if (!settings) return; + + checkSettingsForDeprecatedFonts(settings, offset, ast, ['settings'], context); +} + +function checkSettingsForDeprecatedFonts( + settings: Setting.Any[], + offset: number, + ast: JSONNode, + warningAstPath: string[], + context: Context, +) { + settings.forEach((setting, index) => { + if ( + setting.type === 'font_picker' && + setting.default && + DEPRECATED_FONT_HANDLES.has(setting.default) + ) { + const currentPath = warningAstPath.concat([String(index), 'default']); + reportWarning( + context, + offset, + ast as JSONNode, + currentPath, + `setting '${setting.id}' is using deprecated font '${setting.default}'`, + ); + } + }); +} + +function checkLocalBlocksSettingsForDeprecatedFonts( + schema: ThemeBlock.Schema | Section.Schema, + offset: number, + ast: JSONNode, + context: Context, +) { + const blocks = schema.blocks; + if (!blocks) return; + + blocks.forEach((block, index) => { + if ('settings' in block && block.settings) { + checkSettingsForDeprecatedFonts( + block.settings as Setting.Any[], + offset, + ast, + ['blocks', String(index), 'settings'], + context, + ); + } + }); +} + +async function checkPresetsForDeprecatedFonts( + schema: ThemeBlock.Schema | Section.Schema, + offset: number, + ast: JSONNode, + context: Context, +) { + const presets = schema.presets; + if (!presets) return; + + for (const [preset_index, preset] of presets.entries()) { + const warningAstPath = ['presets', String(preset_index)]; + await checkSettingsAndBlocksForDeprecatedFonts( + preset.settings ?? {}, + 'blocks' in preset ? preset.blocks : undefined, + schema, + offset, + ast, + warningAstPath, + context, + ); + } +} + +async function checkSettingsAndBlocksForDeprecatedFonts( + settings: Setting.Values, + blocks: + | Preset.PresetBlockHash + | Preset.PresetBlockForArray[] + | Section.DefaultBlock[] + | undefined, + schema: ThemeBlock.Schema | Section.Schema, + offset: number, + ast: JSONNode, + warningAstPath: string[], + context: Context, +) { + // check settings for deprecated fonts + if (settings && typeof settings === 'object') { + Object.entries(settings).forEach(([settingKey, settingValue]) => { + if ( + isFontPickerType(schema.settings ?? [], settingKey) && + DEPRECATED_FONT_HANDLES.has(settingValue as string) + ) { + const currentPath = warningAstPath.concat(['settings', settingKey]); + reportWarning( + context, + offset, + ast, + currentPath, + `setting '${settingKey}' is using deprecated font '${settingValue}'`, + ); + } + }); + } + + // check blocks for deprecated fonts + if (blocks) { + await checkBlocksForDeprecatedFonts(blocks, schema, offset, ast, context, warningAstPath); + } +} + +async function checkBlocksForDeprecatedFonts( + blocks: Preset.PresetBlockHash | Preset.PresetBlockForArray[] | Section.DefaultBlock[], + schema: ThemeBlock.Schema | Section.Schema, + offset: number, + ast: JSONNode, + context: Context, + nodePath: string[], +) { + const iterator = Array.isArray(blocks) ? blocks.entries() : Object.entries(blocks!); + + for (const [keyOrIndex, block] of iterator) { + const currentPath = nodePath.concat(['blocks', String(keyOrIndex)]); + + // we'll need the schema to verify that the setting is a font_picker type + // local blocks don't have a schema coming from the another theme file, we need to get it from the schema of the section + // look in the schema blocks for the block type, if this block has a name, it's a local block, otherwise, it's a theme block + let validSchema = null; + + schema.blocks?.forEach((schemaBlock) => { + if (schemaBlock.type === block.type && 'name' in schemaBlock) { + validSchema = schemaBlock; + } + }); + + if (!validSchema) { + const blockSchema = await context.getBlockSchema?.(block.type); + if (!blockSchema || blockSchema instanceof Error) continue; + validSchema = blockSchema.validSchema; + if (!validSchema || validSchema instanceof Error) continue; + } + + // block_value is the hash which can have settings, blocks, etc. + for (const [settingKey, settingValue] of Object.entries(block.settings ?? {})) { + if (settingValue && DEPRECATED_FONT_HANDLES.has(settingValue as string)) { + // Check if the setting is a font_picker + const isFontPickerSetting = isFontPickerType(validSchema.settings ?? [], settingKey); + if (isFontPickerSetting) { + reportWarning( + context, + offset, + ast, + currentPath.concat(['settings', settingKey]), + `setting '${settingKey}' is using deprecated font '${settingValue}'`, + ); + } + } + } + + if ('blocks' in block && block.blocks) { + await checkBlocksForDeprecatedFonts(block.blocks, schema, offset, ast, context, currentPath); + } + } +} + +async function checkSchemaDefaultForDeprecatedFonts( + schema: Section.Schema, + offset: number, + ast: JSONNode, + context: Context, +) { + const defaultValues = schema.default; + if (!defaultValues || typeof defaultValues !== 'object') return; + + const warningAstPath = ['default']; + await checkSettingsAndBlocksForDeprecatedFonts( + defaultValues.settings ?? {}, + 'blocks' in defaultValues ? defaultValues.blocks : undefined, + schema, + offset, + ast, + warningAstPath, + context, + ); +} + +function isFontPickerType(settings: Setting.Any[], settingKey: string) { + return settings.some((setting) => setting.id === settingKey && setting.type === 'font_picker'); +} + +function reportWarning( + context: Context, + offset: number, + ast: JSONNode, + ast_path: string[], + message: string, + fullHighlight: boolean = true, +) { + const node = nodeAtPath(ast, ast_path)! as ArrayNode; + const startIndex = fullHighlight ? offset + getLocStart(node) : offset + getLocEnd(node) - 1; // start to finish of the node or last char of the node + const endIndex = offset + getLocEnd(node); + context.report({ + message: message, + startIndex, + endIndex, + }); +} diff --git a/packages/theme-check-common/src/checks/index.ts b/packages/theme-check-common/src/checks/index.ts index 141840584..3697351cd 100644 --- a/packages/theme-check-common/src/checks/index.ts +++ b/packages/theme-check-common/src/checks/index.ts @@ -13,6 +13,7 @@ import { ContentForHeaderModification } from './content-for-header-modification' import { DeprecateBgsizes } from './deprecate-bgsizes'; import { DeprecateLazysizes } from './deprecate-lazysizes'; import { DeprecatedFilter } from './deprecated-filter'; +import { DeprecatedFontsOnSectionsAndBlocks } from './deprecated-fonts-on-sections-and-blocks'; import { DeprecatedTag } from './deprecated-tag'; import { DuplicateRenderSnippetArguments } from './duplicate-render-snippet-arguments'; import { DuplicateContentForArguments } from './duplicate-content-for-arguments'; @@ -78,6 +79,7 @@ export const allChecks: (LiquidCheckDefinition | JSONCheckDefinition)[] = [ DeprecateBgsizes, DeprecateLazysizes, DeprecatedFilter, + DeprecatedFontsOnSectionsAndBlocks, DeprecatedTag, DuplicateContentForArguments, DuplicateRenderSnippetArguments, diff --git a/packages/theme-check-common/src/types/schemas/section.ts b/packages/theme-check-common/src/types/schemas/section.ts index 54f00d392..b1625283f 100644 --- a/packages/theme-check-common/src/types/schemas/section.ts +++ b/packages/theme-check-common/src/types/schemas/section.ts @@ -41,13 +41,15 @@ export declare namespace Section { settings?: Setting.Any[]; }; + export type DefaultBlock = { + type: string; + settings?: Record; + }; + // Default section configuration (kind of like presets) export interface Default { settings?: Record; - blocks?: Array<{ - type: string; - settings?: Record; - }>; + blocks?: Array; } // Section toggle interface diff --git a/packages/theme-check-node/configs/all.yml b/packages/theme-check-node/configs/all.yml index d7229c622..940c35667 100644 --- a/packages/theme-check-node/configs/all.yml +++ b/packages/theme-check-node/configs/all.yml @@ -49,6 +49,9 @@ DeprecateLazysizes: DeprecatedFilter: enabled: true severity: 1 +DeprecatedFontsOnSectionsAndBlocks: + enabled: true + severity: 1 DeprecatedTag: enabled: true severity: 1 diff --git a/packages/theme-check-node/configs/recommended.yml b/packages/theme-check-node/configs/recommended.yml index 5ede6dbda..0ea416cb9 100644 --- a/packages/theme-check-node/configs/recommended.yml +++ b/packages/theme-check-node/configs/recommended.yml @@ -27,6 +27,9 @@ DeprecateLazysizes: DeprecatedFilter: enabled: true severity: 1 +DeprecatedFontsOnSectionsAndBlocks: + enabled: true + severity: 1 DeprecatedTag: enabled: true severity: 1