diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..acad636 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,14 @@ +module.exports = { + env: { + es2021: true, + node: true + }, + extends: 'standard-with-typescript', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: './tsconfig.json' + }, + rules: { + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..aadf5a8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true, + "source.formatDocument": false, + } +} \ No newline at end of file diff --git a/README.md b/README.md index ff8ff6d..6173d02 100644 --- a/README.md +++ b/README.md @@ -45,14 +45,21 @@ Once you have selected a playlist, you can use the new topbar button to quickly ![](https://i.imgur.com/JrgLaUk.png) +This extension is fully compatible all spicetify theme, thanks to its settions section. + +You can find it by clicking on your avatar -> Settings -> Quick add to playlist (at the very bottom) +There, you can customize the "selected playlist" background color to match your current theme! + +![](https://i.imgur.com/kjkgPrO.png) + ## Usage Notes -- If you find any issues, please report them on the [issues page.](https://github.com/woosy/spicetify-quick-add-to-playlist/issues/new/choose) +- If you find any issues, please report them on the [issues page](https://github.com/woosy/spicetify-quick-add-to-playlist/issues/new/choose). ## Upcoming Features -- Settings, to customize the "selected playlist" background color +- Feel free to suggest any features in the [issues page](https://github.com/woosy/spicetify-quick-add-to-playlist/issues/new/choose). ## Credits diff --git a/dist/quick-add-to-playlist.js b/dist/quick-add-to-playlist.js index 952bc80..7b6410d 100644 --- a/dist/quick-add-to-playlist.js +++ b/dist/quick-add-to-playlist.js @@ -1,14 +1,17 @@ -var quickDaddDtoDplaylist=(()=>{var l="add_to_playlist.playlist",s='',o='',c='';async function n(t){p(t,"?"),d()&&(await async function(){const i=Spicetify.Player.data.track;var t=d();return!!t&&(await Spicetify.CosmosAsync.get("https://api.spotify.com/v1/playlists/"+t.id)).tracks.items.some(t=>t.track.uri===i.uri)}()?p(t,"-"):p(t,"+"))}function p(t,i){var e=d();switch(i){case"+":t.icon=s,t.label="Add to "+e.name;break;case"-":t.icon=o,t.label="Remove from "+e.name;break;case"?":t.icon=c,t.label="Loading..."}}function r(t,i){t&&null!=(t=null==(t=null==(t=document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${t}"]`))?void 0:t.parentElement)?void 0:t.parentElement)&&t.classList.remove("quick-add-to-playlist--selected-playlist"),i&&null!=(t=null==(i=null==(t=document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${i}"]`))?void 0:t.parentElement)?void 0:i.parentElement)&&t.classList.add("quick-add-to-playlist--selected-playlist")}function d(){return JSON.parse(Spicetify.LocalStorage.get(l))}var t=async function(){for(;null==Spicetify||!Spicetify.showNotification;)await new Promise(t=>setTimeout(t,2e3));var t=document.body,i=document.createElement("style");t.classList.contains("quick-add-to-playlist--selected-playlist")||(i.innerHTML=` - .quick-add-to-playlist--selected-playlist { - background-color: #1c1818 !important; - } +var quickDaddDtoDplaylist=(()=>{var o=Object.create,d=Object.defineProperty,r=Object.getOwnPropertyDescriptor,c=Object.getOwnPropertyNames,p=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty,e=(e,t)=>function(){return t||(0,e[c(e)[0]])((t={exports:{}}).exports,t),t.exports},t=(e,t,i)=>{i=null!=e?o(p(e)):{};var l=!t&&e&&e.__esModule?i:d(i,"default",{value:e,enumerable:!0}),a=e,n=void 0,s=void 0;if(a&&"object"==typeof a||"function"==typeof a)for(let e of c(a))u.call(l,e)||e===n||d(l,e,{get:()=>a[e],enumerable:!(s=r(a,e))||s.enumerable});return l},i=e({"external-global-plugin:react-dom"(e,t){t.exports=Spicetify.ReactDOM}}),s=t(e({"external-global-plugin:react"(e,t){t.exports=Spicetify.React}})()),l=t(i()),f={settingsContainer:"settings-module__settingsContainer___10GVL_quickDaddDtoDplaylist",heading:"settings-module__heading___H3Y7k_quickDaddDtoDplaylist",description:"settings-module__description___SrDvZ_quickDaddDtoDplaylist",inputWrapper:"settings-module__inputWrapper___a0OZK_quickDaddDtoDplaylist"},a=class{constructor(e,t,i={}){this.name=e,this.settingsId=t,this.initialSettingsFields=i,this.settingsFields=this.initialSettingsFields,this.setRerender=null,this.buttonClassnames=null,this.pushSettings=async()=>{for(Object.entries(this.settingsFields).forEach(([e,t])=>{"button"!==t.type&&void 0===this.getFieldValue(e)&&this.setFieldValue(e,t.defaultValue)});!Spicetify?.Platform?.History?.listen;)await new Promise(e=>setTimeout(e,100));this.stopHistoryListener&&this.stopHistoryListener(),this.stopHistoryListener=Spicetify.Platform.History.listen(e=>{"/preferences"===e.pathname&&this.render()}),"/preferences"===Spicetify.Platform.History.location.pathname&&await this.render()},this.rerender=()=>{this.setRerender&&this.setRerender(Math.random())},this.render=async()=>{for(;!document.getElementById("desktop.settings.selectLanguage");){if("/preferences"!==Spicetify.Platform.History.location.pathname)return;await new Promise(e=>setTimeout(e,100))}var e=document.querySelector(".main-view-container__scroll-node-child main div");if(!e)return console.error("[spcr-settings] settings container not found");this.buttonClassnames=Array.from(e.querySelectorAll(":scope > button")).at(-1)?.className??null;let t=Array.from(e.children).find(e=>e.id===this.settingsId);t?console.log(t):((t=document.createElement("div")).id=this.settingsId,t.className=f.settingsContainer,e.appendChild(t)),l.default.render(s.default.createElement(this.FieldsContainer,null),t)},this.addButton=(e,t,i,l,a)=>{this.settingsFields[e]={type:"button",description:t,value:i,events:{onClick:l,...a}}},this.addInput=(e,t,i,l,a)=>{this.settingsFields[e]={type:"input",description:t,defaultValue:i,events:{onChange:l,...a}}},this.addHidden=(e,t)=>{this.settingsFields[e]={type:"hidden",defaultValue:t}},this.addToggle=(e,t,i,l,a)=>{this.settingsFields[e]={type:"toggle",description:t,defaultValue:i,events:{onChange:l,...a}}},this.addDropDown=(e,t,i,l,a,n)=>{this.settingsFields[e]={type:"dropdown",description:t,defaultValue:i[l],options:i,events:{onSelect:a,...n}}},this.getFieldValue=e=>JSON.parse(Spicetify.LocalStorage.get(this.settingsId+"."+e)||"{}")?.value,this.setFieldValue=(e,t)=>{Spicetify.LocalStorage.set(this.settingsId+"."+e,JSON.stringify({value:t}))},this.FieldsContainer=()=>{var[e,t]=(0,s.useState)(0);return this.setRerender=t,s.default.createElement("div",{className:f.settingsContainer,key:e},s.default.createElement("h2",{className:["main-shelf-title main-type-cello",f.heading].join(" ")},this.name),Object.entries(this.settingsFields).map(([e,t])=>s.default.createElement(this.Field,{nameId:e,field:t})))},this.Field=i=>{var e=this.settingsId+"."+i.nameId;let t;if(t="button"===i.field.type?i.field.value:this.getFieldValue(i.nameId),"hidden"===i.field.type)return s.default.createElement(s.default.Fragment,null);const[l,a]=(0,s.useState)(t),n=e=>{void 0!==e&&(a(e),this.setFieldValue(i.nameId,e))};return s.default.createElement(s.default.Fragment,null,s.default.createElement("div",{className:"main-type-mesto",style:{color:"var(--spice-subtext)"}},s.default.createElement("label",{className:f.description,htmlFor:e},i.field.description||"")),s.default.createElement("span",{className:["x-settings-secondColumn",f.inputWrapper].join(" ")},"input"===i.field.type?s.default.createElement("input",{className:"main-dropDown-dropDown",id:e,dir:"ltr",value:l,type:"text",...i.field.events,onChange:e=>{n(e.currentTarget.value);var t=i.field.events?.onChange;t&&t(e)}}):"button"===i.field.type?s.default.createElement("span",{className:""},s.default.createElement("button",{id:e,className:this.buttonClassnames??"",...i.field.events,onClick:e=>{n();var t=i.field.events?.onClick;t&&t(e)},type:"button"},l)):"toggle"===i.field.type?s.default.createElement("label",{className:"x-toggle-wrapper x-settings-secondColumn"},s.default.createElement("input",{id:e,className:"x-toggle-input",type:"checkbox",checked:l,...i.field.events,onClick:e=>{n(e.currentTarget.checked);var t=i.field.events?.onClick;t&&t(e)}}),s.default.createElement("span",{className:"x-toggle-indicatorWrapper"},s.default.createElement("span",{className:"x-toggle-indicator"}))):"dropdown"===i.field.type?s.default.createElement("select",{className:"main-dropDown-dropDown",id:e,...i.field.events,onChange:e=>{n(i.field.options[e.currentTarget.selectedIndex]);var t=i.field.events?.onChange;t&&t(e)}},i.field.options.map((e,t)=>s.default.createElement("option",{selected:e===l,value:t+1},e))):s.default.createElement(s.default.Fragment,null)))}}},n="add_to_playlist.playlist",h='',m='',y='';function g(){var e;return null!=(e=JSON.parse(Spicetify.LocalStorage.get(n)))?e:null}async function C(e){e.icon=y,e.label="Loading...";var t=g();null!==t&&(await async function(e){var t=Spicetify.Player.data.track,i=[];let l=await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/playlists/${e}/tracks?limit=100&fields=next,items(track(uri))`);for(i.push(...l.items.map(e=>e.track.uri));null!=l.next;)l=await Spicetify.CosmosAsync.get(l.next),i.push(...l.items.map(e=>e.track.uri));return i.includes(null==t?void 0:t.uri)}(t.id)?(e.icon=m,e.label="Remove from "+t.name):(e.icon=h,e.label="Add to "+t.name))}function v(e,t){null!=e&&null!=(e=null==(e=null==(e=document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${e}"]`))?void 0:e.parentElement)?void 0:e.parentElement)&&e.classList.remove("quick-add-to-playlist--selected-playlist"),null!=t&&null!=(e=null==(t=null==(e=document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${t}"]`))?void 0:e.parentElement)?void 0:t.parentElement)&&e.classList.add("quick-add-to-playlist--selected-playlist")}function w(e="#1c1818"){return` + .quick-add-to-playlist--selected-playlist { + background-color: ${e} !important; + border-radius: 6px; + } - .quick-add-to-playlist--selected-playlist span.ListRowTitle__LineClamp-sc-1xe2if1-0:after { - position: absolute; - right: 10px; - content: " (selected 📂)"; - text-align: right; - color: gray; - font-size: 11px; - } - `,t.appendChild(i)),(t=d())&&r(null,t.id),setTimeout(()=>{var t=document.querySelector(".main-rootlist-wrapper");t&&new MutationObserver(t=>{for(const e of t){var i;"attributes"===e.type&&"style"===e.attributeName&&(i=d())&&r(null,i.id)}}).observe(t,{attributes:!0,childList:!0,subtree:!0})},2e3);const a=new Spicetify.Topbar.Button("Loading...",c,async t=>{var i=Spicetify.Player.data.track;const e=d();e&&(t.icon===s?Spicetify.CosmosAsync.post(`https://api.spotify.com/v1/playlists/${e.id}/tracks`,{uris:[null==i?void 0:i.uri]}).then(()=>{Spicetify.showNotification("Added to "+e.name),p(a,"-")}).catch(()=>{Spicetify.showNotification("An error has occured!")}):t.icon===o&&Spicetify.CosmosAsync.del(`https://api.spotify.com/v1/playlists/${e.id}/tracks`,{tracks:[{uri:null==i?void 0:i.uri}]}).then(()=>{Spicetify.showNotification("Removed from "+e.name),p(a,"+")}).catch(()=>{Spicetify.showNotification("An error has occured!")}))});await n(a),Spicetify.Player.addEventListener("appchange",async()=>{await n(a)}),Spicetify.Player.addEventListener("songchange",async()=>{await n(a)}),new Spicetify.ContextMenu.Item("Select playlist",async([t],[]=[],i)=>{var e=d(),t=await Spicetify.CosmosAsync.get("https://api.spotify.com/v1/playlists/"+t.split(":")[2]);Spicetify.LocalStorage.set(l,JSON.stringify({name:t.name,id:t.id})),r(e?e.id:null,t.id),Spicetify.showNotification(`Selected playlist "${t.name}"`),await n(a)},([t])=>{switch(t.split(":")[1]){case Spicetify.URI.Type.PLAYLIST:case Spicetify.URI.Type.PLAYLIST_V2:return!0;default:return!1}},"playlist-folder").register()};(async()=>{await t()})()})(); \ No newline at end of file + .quick-add-to-playlist--selected-playlist span.ListRowTitle__LineClamp-sc-1xe2if1-0:after { + position: absolute; + right: 10px; + content: " (selected 📂)"; + text-align: right; + color: gray; + font-size: 11px; + } + `}function _(e){var t=document.body,i=t.querySelector("#quick-add-to-playlist-style");null!=i?(i.innerHTML=e,t.appendChild(i)):((i=document.createElement("style")).setAttribute("id","quick-add-to-playlist-style"),i.innerHTML=e,t.appendChild(i))}var S=async function(){var e=await async function(){const e=new a("Quick add to playlist","quick-add-to-playlist");return e.addInput("selected-bgcolor","Selected playlist background color","#1c1818"),e.addButton("save","Apply changes now","Apply",()=>{_(w(e.getFieldValue("selected-bgcolor"))),Spicetify.showNotification("Changes applied!")}),await e.pushSettings(),e}();_(w(e.getFieldValue("selected-bgcolor")));const l=new Spicetify.Topbar.Button("Loading...",y,async e=>{const t=g();var i;null!=t&&null!=(i=Spicetify.Player.data.track)&&(e.icon===h?Spicetify.CosmosAsync.post(`https://api.spotify.com/v1/playlists/${t.id}/tracks`,{uris:[null==i?void 0:i.uri]}).then(()=>{Spicetify.showNotification("Added to "+t.name),l.icon=m,l.label="Remove from "+t.name}).catch(()=>{Spicetify.showNotification("An error has occured!")}):e.icon===m&&Spicetify.CosmosAsync.del(`https://api.spotify.com/v1/playlists/${t.id}/tracks`,{tracks:[{uri:null==i?void 0:i.uri}]}).then(()=>{Spicetify.showNotification("Removed from "+t.name),l.icon=h,l.label="Add to "+t.name}).catch(()=>{Spicetify.showNotification("An error has occured!")}))});await C(l),new Spicetify.ContextMenu.Item("Select playlist",async([e],[]=[],t)=>{var i=g(),e=await Spicetify.CosmosAsync.get("https://api.spotify.com/v1/playlists/"+e.split(":")[2]);Spicetify.LocalStorage.set(n,JSON.stringify({name:e.name,id:e.id})),v(null!=i?i.id:null,e.id),Spicetify.showNotification(`Selected playlist: "${e.name}"`),await C(l)},([e])=>{switch(e.split(":")[1]){case Spicetify.URI.Type.PLAYLIST:case Spicetify.URI.Type.PLAYLIST_V2:return!0;default:return!1}},"playlist-folder").register(),Spicetify.Player.addEventListener("songchange",async()=>{await C(l)}),null!=(e=g())&&v(null,e.id)};(async()=>{await S()})()})();(async()=>{var e;document.getElementById("quickDaddDtoDplaylist")||((e=document.createElement("style")).id="quickDaddDtoDplaylist",e.textContent=String.raw` + .settings-module__settingsContainer___10GVL_quickDaddDtoDplaylist{display:contents}.settings-module__heading___H3Y7k_quickDaddDtoDplaylist{grid-column:1/-1;font-size:1.125rem;line-height:1.5rem;color:#fff;margin-top:24px}.settings-module__description___SrDvZ_quickDaddDtoDplaylist{font-size:.875rem;line-height:1.25rem}.settings-module__inputWrapper___a0OZK_quickDaddDtoDplaylist{display:flex;justify-self:end} + `.trim(),document.head.appendChild(e))})(); \ No newline at end of file diff --git a/package.json b/package.json index ea034e7..b71ae16 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,28 @@ { "name": "quick-add-to-playlist", - "version": "1.0.3", + "version": "1.1.0", "private": true, "scripts": { "build": "spicetify-creator", "build-local": "spicetify-creator --out=dist --minify", - "watch": "spicetify-creator --watch" + "watch": "spicetify-creator --watch", + "lint": "eslint . --ext .ts,.tsx", + "lint:fix": "eslint . --ext .ts,.tsx --fix" }, "license": "MIT", "devDependencies": { - "@types/react": "^18.2.9", + "@types/react": "^18.2.11", "@types/react-dom": "^18.2.4", - "spicetify-creator": "^1.0.13" + "@typescript-eslint/eslint-plugin": "^5.59.9", + "eslint": "^8.42.0", + "eslint-config-standard-with-typescript": "^35.0.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.0.0", + "eslint-plugin-promise": "^6.1.1", + "spicetify-creator": "^1.0.13", + "typescript": "5.0.4" + }, + "dependencies": { + "spcr-settings": "^1.1.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c82256..4381261 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,15 +1,41 @@ lockfileVersion: '6.0' +dependencies: + spcr-settings: + specifier: ^1.1.0 + version: 1.1.0 + devDependencies: '@types/react': - specifier: ^18.2.9 - version: 18.2.9 + specifier: ^18.2.11 + version: 18.2.11 '@types/react-dom': specifier: ^18.2.4 version: 18.2.4 + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.9 + version: 5.59.9(@typescript-eslint/parser@5.59.9)(eslint@8.42.0)(typescript@5.0.4) + eslint: + specifier: ^8.42.0 + version: 8.42.0 + eslint-config-standard-with-typescript: + specifier: ^35.0.0 + version: 35.0.0(@typescript-eslint/eslint-plugin@5.59.9)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.0.0)(eslint-plugin-promise@6.1.1)(eslint@8.42.0)(typescript@5.0.4) + eslint-plugin-import: + specifier: ^2.27.5 + version: 2.27.5(@typescript-eslint/parser@5.59.9)(eslint@8.42.0) + eslint-plugin-n: + specifier: ^15.0.0 + version: 15.0.0(eslint@8.42.0) + eslint-plugin-promise: + specifier: ^6.1.1 + version: 6.1.1(eslint@8.42.0) spicetify-creator: specifier: ^1.0.13 version: 1.0.13(less@4.1.3)(postcss@8.4.24)(sass@1.63.2)(stylus@0.59.0) + typescript: + specifier: 5.0.4 + version: 5.0.4 packages: @@ -26,6 +52,63 @@ packages: dev: true optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.42.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.42.0 + eslint-visitor-keys: 3.4.1 + dev: true + + /@eslint-community/regexpp@4.5.1: + resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.0.3: + resolution: {integrity: sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.5.2 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.42.0: + resolution: {integrity: sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.10: + resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + /@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} @@ -67,6 +150,27 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + /@types/clean-css@4.2.6: resolution: {integrity: sha512-Ze1tf+LnGPmG6hBFMi0B4TEB0mhF7EiMM5oyjLDNPE9hxrPU0W+5+bHvO+eFPA+bt0iC1zkQMoU/iGdRVjcRbw==} dependencies: @@ -85,6 +189,14 @@ packages: resolution: {integrity: sha512-hw3bhStrg5e3FQT8qZKCJTrzt/UbEaunU1xRWJ+aNOTmeBMvE3S4Ml2HiiNnZgL8izu0LFVkHUoPFXL1s5QNpQ==} dev: true + /@types/json-schema@7.0.12: + resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + /@types/minify@8.0.0: resolution: {integrity: sha512-gjkm4vR7KC4raQ/Q9GmWEtDSOvoUa5tV6e/1zRFMmRFe5er6OSMFlkpIXzQNdBS4Qk6H1Y7OCR8J4ur3s0UapA==} dependencies: @@ -103,16 +215,29 @@ packages: /@types/prop-types@15.7.5: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} - dev: true + + /@types/react-dom@17.0.20: + resolution: {integrity: sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==} + dependencies: + '@types/react': 17.0.60 + dev: false /@types/react-dom@18.2.4: resolution: {integrity: sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==} dependencies: - '@types/react': 18.2.9 + '@types/react': 18.2.11 dev: true - /@types/react@18.2.9: - resolution: {integrity: sha512-pL3JAesUkF7PEQGxh5XOwdXGV907te6m1/Qe1ERJLgomojS6Ne790QiA7GUl434JEkFA2aAaB6qJ5z4e1zJn/w==} + /@types/react@17.0.60: + resolution: {integrity: sha512-pCH7bqWIfzHs3D+PDs3O/COCQJka+Kcw3RnO9rFA2zalqoXg7cNjJDh6mZ7oRtY1wmY4LVwDdAbA1F7Z8tv3BQ==} + dependencies: + '@types/prop-types': 15.7.5 + '@types/scheduler': 0.16.3 + csstype: 3.1.2 + dev: false + + /@types/react@18.2.11: + resolution: {integrity: sha512-+hsJr9hmwyDecSMQAmX7drgbDpyE+EgSF6t7+5QEBAn1tQK7kl1vWZ4iRf6SjQ8lk7dyEULxUmZOIpN0W5baZA==} dependencies: '@types/prop-types': 15.7.5 '@types/scheduler': 0.16.3 @@ -121,6 +246,9 @@ packages: /@types/scheduler@0.16.3: resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + + /@types/semver@7.5.0: + resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} dev: true /@types/uglify-js@3.17.1: @@ -129,12 +257,164 @@ packages: source-map: 0.6.1 dev: true + /@typescript-eslint/eslint-plugin@5.59.9(@typescript-eslint/parser@5.59.9)(eslint@8.42.0)(typescript@5.0.4): + resolution: {integrity: sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.5.1 + '@typescript-eslint/parser': 5.59.9(eslint@8.42.0)(typescript@5.0.4) + '@typescript-eslint/scope-manager': 5.59.9 + '@typescript-eslint/type-utils': 5.59.9(eslint@8.42.0)(typescript@5.0.4) + '@typescript-eslint/utils': 5.59.9(eslint@8.42.0)(typescript@5.0.4) + debug: 4.3.4 + eslint: 8.42.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.4 + natural-compare-lite: 1.4.0 + semver: 7.5.1 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@5.59.9(eslint@8.42.0)(typescript@5.0.4): + resolution: {integrity: sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.59.9 + '@typescript-eslint/types': 5.59.9 + '@typescript-eslint/typescript-estree': 5.59.9(typescript@5.0.4) + debug: 4.3.4 + eslint: 8.42.0 + typescript: 5.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.59.9: + resolution: {integrity: sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.59.9 + '@typescript-eslint/visitor-keys': 5.59.9 + dev: true + + /@typescript-eslint/type-utils@5.59.9(eslint@8.42.0)(typescript@5.0.4): + resolution: {integrity: sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.59.9(typescript@5.0.4) + '@typescript-eslint/utils': 5.59.9(eslint@8.42.0)(typescript@5.0.4) + debug: 4.3.4 + eslint: 8.42.0 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.59.9: + resolution: {integrity: sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.59.9(typescript@5.0.4): + resolution: {integrity: sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.59.9 + '@typescript-eslint/visitor-keys': 5.59.9 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.1 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.59.9(eslint@8.42.0)(typescript@5.0.4): + resolution: {integrity: sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.42.0) + '@types/json-schema': 7.0.12 + '@types/semver': 7.5.0 + '@typescript-eslint/scope-manager': 5.59.9 + '@typescript-eslint/types': 5.59.9 + '@typescript-eslint/typescript-estree': 5.59.9(typescript@5.0.4) + eslint: 8.42.0 + eslint-scope: 5.1.1 + semver: 7.5.1 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.59.9: + resolution: {integrity: sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.59.9 + eslint-visitor-keys: 3.4.1 + dev: true + + /acorn-jsx@5.3.2(acorn@8.8.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.2 + dev: true + /acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} hasBin: true dev: true + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -150,6 +430,53 @@ packages: picomatch: 2.3.1 dev: true + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + + /array-includes@3.1.6: + resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + get-intrinsic: 1.2.1 + is-string: 1.0.7 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.flat@1.3.1: + resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + es-shim-unscopables: 1.0.0 + dev: true + + /array.prototype.flatmap@1.3.1: + resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + es-shim-unscopables: 1.0.0 + dev: true + /at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} @@ -171,6 +498,11 @@ packages: postcss-value-parser: 4.2.0 dev: true + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true @@ -209,6 +541,18 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + /caniuse-lite@1.0.30001497: resolution: {integrity: sha512-I4/duVK4wL6rAK/aKZl3HXB4g+lIZvaT4VLAn2rCgJ38jVLb0lv2Xug6QuqmxXFVRJMF74SPPWPJ/1Sdm3vCzw==} dev: true @@ -268,6 +612,15 @@ packages: is-what: 3.14.1 dev: true + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -276,7 +629,6 @@ packages: /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - dev: true /cwd@0.10.0: resolution: {integrity: sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==} @@ -296,7 +648,6 @@ packages: dependencies: ms: 2.1.3 dev: true - optional: true /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -310,6 +661,39 @@ packages: ms: 2.1.2 dev: true + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-properties@1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + /electron-to-chromium@1.4.425: resolution: {integrity: sha512-wv1NufHxu11zfDbY4fglYQApMswleE9FL/DSeyOyauVXDZ+Kco96JK/tPfBUaDqfRarYp2WH2hJ/5UnVywp9Jg==} dev: true @@ -323,6 +707,70 @@ packages: dev: true optional: true + /es-abstract@1.21.2: + resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.2.1 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.10 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.0 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.7 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.9 + dev: true + + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-shim-unscopables@1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dependencies: + has: 1.0.3 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + /esbuild-android-64@0.14.54: resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} engines: {node: '>=12'} @@ -560,59 +1008,404 @@ packages: engines: {node: '>=6'} dev: true - /expand-tilde@1.2.2: - resolution: {integrity: sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==} - engines: {node: '>=0.10.0'} - dependencies: - os-homedir: 1.0.2 + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} dev: true - /expand-tilde@2.0.2: - resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} - engines: {node: '>=0.10.0'} - dependencies: - homedir-polyfill: 1.0.3 + /eslint-config-standard-with-typescript@35.0.0(@typescript-eslint/eslint-plugin@5.59.9)(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.0.0)(eslint-plugin-promise@6.1.1)(eslint@8.42.0)(typescript@5.0.4): + resolution: {integrity: sha512-Xa7DY9GgduZyp0qmXxBF0/dB+Vm4/DgWu1lGpNLJV2d46aCaUxTKDEnkzjUWX/1O9S0a+Dhnw7A4oI0JpYzwtw==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.50.0 + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: ^15.0.0 + eslint-plugin-promise: ^6.0.0 + typescript: '*' + dependencies: + '@typescript-eslint/eslint-plugin': 5.59.9(@typescript-eslint/parser@5.59.9)(eslint@8.42.0)(typescript@5.0.4) + '@typescript-eslint/parser': 5.59.9(eslint@8.42.0)(typescript@5.0.4) + eslint: 8.42.0 + eslint-config-standard: 17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.0.0)(eslint-plugin-promise@6.1.1)(eslint@8.42.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.9)(eslint@8.42.0) + eslint-plugin-n: 15.0.0(eslint@8.42.0) + eslint-plugin-promise: 6.1.1(eslint@8.42.0) + typescript: 5.0.4 + transitivePeerDependencies: + - supports-color dev: true - /extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} + /eslint-config-standard@17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.0.0)(eslint-plugin-promise@6.1.1)(eslint@8.42.0): + resolution: {integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==} + peerDependencies: + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: ^15.0.0 + eslint-plugin-promise: ^6.0.0 dependencies: - is-extendable: 0.1.1 + eslint: 8.42.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.9)(eslint@8.42.0) + eslint-plugin-n: 15.0.0(eslint@8.42.0) + eslint-plugin-promise: 6.1.1(eslint@8.42.0) dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + /eslint-import-resolver-node@0.3.7: + resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} dependencies: - to-regex-range: 5.0.1 + debug: 3.2.7 + is-core-module: 2.12.1 + resolve: 1.22.2 + transitivePeerDependencies: + - supports-color dev: true - /find-file-up@0.1.3: - resolution: {integrity: sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==} - engines: {node: '>=0.10.0'} + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint@8.42.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true dependencies: - fs-exists-sync: 0.1.0 - resolve-dir: 0.1.1 + '@typescript-eslint/parser': 5.59.9(eslint@8.42.0)(typescript@5.0.4) + debug: 3.2.7 + eslint: 8.42.0 + eslint-import-resolver-node: 0.3.7 + transitivePeerDependencies: + - supports-color dev: true - /find-pkg@0.1.2: - resolution: {integrity: sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==} - engines: {node: '>=0.10.0'} + /eslint-plugin-es@4.1.0(eslint@8.42.0): + resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' dependencies: - find-file-up: 0.1.3 + eslint: 8.42.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 dev: true - /fraction.js@4.2.0: - resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.9)(eslint@8.42.0): + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.59.9(eslint@8.42.0)(typescript@5.0.4) + array-includes: 3.1.6 + array.prototype.flat: 1.3.1 + array.prototype.flatmap: 1.3.1 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.42.0 + eslint-import-resolver-node: 0.3.7 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint@8.42.0) + has: 1.0.3 + is-core-module: 2.12.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.6 + resolve: 1.22.2 + semver: 6.3.0 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color dev: true - /fs-exists-sync@0.1.0: - resolution: {integrity: sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==} - engines: {node: '>=0.10.0'} + /eslint-plugin-n@15.0.0(eslint@8.42.0): + resolution: {integrity: sha512-cb70VSsNjteEL+sInXvlyewuE4OCW9CFmcOQKxyQzdAsoK+7pWpygf2q/Vsw/5dKSniO7qbawLjDqAakaILCIw==} + engines: {node: '>=12.22.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.42.0 + eslint-plugin-es: 4.1.0(eslint@8.42.0) + eslint-utils: 3.0.0(eslint@8.42.0) + ignore: 5.2.4 + is-core-module: 2.12.1 + minimatch: 3.1.2 + resolve: 1.22.2 + semver: 6.3.0 dev: true - /fs-extra@9.1.0: + /eslint-plugin-promise@6.1.1(eslint@8.42.0): + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.42.0 + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope@7.2.0: + resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-utils@2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-utils@3.0.0(eslint@8.42.0): + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.42.0 + eslint-visitor-keys: 2.1.0 + dev: true + + /eslint-visitor-keys@1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint-visitor-keys@3.4.1: + resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.42.0: + resolution: {integrity: sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.42.0) + '@eslint-community/regexpp': 4.5.1 + '@eslint/eslintrc': 2.0.3 + '@eslint/js': 8.42.0 + '@humanwhocodes/config-array': 0.11.10 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.0 + eslint-visitor-keys: 3.4.1 + espree: 9.5.2 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.20.0 + graphemer: 1.4.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.5.2: + resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.2 + acorn-jsx: 5.3.2(acorn@8.8.2) + eslint-visitor-keys: 3.4.1 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /expand-tilde@1.2.2: + resolution: {integrity: sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==} + engines: {node: '>=0.10.0'} + dependencies: + os-homedir: 1.0.2 + dev: true + + /expand-tilde@2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + dependencies: + homedir-polyfill: 1.0.3 + dev: true + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-file-up@0.1.3: + resolution: {integrity: sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==} + engines: {node: '>=0.10.0'} + dependencies: + fs-exists-sync: 0.1.0 + resolve-dir: 0.1.1 + dev: true + + /find-pkg@0.1.2: + resolution: {integrity: sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==} + engines: {node: '>=0.10.0'} + dependencies: + find-file-up: 0.1.3 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /fraction.js@4.2.0: + resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} + dev: true + + /fs-exists-sync@0.1.0: + resolution: {integrity: sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==} + engines: {node: '>=0.10.0'} + dev: true + + /fs-extra@9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} dependencies: @@ -638,12 +1431,43 @@ packages: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true + /function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + /generic-names@4.0.0: resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} dependencies: loader-utils: 3.2.1 dev: true + /get-intrinsic@1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -651,6 +1475,13 @@ packages: is-glob: 4.0.3 dev: true + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -680,15 +1511,82 @@ packages: which: 1.3.1 dev: true + /globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} dev: true + /grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} dev: true + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + /has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} @@ -724,6 +1622,11 @@ packages: postcss: 8.4.24 dev: true + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + /image-size@0.5.5: resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} engines: {node: '>=0.10.0'} @@ -736,6 +1639,19 @@ packages: resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==} dev: true + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: @@ -751,6 +1667,29 @@ packages: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.10 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -758,16 +1697,36 @@ packages: binary-extensions: 2.2.0 dev: true + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + /is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} dev: true + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + /is-core-module@2.12.1: resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} dependencies: has: 1.0.3 dev: true + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + /is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -785,11 +1744,73 @@ packages: is-extglob: 2.1.1 dev: true + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} dev: true + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.10: + resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + /is-what@3.14.1: resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} dev: true @@ -803,6 +1824,28 @@ packages: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: @@ -845,15 +1888,41 @@ packages: - supports-color dev: true + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + /loader-utils@3.2.1: resolution: {integrity: sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==} engines: {node: '>= 12.13.0'} dev: true + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + /lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: true + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + /make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -864,6 +1933,19 @@ packages: dev: true optional: true + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + /mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -889,7 +1971,6 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: true - optional: true /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} @@ -897,6 +1978,14 @@ packages: hasBin: true dev: true + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + /needle@3.2.0: resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==} engines: {node: '>= 4.4.x'} @@ -925,17 +2014,78 @@ packages: engines: {node: '>=0.10.0'} dev: true + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.values@1.1.6: + resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 dev: true + /optionator@0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + /os-homedir@1.0.2: resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} engines: {node: '>=0.10.0'} dev: true + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + /parse-node-version@1.0.1: resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} engines: {node: '>= 0.10'} @@ -946,15 +2096,30 @@ packages: engines: {node: '>=0.10.0'} dev: true + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} dev: true + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -1048,11 +2213,25 @@ packages: source-map-js: 1.0.2 dev: true + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + /prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} dev: true optional: true + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1060,6 +2239,20 @@ packages: picomatch: 2.3.1 dev: true + /regexp.prototype.flags@1.5.0: + resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + /resolve-dir@0.1.1: resolution: {integrity: sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==} engines: {node: '>=0.10.0'} @@ -1081,6 +2274,11 @@ packages: resolve: 1.22.2 dev: true + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + /resolve@1.22.2: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true @@ -1090,6 +2288,11 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true @@ -1097,6 +2300,20 @@ packages: glob: 7.2.3 dev: true + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-regex: 1.1.4 + dev: true + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true @@ -1122,6 +2339,19 @@ packages: dev: true optional: true + /semver@6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + + /semver@7.5.1: + resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + /set-getter@0.1.1: resolution: {integrity: sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==} engines: {node: '>=0.10.0'} @@ -1129,6 +2359,31 @@ packages: to-object-path: 0.3.0 dev: true + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} @@ -1151,6 +2406,13 @@ packages: engines: {node: '>= 8'} dev: true + /spcr-settings@1.1.0: + resolution: {integrity: sha512-aLtJDmhHRCmRBJb/gHlRkKd+7+Tz8Y1h2W26YA4vhDu/p4UEH9/1IMKDGI/7robYc512OYYfUAzYHA+tDMSCfg==} + dependencies: + '@types/react': 17.0.60 + '@types/react-dom': 17.0.20 + dev: false + /spicetify-creator@1.0.13(less@4.1.3)(postcss@8.4.24)(sass@1.63.2)(stylus@0.59.0): resolution: {integrity: sha512-c8vVlPrQoYoaiioj+D2hXup2sGjVP//9Tyzdh3vwBkBh2IAe7jvGMkbI03jwga3W5GPBdRBzdXyKjYWNV9/GBA==} hasBin: true @@ -1178,6 +2440,48 @@ packages: resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} dev: true + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + /stylus@0.59.0: resolution: {integrity: sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==} hasBin: true @@ -1214,6 +2518,10 @@ packages: source-map-support: 0.5.21 dev: true + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + /tmp@0.2.1: resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} engines: {node: '>=8.17.0'} @@ -1235,16 +2543,74 @@ packages: is-number: 7.0.0 dev: true + /tsconfig-paths@3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + /tslib@2.5.3: resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} dev: true + /tsutils@3.21.0(typescript@5.0.4): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.0.4 + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.10 + dev: true + + /typescript@5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} + engines: {node: '>=12.20'} + hasBin: true + dev: true + /uglify-js@3.17.4: resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} engines: {node: '>=0.8.0'} hasBin: true dev: true + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} @@ -1261,10 +2627,38 @@ packages: picocolors: 1.0.0 dev: true + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array@1.1.9: + resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.10 + dev: true + /which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true @@ -1272,6 +2666,28 @@ packages: isexe: 2.0.0 dev: true + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /word-wrap@1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + dev: true + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..39a2b6e --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +} diff --git a/src/app.tsx b/src/app.tsx index 285fbb9..a05551e 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,248 +1,218 @@ -const LOCALSTORAGE_PLAYLIST_KEY = 'add_to_playlist.playlist' - -const ICON_PLUS = `` -const ICON_MINUS = `` -const ICON_LOADING = `` - -async function main() { - // ============================================================================================================== - // ============================================================================================================== - // ============================================================================================================== - - // ------------------------------------------------------------ - // Wait for Spotify + Spicetify to load - - while (!Spicetify?.showNotification) { - await new Promise(resolve => setTimeout(resolve, 2000)) - } - - // Inject CSS - initInjectCss() - - // ------------------------------------------------------------ - // Create extension Button - - const topBarButton: Spicetify.Topbar.Button = new Spicetify.Topbar.Button( - 'Loading...', - ICON_LOADING, - async (self) => { - const track: any = Spicetify.Player.data.track - const playlist = getPlaylistFromLocalstorage() - if (!playlist) return - - // Add to playlist - if (self.icon === ICON_PLUS) { - Spicetify.CosmosAsync.post(`https://api.spotify.com/v1/playlists/${playlist.id}/tracks`, { uris: [track?.uri] }) - .then(() => { - Spicetify.showNotification(`Added to ${playlist.name}`) - updateTopBarButton(topBarButton, '-') - }) - .catch(() => { Spicetify.showNotification(`An error has occured!`) }) - - // Remove from playlist - } else if (self.icon === ICON_MINUS) { - Spicetify.CosmosAsync.del(`https://api.spotify.com/v1/playlists/${playlist.id}/tracks`, { tracks: [{ uri: track?.uri }] }) - .then(() => { - Spicetify.showNotification(`Removed from ${playlist.name}`) - updateTopBarButton(topBarButton, '+') - }) - .catch(() => { Spicetify.showNotification(`An error has occured!`) }) - } - } - ) - - await updateTopBar(topBarButton) - - // ------------------------------------------------------------ - // Event listeners: update icon (if already in playlist or not) - // ------------------------------------------------------------ - - // On app start - Spicetify.Player.addEventListener('appchange', async () => { - await updateTopBar(topBarButton) - }) - - // On song change - Spicetify.Player.addEventListener("songchange", async () => { - await updateTopBar(topBarButton) - }) - - - // ============================================================================================================== - // ============================================================================================================== - // ============================================================================================================== - - // ------------------------------------------------------------ - // Create option in ContextMenu - - new Spicetify.ContextMenu.Item( - 'Select playlist', - // Anonymous function called when selecting a playlist - async ([uri], [uid] = [], context = undefined) => { - const oldPlaylist = getPlaylistFromLocalstorage() - const newPlaylist = await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/playlists/${uri.split(":")[2]}`) - - Spicetify.LocalStorage.set( - LOCALSTORAGE_PLAYLIST_KEY, - JSON.stringify({ - name: newPlaylist.name, - id: newPlaylist.id - }) - ) - - updateStyle(oldPlaylist? oldPlaylist.id : null, newPlaylist.id) - Spicetify.showNotification(`Selected playlist "${newPlaylist.name}"`) - await updateTopBar(topBarButton) - }, - // Enable "Select playlist" only when right-clicking playlists - ([uri]) => { - const type = uri.split(":")[1] - switch (type) { - case Spicetify.URI.Type.PLAYLIST: - case Spicetify.URI.Type.PLAYLIST_V2: - return true - default: - return false - } - }, - 'playlist-folder' - ).register() -} - -// ============================================================================================================== -// ============================================================================================================== -// ============================================================================================================== - -// Check if current track is in playlist -async function isCurrentTrackInSelectedPlaylist (): Promise { - const track: any = Spicetify.Player.data.track - const playlist = getPlaylistFromLocalstorage() - if (!playlist) return false - const updatedPlaylist = await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/playlists/${playlist.id}`) - - return updatedPlaylist.tracks.items.some((item: any) => item.track.uri === track.uri) -} - -// ============================================================================================================== -// ============================================================================================================== -// ============================================================================================================== - -// Update Topbar icon/label -async function updateTopBar (topBarButton: Spicetify.Topbar.Button): Promise { - updateTopBarButton(topBarButton, '?') - - // first load: no playlist selected - const playlist = getPlaylistFromLocalstorage() - if (!playlist) return - - await isCurrentTrackInSelectedPlaylist() - ? updateTopBarButton(topBarButton, '-') - : updateTopBarButton(topBarButton, '+') -} - -// Update Topbar.Button icon & label -function updateTopBarButton (topBarButton: Spicetify.Topbar.Button, icon: '+' | '-' | '?'): void { - const playlist = getPlaylistFromLocalstorage() - - switch (icon) { - case '+': - topBarButton.icon = ICON_PLUS - topBarButton.label = `Add to ${playlist.name}` - break - case '-': - topBarButton.icon = ICON_MINUS - topBarButton.label = `Remove from ${playlist.name}` - break - case '?': - topBarButton.icon = ICON_LOADING - topBarButton.label = 'Loading...' - break - } -} - -// ============================================================================================================== -// ============================================================================================================== -// ============================================================================================================== - -// Inject a new class used to highlight selected playlist -function initInjectCss (): void { - const body = document.body - const style = document.createElement('style') - - // ---------------------------------------------------------- - // Avoid double injection - - if (!body.classList.contains('quick-add-to-playlist--selected-playlist')) { - style.innerHTML = ` - .quick-add-to-playlist--selected-playlist { - background-color: #1c1818 !important; - } - - .quick-add-to-playlist--selected-playlist span.ListRowTitle__LineClamp-sc-1xe2if1-0:after { - position: absolute; - right: 10px; - content: " (selected 📂)"; - text-align: right; - color: gray; - font-size: 11px; - } - ` - - body.appendChild(style) - } - - // ---------------------------------------------------------- - // init selected playlist style - - const playlist = getPlaylistFromLocalstorage() - if (playlist) updateStyle(null, playlist.id) - - // ---------------------------------------------------------- - // create an observer to watch for playlist folders wrapping - - setTimeout(() => { - // Select the node that will be observed for mutations - const targetNode = document.querySelector('.main-rootlist-wrapper') - if (!targetNode) return - - // Options for the observer (which mutations to observe) - const config = { attributes: true, childList: true, subtree: true } - - // Callback function to execute when mutations are observed - const callback = (mutationList: any) => { - for (const mutation of mutationList) { - if (mutation.type === 'attributes' && mutation.attributeName === 'style') { - const playlist = getPlaylistFromLocalstorage() - if (playlist) updateStyle(null, playlist.id) - } - } - } - - // Create an observer instance linked to the callback function - const observer = new MutationObserver(callback) - observer.observe(targetNode, config) - }, 2000) -} - -// Add/remove class to playlist's div container -function updateStyle (oldPlaylistId: string | null, newPlaylistId: string | null): void { - if (oldPlaylistId) { - const oldPlaylistLink = document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${oldPlaylistId}"]`) - oldPlaylistLink?.parentElement?.parentElement?.classList.remove('quick-add-to-playlist--selected-playlist') - } - - if (newPlaylistId) { - const newPlaylistLink = document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${newPlaylistId}"]`) - newPlaylistLink?.parentElement?.parentElement?.classList.add('quick-add-to-playlist--selected-playlist') - } -} - -// ============================================================================================================== -// ============================================================================================================== -// ============================================================================================================== - -function getPlaylistFromLocalstorage () { - return JSON.parse(Spicetify.LocalStorage.get(LOCALSTORAGE_PLAYLIST_KEY) as string) -} - -export default main +/* eslint-disable @typescript-eslint/no-misused-promises */ +import { SettingsSection } from 'spcr-settings' + +const LOCALSTORAGE_PLAYLIST_KEY = 'add_to_playlist.playlist' + +const ICON_PLUS = '' +const ICON_MINUS = '' +const ICON_LOADING = '' + +async function setupSettings (): Promise { + const settings = new SettingsSection('Quick add to playlist', 'quick-add-to-playlist') + + settings.addInput('selected-bgcolor', 'Selected playlist background color', '#1c1818') + + settings.addButton('save', 'Apply changes now', 'Apply', () => { + const styles = generateStyles(settings.getFieldValue('selected-bgcolor')) + injectStyles(styles) + Spicetify.showNotification('Changes applied!') + }) + + await settings.pushSettings() + return settings +} + +function getPlaylistFromLocalstorage (): { name: string, id: string } | null { + return JSON.parse(Spicetify.LocalStorage.get(LOCALSTORAGE_PLAYLIST_KEY) as string) ?? null +} + +async function getIsCurrentTrackInPlaylist (playlistId: string): Promise { + const track = Spicetify.Player.data.track + + const tracks = [] + + let playlist: { next: string, items: unknown[] } = await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/playlists/${playlistId}/tracks?limit=100&fields=next,items(track(uri))`) + tracks.push(...playlist.items.map((item: any) => item.track.uri)) + + while (playlist.next != null) { + playlist = await Spicetify.CosmosAsync.get(playlist.next) + tracks.push(...playlist.items.map((item: any) => item.track.uri)) + } + + return tracks.includes(track?.uri) +} + +async function updateTopbarButton (topbarButton: Spicetify.Topbar.Button): Promise { + topbarButton.icon = ICON_LOADING + topbarButton.label = 'Loading...' + + // check if current track is in selected playlist + const playlist = getPlaylistFromLocalstorage() + if (playlist === null) return + const isTrackInPlaylist = await getIsCurrentTrackInPlaylist(playlist.id) + + // if yes => set icon to "-" + if (isTrackInPlaylist) { + topbarButton.icon = ICON_MINUS + topbarButton.label = `Remove from ${playlist.name}` + // if no => set icon to "+" + } else { + topbarButton.icon = ICON_PLUS + topbarButton.label = `Add to ${playlist.name}` + } +} + +function updateSelectedStyles (oldPlaylistId: string | null, newPlaylistId: string | null): void { + if (oldPlaylistId != null) { + const oldPlaylistLink = document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${oldPlaylistId}"]`) + oldPlaylistLink?.parentElement?.parentElement?.classList.remove('quick-add-to-playlist--selected-playlist') + } + + if (newPlaylistId != null) { + const newPlaylistLink = document.querySelector(`[aria-describedby="onClickHintspotify:playlist:${newPlaylistId}"]`) + newPlaylistLink?.parentElement?.parentElement?.classList.add('quick-add-to-playlist--selected-playlist') + } +} + +function generateStyles (selectedPlaylistBgColor: string = '#1c1818'): string { + return ` + .quick-add-to-playlist--selected-playlist { + background-color: ${selectedPlaylistBgColor} !important; + border-radius: 6px; + } + + .quick-add-to-playlist--selected-playlist span.ListRowTitle__LineClamp-sc-1xe2if1-0:after { + position: absolute; + right: 10px; + content: " (selected 📂)"; + text-align: right; + color: gray; + font-size: 11px; + } + ` +} + +function injectStyles (styles: string): void { + const body = document.body + + // if already injected, update it + const style = body.querySelector('#quick-add-to-playlist-style') + if (style != null) { + style.innerHTML = styles + body.appendChild(style) + // otherwise, initialize it + } else { + const style = document.createElement('style') + style.setAttribute('id', 'quick-add-to-playlist-style') + style.innerHTML = styles + body.appendChild(style) + } +} + +// ============================================================================================================== +// ============================================================================================================== +// ============================================================================================================== + +async function main (): Promise { + const settings = await setupSettings() + + // ------------------------------------------------------------ + // Initialize extension's styles + + const styles = generateStyles(settings.getFieldValue('selected-bgcolor')) + injectStyles(styles) + + // ------------------------------------------------------------ + // Create Topbar Button + + const topbarButton: Spicetify.Topbar.Button = new Spicetify.Topbar.Button( + 'Loading...', + ICON_LOADING, + async (self) => { + // retrieve previously selected playlist + const playlist = getPlaylistFromLocalstorage() + if (playlist == null) return + + // get current track + const track = Spicetify.Player.data.track + if (track == null) return + + // if track isn't in playlist => add it + if (self.icon === ICON_PLUS) { + Spicetify.CosmosAsync.post(`https://api.spotify.com/v1/playlists/${playlist.id}/tracks`, { uris: [track?.uri] }) + .then(() => { + Spicetify.showNotification(`Added to ${playlist.name}`) + topbarButton.icon = ICON_MINUS + topbarButton.label = `Remove from ${playlist.name}` + }) + .catch(() => { Spicetify.showNotification('An error has occured!') }) + // if track is in playlist => remove it + } else if (self.icon === ICON_MINUS) { + Spicetify.CosmosAsync.del(`https://api.spotify.com/v1/playlists/${playlist.id}/tracks`, { tracks: [{ uri: track?.uri }] }) + .then(() => { + Spicetify.showNotification(`Removed from ${playlist.name}`) + topbarButton.icon = ICON_PLUS + topbarButton.label = `Add to ${playlist.name}` + }) + .catch(() => { Spicetify.showNotification('An error has occured!') }) + } + } + ) + + // update topbarButton on startup + await updateTopbarButton(topbarButton) + + // ------------------------------------------------------------ + // Create option in ContextMenu + + new Spicetify.ContextMenu.Item( + 'Select playlist', + // anonymous function called when selecting a playlist + async ([uri], [uid] = [], _context = undefined) => { + const oldPlaylist = getPlaylistFromLocalstorage() + const newPlaylist: { name: string, id: string } = await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/playlists/${uri.split(':')[2]}`) + + // save playlist in localStorage to persist it across app restart + Spicetify.LocalStorage.set( + LOCALSTORAGE_PLAYLIST_KEY, + JSON.stringify({ + name: newPlaylist.name, + id: newPlaylist.id + }) + ) + + updateSelectedStyles((oldPlaylist != null) ? oldPlaylist.id : null, newPlaylist.id) + Spicetify.showNotification(`Selected playlist: "${newPlaylist.name}"`) + + await updateTopbarButton(topbarButton) + }, + // only show when right-clicking playlists + ([uri]) => { + const type = uri.split(':')[1] + switch (type) { + case Spicetify.URI.Type.PLAYLIST: + case Spicetify.URI.Type.PLAYLIST_V2: + return true + default: + return false + } + }, + 'playlist-folder' + ).register() + + // ------------------------------------------------------------ + // Create listeners + + // @song-change: update Topbar icon + Spicetify.Player.addEventListener('songchange', async () => { + await updateTopbarButton(topbarButton) + }) + + // ---------------------------------------------------------- + // Init selected playlist style + + const playlist = getPlaylistFromLocalstorage() + if (playlist != null) updateSelectedStyles(null, playlist.id) +} + +export default main diff --git a/src/types/css-modules.d.ts b/src/types/css-modules.d.ts index 8c454a3..7e07787 100644 --- a/src/types/css-modules.d.ts +++ b/src/types/css-modules.d.ts @@ -1,9 +1,9 @@ declare module '*.module.css' { - const classes: { [key: string]: string }; - export default classes; + const classes: Record + export default classes } declare module '*.module.scss' { - const classes: { [key: string]: string }; - export default classes; + const classes: Record + export default classes } diff --git a/src/types/spicetify.d.ts b/src/types/spicetify.d.ts index c5d579a..fc14433 100644 --- a/src/types/spicetify.d.ts +++ b/src/types/spicetify.d.ts @@ -1,78 +1,78 @@ declare namespace Spicetify { - type Metadata = Partial>; - type ContextTrack = { - uri: string; - uid?: string; - metadata?: Metadata; - }; + type Metadata = Partial> + interface ContextTrack { + uri: string + uid?: string + metadata?: Metadata + } type ProvidedTrack = ContextTrack & { - removed?: string[]; - blocked?: string[]; - provider?: string; - }; + removed?: string[] + blocked?: string[] + provider?: string + } interface ContextOption { - contextURI?: string; - index?: number; - trackUri?: string; - page?: number; - trackUid?: string; - sortedBy?: string; - filteredBy?: string; - shuffleContext?: boolean; - repeatContext?: boolean; - repeatTrack?: boolean; - offset?: number; - next_page_url?: string; - restrictions?: Record; - referrer?: string; - }; - type PlayerState = { - timestamp: number; - context_uri: string; - context_url: string; - context_restrictions: Record; - index?: { - page: number; - track: number; - }; - track?: ProvidedTrack; - playback_id?: string; - playback_quality?: string; - playback_speed?: number; - position_as_of_timestamp: number; - duration: number; - is_playing: boolean; - is_paused: boolean; - is_buffering: boolean; - play_origin: { - feature_identifier: string; - feature_version: string; - view_uri?: string; - external_referrer?: string; - referrer_identifier?: string; - device_identifier?: string; - }; - options: { - shuffling_context?: boolean; - repeating_context?: boolean; - repeating_track?: boolean; - }; - restrictions: Record; - suppressions: { - providers: string[]; - }; - debug: { - log: string[]; - }; - prev_tracks: ProvidedTrack[]; - next_tracks: ProvidedTrack[]; - context_metadata: Metadata; - page_metadata: Metadata; - session_id: string; - queue_revision: string; + contextURI?: string + index?: number + trackUri?: string + page?: number + trackUid?: string + sortedBy?: string + filteredBy?: string + shuffleContext?: boolean + repeatContext?: boolean + repeatTrack?: boolean + offset?: number + next_page_url?: string + restrictions?: Record + referrer?: string }; + interface PlayerState { + timestamp: number + context_uri: string + context_url: string + context_restrictions: Record + index?: { + page: number + track: number + } + track?: ProvidedTrack + playback_id?: string + playback_quality?: string + playback_speed?: number + position_as_of_timestamp: number + duration: number + is_playing: boolean + is_paused: boolean + is_buffering: boolean + play_origin: { + feature_identifier: string + feature_version: string + view_uri?: string + external_referrer?: string + referrer_identifier?: string + device_identifier?: string + } + options: { + shuffling_context?: boolean + repeating_context?: boolean + repeating_track?: boolean + } + restrictions: Record + suppressions: { + providers: string[] + } + debug: { + log: string[] + } + prev_tracks: ProvidedTrack[] + next_tracks: ProvidedTrack[] + context_metadata: Metadata + page_metadata: Metadata + session_id: string + queue_revision: string + } namespace Player { - /** + /** * Register a listener `type` on Spicetify.Player. * * On default, `Spicetify.Player` always dispatch: @@ -81,33 +81,33 @@ declare namespace Spicetify { * - `onprogress` type when track progress changes. * - `appchange` type when user changes page. */ - function addEventListener(type: string, callback: (event?: Event) => void): void; - function addEventListener(type: "songchange", callback: (event?: Event & { data: PlayerState }) => void): void; - function addEventListener(type: "onplaypause", callback: (event?: Event & { data: PlayerState }) => void): void; - function addEventListener(type: "onprogress", callback: (event?: Event & { data: number }) => void): void; - function addEventListener(type: "appchange", callback: (event?: Event & { data: { - /** + function addEventListener (type: string, callback: (event?: Event) => void): void + function addEventListener (type: 'songchange', callback: (event?: Event & { data: PlayerState }) => void): void + function addEventListener (type: 'onplaypause', callback: (event?: Event & { data: PlayerState }) => void): void + function addEventListener (type: 'onprogress', callback: (event?: Event & { data: number }) => void): void + function addEventListener (type: 'appchange', callback: (event?: Event & { data: { + /** * App href path */ - path: string; - /** + path: string + /** * App container */ - container: HTMLElement; - } }) => void): void; - /** + container: HTMLElement + } }) => void): void + /** * Skip to previous track. */ - function back(): void; - /** + function back (): void + /** * An object contains all information about current track and player. */ - const data: PlayerState; - /** + const data: PlayerState + /** * Decrease a small amount of volume. */ - function decreaseVolume(): void; - /** + function decreaseVolume (): void + /** * Dispatches an event at `Spicetify.Player`. * * On default, `Spicetify.Player` always dispatch @@ -116,305 +116,304 @@ declare namespace Spicetify { * - `onprogress` type when track progress changes. * - `appchange` type when user changes page. */ - function dispatchEvent(event: Event): void; - const eventListeners: { - [key: string]: Array<(event?: Event) => void> - }; - /** + function dispatchEvent (event: Event): void + const eventListeners: Record void>> + /** * Convert milisecond to `mm:ss` format * @param milisecond */ - function formatTime(milisecond: number): string; - /** + function formatTime (milisecond: number): string + /** * Return song total duration in milisecond. */ - function getDuration(): number; - /** + function getDuration (): number + /** * Return mute state */ - function getMute(): boolean; - /** + function getMute (): boolean + /** * Return elapsed duration in milisecond. */ - function getProgress(): number; - /** + function getProgress (): number + /** * Return elapsed duration in percentage (0 to 1). */ - function getProgressPercent(): number; - /** + function getProgressPercent (): number + /** * Return current Repeat state (No repeat = 0/Repeat all = 1/Repeat one = 2). */ - function getRepeat(): number; - /** + function getRepeat (): number + /** * Return current shuffle state. */ - function getShuffle(): boolean; - /** + function getShuffle (): boolean + /** * Return track heart state. */ - function getHeart(): boolean; - /** + function getHeart (): boolean + /** * Return current volume level (0 to 1). */ - function getVolume(): number; - /** + function getVolume (): number + /** * Increase a small amount of volume. */ - function increaseVolume(): void; - /** + function increaseVolume (): void + /** * Return a boolean whether player is playing. */ - function isPlaying(): boolean; - /** + function isPlaying (): boolean + /** * Skip to next track. */ - function next(): void; - /** + function next (): void + /** * Pause track. */ - function pause(): void; - /** + function pause (): void + /** * Resume track. */ - function play(): void; - /** + function play (): void + /** * Play a track, playlist, album, etc. immediately * @param uri Spotify URI * @param context * @param options */ - async function playUri(uri: string, context: any = {}, options: Options = {}); - /** + async function playUri (uri: string, context: any = {}, options: Options = {}) + /** * Unregister added event listener `type`. * @param type * @param callback */ - function removeEventListener(type: string, callback: (event?: Event) => void): void; - /** + function removeEventListener (type: string, callback: (event?: Event) => void): void + /** * Seek track to position. * @param position can be in percentage (0 to 1) or in milisecond. */ - function seek(position: number): void; - /** + function seek (position: number): void + /** * Turn mute on/off * @param state */ - function setMute(state: boolean): void; - /** + function setMute (state: boolean): void + /** * Change Repeat mode * @param mode `0` No repeat. `1` Repeat all. `2` Repeat one track. */ - function setRepeat(mode: number): void; - /** + function setRepeat (mode: number): void + /** * Turn shuffle on/off. * @param state */ - function setShuffle(state: boolean): void; - /** + function setShuffle (state: boolean): void + /** * Set volume level * @param level 0 to 1 */ - function setVolume(level: number): void; - /** + function setVolume (level: number): void + /** * Seek to previous `amount` of milisecond * @param amount in milisecond. Default: 15000. */ - function skipBack(amount?: number): void; - /** + function skipBack (amount?: number): void + /** * Seek to next `amount` of milisecond * @param amount in milisecond. Default: 15000. */ - function skipForward(amount?: number): void; - /** + function skipForward (amount?: number): void + /** * Toggle Heart (Favourite) track state. */ - function toggleHeart(): void; - /** + function toggleHeart (): void + /** * Toggle Mute/No mute. */ - function toggleMute(): void; - /** + function toggleMute (): void + /** * Toggle Play/Pause. */ - function togglePlay(): void; - /** + function togglePlay (): void + /** * Toggle No repeat/Repeat all/Repeat one. */ - function toggleRepeat(): void; - /** + function toggleRepeat (): void + /** * Toggle Shuffle/No shuffle. */ - function toggleShuffle(): void; + function toggleShuffle (): void } /** * Adds a track/album or array of tracks/albums to prioritized queue. */ - function addToQueue(uri: string | string[]): Promise; + function addToQueue (uri: string | string[]): Promise /** * @deprecated */ - const BridgeAPI: any; + const BridgeAPI: any /** * @deprecated */ - const CosmosAPI: any; + const CosmosAPI: any /** * Async wrappers of CosmosAPI */ namespace CosmosAsync { - type Method = "DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT" | "SUB"; + type Method = 'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'SUB' interface Error { - code: number; - error: string; - message: string; - stack?: string; + code: number + error: string + message: string + stack?: string } - type Headers = Record; - type Body = Record; + type Headers = Record + type Body = Record interface Response { - body: any; - headers: Headers; - status: number; - uri: string; - static isSuccessStatus(status: number): boolean; + body: any + headers: Headers + status: number + uri: string + // eslint-disable-next-line @typescript-eslint/method-signature-style + static isSuccessStatus(status: number): boolean } - function head(url: string, headers?: Headers): Promise; - function get(url: string, body?: Body, headers?: Headers): Promise; - function post(url: string, body?: Body, headers?: Headers): Promise; - function put(url: string, body?: Body, headers?: Headers): Promise; - function del(url: string, body?: Body, headers?: Headers): Promise; - function patch(url: string, body?: Body, headers?: Headers): Promise; - function sub(url: string, callback: ((b: Response.body) => void), onError?: ((e: Error) => void), body?: Body, headers?: Headers): Promise; - function postSub(url: string, body?: Body, callback: ((b: Response.body) => void), onError?: ((e: Error) => void)): Promise; - function request(method: Method, url: string, body?: Body, headers?: Headers): Promise; - function resolve(method: Method, url: string, body?: Body, headers?: Headers): Promise; + function head (url: string, headers?: Headers): Promise + function get (url: string, body?: Body, headers?: Headers): Promise + function post (url: string, body?: Body, headers?: Headers): Promise + function put (url: string, body?: Body, headers?: Headers): Promise + function del (url: string, body?: Body, headers?: Headers): Promise + function patch (url: string, body?: Body, headers?: Headers): Promise + function sub (url: string, callback: ((b: Response.body) => void), onError?: ((e: Error) => void), body?: Body, headers?: Headers): Promise + function postSub (url: string, body?: Body, callback: ((b: Response.body) => void), onError?: ((e: Error) => void)): Promise + function request (method: Method, url: string, body?: Body, headers?: Headers): Promise + function resolve (method: Method, url: string, body?: Body, headers?: Headers): Promise } /** * Fetch interesting colors from URI. * @param uri Any type of URI that has artwork (playlist, track, album, artist, show, ...) */ - function colorExtractor(uri: string): Promise<{ - DESATURATED: string; - LIGHT_VIBRANT: string; - PROMINENT: string; - VIBRANT: string; - VIBRANT_NON_ALARMING: string; - }>; + function colorExtractor (uri: string): Promise<{ + DESATURATED: string + LIGHT_VIBRANT: string + PROMINENT: string + VIBRANT: string + VIBRANT_NON_ALARMING: string + }> /** * @deprecated */ - function getAblumArtColors(): any; + function getAblumArtColors (): any /** * Fetch track analyzed audio data. * Beware, not all tracks have audio data. * @param uri is optional. Leave it blank to get current track * or specify another track uri. */ - function getAudioData(uri?: string): Promise; + function getAudioData (uri?: string): Promise /** * Set of APIs method to register, deregister hotkeys/shortcuts */ namespace Keyboard { - type ValidKey = "BACKSPACE" | "TAB" | "ENTER" | "SHIFT" | "CTRL" | "ALT" | "CAPS" | "ESCAPE" | "SPACE" | "PAGE_UP" | "PAGE_DOWN" | "END" | "HOME" | "ARROW_LEFT" | "ARROW_UP" | "ARROW_RIGHT" | "ARROW_DOWN" | "INSERT" | "DELETE" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "WINDOW_LEFT" | "WINDOW_RIGHT" | "SELECT" | "NUMPAD_0" | "NUMPAD_1" | "NUMPAD_2" | "NUMPAD_3" | "NUMPAD_4" | "NUMPAD_5" | "NUMPAD_6" | "NUMPAD_7" | "NUMPAD_8" | "NUMPAD_9" | "MULTIPLY" | "ADD" | "SUBTRACT" | "DECIMAL_POINT" | "DIVIDE" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12" | ";" | "=" | " | " | "-" | "." | "/" | "`" | "[" | "\\" | "]" | "\"" | "~" | "!" | "@" | "#" | "$" | "%" | "^" | "&" | "*" | "(" | ")" | "_" | "+" | ":" | "<" | ">" | "?" | "|"; + type ValidKey = 'BACKSPACE' | 'TAB' | 'ENTER' | 'SHIFT' | 'CTRL' | 'ALT' | 'CAPS' | 'ESCAPE' | 'SPACE' | 'PAGE_UP' | 'PAGE_DOWN' | 'END' | 'HOME' | 'ARROW_LEFT' | 'ARROW_UP' | 'ARROW_RIGHT' | 'ARROW_DOWN' | 'INSERT' | 'DELETE' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | 'WINDOW_LEFT' | 'WINDOW_RIGHT' | 'SELECT' | 'NUMPAD_0' | 'NUMPAD_1' | 'NUMPAD_2' | 'NUMPAD_3' | 'NUMPAD_4' | 'NUMPAD_5' | 'NUMPAD_6' | 'NUMPAD_7' | 'NUMPAD_8' | 'NUMPAD_9' | 'MULTIPLY' | 'ADD' | 'SUBTRACT' | 'DECIMAL_POINT' | 'DIVIDE' | 'F1' | 'F2' | 'F3' | 'F4' | 'F5' | 'F6' | 'F7' | 'F8' | 'F9' | 'F10' | 'F11' | 'F12' | ';' | '=' | ' | ' | '-' | '.' | '/' | '`' | '[' | '\\' | ']' | '"' | '~' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')' | '_' | '+' | ':' | '<' | '>' | '?' | '|' type KeysDefine = string | { - key: string; - ctrl?: boolean; - shift?: boolean; - alt?: boolean; - meta?: boolean; - }; - const KEYS: Record; - function registerShortcut(keys: KeysDefine, callback: (event: KeyboardEvent) => void); - function registerIsolatedShortcut(keys: KeysDefine, callback: (event: KeyboardEvent) => void); - function registerImportantShortcut(keys: KeysDefine, callback: (event: KeyboardEvent) => void); - function _deregisterShortcut(keys: KeysDefine); - function deregisterImportantShortcut(keys: KeysDefine); + key: string + ctrl?: boolean + shift?: boolean + alt?: boolean + meta?: boolean + } + const KEYS: Record + function registerShortcut (keys: KeysDefine, callback: (event: KeyboardEvent) => void) + function registerIsolatedShortcut (keys: KeysDefine, callback: (event: KeyboardEvent) => void) + function registerImportantShortcut (keys: KeysDefine, callback: (event: KeyboardEvent) => void) + function _deregisterShortcut (keys: KeysDefine) + function deregisterImportantShortcut (keys: KeysDefine) }; /** * @deprecated */ - const LiveAPI: any; + const LiveAPI: any namespace LocalStorage { - /** + /** * Empties the list associated with the object of all key/value pairs, if there are any. */ - function clear(): void; - /** + function clear (): void + /** * Get key value */ - function get(key: string): string | null; - /** + function get (key: string): string | null + /** * Delete key */ - function remove(key: string): void; - /** + function remove (key: string): void + /** * Set new value for key */ - function set(key: string, value: string): void; + function set (key: string, value: string): void } /** * To create and prepend custom menu item in profile menu. */ namespace Menu { - /** + /** * Create a single toggle. */ - class Item { - constructor(name: string, isEnabled: boolean, onClick: (self: Item) => void); - name: string; - isEnabled: boolean; - /** + class Item { + constructor (name: string, isEnabled: boolean, onClick: (self: Item) => void) + name: string + isEnabled: boolean + /** * Change item name */ - setName(name: string): void; - /** + setName (name: string): void + /** * Change item enabled state. * Visually, item would has a tick next to it if its state is enabled. */ - setState(isEnabled: boolean): void; - /** + setState (isEnabled: boolean): void + /** * Item is only available in Profile menu when method "register" is called. */ - register(): void; - /** + register (): void + /** * Stop item to be prepended into Profile menu. */ - deregister(): void; - } + deregister (): void + } - /** + /** * Create a sub menu to contain Item toggles. * `Item`s in `subItems` array shouldn't be registered. */ - class SubMenu { - constructor(name: string, subItems: Item[]); - name: string; - /** + class SubMenu { + constructor (name: string, subItems: Item[]) + name: string + /** * Change SubMenu name */ - setName(name: string): void; - /** + setName (name: string): void + /** * Add an item to sub items list */ - addItem(item: Item); - /** + addItem (item: Item) + /** * Remove an item from sub items list */ - removeItem(item: Item); - /** + removeItem (item: Item) + /** * SubMenu is only available in Profile menu when method "register" is called. */ - register(): void; - /** + register (): void + /** * Stop SubMenu to be prepended into Profile menu. */ - deregister(): void; - } + deregister (): void + } } /** @@ -425,124 +424,125 @@ declare namespace Spicetify { * Spicetify.Keyboard is wrapper of this library to be compatible with legacy Spotify, * so new extension should use this library instead. */ - function Mousetrap(element?: any): void; + function Mousetrap (element?: any): void /** * Contains vast array of internal APIs. * Please explore in Devtool Console. */ - const Platform: any; + const Platform: any /** * Queue object contains list of queuing tracks, * history of played tracks and current track metadata. */ const Queue: { - nextTracks: any[]; - prevTracks: any[]; - queueRevision: string; - track: any; - }; + nextTracks: any[] + prevTracks: any[] + queueRevision: string + track: any + } /** * Remove a track/album or array of tracks/albums from current queue. */ - function removeFromQueue(uri: string | string[]): Promise; + function removeFromQueue (uri: string | string[]): Promise /** * Display a bubble of notification. Useful for a visual feedback. */ - function showNotification(text: string): void; + function showNotification (text: string): void /** * Set of APIs method to parse and validate URIs. */ class URI { - constructor(type: string, props: any); - public type: string; - public id: string; + constructor (type: string, props: any) + public type: string + public id: string - /** + /** * Creates an application URI object from the current URI object. * * If the current URI object is already an application type, a copy is made. * * @return The current URI as an application URI. */ - toAppType(): URI; + toAppType (): URI - /** + /** * Creates a URI object from an application URI object. * * If the current URI object is not an application type, a copy is made. * * @return The current URI as a real typed URI. */ - toRealType(): URI; + toRealType (): URI - /** + /** * * @return The URI representation of this uri. */ - toURI(): string; + toURI (): string - /** + /** * * @return The URI representation of this uri. */ - toString(): string; + toString (): string - /** + /** * Get the URL path of this uri. * * @param opt_leadingSlash True if a leading slash should be prepended. * @return The path of this uri. */ - toURLPath(opt_leadingSlash: boolean): string; + // eslint-disable-next-line @typescript-eslint/naming-convention + toURLPath (opt_leadingSlash: boolean): string - /** + /** * * @return The Play URL string for the uri. */ - toPlayURL(): string; + toPlayURL (): string - /** + /** * * @return The URL string for the uri. */ - toURL(): string; + toURL (): string - /** + /** * * @return The Open URL string for the uri. */ - toOpenURL(): string; + toOpenURL (): string - /** + /** * * @return The Play HTTPS URL string for the uri. */ - toSecurePlayURL(): string; + toSecurePlayURL (): string - /** + /** * * @return The HTTPS URL string for the uri. */ - toSecureURL(): string; + toSecureURL (): string - /** + /** * * @return The Open HTTPS URL string for the uri. */ - toSecureOpenURL(): string; + toSecureOpenURL (): string - /** + /** * * @return The id of the uri as a bytestring. */ - idToByteString(): string; + idToByteString (): string - getPath(): string; + getPath (): string - getBase62Id(): string; + getBase62Id (): string - /** + /** * Checks whether two URI:s refer to the same thing even though they might * not necessarily be equal. * @@ -554,75 +554,75 @@ declare namespace Spicetify { * @param uri The uri to compare identity for. * @return Whether they shared idenitity */ - isSameIdentity(uri: any): boolean; + isSameIdentity (uri: any): boolean - /** + /** * The various URI Types. * * Note that some of the types in this enum are not real URI types, but are * actually URI particles. They are marked so. * */ - static Type: { - EMPTY: string; - ALBUM: string; - AD: string; - /** URI particle; not an actual URI. */ - APP: string; - APPLICATION: string; - ARTIST: string; - ARTIST_TOPLIST: string; - AUDIO_FILE: string; - COLLECTION: string; - COLLECTION_ALBUM: string; - COLLECTION_MISSING_ALBUM: string; - COLLECTION_ARTIST: string; - CONTEXT_GROUP: string; - DAILY_MIX: string; - EPISODE: string; - /** URI particle; not an actual URI. */ - FACEBOOK: string; - FOLDER: string; - FOLLOWERS: string; - FOLLOWING: string; - /** URI particle; not an actual URI. */ - GLOBAL: string; - IMAGE: string; - INBOX: string; - INTERRUPTION: string; - LOCAL_ARTIST: string; - LOCAL_ALBUM: string; - LOCAL: string; - LIBRARY: string; - MOSAIC: string; - PLAYLIST: string; - /** Only used for URI classification. Not a valid URI fragment. */ - PLAYLIST_V2: string; - PROFILE: string; - PUBLISHED_ROOTLIST: string; - RADIO: string; - ROOTLIST: string; - COLLECTION_TRACK_LIST: string; - SEARCH: string; - SHOW: string; - SOCIAL_SESSION: string, - CONCERT: string; - SPECIAL: string; - STARRED: string; - STATION: string; - TEMP_PLAYLIST: string; - /** URI particle; not an actual URI. */ - TOP: string; - TOPLIST: string; - TRACK: string; - TRACKSET: string; - /** URI particle; not an actual URI. */ - USER: string; - USER_TOPLIST: string; - USER_TOP_TRACKS: string; - }; - - /** + static Type: { + EMPTY: string + ALBUM: string + AD: string + /** URI particle; not an actual URI. */ + APP: string + APPLICATION: string + ARTIST: string + ARTIST_TOPLIST: string + AUDIO_FILE: string + COLLECTION: string + COLLECTION_ALBUM: string + COLLECTION_MISSING_ALBUM: string + COLLECTION_ARTIST: string + CONTEXT_GROUP: string + DAILY_MIX: string + EPISODE: string + /** URI particle; not an actual URI. */ + FACEBOOK: string + FOLDER: string + FOLLOWERS: string + FOLLOWING: string + /** URI particle; not an actual URI. */ + GLOBAL: string + IMAGE: string + INBOX: string + INTERRUPTION: string + LOCAL_ARTIST: string + LOCAL_ALBUM: string + LOCAL: string + LIBRARY: string + MOSAIC: string + PLAYLIST: string + /** Only used for URI classification. Not a valid URI fragment. */ + PLAYLIST_V2: string + PROFILE: string + PUBLISHED_ROOTLIST: string + RADIO: string + ROOTLIST: string + COLLECTION_TRACK_LIST: string + SEARCH: string + SHOW: string + SOCIAL_SESSION: string + CONCERT: string + SPECIAL: string + STARRED: string + STATION: string + TEMP_PLAYLIST: string + /** URI particle; not an actual URI. */ + TOP: string + TOPLIST: string + TRACK: string + TRACKSET: string + /** URI particle; not an actual URI. */ + USER: string + USER_TOPLIST: string + USER_TOP_TRACKS: string + } + + /** * Creates a new URI object from a parsed string argument. * * @param str The string that will be parsed into a URI object. @@ -630,9 +630,9 @@ declare namespace Spicetify { * be thrown. * @return The parsed URI object. */ - static fromString(str: string): URI; + static fromString (str: string): URI - /** + /** * Parses a given object into a URI instance. * * Unlike URI.fromString, this function could receive any kind of value. If @@ -646,9 +646,9 @@ declare namespace Spicetify { * @return The corresponding URI instance, or null if the * passed value is not a valid value. */ - static from(value: any): URI | null; + static from (value: any): URI | null - /** + /** * Creates a new URI from a bytestring. * * @param type The type of the URI. @@ -656,115 +656,116 @@ declare namespace Spicetify { * @param opt_args Optional arguments to the URI constructor. * @return The URI object created. */ - static fromByteString(type: string, idByteString: string, opt_args?: any): URI; + // eslint-disable-next-line @typescript-eslint/naming-convention + static fromByteString (type: string, idByteString: string, opt_args?: any): URI - /** + /** * Clones a given SpotifyURI instance. * * @param uri The uri to clone. * @return An instance of URI. */ - static clone(uri: URI): URI | null; + static clone (uri: URI): URI | null - /** + /** * Returns the canonical representation of a username. * * @param username The username to encode. * @return The encoded canonical representation of the username. */ - static getCanonicalUsername(username: string): string; + static getCanonicalUsername (username: string): string - /** + /** * Returns the non-canonical representation of a username. * * @param username The username to encode. * @return The unencoded canonical representation of the username. */ - static getDisplayUsername(username: string): string; + static getDisplayUsername (username: string): string - /** + /** * Returns the hex representation of a Base62 encoded id. * * @param id The base62 encoded id. * @return The hex representation of the base62 id. */ - static idToHex(id: string): string; + static idToHex (id: string): string - /** + /** * Returns the base62 representation of a hex encoded id. * * @param hex The hex encoded id. * @return The base62 representation of the id. */ - static hexToId(hex: string): string; + static hexToId (hex: string): string - /** + /** * Creates a new empty URI. * * @return The empty URI. */ - static emptyURI(): URI; + static emptyURI (): URI - /** + /** * Creates a new 'album' type URI. * * @param id The id of the album. * @param disc The disc number of the album. * @return The album URI. */ - static albumURI(id: string, disc: number): URI; + static albumURI (id: string, disc: number): URI - /** + /** * Creates a new 'ad' type URI. * * @param id The id of the ad. * @return The ad URI. */ - static adURI(id: string): URI; + static adURI (id: string): URI - /** + /** * Creates a new 'audiofile' type URI. * * @param extension The extension of the audiofile. * @param id The id of the extension. * @return The audiofile URI. */ - static audioFileURI(extension: string, id: string): URI; + static audioFileURI (extension: string, id: string): URI - /** + /** * Creates a new 'artist' type URI. * * @param id The id of the artist. * @return The artist URI. */ - static artistURI(id: string): URI; + static artistURI (id: string): URI - /** + /** * Creates a new 'artist-toplist' type URI. * * @param id The id of the artist. * @param toplist The toplist type. * @return The artist-toplist URI. */ - static artistToplistURI(id: string, toplist: string): URI; + static artistToplistURI (id: string, toplist: string): URI - /** + /** * Creates a new 'dailymix' type URI. * * @param args An array of arguments for the dailymix. * @return The dailymix URI. */ - static dailyMixURI(args: string[]): URI; + static dailyMixURI (args: string[]): URI - /** + /** * Creates a new 'search' type URI. * * @param query The unencoded search query. * @return The search URI */ - static searchURI(query: string): URI; + static searchURI (query: string): URI - /** + /** * Creates a new 'track' type URI. * * @param id The id of the track. @@ -773,9 +774,9 @@ declare namespace Spicetify { * @param play Toggles autoplay * @return The track URI. */ - static trackURI(id: string, anchor: string, context: string, play: boolean): URI; + static trackURI (id: string, anchor: string, context: string, play: boolean): URI - /** + /** * Creates a new 'trackset' type URI. * * @param tracks An array of 'track' type URIs. @@ -783,94 +784,94 @@ declare namespace Spicetify { * @param index The index in the trackset. * @return The trackset URI. */ - static tracksetURI(tracks: URI[], name: string, index: number): URI; + static tracksetURI (tracks: URI[], name: string, index: number): URI - /** + /** * Creates a new 'facebook' type URI. * * @param uid The user id. * @return The facebook URI. */ - static facebookURI(uid: string): URI; + static facebookURI (uid: string): URI - /** + /** * Creates a new 'followers' type URI. * * @param username The non-canonical username. * @return The followers URI. */ - static followersURI(username: string): URI; + static followersURI (username: string): URI - /** + /** * Creates a new 'following' type URI. * * @param username The non-canonical username. * @return The following URI. */ - static followingURI(username: string): URI; + static followingURI (username: string): URI - /** + /** * Creates a new 'playlist' type URI. * * @param username The non-canonical username of the playlist owner. * @param id The id of the playlist. * @return The playlist URI. */ - static playlistURI(username: string, id: string): URI; + static playlistURI (username: string, id: string): URI - /** + /** * Creates a new 'playlist-v2' type URI. * * @param id The id of the playlist. * @return The playlist URI. */ - static playlistV2URI(id: string): URI; + static playlistV2URI (id: string): URI - /** + /** * Creates a new 'folder' type URI. * * @param username The non-canonical username of the folder owner. * @param id The id of the folder. * @return The folder URI. */ - static folderURI(username: string, id: string): URI; + static folderURI (username: string, id: string): URI - /** + /** * Creates a new 'collectiontracklist' type URI. * * @param username The non-canonical username of the collection owner. * @param id The id of the tracklist. * @return The collectiontracklist URI. */ - static collectionTrackList(username: string, id: string): URI; + static collectionTrackList (username: string, id: string): URI - /** + /** * Creates a new 'starred' type URI. * * @param username The non-canonical username of the starred list owner. * @return The starred URI. */ - static starredURI(username: string): URI; + static starredURI (username: string): URI - /** + /** * Creates a new 'user-toplist' type URI. * * @param username The non-canonical username of the toplist owner. * @param toplist The toplist type. * @return The user-toplist URI. */ - static userToplistURI(username: string, toplist: string): URI; + static userToplistURI (username: string, toplist: string): URI - /** + /** * Creates a new 'user-top-tracks' type URI. * * @deprecated * @param username The non-canonical username of the toplist owner. * @return The user-top-tracks URI. */ - static userTopTracksURI(username: string): URI; + static userTopTracksURI (username: string): URI - /** + /** * Creates a new 'toplist' type URI. * * @param toplist The toplist type. @@ -878,50 +879,50 @@ declare namespace Spicetify { * @param global True if this is a global rather than a country list. * @return The toplist URI. */ - static toplistURI(toplist: string, country: string, global: boolean): URI; + static toplistURI (toplist: string, country: string, global: boolean): URI - /** + /** * Creates a new 'inbox' type URI. * * @param username The non-canonical username of the inbox owner. * @return The inbox URI. */ - static inboxURI(username: string): URI; + static inboxURI (username: string): URI - /** + /** * Creates a new 'rootlist' type URI. * * @param username The non-canonical username of the rootlist owner. * @return The rootlist URI. */ - static rootlistURI(username: string): URI; + static rootlistURI (username: string): URI - /** + /** * Creates a new 'published-rootlist' type URI. * * @param username The non-canonical username of the published-rootlist owner. * @return The published-rootlist URI. */ - static publishedRootlistURI(username: string): URI; + static publishedRootlistURI (username: string): URI - /** + /** * Creates a new 'local-artist' type URI. * * @param artist The artist name. * @return The local-artist URI. */ - static localArtistURI(artist: string): URI; + static localArtistURI (artist: string): URI - /** + /** * Creates a new 'local-album' type URI. * * @param artist The artist name. * @param album The album name. * @return The local-album URI. */ - static localAlbumURI(artist: string, album: string): URI; + static localAlbumURI (artist: string, album: string): URI - /** + /** * Creates a new 'local' type URI. * * @param artist The artist name. @@ -930,36 +931,36 @@ declare namespace Spicetify { * @param duration The track duration in ms. * @return The local URI. */ - static localURI(artist: string, album: string, track: string, duration: number): URI; + static localURI (artist: string, album: string, track: string, duration: number): URI - /** + /** * Creates a new 'library' type URI. * * @param username The non-canonical username of the rootlist owner. * @param category The category of the library. * @return The library URI. */ - static libraryURI(username: string, category: string): URI; + static libraryURI (username: string, category: string): URI - /** + /** * Creates a new 'collection' type URI. * * @param username The non-canonical username of the rootlist owner. * @param category The category of the collection. * @return The collection URI. */ - static collectionURI(username: string, category: string): URI; + static collectionURI (username: string, category: string): URI - /** + /** * Creates a new 'temp-playlist' type URI. * * @param origin The origin of the temporary playlist. * @param data Additional data for the playlist. * @return The temp-playlist URI. */ - static temporaryPlaylistURI(origin: string, data: string): URI; + static temporaryPlaylistURI (origin: string, data: string): URI - /** + /** * Creates a new 'context-group' type URI. * * @deprecated @@ -967,95 +968,94 @@ declare namespace Spicetify { * @param name The name of the context group. * @return The context-group URI. */ - static contextGroupURI(origin: string, name: string): URI; + static contextGroupURI (origin: string, name: string): URI - /** + /** * Creates a new 'profile' type URI. * * @param username The non-canonical username of the rootlist owner. * @param args A list of arguments. * @return The profile URI. */ - static profileURI(username: string, args: string[]): URI; + static profileURI (username: string, args: string[]): URI - /** + /** * Creates a new 'image' type URI. * * @param id The id of the image. * @return The image URI. */ - static imageURI(id: string): URI; - + static imageURI (id: string): URI - /** + /** * Creates a new 'mosaic' type URI. * * @param ids The ids of the mosaic immages. * @return The mosaic URI. */ - static mosaicURI(ids: string[]): URI; + static mosaicURI (ids: string[]): URI - /** + /** * Creates a new 'radio' type URI. * * @param args The radio seed arguments. * @return The radio URI. */ - static radioURI(args: string): URI; + static radioURI (args: string): URI - /** + /** * Creates a new 'special' type URI. * * @param args An array containing the other arguments. * @return The special URI. */ - static specialURI(args: string[]): URI; + static specialURI (args: string[]): URI - /** + /** * Creates a new 'station' type URI. * * @param args An array of arguments for the station. * @return The station URI. */ - static stationURI(args: string[]): URI; + static stationURI (args: string[]): URI - /** + /** * Creates a new 'application' type URI. * * @param id The id of the application. * @param args An array containing the arguments to the app. * @return The application URI. */ - static applicationURI(id: string, args: string[]): URI; + static applicationURI (id: string, args: string[]): URI - /** + /** * Creates a new 'collection-album' type URI. * * @param username The non-canonical username of the rootlist owner. * @param id The id of the album. * @return The collection-album URI. */ - static collectionAlbumURI(username: string, id: string): URI; + static collectionAlbumURI (username: string, id: string): URI - /** + /** * Creates a new 'collection-album-missing' type URI. * * @param username The non-canonical username of the rootlist owner. * @param id The id of the album. * @return The collection-album-missing URI. */ - static collectionMissingAlbumURI(username: string, id: string): URI; + static collectionMissingAlbumURI (username: string, id: string): URI - /** + /** * Creates a new 'collection-artist' type URI. * * @param username The non-canonical username of the rootlist owner. * @param id The id of the artist. * @return The collection-artist URI. */ - static collectionArtistURI(username: string, id: string): URI; + static collectionArtistURI (username: string, id: string): URI - /** + /** * Creates a new 'episode' type URI. * * @param id The id of the episode. @@ -1063,104 +1063,104 @@ declare namespace Spicetify { * @param play Toggles autoplay in the episode URI * @return The episode URI. */ - static episodeURI(id: string, context: string, play: boolean): URI; + static episodeURI (id: string, context: string, play: boolean): URI - /** + /** * Creates a new 'show' type URI. * * @param id The id of the show. * @return The show URI. */ - static showURI(id: string): URI; + static showURI (id: string): URI - /** + /** * Creates a new 'concert' type URI. * * @param id The id of the concert. * @return The concert URI. */ - static concertURI(id: string): URI; + static concertURI (id: string): URI - /** + /** * Creates a new 'socialsession' type URI. * * @param id The token needed to join a social session. * @return The socialsession URI. */ - static socialSessionURI(id: string): URI; + static socialSessionURI (id: string): URI - /** + /** * Creates a new 'interruption' type URI. * * @param id The id of the interruption. * @return The ad URI. */ - static interruptionURI(id: string): URI; - - static isAlbum(uri: any): boolean; - static isAd(uri: any): boolean; - static isApplication(uri: any): boolean; - static isArtist(uri: any): boolean; - static isCollection(uri: any): boolean; - static isCollectionAlbum(uri: any): boolean; - static isCollectionArtist(uri: any): boolean; - static isDailyMix(uri: any): boolean; - static isEpisode(uri: any): boolean; - static isFacebook(uri: any): boolean; - static isFolder(uri: any): boolean; - static isLocalArtist(uri: any): boolean; - static isLocalAlbum(uri: any): boolean; - static isLocalTrack(uri: any): boolean; - static isMosaic(uri: any): boolean; - static isPlaylistV1(uri: any): boolean; - static isPlaylistV2(uri: any): boolean; - static isRadio(uri: any): boolean; - static isRootlist(uri: any): boolean; - static isSearch(uri: any): boolean; - static isShow(uri: any): boolean; - static isConcert(uri: any): boolean; - static isStation(uri: any): boolean; - static isTrack(uri: any): boolean; - static isProfile(uri: any): boolean; - static isPlaylistV1OrV2(uri: any): boolean; - static isSocialSession(uri: any): boolean; - static isInterruption(uri: any): boolean; + static interruptionURI (id: string): URI + + static isAlbum (uri: any): boolean + static isAd (uri: any): boolean + static isApplication (uri: any): boolean + static isArtist (uri: any): boolean + static isCollection (uri: any): boolean + static isCollectionAlbum (uri: any): boolean + static isCollectionArtist (uri: any): boolean + static isDailyMix (uri: any): boolean + static isEpisode (uri: any): boolean + static isFacebook (uri: any): boolean + static isFolder (uri: any): boolean + static isLocalArtist (uri: any): boolean + static isLocalAlbum (uri: any): boolean + static isLocalTrack (uri: any): boolean + static isMosaic (uri: any): boolean + static isPlaylistV1 (uri: any): boolean + static isPlaylistV2 (uri: any): boolean + static isRadio (uri: any): boolean + static isRootlist (uri: any): boolean + static isSearch (uri: any): boolean + static isShow (uri: any): boolean + static isConcert (uri: any): boolean + static isStation (uri: any): boolean + static isTrack (uri: any): boolean + static isProfile (uri: any): boolean + static isPlaylistV1OrV2 (uri: any): boolean + static isSocialSession (uri: any): boolean + static isInterruption (uri: any): boolean } /** * Create custom menu item and prepend to right click context menu */ namespace ContextMenu { - type Icon = "album" | "artist" | "block" | "chart-down" | "chart-up" | "check" | "check-alt-fill" | "chevron-left" | "chevron-right" | "chromecast-disconnected" | "copy" | "download" | "downloaded" | "edit" | "exclamation-circle" | "external-link" | "facebook" | "follow" | "fullscreen" | "grid-view" | "heart" | "heart-active" | "instagram" | "list-view" | "locked" | "locked-active" | "lyrics" | "minimize" | "more" | "new-spotify-connect" | "offline" | "pause" | "play" | "playlist" | "playlist-folder" | "plus2px" | "plus-alt" | "podcasts" | "repeat" | "repeat-once" | "search" | "search-active" | "shuffle" | "skip-back" | "skip-back15" | "skip-forward" | "skip-forward15" | "soundbetter" | "subtitles" | "twitter" | "volume" | "volume-off" | "volume-one-wave" | "volume-two-wave" | "x"; - type OnClickCallback = (uris: string[], uids?: string[], contextUri?: string) => void; - type ShouldAddCallback = (uris: string[], uids?: string[], contextUri?: string) => boolean; + type Icon = 'album' | 'artist' | 'block' | 'chart-down' | 'chart-up' | 'check' | 'check-alt-fill' | 'chevron-left' | 'chevron-right' | 'chromecast-disconnected' | 'copy' | 'download' | 'downloaded' | 'edit' | 'exclamation-circle' | 'external-link' | 'facebook' | 'follow' | 'fullscreen' | 'grid-view' | 'heart' | 'heart-active' | 'instagram' | 'list-view' | 'locked' | 'locked-active' | 'lyrics' | 'minimize' | 'more' | 'new-spotify-connect' | 'offline' | 'pause' | 'play' | 'playlist' | 'playlist-folder' | 'plus2px' | 'plus-alt' | 'podcasts' | 'repeat' | 'repeat-once' | 'search' | 'search-active' | 'shuffle' | 'skip-back' | 'skip-back15' | 'skip-forward' | 'skip-forward15' | 'soundbetter' | 'subtitles' | 'twitter' | 'volume' | 'volume-off' | 'volume-one-wave' | 'volume-two-wave' | 'x' + type OnClickCallback = (uris: string[], uids?: string[], contextUri?: string) => void + type ShouldAddCallback = (uris: string[], uids?: string[], contextUri?: string) => boolean // Single context menu item class Item { - /** + /** * List of valid icons to use. */ - static readonly iconList: Icon[]; - constructor(name: string, onClick: OnClickCallback, shouldAdd?: ShouldAddCallback, icon?: Icon, disabled?: boolean); - name: string; - icon: Icon | string; - disabled: boolean; - /** + static readonly iconList: Icon[] + constructor (name: string, onClick: OnClickCallback, shouldAdd?: ShouldAddCallback, icon?: Icon, disabled?: boolean) + name: string + icon: Icon | string + disabled: boolean + /** * A function returning boolean determines whether item should be prepended. */ - shouldAdd: ShouldAddCallback; - /** + shouldAdd: ShouldAddCallback + /** * A function to call when item is clicked */ - onClick: OnClickCallback; - /** + onClick: OnClickCallback + /** * Item is only available in Context Menu when method "register" is called. */ - register: () => void; - /** + register: () => void + /** * Stop Item to be prepended into Context Menu. */ - deregister: () => void; + deregister: () => void } /** @@ -1168,23 +1168,23 @@ declare namespace Spicetify { * `Item`s in `subItems` array shouldn't be registered. */ class SubMenu { - constructor(name: string, subItems: Iterable, shouldAdd?: ShouldAddCallback, disabled?: boolean); - name: string; - disabled: boolean; - /** + constructor (name: string, subItems: Iterable, shouldAdd?: ShouldAddCallback, disabled?: boolean) + name: string + disabled: boolean + /** * A function returning boolean determines whether item should be prepended. */ - shouldAdd: ShouldAddCallback; - addItem: (item: Item) => void; - removeItem: (item: Item) => void; - /** + shouldAdd: ShouldAddCallback + addItem: (item: Item) => void + removeItem: (item: Item) => void + /** * SubMenu is only available in Context Menu when method "register" is called. */ - register: () => void; - /** + register: () => void + /** * Stop SubMenu to be prepended into Context Menu. */ - deregister: () => void; + deregister: () => void } } @@ -1192,135 +1192,135 @@ declare namespace Spicetify { * Popup Modal */ namespace PopupModal { - interface Content { - title: string; - /** + interface Content { + title: string + /** * You can specify a string for simple text display * or a HTML element for interactive config/setting menu */ - content: string | Element; - /** + content: string | Element + /** * Bigger window */ - isLarge?: boolean; - } + isLarge?: boolean + } - function display(e: Content): void; - function hide(): void; + function display (e: Content): void + function hide (): void } /** React instance to create components */ - const React: any; + const React: any /** React DOM instance to render and mount components */ - const ReactDOM: any; + const ReactDOM: any /** Stock React components exposed from Spotify library */ namespace ReactComponent { - type ContextMenuProps = { - /** + interface ContextMenuProps { + /** * Decide whether to use the global singleton context menu (rendered in ) * or a new inline context menu (rendered in a sibling * element to `children`) */ - renderInline?: boolean; - /** + renderInline?: boolean + /** * Determins what will trigger the context menu. For example, a click, or a right-click */ - trigger?: 'click' | 'right-click'; - /** + trigger?: 'click' | 'right-click' + /** * Determins is the context menu should open or toggle when triggered */ - action?: 'toggle' | 'open'; - /** + action?: 'toggle' | 'open' + /** * The preferred placement of the context menu when it opens. * Relative to trigger element. */ - placement?: 'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end'; - /** + placement?: 'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' + /** * The x and y offset distances at which the context menu should open. * Relative to trigger element and `position`. */ - offset?: [number, number]; - /** + offset?: [number, number] + /** * Will stop the client from scrolling while the context menu is open */ - preventScrollingWhileOpen?: boolean; - /** + preventScrollingWhileOpen?: boolean + /** * The menu UI to render inside of the context menu. */ - menu: Spicetify.ReactComponent.Menu | - Spicetify.ReactComponent.AlbumMenu | - Spicetify.ReactComponent.PodcastShowMenu | - Spicetify.ReactComponent.ArtistMenu | - Spicetify.ReactComponent.PlaylistMenu; - /** + menu: Spicetify.ReactComponent.Menu | + Spicetify.ReactComponent.AlbumMenu | + Spicetify.ReactComponent.PodcastShowMenu | + Spicetify.ReactComponent.ArtistMenu | + Spicetify.ReactComponent.PlaylistMenu + /** * A child of the context menu. Should be `