diff --git a/1020038/classmap.json b/1020038/classmap.json deleted file mode 100644 index 14b7560..0000000 --- a/1020038/classmap.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "main": { - "playbar": { - "buttons": { - "button": { - "wrapper": "KAZD28usA1vPz5GVpm63", - "wrapper__active": "RK45o6dbvO1mb0wQtSwq", - "wrapper__indicator": "EHxL6K_6WWDlTCZP6x5w" - } - } - }, - "topbar": { - "left": { - "button": { - "icon": { - "wrapper": "IYDlXmBmmUKHveMzIPCF" - }, - "wrapper": "ql0zZd7giPXSnPg75NR0" - }, - "button_t": { - "wrapper": "rBX1EWVZ2EaPwP4y1Gkd" - } - }, - "right": { - "button": { - "wrapper": "WtC1lGbmQRplD6JBhNFU" - }, - "button_t": { - "wrapper": "OomFKn3bsxs5JfNUoWhz" - } - } - } - } -} diff --git a/1020040/classmap.json b/1020040/classmap.json deleted file mode 100644 index cdde094..0000000 --- a/1020040/classmap.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "context_menu": { - "menu_item": "rQ6LXqVlEOGZdGIG0LgP" - }, - "main": { - "navbar": { - "link": { - "container": "hNvCMxbfz7HwgzLjt3IZ", - "container__active": "DzWw3g4E_66wu9ktqn36", - "wrapper": "KAcp7QFuEYSouAsuC5i_" - } - }, - "playbar": { - "buttons": { - "button": { - "wrapper": "KAZD28usA1vPz5GVpm63", - "wrapper__active": "RK45o6dbvO1mb0wQtSwq", - "wrapper__indicator": "EHxL6K_6WWDlTCZP6x5w" - } - } - }, - "topbar": { - "left": { - "button": { - "icon": { - "wrapper": "IYDlXmBmmUKHveMzIPCF" - }, - "wrapper": "ql0zZd7giPXSnPg75NR0" - }, - "button_t": { - "wrapper": "rBX1EWVZ2EaPwP4y1Gkd" - } - }, - "right": { - "button": { - "wrapper": "WtC1lGbmQRplD6JBhNFU" - }, - "button_t": { - "wrapper": "OomFKn3bsxs5JfNUoWhz" - }, - "upgrade_button": { - "wrapper": "Upqw01TOXETOmR5Td7Dj" - } - }, - "wrapper": "qHWqOt_TYlFxiF0Dm2fD" - } - }, - "modal": { - "track_credits": { - "container": "uV8q95GGAb2VDtL3gpYa", - "content": { - "container": "Nw1INlIyra3LT1JjvoqH" - }, - "header": { - "close": "VKCcyYujazVPj6VkksPM", - "container": "pGU_qEtNT1qWKjrRbvan" - } - }, - "widget_generator": { - "container": "uUYNnjSt8m3EqVjsnHgh", - "content": { - "container": "IJHNf0vxPSbPE1egoG4N" - }, - "header": { - "close": "oBoIIlKrwQjxXpvOiOa0", - "container": "bOIRpQiHUAEfp8ntStTo" - } - } - }, - "scrollable_text": { - "container": "bMurPtRDRv5LuN78MTVG", - "wrapper": "KjPUGV8uMbl_0bvk9ePv" - }, - "search_box": { - "container": "JzZyf6OGCGtdscOZGt8Y", - "expand_button": "wCl7pMTEE68v1xuZeZiB" - }, - "search_chips": { - "chip": "UnwG2v9ISmcUhnjKj22Y", - "container": "IDNDdMa6ACThrEsGWsXX", - "wrapper": "XAwhJzXeTM5Iv2jLMCEj", - "wrapper_wrapper": "qG4q41T8PJl0SkVgUeJc" - }, - "settings": { - "button": { - "wrapper": "rFFJg1UIumqUUFDgo6n7" - }, - "header": { - "container": "O2vRz41OsAH0O7xVA4La" - }, - "section": { - "container": "k6GFKyOKVR5Ruofj3aTQ" - }, - "text_input": "SkbGMKYv49KtJNB5XxdX" - }, - "sort_box": { - "list": { - "button": "w6j_vX6SF5IxSXrrkYw5" - } - }, - "tracklist": { - "column_header": "rGujAXjCLKEd_N6yTwds" - } -} diff --git a/1020045/classmap.json b/1020045/classmap.json deleted file mode 100644 index 7cf387d..0000000 --- a/1020045/classmap.json +++ /dev/null @@ -1,311 +0,0 @@ -{ - "main": { - "main_view": { - "album": { - "section": "m2grVeuHNwfGLVpaSBle" - }, - "artist": { - "section": "D6IunHuzuULf_Sr88GOA" - }, - "carousel": { - "container": "bjB8WZd0Ev30ZFbiScDm", - "title": { - "wrapper": "q8AZzDc_1BumBHZg0tZb" - }, - "wrapper": "BagEpNps_J8R2QuHRZMa" - }, - "content_container": "T0fKO6B7LQSCE_VaSM1P", - "entity": { - "actions": { - "container": "eSg4ntPU2KQLfpLGXAww", - "wrapper": "E4q8ogfdWtye7YgotBlN" - }, - "background": "CoLO4pdSl8LGWyVZA00t" - }, - "gradient": "S4OmZ_IZexmZ5dasPqW5", - "header": { - "background": "gHImFiUWOg93pvTefeAD", - "background_overlay": "xYgjMpAjE5XT05aRIezb", - "container": "NXiYChVp4Oydfxd7rT5r", - "contents": { - "container": "iWTIFTzhRZT0rCD0_gOK", - "image": { - "container": "_gLjHpwOxHFwo5nLM8hb", - "content": "CmkY1Ag0tJDfnFXbGgju", - "wrapper": "Ws8Ec3GREpT5PAUesr9b" - }, - "info": { - "container": "RP2rRchy4i8TIp1CTmb7", - "description": { - "content": "fUYMR7LuRXv0KJWFvRZA", - "wrapper": "jpVuvMOCbpaRr_6FLf3W" - }, - "metadata": { - "container": "Fb61sprjhh75aOITDnsJ", - "duration": "UyzJidwrGk3awngSGIwv", - "profile": "NO_VO3MRVl9z3z56d8Lg", - "text": "RANLXG3qKB61Bh33I0r2" - }, - "pretitle": "lp9Tfm4rsM9_pfbIE0zd", - "title": "rEN7ncpaUeSGL9z0NGQR" - } - } - }, - "home": { - "chips": { - "background": "hIFR8WDm_54EEIa1gwpC", - "container": "cj6vRk3nFAi80HSVqX91" - }, - "section": "ZLSAuA1tn0bSdQRwhhj6", - "shortcuts": { - "chip": { - "container": "g3f_cI5usQX7ZOQyDtA9", - "wrapper": "Z35BWOA10YGn5uc9YgAp" - }, - "container": "nlOU1unbFAd7ZHyeSMTH", - "wrapper": "rPV8BmHZXaGIGT2HwvBB" - }, - "wrapper": "UqLpBiryzmdVyUucfSTQ" - }, - "playlist": { - "section": "dZ3U5sTGUTdanNamXe1z" - }, - "topbar": { - "background": "T1xI1RTSFU7Wu94UuvE6", - "background_overlay": "EvIR4O7jOSbNmxtMdIQ0", - "container": "hV9v6y_uYwdAsoiOHpzk", - "wrapper": "facDIsOQo9q7kiWc4jSg" - }, - "wrapper": "jEMA2gVoLgPQqAFrPhFw" - }, - "panel": { - "aside": "ffFwfKcPDbmAPLXzxzKq", - "container": "AAdBM1nhG73supMfnYX7", - "content": { - "wrapper": "zduvaX0Ioxqd5ypeWoAf", - "wrapper_wrapper": "cZCuJDjrGA2QMXja_Sua" - }, - "header": { - "container": "fNXmHtlrj4UVWmhQrJ_5", - "controls": { - "container": "icNf66tgG3uxDMbCCIaN" - }, - "title": { - "link": "gwmgu53xszgwAXxqLT0h", - "wrapper": "eTT681T6oUKXsIMiP8pT" - }, - "wrapper": "W3E0IT3_STcazjTeyOJa" - }, - "root": "OTfMDdomT5S7B5dbYTT8", - "wrapper": "XOawmCGZcQx4cesyNfVO" - }, - "playbar": { - "buttons": { - "button": { - "wrapper": "KAZD28usA1vPz5GVpm63", - "wrapper__active": "RK45o6dbvO1mb0wQtSwq", - "wrapper__indicator": "EHxL6K_6WWDlTCZP6x5w" - }, - "container": "mwpJrmCgLlVkJVtWjlI1", - "volume": "rT09bwCEwXECMbLbX_7A", - "wrapper": "pLifNBuHRY8cZkZyEqwL" - }, - "container": "udArIAqnfUQPQew2VAns", - "controls": { - "buttons": { - "left": "NKUrT1GciYXAEEUtagN1", - "loop": "Vz6yjzttS0YlLcwrkoUR", - "loop_active": "tP0mccyU1WAa7I9PevC1", - "next": "mnipjT4SLDMgwiDCEnRC", - "play": "cLkUmr", - "previous": "fn72ari9aEmKo4JcwteT", - "right": "Qt226Z4rBQs53aedRQBQ", - "wrapper": "XrZ1iHVHAPMya3jkB2sa" - }, - "container": "gItY2hnfCB4TsDJCkPiO", - "wrapper": "sVv2OQORCQ4kf6iKfUTF" - }, - "footer": "yglmI5m3fCc8baD1Kwdw", - "progress": { - "bar": "B1vgcMXBqOxgMxXh5j1f", - "container": "pn5V0OzovI9p6b8nWq8p", - "time-elapsed": "IPbBrI6yF4zhaizFmrg6", - "time-total": "kQqIrFPM5PjMWb5qUS56", - "wrapper": "w6j_vX6SF5IxSXrrkYw5" - }, - "widget": { - "container": "deomraqfhIAoSB3SgXpu", - "cover": { - "art": { - "container": "H0HbpIM3UrcupWIAjLWu", - "image": "FqmFsMhuF4D0s35Z62Js", - "wrapper": "BFR9Zt3zpL8BATBMiwQB" - }, - "button": "HD9s7U5E1RLSWKpXmrqx", - "wrapper": "GQ5_gIWzIqAfBdmQm8yJ" - }, - "info": { - "artist_text": "w_TTPh4y9H1YD6UrTMHa", - "container": "j96cpCtZAIdqxcDrYHPI", - "text_content": { - "content": "PGSe59fD1Hwc9yUM2d3U", - "wrapper": "W5cB_o0XkkU7Q8tlTGxq", - "wrapper__wrapper": "eSMjmiD29Ox35O95waw6" - }, - "title_text": "PcH6VnzkkDqD36P93i9Q" - }, - "wrapper": "snFK6_ei0caqvFI6As9Q" - }, - "wrapper": "JG5J9NWJkaUO9fiKECMA" - }, - "sidebar": { - "container": "lYpiKR_qEjl1jGGyEvsA", - "navlinks": { - "container": "fFvRIGtMIgsOLVSq_JNS", - "link": { - "container": "hNvCMxbfz7HwgzLjt3IZ", - "container__active": "DzWw3g4E_66wu9ktqn36", - "wrapper": "KAcp7QFuEYSouAsuC5i_" - }, - "links": { - "library": "i_FRcsaqNCEJmoyObIP0" - } - }, - "root": "BdcvqBAid96FaHAmPYw_", - "section": "lHJd4oSttKLxkxuoZ0Lr", - "ylx": { - "container": "hgJel0bLlS_1Uf0EIfSA", - "header": "HjPqU_UW2egr14mRSom9", - "image": { - "container": "vreceNX3ABcxyddeS83B" - }, - "items": { - "container": "WxM1eb7qnneSkMiT4dvw", - "wrapper": "_W_0W9Uld1vxrRfsgdQR" - }, - "rootlist": { - "bottom_sentinel": "qnYVzttodnzg9WdrVQ1p", - "container": "JUa6JJNj7R_Y3i4P8YUX", - "item": "vSC5QuwmzUhqUNWdMTJ5", - "top_sentinel": "lyVkg68L7ycnwyOcO3vj" - }, - "wrapper": "wM72343CksOCaL3bZvKK" - } - }, - "topbar": { - "left": { - "button": { - "icon": { - "wrapper": "IYDlXmBmmUKHveMzIPCF" - }, - "wrapper": "ql0zZd7giPXSnPg75NR0" - }, - "button_t": { - "wrapper": "rBX1EWVZ2EaPwP4y1Gkd" - } - }, - "right": { - "button": { - "wrapper": "WtC1lGbmQRplD6JBhNFU" - }, - "button_t": { - "wrapper": "OomFKn3bsxs5JfNUoWhz" - } - }, - "wrapper": "qHWqOt_TYlFxiF0Dm2fD" - }, - "wrapper": "ZQftYELq0aOsg6tPbVbV" - }, - "modal": { - "track_credits": { - "container": "uV8q95GGAb2VDtL3gpYa", - "content": { - "container": "Nw1INlIyra3LT1JjvoqH" - }, - "header": { - "close": "VKCcyYujazVPj6VkksPM", - "container": "pGU_qEtNT1qWKjrRbvan" - } - }, - "widget_generator": { - "container": "uUYNnjSt8m3EqVjsnHgh", - "content": { - "container": "IJHNf0vxPSbPE1egoG4N" - }, - "header": { - "close": "oBoIIlKrwQjxXpvOiOa0", - "container": "bOIRpQiHUAEfp8ntStTo" - } - } - }, - "play_button": { - "wrapper": "ix_8kg3iUb9VS5SmTnBY" - }, - "profile": { - "figure": "tp8rO9vtqBGPLOhwcdYv", - "image": "Xz3tlahv16UpqKBW5HdK" - }, - "scrollable_text": { - "container": "bMurPtRDRv5LuN78MTVG", - "wrapper": "KjPUGV8uMbl_0bvk9ePv" - }, - "search_box": { - "container": "JzZyf6OGCGtdscOZGt8Y", - "expand_button": "wCl7pMTEE68v1xuZeZiB" - }, - "search_chips": { - "chip": "UnwG2v9ISmcUhnjKj22Y", - "container": "IDNDdMa6ACThrEsGWsXX", - "wrapper": "XAwhJzXeTM5Iv2jLMCEj", - "wrapper_wrapper": "qG4q41T8PJl0SkVgUeJc" - }, - "settings": { - "button": { - "wrapper": "rFFJg1UIumqUUFDgo6n7" - }, - "header": { - "container": "O2vRz41OsAH0O7xVA4La" - }, - "section": { - "container": "k6GFKyOKVR5Ruofj3aTQ" - }, - "text_input": "SkbGMKYv49KtJNB5XxdX" - }, - "shuffle": { - "active": "E1ikFpkPVaoLplbQdrTP", - "button": "lihLVK", - "wrapper": "ecHWOS" - }, - "slider": { - "background": "NoOAOv6U6vtqj_ybS1Cd", - "bar": "TywOcKZEqNynWecCiATc", - "handle": "Vis45PPawTyED7Lt2_LI", - "interactive": "DFtdzavKSbEhwKYkPTa6", - "slider": "epWhU7hHGktzlO_dop6z", - "sliderail": "w699O0LgQRghXyl3bs9u", - "wrapper": "p1ULRzPc4bD8eQ4T_wyp" - }, - "sort_box": { - "list": { - "button": "w6j_vX6SF5IxSXrrkYw5" - } - }, - "tracklist": { - "container": "oIeuP60w1eYpFaXESRSg", - "header": { - "album": "_TH6YAXEzJtzSxhkGSqu", - "column": "rGujAXjCLKEd_N6yTwds", - "container": "ePPpO_NuGDUxVRTw7y6W", - "duration": "PAqIqZXvse_3h6sDVxU0", - "index": "fS0C4IgbHviZxIVGC736", - "title": "w46g_LQVSLE9xK399VYf", - "wrapper": "IpXjqI9ouS_N5zi0WM88" - }, - "row": { - "container": "IjYxRc5luMiDPhKhZVUH", - "container_active": "JgERXNoqNav5zOHiZGfG", - "more": "ObVor_8sQq5whKbtWs8a", - "play": "j2s64Lz8y6VzBLB_V9Gm" - } - } -} diff --git a/README.md b/README.md index f764bc0..7946e89 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,13 @@ SHA-256 digests, and the CLI downloads only what the index names. | --- | --- | --- | | `classmap.json` | Yes | Nested groups whose leaves are Spotify's stock class strings. | | `css-map.json` | No | Flat overlay from stock class to Spicetify name for this build. | -| `META.json` | For verified keys | The fields the CLI and tooling read, described below. | -| `VERIFICATION.md` | With `META.json` | Pipeline, notes, statistics, and verification runs. | +| `META.json` | Yes | The fields the CLI and tooling read, described below. | +| `VERIFICATION.md` | Yes | Pipeline, notes, statistics, and verification runs. | Leaves store the class exactly as it appears in the stock client, never the Spicetify name the css-map rewrites it to. The CLI rewrites staged modules in the same css-map pass as the client, so both forms reach the same DOM class, -but only the stock form can be checked against a stock archive. Keys -1020038, 1020040, and 1020045 predate the pipeline and have no `META.json`. +but only the stock form can be checked against a stock archive. Every JSON file uses two-space indentation and ends with a newline. `classmap.json`, `css-map.json`, `META.json`, and `index.json` also sort their diff --git a/index.json b/index.json index 5bb8c8b..2b7eb81 100644 --- a/index.json +++ b/index.json @@ -4,24 +4,6 @@ "sha256": "9d6ceb358e7e7d7e4099e0e8bce13bd9d9825e69741411b0d235eada8a48c655" }, "keys": { - "1020038": { - "classmap": { - "file": "classmap.json", - "sha256": "d5be975944065eff2525b0df7d6d3c87e5abd913757e1c92a8f4e6d510ea18dd" - } - }, - "1020040": { - "classmap": { - "file": "classmap.json", - "sha256": "49babed3d08a81926bbd860d0320904510c88e5c614705539839bb33154dcf31" - } - }, - "1020045": { - "classmap": { - "file": "classmap.json", - "sha256": "bd36f3890364fe30db8a41b5a34cb9ca24c05309e29ae57b7b3670a947a0ad1d" - } - }, "1020084": { "classmap": { "file": "classmap.json", diff --git a/scripts/validate-classmaps.test.mts b/scripts/validate-classmaps.test.mts index 8a13fd0..c87e096 100644 --- a/scripts/validate-classmaps.test.mts +++ b/scripts/validate-classmaps.test.mts @@ -167,5 +167,10 @@ test("reports a directory named like a published file instead of crashing", () = assert.doesNotThrow(() => errors(child)); rmSync(path.join(child, "VERIFICATION.md")); mkdirSync(path.join(child, "VERIFICATION.md")); - assert.ok(errors(child).includes("VERIFICATION.md: required beside META.json")); + assert.ok(errors(child).includes("VERIFICATION.md: missing")); +}); + +test("requires META.json for every key", () => { + rmSync(path.join(child, "META.json")); + assert.ok(errors(child).includes("META.json: missing")); }); diff --git a/scripts/validate-classmaps.ts b/scripts/validate-classmaps.ts index db651e4..bb837bc 100644 --- a/scripts/validate-classmaps.ts +++ b/scripts/validate-classmaps.ts @@ -2,7 +2,7 @@ // // /classmap.json nested groups of class-name leaves (required) // /css-map.json flat hash -> semantic overlay (optional) -// /META.json schema_version 2 metadata (optional for legacy keys) +// /META.json schema_version 2 metadata (required) // /VERIFICATION.md verification history (required beside META.json) // // JSON files must be in canonical form (renderJson). META claims are checked @@ -226,13 +226,10 @@ export function keyErrors(keyDir: string, key = path.basename(keyDir), root = RO } const metaPath = path.join(keyDir, "META.json"); - if (isFile(metaPath)) { - const meta = loadCanonical(metaPath, errors); - if (meta !== undefined) errors.push(...metaErrors(meta, key, leaves, root, readFileSync(classmapPath))); - if (!isFile(path.join(keyDir, "VERIFICATION.md"))) { - errors.push("VERIFICATION.md: required beside META.json"); - } - } + if (!isFile(metaPath)) return [...errors, "META.json: missing"]; + const meta = loadCanonical(metaPath, errors); + if (meta !== undefined) errors.push(...metaErrors(meta, key, leaves, root, readFileSync(classmapPath))); + if (!isFile(path.join(keyDir, "VERIFICATION.md"))) errors.push("VERIFICATION.md: missing"); return errors; }