commit af4eff6b9922b8f6eee8bc1be40b43bf21c4d081 Author: Stefano Pigozzi Date: Sun Jun 16 13:49:13 2024 +0200 First commit diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cce52e5 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# Get your API key here: +# https://steamcommunity.com/dev +STEAM_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +# Get your SteamID here: +# https://steamdb.info/calculator/ +STEAM_ID=765611XXXXXXXXXXX + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1cdad14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +_site +_cache +.env diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..8bf4d45 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,6 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..dc741b7 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,34 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d285c50 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..881763a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/peafowl.iml b/.idea/peafowl.iml new file mode 100644 index 0000000..060f1d9 --- /dev/null +++ b/.idea/peafowl.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Run.xml b/.idea/runConfigurations/Run.xml new file mode 100644 index 0000000..e64f8dd --- /dev/null +++ b/.idea/runConfigurations/Run.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..abcdf46 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,4 @@ +{ + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b2461fe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/.gitignore": true, + "_*": true, + "LICENSE-CODE.txt": true, + "deno.json": true, + "deno.lock": true, + ".vscode": true, + } +} \ No newline at end of file diff --git a/LICENSE-CODE.txt b/LICENSE-CODE.txt new file mode 100644 index 0000000..4153cd3 --- /dev/null +++ b/LICENSE-CODE.txt @@ -0,0 +1,287 @@ + EUROPEAN UNION PUBLIC LICENCE v. 1.2 + EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + + Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +1. Definitions + +In this Licence, the following terms have the following meaning: + +- ‘The Licence’: this Licence. + +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. + +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. + +- ‘The Work’: the Original Work or its Derivative Works. + +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. + +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. + +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. + +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. + +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. + +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. diff --git a/_CREDITS.md b/_CREDITS.md new file mode 100644 index 0000000..0a5d86e --- /dev/null +++ b/_CREDITS.md @@ -0,0 +1,9 @@ +# Credits + +## Inspired by + +- [The Backloggery](https://backloggery.com/) + +## A couple ideas by + +- [Gattopandacorno](https://github.com/gattopandacorno/) diff --git a/_cms.ts b/_cms.ts new file mode 100644 index 0000000..40b2747 --- /dev/null +++ b/_cms.ts @@ -0,0 +1,221 @@ +import { default as lumeCMS } from "lume/cms/mod.ts"; +import {formatDateIso} from "./_utils/date.ts" + +const cms = lumeCMS(); + + +cms.document( + "globals", + "src:_data.yml", + [ + { + name: "title", + type: "text", + label: "Site title", + description: "The main title of the site.", + attributes: { + placeholder: "Peafowl", + } + }, + { + name: "subtitle", + type: "text", + label: "Site subtitle", + description: "The caption to be displayed below the title of the site.", + attributes: { + placeholder: "Review CMS", + } + }, + ] +) + +cms.document( + "index", + "src:index.md", + [ + { + name: "content", + type: "markdown", + label: "Introduction text", + description: "The text to display at the top of the home page." + } + ] +) + +cms.document( + "list-games", + "src:list-games.md", + [ + { + name: "content", + type: "markdown", + label: "Introduction", + description: "The text to display at the top of the page." + } + ] +) + +cms.collection( + "games", + "src:games/*.md", + [ + { + name: "name", + type: "text", + label: "Name", + description: "The full name of the game.", + attributes: { + required: true, + placeholder: "Ricochet Returns" + } + }, + { + name: "name_sort", + type: "text", + label: "Sort as", + description: "If specified, when sorting games alphabetically, the game will be sorted as if this was its actual name.", + attributes: { + placeholder: "Ricochet 2" + } + }, + { + name: "active", + type: "checkbox", + label: "Now playing", + description: "Whether you're currently playing this game or not. If checked, prominently displays the game on the home page." + }, + { + name: "rating", + type: "number", + label: "Rating", + description: "The rating from 1 to 100 you want to give to the game. A rating from 1 to 35 is considered negative, from 36 to 65 mixed, from 66 to 95 positive, and from 96 to 100 perfect. A rating of 0 means unscored.", + attributes: { + placeholder: "Unscored" + } + }, + { + name: "content", + type: "markdown", + label: "Review", + description: "The review to display on the game page.", + attributes: { + placeholder: "Truly, the most *game* of all times." + } + }, + { + name: "progress", + type: "select", + label: "Progress", + description: "How much progress you've made in the game.", + options: [ + { + value: "", + label: "", + }, + { + value: "notapplicable", + label: "Not applicable: the game has nothing to progress in.", + }, + { + value: "new", + label: "New: you haven't started playing the game yet.", + }, + { + value: "started", + label: "Started: you have started the game, but not reached its end.", + }, + { + value: "beaten", + label: "Beaten: you have reached the end of the game, such as the credits, but haven't done everything yet.", + }, + { + value: "completed", + label: "Completed: you have cleared everything that this game has to offer.", + }, + { + value: "mastered", + label: "Mastered: you have overcome self-imposed challenges far greater than the ones intended by the game." + }, + ] + }, + { + name: "hours_played", + type: "number", + label: "Hours played", + description: "The number of hours you've played the game for. 0 is considered unknown; set to a negative value to explicitly state that you haven't played this game at all." + }, + { + name: "purchased_on", + type: "date", + label: "Purchased on", + description: "The date on which you've purchased the game.", + }, + { + name: "started_on", + type: "date", + label: "Started on", + description: "The date on which you've first started playing the game.", + }, + { + name: "beaten_on", + type: "date", + label: "Beaten on", + description: "The date on which you've first beaten the game.", + }, + { + name: "completed_on", + type: "date", + label: "Completed on", + description: "The date on which you've first completed the game.", + }, + { + name: "mastered_on", + type: "date", + label: "Mastered on", + description: "The date on which you've achieved mastery of the game.", + }, + { + name: "identifiers", + type: "choose-list", + label: "Identifiers", + description: "Details that unequivocabily and globally identify the game. Shouldn't be edited manually.", + fields: [ + { + name: "steam", + type: "object", + label: "Steam", + description: "", + fields: [ + { + name: "platform", + type: "hidden", + label: "Platform", + value: "steam", + }, + { + name: "appid", + type: "text", + label: "AppID", + description: "The AppID that the game has on Steam. Usually ends with a 0. Can be obtained from the store page link, after the /app/ segment.", + }, + { + name: "name", + type: "text", + label: "Name", + description: "The title of the game, as it appears on Steam." + }, + { + name: "synced_on", + type: "date", + label: "Last sync", + description: "The date of the last sync." + } + ] + } + ] + } + ] +) + + +export default cms; diff --git a/_components/GameRow.tsx b/_components/GameRow.tsx new file mode 100644 index 0000000..b1dc68a --- /dev/null +++ b/_components/GameRow.tsx @@ -0,0 +1,101 @@ +import {formatDateIso} from "../_utils/date.ts" +import {GameData} from "../_utils/game.ts" +import {Progress, progressToClassName, progressToIconDef, progressToTitle} from "../_utils/progress.ts" +import {ratingToClassName} from "../_utils/rating.ts" + + +export type GameRowColumnKind = "rating" | "progress" | "name" | "hascontent" | "date" | "hoursplayed" +export type GameRowColumnPriority = undefined | "rating" | "progress" | "mixed" + +export const gameRowColumnKindDefault: GameRowColumnKind[] = ["rating", "name", "hascontent", "date", "progress", "hoursplayed"] + + +export type GameRowProps = { + game: GameData, + columns?: GameRowColumnKind[] + priority?: GameRowColumnPriority +} + + +export function GameRow({game, columns = gameRowColumnKindDefault, priority}: GameRowProps) { + const activeClass: string = game.active ? "review-active" : "" + const activeClassFa: string = game.active ? "fa-beat-fade" : "" + + const ratingText: string = game.rating ? `${game.rating}` : "" + + const ratingClass: string = ratingToClassName(game.rating) + + const progressClass: string = progressToClassName(game.progress) + const progressIcon: string = progressToIconDef(game.progress) + const progressTitle: string = progressToTitle(game.progress) + + const priorityClass: string = priority ? `priority-${priority}` : "" + + const columnsElements = columns.map((kind, index) => { + switch(kind) { + case "rating": { + return ( + + + {ratingText} + + + ) + } + case "progress": { + return ( + + + {progressIcon && } + + + ) + } + case "name": { + return ( + + + + {game.name} + + + + ) + } + case "hascontent": { + return ( + + + + + + ) + } + case "date": { + const date = formatDateIso(game.date) + return ( + + + + ) + } + case "hoursplayed": { + return ( + + + {(game.hours_played ?? 0) > 0 ? `${game.hours_played} h` : ""} + + + ) + } + } + }) + + return ( + + {columnsElements} + + ) +} \ No newline at end of file diff --git a/_components/GameTable.tsx b/_components/GameTable.tsx new file mode 100644 index 0000000..c4f7c46 --- /dev/null +++ b/_components/GameTable.tsx @@ -0,0 +1,103 @@ +import {GameData} from "../_utils/game.ts" +import {GameRow, GameRowColumnKind, gameRowColumnKindDefault, GameRowColumnPriority} from "./GameRow.tsx" + + +export type GameTableProps = { + games: GameData[], + columns?: GameRowColumnKind[] + priority?: GameRowColumnPriority +} + + +export function GameTable({games, columns = gameRowColumnKindDefault, priority}: GameTableProps) { + const colElements = columns.map((column, index) => { + switch(column) { + case "rating": return ( + + ) + case "progress": return ( + + ) + case "name": return ( + + ) + case "hascontent": return ( + + ) + case "date": return ( + + ) + case "hoursplayed": return ( + + ) + } + }) + + const thElements = columns.map((column, index) => { + switch(column) { + case "rating": return ( + + + + + + ) + case "progress": return ( + + + + + + ) + case "name": return ( + + + Title + + + ) + case "hascontent": return ( + + + + + + ) + case "date": return ( + + + Date + + + ) + case "hoursplayed": return ( + + + Playtime + + + ) + + } + }) + + const trTdElements = games.map((game: GameData) => ( + + )) + + return ( + + + {colElements} + + + + {thElements} + + + + {trTdElements} + +
+ ) +} \ No newline at end of file diff --git a/_components/ReviewInfo.tsx b/_components/ReviewInfo.tsx new file mode 100644 index 0000000..eed4fe7 --- /dev/null +++ b/_components/ReviewInfo.tsx @@ -0,0 +1,75 @@ +import {React} from "https://deno.land/x/lume@v2.2.1/deps/react.ts" +import {ratingToClassName} from "../_utils/rating.ts" + + +export type ReviewInfoProps = { + name?: string, + rating?: number, + metadata?: React.ReactNode, + children?: React.ReactNode, +} + +export function ReviewInfo({name, rating, metadata, children}: ReviewInfoProps) { + const reviewBarStyle = {} + if(rating) { + reviewBarStyle["width"] = `${rating}%` + } + + const ratingClass = ratingToClassName(rating); + + return ( +
+

+ + {name} + +

+
+ + {rating} + +
+
+
+
+
+
+ {metadata} +
+
+ {children} +
+
+ ) +} + +export type ReviewInfoMetadataRowProps = { + label?: React.ReactNode, + icon?: React.ReactNode, + className?: string, + children?: React.ReactNode +} + +ReviewInfo.MetadataRow = function ReviewInfoMetadataRow({label, icon, className, children}: ReviewInfoMetadataRowProps) { + return <> +
+
+ {label} +
+
+
+ {icon && +
+ {icon} +
+ } +
+ {children} +
+
+ +} diff --git a/_config.ts b/_config.ts new file mode 100644 index 0000000..254c9af --- /dev/null +++ b/_config.ts @@ -0,0 +1,88 @@ +import {default as lume} from "lume/mod.ts"; +import {default as jsx} from "lume/plugins/jsx.ts" +import {default as feed} from "lume/plugins/feed.ts" +import fileData from "./_plugins/fileData.ts" + + +const site = lume({ + prettyUrls: false, +}) + +site.use(jsx({})) + +site.copy("_static") + +site.data("styles", ["/_static/styles/base.css"]) +site.data("lang", "en") +site.data("date", "Git Last Modified") + +site.data("layout", "index.tsx", "/index.md") +site.data("tags", ["index"], "/index.md") + +site.data("url", "/games/index.html", "/list-games.md") +site.data("layout", "list-games.tsx", "/list-games.md") +site.data("tags", ["list", "list-games"], "/list-games.md") + +site.data("layout", "game.tsx", "/games") +site.data("tags", ["review", "game"], "/games") + +site.use(fileData({ + query: "index", + urlizer(data) { + return data.url.replace(".html", ".json") + }, + contentizer(data) { + return JSON.stringify({ + title: data.title, + subtitle: data.subtitle, + lists: site.search.pages("list").map((data) => data.url) + }) + } +})) +site.use(fileData({ + query: "list-games", + urlizer(data) { + return "/games/index.json" + }, + contentizer(data) { + return JSON.stringify({ + content: data.content, + items: site.search.pages("game").map((data) => data.url) + }) + } +})) +site.use(fileData({ + query: "game", + urlizer(data) { + return data.url.replace(".html", ".json") + }, + contentizer(data) { + return JSON.stringify({ + name: data.name ?? null, + rating: data.rating ?? null, + content: data.content ?? null, + active: data.active ?? null, + progress: data.progress ?? null, + hours_played: data.hours_played ?? null, + purchased_on: data.purchased_on ?? null, + started_on: data.started_on ?? null, + beaten_on: data.beaten_on ?? null, + completed_on: data.completed_on ?? null, + mastered_on: data.mastered_on ?? null, + identifiers: data.identifiers ?? null, + }) + } +})) +site.use(feed({ + output: ["/games/feed.rss", "/games/feed.json"], + query: "game", + limit: 10, + info: { + title: "Videogames", + }, + items: { + title: "=name" + } +})) + +export default site; diff --git a/_data.yml b/_data.yml new file mode 100644 index 0000000..e69de29 diff --git a/_includes/base.tsx b/_includes/base.tsx new file mode 100644 index 0000000..9869caf --- /dev/null +++ b/_includes/base.tsx @@ -0,0 +1,53 @@ +export default function(data: Lume.Data, helpers: Lume.Helpers) { + const charset = ( + + ) + + const viewport = ( + + ) + + const title = ( + + ) + + const stylesheets = data.styles.map((style: string) => ( + <link + key={style} + rel={"stylesheet"} + href={style} + /> + )) + + const header = ( + <header> + <hgroup className={"base-titles"}> + <a href={helpers.url("/")}> + <h1>{data.title}</h1> + <div>{data.subtitle}</div> + </a> + </hgroup> + </header> + ) + + const children = data.children + + // noinspection HtmlRequiredTitleElement + return ( + <html> + <head> + {charset} + {viewport} + {title} + {stylesheets} + </head> + <body> + {header} + {children} + </body> + </html> + ) +} diff --git a/_includes/game.tsx b/_includes/game.tsx new file mode 100644 index 0000000..e97e4fa --- /dev/null +++ b/_includes/game.tsx @@ -0,0 +1,162 @@ +import {formatDateIso} from "../_utils/date.ts" +import {GameData, GameIdentifier} from "../_utils/game.ts" +import {Progress, progressToClassName, progressToIconDef, progressToTitle} from "../_utils/progress.ts" +import {ReviewInfo} from "../_components/ReviewInfo.tsx" + + +export const layout = "base.tsx" + +export default function(data: GameData, helpers: Lume.Helpers) { + const dateRow = ( + <ReviewInfo.MetadataRow + className={"review-date"} + label={"Last updated"} + > + {formatDateIso(data.date)} + </ReviewInfo.MetadataRow> + ) + + const dateSeparator = (data.progress || data.hours_played) ? <hr/> : null + + const progressRow = data.progress ? ( + <ReviewInfo.MetadataRow + className={`game-progress ${progressToClassName(data.progress)}`} + label={"Progress"} + icon={<i className={`fa-sharp fa-regular ${progressToIconDef(data.progress)} ${data.active ? "fa-beat-fade" : ""}`}/>} + > + <data value={data.progress}> + {progressToTitle(data.progress)} + </data> + {data.active && + <> + ,  + <span className={"fa-fade"} style={{animationDelay: '-0.5s'}}>now playing</span> + </> + } + </ReviewInfo.MetadataRow> + ) : null + + const hoursPlayedRow = data.hours_played ? ( + <ReviewInfo.MetadataRow + className={`game-hoursplayed`} + label={"Playtime"} + > + <data value={data.hours_played}> + {data.hours_played} + </data> +   + h + </ReviewInfo.MetadataRow> + ) : null + + const playedSeparator = (data.purchased_on || data.started_on || data.beaten_on || data.completed_on || data.mastered_on) ? <hr/> : null + + const purchasedOnValue = formatDateIso(data.purchased_on) + const purchasedOnRow = purchasedOnValue ? ( + <ReviewInfo.MetadataRow + className={`game-purchasedon`} + label={"Purchased on"} + icon={<i className={`fa-sharp fa-regular ${progressToIconDef(Progress.New)}`}/>} + > + <time dateTime={purchasedOnValue}> + {purchasedOnValue} + </time> + </ReviewInfo.MetadataRow> + ) : null + + const startedOnValue = formatDateIso(data.started_on) + const startedOnRow = startedOnValue ? ( + <ReviewInfo.MetadataRow + className={`game-startedon`} + label={"Started on"} + icon={<i className={`fa-sharp fa-regular ${progressToIconDef(Progress.Started)}`}/>} + > + <time dateTime={startedOnValue}> + {startedOnValue} + </time> + </ReviewInfo.MetadataRow> + ) : null + + const beatenOnValue = formatDateIso(data.beaten_on) + const beatenOnRow = beatenOnValue ? ( + <ReviewInfo.MetadataRow + className={`game-beatenon`} + label={"Beaten on"} + icon={<i className={`fa-sharp fa-regular ${progressToIconDef(Progress.Beaten)}`}/>} + > + <time dateTime={beatenOnValue}> + {beatenOnValue} + </time> + </ReviewInfo.MetadataRow> + ) : null + + const completedOnValue = formatDateIso(data.completed_on) + const completedOnRow = completedOnValue ? ( + <ReviewInfo.MetadataRow + className={`game-completedon`} + label={"Completed on"} + icon={<i className={`fa-sharp fa-regular ${progressToIconDef(Progress.Completed)}`}/>} + > + <time dateTime={completedOnValue}> + {completedOnValue} + </time> + </ReviewInfo.MetadataRow> + ) : null + + const masteredOnValue = formatDateIso(data.mastered_on) + const masteredOnRow = masteredOnValue ? ( + <ReviewInfo.MetadataRow + className={`game-masteredon`} + label={"Mastered on"} + icon={<i className={`fa-sharp fa-regular ${progressToIconDef(Progress.Mastered)}`}/>} + > + <time dateTime={masteredOnValue}> + {masteredOnValue} + </time> + </ReviewInfo.MetadataRow> + ) : null + + const milestonesSeparator = ((data.identifiers?.length ?? 0) > 0) ? <hr/> : null + + const identifiersRows = data.identifiers?.map((identifier: GameIdentifier, index: number) => { + switch(identifier.platform) { + case "steam": + return ( + <ReviewInfo.MetadataRow + key={index} + className={`game-identifier-steam`} + label={<span><i className={`fa-brands fa-steam`}/> Steam</span>} + > + <a href={`https://store.steampowered.com/app/${identifier.appid}/`}> + {identifier.name ?? identifier.appid} + </a> + </ReviewInfo.MetadataRow> + ) + } + }) + + return ( + <main id={"game-main"}> + <ReviewInfo + name={data.name} + rating={data.rating} + metadata={<> + {dateRow} + {dateSeparator} + {progressRow} + {hoursPlayedRow} + {playedSeparator} + {purchasedOnRow} + {startedOnRow} + {beatenOnRow} + {completedOnRow} + {masteredOnRow} + {milestonesSeparator} + {identifiersRows} + </>} + > + {data.children} + </ReviewInfo> + </main> + ) +} diff --git a/_includes/index.tsx b/_includes/index.tsx new file mode 100644 index 0000000..401569e --- /dev/null +++ b/_includes/index.tsx @@ -0,0 +1,131 @@ +import {compareDate} from "../_utils/date.ts" +import { GameData } from "../_utils/game.ts"; +import {GameTable} from "../_components/GameTable.tsx" +import {compare_progress} from "../_utils/progress.ts" +import {GlobalData} from "../_utils/site.ts" + + +export const layout = "base.tsx" + +export default function(data: GlobalData, helpers: Lume.Helpers) { + const intro_section = data.content ? ( + <section id={"index-section-intro"}> + {data.children} + </section> + ) : null + + const games: GameData[] = data.search.pages("game") + + const active_games = games + .filter(game => game.active) + .sort(compareDate as any) + + const active_games_section = ( + <section id={"index-section-games-active"} className={"flex flex-v"}> + <h3> + Now playing + </h3> + <div> + <GameTable games={active_games} columns={["progress", "name", "hoursplayed", "date"]} priority={"progress"}/> + </div> + </section> + ) + + const top_games = games + .sort((a, b) => ((b.rating ?? 0) - (a.rating ?? 0))) + .slice(0, 10) + + const top_games_section = ( + <section id={"index-section-games-top"} className={"flex flex-v"}> + <h3> + Top games + </h3> + <div> + <GameTable games={top_games} columns={["rating", "name", "hascontent"]} priority={"rating"}/> + </div> + </section> + ) + + const played_games = games + .sort((a, b) => ((b.hours_played ?? 0) - (a.hours_played ?? 0))) + .slice(0, 10) + + const played_games_section = ( + <section id={"index-section-games-top"} className={"flex flex-v"}> + <h3> + Most played games + </h3> + <div> + <GameTable games={played_games} columns={["hoursplayed", "name"]}/> + </div> + </section> + ) + + const progress_games = games + .sort((a, b) => -compare_progress(a, b)) + .slice(0, 10) + + const progress_games_section = ( + <section id={"index-section-games-top"} className={"flex flex-v"}> + <h3> + Most progressed games + </h3> + <div> + <GameTable games={progress_games} columns={["progress", "name", "hoursplayed"]} priority={"progress"}/> + </div> + </section> + ) + + const latest_games = games + .sort((a, b) => -compareDate(a, b)) + .slice(0, 10) + + const latest_games_section = ( + <section id={"index-section-games-latest"} className={"flex flex-v"}> + <h3> + Latest updates + </h3> + <div> + <GameTable games={latest_games} columns={["hascontent", "name", "date"]}/> + </div> + </section> + ) + + const games_cols = (games.length > 0) ? ( + <section className={"flex flex-v"}> + <h2> + Videogames + <small> + <a href={helpers.url("~/list-games.md")}> + <i className={"fa-sharp fa-solid fa-magnifying-glass"}/> View all + </a> + </small> + <small> + <a href={helpers.url("/games/feed.rss")}> + <i className={"fa-sharp fa-solid fa-rss"}/> Feed + </a> + </small> + </h2> + {active_games.length > 0 && ( + <div className={"flex flex-1"}> + {active_games_section} + </div> + )} + <div className={"flex flex-2"}> + {top_games_section} + {progress_games_section} + </div> + <div className={"flex flex-2"}> + {played_games_section} + {latest_games_section} + </div> + </section> + ) : null + + return ( + <main id={"index-main"} className={"flex flex-v"}> + {intro_section} + {games_cols} + </main> + ) +} diff --git a/_includes/list-games.tsx b/_includes/list-games.tsx new file mode 100644 index 0000000..903d933 --- /dev/null +++ b/_includes/list-games.tsx @@ -0,0 +1,35 @@ +import {GameTable} from "../_components/GameTable.tsx" +import { GameData } from "../_utils/game.ts"; + + +export const layout = "base.tsx" +export const url = "/games.html" + +export default function(data: Lume.Data, helpers: Lume.Helpers) { + const intro_section = data.content ? ( + <section id={"list-games-section-intro"}> + {data.children} + </section> + ) : null + + const games: GameData[] = data.search.pages("game") + .sort((a, b) => (b.rating - a.rating)) as GameData[] + + const games_section = ( + <section id={"list-games-section-games"}> + <h2> + Videogames list + </h2> + <div> + <GameTable games={games} priority={"mixed"}/> + </div> + </section> + ) + + return ( + <main id={"list-games-main"}> + {intro_section} + {games_section} + </main> + ) +} diff --git a/_plugins/fileData.ts b/_plugins/fileData.ts new file mode 100644 index 0000000..8713511 --- /dev/null +++ b/_plugins/fileData.ts @@ -0,0 +1,22 @@ +import {Page} from "lume/core/file.ts" +import Site from "lume/core/site.ts"; + +export type FileDataOptions = { + query: string, + urlizer: (data: Lume.Data) => string, + contentizer: (data: Lume.Data) => string, +} + +export default function fileData({query, urlizer, contentizer}: FileDataOptions) { + return (site: Site) => { + site.addEventListener("beforeSave", () => { + const datas: Lume.Data[] = site.search.pages(query) + for(const data of datas) { + site.pages.push(Page.create({ + url: urlizer(data), + content: contentizer(data), + })) + } + }) + } +} \ No newline at end of file diff --git a/_run.ts b/_run.ts new file mode 100644 index 0000000..34deff4 --- /dev/null +++ b/_run.ts @@ -0,0 +1,10 @@ +import {default as site} from "./_config.ts" +import {default as cms} from "./_cms.ts" +import {default as adapter} from "lume/cms/adapters/lume.ts" + +const app = await adapter({site, cms}) + +Deno.serve({ + port: 8080, + handler: app.fetch +}) diff --git a/_scripts/importSteam.ts b/_scripts/importSteam.ts new file mode 100644 index 0000000..b79c7c7 --- /dev/null +++ b/_scripts/importSteam.ts @@ -0,0 +1,131 @@ +import { loadSync as loadEnv } from "dotenv/mod.ts"; +import site from "../_config.ts" +import {formatDateIso} from "../_utils/date.ts" +import {GameData, GameIdentifier} from "../_utils/game.ts" +import {stringifyYaml} from "lume/cms/deps/std.ts" + +/* This is arguably one of the worst scripts I've ever written. */ + +type SteamGame = { + appid: number, + name: string, + playtime_forever: number, + img_icon_url?: string, + has_community_visible_stats: boolean, + playtime_windows_forever: number, + playtime_mac_forever: number, + playtime_linux_forever: number, + playtime_deck_forever: number, + rtime_last_played: number, + sort_as: string, + capsule_filename?: string, + has_workshop: boolean, + has_market: boolean, + has_dlc: boolean, + content_descriptorids?: number[], + playtime_disconnected: number +} + +const env = loadEnv() + +const apiKey = env["STEAM_API_KEY"] +const steamId = env["STEAM_ID"] + +console.debug("Creating reviewed games indexes...") + +const appIdToPage: {[appId: string]: GameData | null} = {} +const filenameToAppId: {[filename: string]: string | null} = {} + +for(const _page of site.search.pages("game")) { + const page = _page as GameData + const file: string = page.sourcePath + const identifiers: GameIdentifier[] = page.data.identifiers.filter((i: GameIdentifier) => i.platform === "steam") + + let nullify: boolean = false + for(const identifier of identifiers) { + const appId = identifier.appid + if(appIdToPage[appId] !== undefined) { + console.warn(`AppID ${appId} from ${file} is already set at ${appIdToPage[appId]}, ignoring it.`) + nullify = true + } + if(filenameToAppId[file] !== undefined) { + console.warn(`File ${file} is already set with ${appId} at ${filenameToAppId[file]}, ignoring it.`) + nullify = true + } + } + for(const identifier of identifiers) { + const appId = identifier.appid + appIdToPage[appId] = nullify ? null : page + filenameToAppId[file] = nullify ? null : appId + } +} + +console.debug("Fetching list of owned games via IPlayerService/GetOwnedGames/v1...") +const gamesResponse = await fetch(`http://api.steampowered.com/IPlayerService/GetOwnedGames/v1/?key=${apiKey}&steamid=${steamId}&include_appinfo=true&include_extended_appinfo=true&include_played_free_games=true`) +const gamesData = await gamesResponse.json() +const games: SteamGame[] = gamesData["response"]["games"] +console.debug(`Detected ${games.length} games.`) + +for(const game of games) { + const appId = `${game.appid}` + const page = appIdToPage[appId] + let fullName = page?.page.sourcePath + if(page === null) { + continue + } + else if(page === undefined) { + const cleanName = game.name + .toLocaleLowerCase() + .replaceAll(/[^a-z0-9]/g, '-') + .replaceAll(/-{2,}/g, '-') + fullName = `games/${cleanName}.md` + try { + await Deno.lstat(fullName) + console.warn(`File ${fullName} already exists, but is not identified by ${appId}, skipping...`) + continue + } catch(e) { + console.info(`Importing new game: ${fullName}`) + await Deno.create(fullName) + } + } + + const contents = { + name: page?.name ?? game?.name, + name_sort: page?.name_sort ?? game?.sort_as, + rating: page?.rating, + content: page?.content, + active: page?.active, + progress: page?.progress, + hours_played: Math.max(page?.hours_played ?? 0, Math.round((game?.playtime_forever ?? 0) / 60)), + purchased_on: page?.purchased_on, + started_on: page?.started_on, + beaten_on: page?.beaten_on, + completed_on: page?.completed_on, + mastered_on: page?.mastered_on, + identifiers: [ + ...(page?.identifiers?.filter(i => i.platform !== "steam") ?? []), + { + platform: "steam", + appid: appId, + name: game.name, + synced_on: formatDateIso(new Date()) + } + ], + } + + Object.entries(contents).forEach(([key, value]) => { + if(value === undefined) { + delete contents[key] + } + }) + + + + const fsfile = await Deno.open(fullName!, {read: true, write: true}) + const encoder = new TextEncoder(); + const writer = fsfile.writable.getWriter() + await writer.write( + encoder.encode(`---\n${stringifyYaml(contents)}\n---\n`) + ) + fsfile.close() +} diff --git a/_static/fonts/FiraCode-Bold.woff2 b/_static/fonts/FiraCode-Bold.woff2 new file mode 100644 index 0000000..349dc36 Binary files /dev/null and b/_static/fonts/FiraCode-Bold.woff2 differ diff --git a/_static/fonts/FiraCode-Regular.woff2 b/_static/fonts/FiraCode-Regular.woff2 new file mode 100644 index 0000000..f8b63fb Binary files /dev/null and b/_static/fonts/FiraCode-Regular.woff2 differ diff --git a/_static/fonts/FiraCode.css b/_static/fonts/FiraCode.css new file mode 100644 index 0000000..db1afc9 --- /dev/null +++ b/_static/fonts/FiraCode.css @@ -0,0 +1,11 @@ +@font-face { + font-family: "Fira Code"; + font-weight: 400; + src: url("../fonts/FiraCode-Regular.woff2") format("woff2"); +} + +@font-face { + font-family: "Fira Code"; + font-weight: 700; + src: url("../fonts/FiraCode-Bold.woff2") format("woff2"); +} \ No newline at end of file diff --git a/_static/fonts/FiraCode.license.txt b/_static/fonts/FiraCode.license.txt new file mode 100644 index 0000000..805e0b3 --- /dev/null +++ b/_static/fonts/FiraCode.license.txt @@ -0,0 +1,93 @@ +Copyright (c) 2014, The Fira Code Project Authors (https://github.com/tonsky/FiraCode) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/_static/fonts/FiraSans-Bold.woff2 b/_static/fonts/FiraSans-Bold.woff2 new file mode 100644 index 0000000..9216d5e Binary files /dev/null and b/_static/fonts/FiraSans-Bold.woff2 differ diff --git a/_static/fonts/FiraSans-Regular.woff2 b/_static/fonts/FiraSans-Regular.woff2 new file mode 100644 index 0000000..60c2cb4 Binary files /dev/null and b/_static/fonts/FiraSans-Regular.woff2 differ diff --git a/_static/fonts/FiraSans.css b/_static/fonts/FiraSans.css new file mode 100644 index 0000000..70f9027 --- /dev/null +++ b/_static/fonts/FiraSans.css @@ -0,0 +1,13 @@ +@font-face { + font-family: "Fira Sans"; + font-weight: 400; + src: url("FiraSans-Regular.woff2") format("woff2"); + size-adjust: 110%; +} + +@font-face { + font-family: "Fira Sans"; + font-weight: 700; + src: url("FiraSans-Bold.woff2") format("woff2"); + size-adjust: 110%; +} diff --git a/_static/fonts/FiraSans.license.txt b/_static/fonts/FiraSans.license.txt new file mode 100644 index 0000000..880f683 --- /dev/null +++ b/_static/fonts/FiraSans.license.txt @@ -0,0 +1,92 @@ +Digitized data copyright 2012-2018: The Mozilla Foundation, Telefonica S.A., Carrois Corporate GbR and bBox Type GmbH. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/_static/fonts/FontAwesomePro.css b/_static/fonts/FontAwesomePro.css new file mode 100644 index 0000000..d105d92 --- /dev/null +++ b/_static/fonts/FontAwesomePro.css @@ -0,0 +1 @@ +@import "https://kit.fontawesome.com/29ba482ba4.css"; diff --git a/_static/fonts/ZillaSlab-Bold.woff2 b/_static/fonts/ZillaSlab-Bold.woff2 new file mode 100644 index 0000000..fbcd8e7 Binary files /dev/null and b/_static/fonts/ZillaSlab-Bold.woff2 differ diff --git a/_static/fonts/ZillaSlab-Regular.woff2 b/_static/fonts/ZillaSlab-Regular.woff2 new file mode 100644 index 0000000..3170cc5 Binary files /dev/null and b/_static/fonts/ZillaSlab-Regular.woff2 differ diff --git a/_static/fonts/ZillaSlab.css b/_static/fonts/ZillaSlab.css new file mode 100644 index 0000000..53bdc24 --- /dev/null +++ b/_static/fonts/ZillaSlab.css @@ -0,0 +1,13 @@ +@font-face { + font-family: "Zilla Slab"; + font-weight: 400; + src: url("ZillaSlab-Regular.woff2") format("woff2"); + size-adjust: 110%; +} + +@font-face { + font-family: "Zilla Slab"; + font-weight: 700; + src: url("ZillaSlab-Bold.woff2") format("woff2"); + size-adjust: 110%; +} diff --git a/_static/fonts/ZillaSlab.license.txt b/_static/fonts/ZillaSlab.license.txt new file mode 100644 index 0000000..af9d668 --- /dev/null +++ b/_static/fonts/ZillaSlab.license.txt @@ -0,0 +1,93 @@ +Copyright 2017, The Mozilla Foundation + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/_static/styles/base.css b/_static/styles/base.css new file mode 100644 index 0000000..4a3fe26 --- /dev/null +++ b/_static/styles/base.css @@ -0,0 +1,535 @@ +@import "../fonts/ZillaSlab.css"; +@import "../fonts/FiraSans.css"; +@import "../fonts/FiraCode.css"; +@import "../fonts/FontAwesomePro.css"; + +:root { + --font-title: "Zilla Slab", serif; + --font-text: "Fira Sans", sans-serif; + --font-mono: "Fira Code", monospace; + + --color-body: #1E1E1E; + --color-body-over: #FFFFFF; + + --color-link: #99ffff; + + --color-unset: #474747; + --color-unset-over: #FFFFFF; + --image-unset: linear-gradient(var(--color-unset)); + + --color-bad: #FF0000; + --color-bad-over: #FFFFFF; + + --color-mixed: #FFD300; + --color-mixed-over: #000000; + + --color-good: #00FF00; + --color-good-over: #000000; + + --color-perfect: #531DFF; + --color-perfect-over: #FFFFFF; + + --color-new: #394739; + --color-new-over: #a8e0a8; + --image-new: linear-gradient(0deg, #394739 0%, #496149 100%); + + --color-started: #82562b; + --color-started-over: #ffe1bf; + --gradient-started: linear-gradient(45deg, #a86747 0%, #50382b 100%); + + --color-beaten: #a6a6a6; + --color-beaten-over: #111111; + --gradient-beaten: radial-gradient(#dddddd 0%, #737373 100%); + + --color-completed: #b37e36; + --color-completed-over: #6c3200; + --gradient-completed: linear-gradient(105deg, #cd6d1d 0%, #ffea00 50%, #cd6d1d 100%); + + --color-mastered: #33b4ff; + --color-mastered-over: #58ffff; + --gradient-mastered: conic-gradient(from 180deg at 50% 71%, #0055ff 0%, #000070 50%, #0055ff 100%); + + --color-notapplicable: #812281; + --color-notapplicable-over: #b32db3; + --gradient-notapplicable: radial-gradient(#220f22 0%, #812281 150%); + + --color-current: var(--color-body-over); + --color-current-over: var(--color-body); +} + +@media print, (prefers-color-scheme: light) { + :root { + --color-body: #FFFFFF; + --color-body-over: #1E1E1E; + + --color-link: #006666; + } +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + + display: grid; + grid-template-areas: + ". . ." + "h h h" + ". m ." + ". . ."; + grid-template-rows: 0 auto auto 0; + grid-template-columns: 1fr auto 1fr; + row-gap: 16px; + column-gap: 16px; + + font-family: var(--font-text), sans-serif; + font-size: 15px; + + background-color: var(--color-body); + color: var(--color-body-over); +} + +@media screen and (max-width: 816px) { + body { + grid-template-columns: 0 1fr 0; + } +} + +main { + grid-area: m; + width: 800px; +} + +@media screen and (max-width: 816px) { + main { + width: 100%; + } +} + +header { + grid-area: h; + + text-align: center; +} + +header h1 { + font-size: 2rem; + + margin: 0; +} + +header div { + font-size: 1rem; +} + +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-title), serif; +} + +:is(h1, h2, h3, h4, h5, h6) small { + margin-left: 12px; +} + +a { + color: var(--color-link); + + text-decoration: 1px solid var(--color-link) underline; +} + +/* Kind of an hack but ok */ +a[href] i[class^="fa-"]::before { + text-decoration: 1px solid currentColor underline; + vertical-align: text-top; +} + +*[title] { + cursor: help; +} + +abbr[title] i[class^="fa-"]::before { + text-decoration: 1px dotted currentColor underline; + vertical-align: text-top; +} + +.flex { + --gap: 2rem; + + display: flex; + flex-wrap: wrap; + gap: var(--gap); +} + +.flex-v .flex-v { + --gap: 1rem; +} + +.flex-v .flex-v .flex-v { + --gap: 0.5rem; +} + +.flex-v { + flex-direction: column; + flex-wrap: nowrap; +} + +.flex.flex-v > * { + flex-grow: 0; +} + +.flex :is(h1, h2, h3, h4, h5, h6):first-child { + margin-top: 0; + margin-bottom: 0; +} + +.flex > * { + flex-grow: 1; + flex-shrink: 0; + + /* This is probably a bad idea */ + min-width: 320px; +} + +.flex-1 > * { + width: calc(100% / 2); +} + +.flex-2 > * { + width: calc(100% / 3); +} + +div:has(> table) { + width: 100%; + overflow-x: auto; +} + +div > table { + width: 100%; +} + +tr { + height: 38px; +} + +tr.priority-rating.rating-unset, .priority-mixed.rating-unset td:is(.review-rating, .review-date, .review-name, .review-hascontent), .reviewinfo.rating-unset { + --color-current: var(--color-unset); + --color-current-over: var(--color-unset-over); +} + +tr.priority-rating.rating-bad, .priority-mixed.rating-bad td:is(.review-rating, .review-date, .review-name, .review-hascontent), .reviewinfo.rating-bad { + --color-current: var(--color-bad); + --color-current-over: var(--color-bad-over); +} + +tr.priority-rating.rating-mixed, .priority-mixed.rating-mixed td:is(.review-rating, .review-date, .review-name, .review-hascontent), .reviewinfo.rating-mixed { + --color-current: var(--color-mixed); + --color-current-over: var(--color-mixed-over); +} + +tr.priority-rating.rating-good, .priority-mixed.rating-good td:is(.review-rating, .review-date, .review-name, .review-hascontent), .reviewinfo.rating-good { + --color-current: var(--color-good); + --color-current-over: var(--color-good-over); +} + +tr.priority-rating.rating-perfect, .priority-mixed.rating-perfect td:is(.review-rating, .review-date, .review-name, .review-hascontent), .reviewinfo.rating-perfect { + --color-current: var(--color-perfect); + --color-current-over: var(--color-perfect-over); +} + +tr.priority-progress.progress-unset, .priority-mixed.progress-unset td:is(.game-progress, .game-hoursplayed) { + --color-current: var(--color-unset); + --color-current-over: var(--color-unset-over); +} + +tr.priority-progress.progress-new, .priority-mixed.progress-new td:is(.game-progress, .game-hoursplayed) { + --color-current: var(--color-new); + --color-current-over: var(--color-new-over); +} + +tr.priority-progress.progress-started, .priority-mixed.progress-started td:is(.game-progress, .game-hoursplayed) { + --color-current: var(--color-started); + --color-current-over: var(--color-started-over); +} + +tr.priority-progress.progress-beaten, .priority-mixed.progress-beaten td:is(.game-progress, .game-hoursplayed) { + --color-current: var(--color-beaten); + --color-current-over: var(--color-beaten-over); +} + +tr.priority-progress.progress-completed, .priority-mixed.progress-completed td:is(.game-progress, .game-hoursplayed) { + --color-current: var(--color-completed); + --color-current-over: var(--color-completed-over); +} + +tr.priority-progress.progress-mastered, .priority-mixed.progress-mastered td:is(.game-progress, .game-hoursplayed) { + --color-current: var(--color-mastered); + --color-current-over: var(--color-mastered-over); +} + +tr.priority-progress.progress-notapplicable, .priority-mixed.progress-notapplicable td:is(.game-progress, .game-hoursplayed) { + --color-current: var(--color-notapplicable); + --color-current-over: var(--color-notapplicable-over); +} + +td, th { + padding: 6px; + border-bottom: 1px solid color-mix(in srgb, var(--color-current) 30%, transparent); +} + +thead th { + border-bottom: 2px solid var(--color-current); +} + +tbody th { + font-family: var(--font-title), serif; + font-weight: 700; +} + +td.review-rating, td.game-progress { + border-bottom: 0; + + font-family: var(--font-title), serif; + font-weight: 700; +} + +td.rating-unset { + background-color: var(--color-unset); + color: var(--color-unset-over); +} + +td.rating-bad { + background-color: var(--color-bad); + color: var(--color-bad-over); +} + +td.rating-mixed { + background-color: var(--color-mixed); + color: var(--color-mixed-over); +} + +td.rating-good { + background-color: var(--color-good); + color: var(--color-good-over); +} + +td.rating-perfect { + background-color: var(--color-perfect); + color: var(--color-perfect-over); +} + +td.progress-unset, .reviewinfo-metadata-content.game-progress.progress-unset .reviewinfo-metadata-icon { + background-image: var(--image-unset); + background-color: var(--color-unset); + color: var(--color-unset-over); +} + +td.progress-new, .reviewinfo-metadata-content.game-progress.progress-new .reviewinfo-metadata-icon { + background-image: var(--image-new); + background-color: var(--color-new); + color: var(--color-new-over); +} + +td.progress-started, .reviewinfo-metadata-content.game-progress.progress-started .reviewinfo-metadata-icon { + background-image: var(--gradient-started); + background-color: var(--color-started); + color: var(--color-started-over); +} + +td.progress-beaten, .reviewinfo-metadata-content.game-progress.progress-beaten .reviewinfo-metadata-icon { + background-image: var(--gradient-beaten); + background-color: var(--color-beaten); + color: var(--color-beaten-over); +} + +td.progress-completed, .reviewinfo-metadata-content.game-progress.progress-completed .reviewinfo-metadata-icon { + background-image: var(--gradient-completed); + background-color: var(--color-completed); + color: var(--color-completed-over); +} + +td.progress-mastered, .reviewinfo-metadata-content.game-progress.progress-mastered .reviewinfo-metadata-icon { + background-image: var(--gradient-mastered); + background-color: var(--color-mastered); + color: var(--color-mastered-over); +} + +td.progress-notapplicable, .reviewinfo-metadata-content.game-progress.progress-notapplicable .reviewinfo-metadata-icon { + background-image: var(--gradient-notapplicable); + background-color: var(--color-notapplicable); + color: var(--color-notapplicable-over); +} + +td.review-rating, td.game-progress { + width: 38px; + height: 38px; + min-width: 38px; + min-height: 38px; + text-align: center; +} + +td.review-date { + font-family: var(--font-mono), monospace; + text-align: center; + + width: 108px; + min-width: 108px; +} + +td.game-hoursplayed { + text-align: right; + + width: 66px; + min-width: 66px; +} + +:is(.review-date, .game-hoursplayed, .game-purchasedon, .game-startedon, .game-beatenon, .game-completedon, .game-masteredon) :is(data, time) { + font-family: var(--font-mono), monospace; +} + +td.review-hascontent { + width: 28px; +} + +.reviewinfo { + --size-rating: 96px; + --size-bar: 12px; + + display: grid; + grid-template-areas: + "rating name" + "base empty" + "metadata metadata" + "content content"; + grid-template-rows: + auto + var(--size-bar) + auto + 1fr; + grid-template-columns: var(--size-rating) 1fr; +} + +@media screen and (max-width: 816px) { + .reviewinfo { + --size-rating: 64px; + --size-bar: 8px; + } +} + +.reviewinfo-rating { + grid-area: rating; + min-height: calc(var(--size-rating) - var(--size-bar)); + + display: flex; + justify-content: center; + align-items: center; + + background-color: var(--color-current); + color: var(--color-current-over); + + font-family: var(--font-title), var(--font-mono), monospace, serif; + font-weight: 700; +} + +.reviewinfo-name { + grid-area: name; + display: flex; + justify-content: left; + align-items: center; + + margin-top: 0; + margin-bottom: 0; + margin-left: var(--size-bar); +} + +.reviewinfo-rating, .reviewinfo-name { + font-size: 3rem; +} + +@media screen and (max-width: 816px) { + .reviewinfo-rating, .reviewinfo-name { + font-size: 2rem; + } +} + +.reviewinfo-bar-base { + grid-area: base; + + background-color: var(--color-current); + color: var(--color-current-over); +} + +.reviewinfo-bar-empty { + grid-area: empty; + + background-color: color-mix(in srgb, var(--color-current) 30%, transparent); + color: var(--color-current-over); +} + +.reviewinfo-bar-fill { + height: 100%; + + background-color: var(--color-current); + color: var(--color-current-over); +} + +.reviewinfo-metadata { + grid-area: metadata; + + padding: var(--size-bar); + + display: grid; + grid-template-columns: auto 1fr; + grid-column-gap: var(--size-bar); + grid-row-gap: calc(var(--size-bar) / 2); + + background-color: color-mix(in srgb, var(--color-current) 10%, transparent); +} + +.reviewinfo-metadata * { + display: flex; + align-items: center; + + height: 32px; +} + +.reviewinfo-metadata-label { + grid-column: 1; + + justify-content: start; + + font-family: var(--font-title), serif; + font-weight: 700; + + width: 108px; +} + +.reviewinfo-metadata-content { + grid-column: 2; + + justify-content: start; + gap: 1ch; +} + +.reviewinfo-metadata-icon { + justify-content: center; + align-items: center; + + height: 32px; + width: 32px; + + border-radius: 100%; + background-color: color-mix(in srgb, var(--color-current) 20%, transparent); +} + +.reviewinfo-metadata hr { + grid-column: 1 / 3; + width: 100%; + height: 0; + + border: 2px solid color-mix(in srgb, var(--color-current) 20%, transparent); +} + +.reviewinfo-content { + grid-area: content; +} diff --git a/_utils/date.ts b/_utils/date.ts new file mode 100644 index 0000000..a5de1de --- /dev/null +++ b/_utils/date.ts @@ -0,0 +1,11 @@ +import { GlobalData } from "./site.ts"; + +export function formatDateIso(date?: Date): string { + if(date === undefined) return "" + date = new Date(date) + return `${date.getFullYear().toString().padStart(4, "0")}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}` +} + +export function compareDate(a: GlobalData, b: GlobalData): number { + return new Date(a.date ?? 0).getTime() - new Date(b.date ?? 0).getTime() +} diff --git a/_utils/game.ts b/_utils/game.ts new file mode 100644 index 0000000..0453970 --- /dev/null +++ b/_utils/game.ts @@ -0,0 +1,33 @@ +import {Progress} from "./progress.ts" +import {ReviewData} from "./review.ts" + + +export interface GameBaseIdentifier { + platform: string, + synced_on?: string, +} + +export interface GameSteamIdentifier extends GameBaseIdentifier { + platform: "steam", + appid: string, + name?: string, +} + +export type GameIdentifier = GameSteamIdentifier; + +export interface GameData extends ReviewData { + active?: boolean, + + progress?: Progress, + hours_played?: number + + purchased_on?: Date, + started_on?: Date, + beaten_on?: Date, + completed_on?: Date, + mastered_on?: Date, + + identifiers?: GameIdentifier[] +} + +export type GamePage = Lume.Page<GameData> diff --git a/_utils/progress.ts b/_utils/progress.ts new file mode 100644 index 0000000..af8348e --- /dev/null +++ b/_utils/progress.ts @@ -0,0 +1,100 @@ +import {GameData} from "./game.ts" + + +export enum Progress { + Unset = "", + NotApplicable = "notapplicable", + New = "new", + Started = "started", + Beaten = "beaten", + Completed = "completed", + Mastered = "mastered", +} + +export function progressToIconDef(progress?: Progress): string { + switch (progress) { + case undefined: + return ""; + case Progress.Unset: + return ""; + case Progress.NotApplicable: + return "fa-x"; + case Progress.New: + return "fa-ellipsis"; + case Progress.Started: + return "fa-play"; + case Progress.Beaten: + return "fa-circle-check"; + case Progress.Completed: + return "fa-star"; + case Progress.Mastered: + return "fa-trophy"; + } +} + +export function progressToClassName(progress?: Progress): string { + switch (progress) { + case undefined: + return "progress-unset"; + case Progress.Unset: + return "progress-unset"; + case Progress.NotApplicable: + return "progress-notapplicable"; + case Progress.New: + return "progress-new"; + case Progress.Started: + return "progress-started"; + case Progress.Beaten: + return "progress-beaten"; + case Progress.Completed: + return "progress-completed"; + case Progress.Mastered: + return "progress-mastered"; + } +} + +export function progressToTitle(progress?: Progress): string { + switch (progress) { + case undefined: + return ""; + case Progress.Unset: + return ""; + case Progress.NotApplicable: + return "Not applicable"; + case Progress.New: + return "New"; + case Progress.Started: + return "Started"; + case Progress.Beaten: + return "Beaten"; + case Progress.Completed: + return "Completed"; + case Progress.Mastered: + return "Mastered"; + } +} + +export function progress_to_number(progress?: Progress): number { + switch (progress) { + case undefined: + return 0; + case Progress.Unset: + return 0; + case Progress.NotApplicable: + return 5; + case Progress.New: + return 10; + case Progress.Started: + return 20; + case Progress.Beaten: + return 30; + case Progress.Completed: + return 40; + case Progress.Mastered: + return 50; + } +} + +export function compare_progress(a: GameData, b: GameData): number { + return progress_to_number(a.progress) - progress_to_number(b.progress) +} \ No newline at end of file diff --git a/_utils/rating.ts b/_utils/rating.ts new file mode 100644 index 0000000..a808ae0 --- /dev/null +++ b/_utils/rating.ts @@ -0,0 +1,43 @@ +export type Rating = number + +export function ratingToIconDef(rating?: Rating): string { + if(rating === undefined) { + return "fa-face-meh-blank" + } + else if(rating == 0) { + return "fa-face-meh-blank" + } + else if(rating < 35) { + return "fa-face-frown" + } + else if(rating < 65) { + return "fa-face-meh" + } + else if(rating < 95) { + return "fa-face-smile" + } + else { + return "fa-face-grin-stars" + } +} + +export function ratingToClassName(rating?: Rating): string { + if(rating === undefined) { + return "rating-unset" + } + else if(rating === 0) { + return "rating-unset" + } + else if(rating < 35) { + return "rating-bad" + } + else if(rating < 65) { + return "rating-mixed" + } + else if(rating < 95) { + return "rating-good" + } + else { + return "rating-perfect" + } +} diff --git a/_utils/review.ts b/_utils/review.ts new file mode 100644 index 0000000..1449623 --- /dev/null +++ b/_utils/review.ts @@ -0,0 +1,17 @@ +import {Rating} from "./rating.ts" +import {GlobalData} from "./site.ts" + + +export interface ReviewData extends GlobalData { + name?: string, + name_sort?: string, + rating?: Rating, + content?: string, +} + +export function compareName(a: ReviewData, b: ReviewData): number { + const aName = a.name_sort ?? a.name ?? "" + const bName = b.name_sort ?? b.name ?? "" + + return aName.localeCompare(bName) +} \ No newline at end of file diff --git a/_utils/site.ts b/_utils/site.ts new file mode 100644 index 0000000..ef46993 --- /dev/null +++ b/_utils/site.ts @@ -0,0 +1,5 @@ +export interface GlobalData extends Lume.Data { + title: string, + subtitle: string, + styles: string[], +} diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..37ad8c6 --- /dev/null +++ b/deno.json @@ -0,0 +1,32 @@ +{ + "imports": { + "lume/": "https://deno.land/x/lume@v2.2.1/", + "lume/cms/": "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/", + "dotenv/": "https://deno.land/std@0.224.0/dotenv/" + }, + "tasks": { + "lume": "echo \"import 'lume/cli.ts'\" | deno run -A -", + "build": "deno task lume", + "serve": "deno task lume -s", + "cms": "deno task lume cms", + "import-steam": "deno run run --allow-env --allow-read --allow-net --allow-write _scripts/importSteam.ts" + }, + "compilerOptions": { + "types": [ + "lume/types.ts" + ], + "jsx": "react-jsx", + "jsxImportSource": "npm:react", + "jsxImportSourceTypes": "npm:@types/react", + "noImplicitAny": false + }, + "lint": { + "rules": { + "exclude": [ + "no-implicit-any", + "no-explicit-any", + "no-unused-vars" + ] + } + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..80d2f1d --- /dev/null +++ b/deno.lock @@ -0,0 +1,761 @@ +{ + "version": "3", + "packages": { + "specifiers": { + "jsr:@hono/hono@4.4.0": "jsr:@hono/hono@4.4.0", + "jsr:@hono/hono@4.4.5": "jsr:@hono/hono@4.4.5", + "jsr:@libs/typing@2": "jsr:@libs/typing@2.1.1", + "jsr:@std/assert@^0.224.0": "jsr:@std/assert@0.224.0", + "jsr:@std/assert@^0.225.1": "jsr:@std/assert@0.225.3", + "jsr:@std/assert@^0.225.2": "jsr:@std/assert@0.225.3", + "jsr:@std/assert@^0.226.0": "jsr:@std/assert@0.226.0", + "jsr:@std/cli@0.224.5": "jsr:@std/cli@0.224.5", + "jsr:@std/cli@^0.224.5": "jsr:@std/cli@0.224.5", + "jsr:@std/collections@^1.0.0-rc.1": "jsr:@std/collections@1.0.0-rc.1", + "jsr:@std/crypto@0.224.0": "jsr:@std/crypto@0.224.0", + "jsr:@std/encoding@0.224.3": "jsr:@std/encoding@0.224.3", + "jsr:@std/encoding@1.0.0-rc.1": "jsr:@std/encoding@1.0.0-rc.1", + "jsr:@std/encoding@^0.224.0": "jsr:@std/encoding@0.224.3", + "jsr:@std/fmt@0.225.2": "jsr:@std/fmt@0.225.2", + "jsr:@std/fmt@0.225.3": "jsr:@std/fmt@0.225.3", + "jsr:@std/fmt@0.225.4": "jsr:@std/fmt@0.225.4", + "jsr:@std/fmt@^0.225.0": "jsr:@std/fmt@0.225.4", + "jsr:@std/fmt@^0.225.3": "jsr:@std/fmt@0.225.4", + "jsr:@std/fmt@^0.225.4": "jsr:@std/fmt@0.225.4", + "jsr:@std/front-matter@0.224.1": "jsr:@std/front-matter@0.224.1", + "jsr:@std/front-matter@0.224.2": "jsr:@std/front-matter@0.224.2", + "jsr:@std/fs@0.229.1": "jsr:@std/fs@0.229.1", + "jsr:@std/fs@0.229.3": "jsr:@std/fs@0.229.3", + "jsr:@std/fs@^0.229.0": "jsr:@std/fs@0.229.3", + "jsr:@std/fs@^0.229.2": "jsr:@std/fs@0.229.3", + "jsr:@std/html@0.224.1": "jsr:@std/html@0.224.1", + "jsr:@std/html@0.224.2": "jsr:@std/html@0.224.2", + "jsr:@std/http@0.224.3": "jsr:@std/http@0.224.3", + "jsr:@std/io@^0.224.0": "jsr:@std/io@0.224.1", + "jsr:@std/io@^0.224.1": "jsr:@std/io@0.224.1", + "jsr:@std/json@^0.224.1": "jsr:@std/json@0.224.1", + "jsr:@std/jsonc@0.224.1": "jsr:@std/jsonc@0.224.1", + "jsr:@std/log@0.224.1": "jsr:@std/log@0.224.1", + "jsr:@std/log@0.224.2": "jsr:@std/log@0.224.2", + "jsr:@std/media-types@0.224.1": "jsr:@std/media-types@0.224.1", + "jsr:@std/media-types@^1.0.0-rc.1": "jsr:@std/media-types@1.0.0-rc.1", + "jsr:@std/net@^0.224.2": "jsr:@std/net@0.224.3", + "jsr:@std/path@0.225.1": "jsr:@std/path@0.225.1", + "jsr:@std/path@0.225.2": "jsr:@std/path@0.225.2", + "jsr:@std/path@1.0.0-rc.1": "jsr:@std/path@1.0.0-rc.1", + "jsr:@std/path@^0.225.1": "jsr:@std/path@0.225.2", + "jsr:@std/path@^0.225.2": "jsr:@std/path@0.225.2", + "jsr:@std/streams@^0.224.3": "jsr:@std/streams@0.224.4", + "jsr:@std/toml@0.224.1": "jsr:@std/toml@0.224.1", + "jsr:@std/toml@^0.224.0": "jsr:@std/toml@0.224.1", + "jsr:@std/toml@^0.224.1": "jsr:@std/toml@0.224.1", + "jsr:@std/yaml@0.224.1": "jsr:@std/yaml@0.224.1", + "jsr:@std/yaml@^0.224.1": "jsr:@std/yaml@0.224.1", + "npm:@js-temporal/polyfill@0.4.4": "npm:@js-temporal/polyfill@0.4.4", + "npm:@types/estree@1.0.5": "npm:@types/estree@1.0.5", + "npm:@types/react": "npm:@types/react@18.3.3", + "npm:@types/react-dom@18.3.0": "npm:@types/react-dom@18.3.0", + "npm:@types/react@18.3.3": "npm:@types/react@18.3.3", + "npm:estree-walker@3.0.3": "npm:estree-walker@3.0.3", + "npm:markdown-it-attrs@4.1.6": "npm:markdown-it-attrs@4.1.6_markdown-it@14.1.0", + "npm:markdown-it-deflist@3.0.0": "npm:markdown-it-deflist@3.0.0", + "npm:markdown-it@14.1.0": "npm:markdown-it@14.1.0", + "npm:meriyah@4.4.2": "npm:meriyah@4.4.2", + "npm:react": "npm:react@18.3.1", + "npm:react-dom@18.3.1": "npm:react-dom@18.3.1_react@18.3.1", + "npm:react@18.3.1": "npm:react@18.3.1", + "npm:unidecode@1.1.0": "npm:unidecode@1.1.0" + }, + "jsr": { + "@hono/hono@4.4.0": { + "integrity": "3a720bde9692549ecef9117b2069b318e9e976a8af7588d9d8f3051b81d95b8d" + }, + "@hono/hono@4.4.5": { + "integrity": "8b0f005253251e7e3dcd5c1d54cd236b24db9634e5483815fad67aca2fb2eaf2" + }, + "@libs/typing@2.1.1": { + "integrity": "964e61860716140671718b170d8de4a8705e05d86e7ed0c41883fe2687c91c80" + }, + "@std/assert@0.224.0": { + "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f" + }, + "@std/assert@0.225.3": { + "integrity": "b3c2847aecf6955b50644cdb9cf072004ea3d1998dd7579fc0acb99dbb23bd4f" + }, + "@std/assert@0.226.0": { + "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3" + }, + "@std/cli@0.224.5": { + "integrity": "79f1b02ac18f6c26de3eb33fe6458c02447eaa21b9be1db1b6efb907f02acd7a", + "dependencies": [ + "jsr:@std/assert@^0.226.0" + ] + }, + "@std/collections@1.0.0-rc.1": { + "integrity": "e69fa667e4bede8f1013be9fb48915e564707a2b054848ca4a4da1f3f10251d9" + }, + "@std/crypto@0.224.0": { + "integrity": "154ef3ff08ef535562ef1a718718c5b2c5fc3808f0f9100daad69e829bfcdf2d", + "dependencies": [ + "jsr:@std/assert@^0.224.0", + "jsr:@std/encoding@^0.224.0" + ] + }, + "@std/encoding@0.224.3": { + "integrity": "5e861b6d81be5359fad4155e591acf17c0207b595112d1840998bb9f476dbdaf" + }, + "@std/encoding@1.0.0-rc.1": { + "integrity": "28065e53f31b4f2da5abb5a4a2776906c6a72ffe25d130d45c13ff7572b2ec35" + }, + "@std/fmt@0.225.2": { + "integrity": "8a2d157586372f9d5e74cdf0f463a828dee5d09d7de10e56394d8f20dbb5bf26" + }, + "@std/fmt@0.225.3": { + "integrity": "cb6ea567155f9865b80b502b2dde7671803eddd6dad743d8851d0de2c40bd349" + }, + "@std/fmt@0.225.4": { + "integrity": "584c681cf422b70e28959b57e59012823609c087384cbf12d05f67814797fda3" + }, + "@std/front-matter@0.224.1": { + "integrity": "d6551621d5318dfea44577ca95e8d833e9eb36d64797ce57a568ca0d7627c708", + "dependencies": [ + "jsr:@std/toml@^0.224.0", + "jsr:@std/yaml@^0.224.1" + ] + }, + "@std/front-matter@0.224.2": { + "integrity": "e445a33b6d2f5d24ec3a446fa440c4d677129ad19ee7a663ac0d423149017401", + "dependencies": [ + "jsr:@std/toml@^0.224.1", + "jsr:@std/yaml@^0.224.1" + ] + }, + "@std/fs@0.229.1": { + "integrity": "38d3fb31f0ca0a8c1118e039939188f32e291a3f7f17dc0868fec22024bdfadd", + "dependencies": [ + "jsr:@std/assert@^0.225.2", + "jsr:@std/path@^0.225.1" + ] + }, + "@std/fs@0.229.3": { + "integrity": "783bca21f24da92e04c3893c9e79653227ab016c48e96b3078377ebd5222e6eb", + "dependencies": [ + "jsr:@std/path@1.0.0-rc.1" + ] + }, + "@std/html@0.224.1": { + "integrity": "e573c429eb87f00513a8e89f5ca01e102d78ceb1e72315c254ee0f26fdef44e7" + }, + "@std/html@0.224.2": { + "integrity": "2f7bfd71081fad988af9ce991750ed1574917dc8e6fae0e151987ea020d1e21a" + }, + "@std/http@0.224.3": { + "integrity": "dac3a3640c730b9a4bcdb916b5231f4f2f5c141daf8dafc2b46011e1dab08eed", + "dependencies": [ + "jsr:@std/cli@^0.224.5", + "jsr:@std/encoding@1.0.0-rc.1", + "jsr:@std/fmt@^0.225.3", + "jsr:@std/media-types@^1.0.0-rc.1", + "jsr:@std/net@^0.224.2", + "jsr:@std/path@^0.225.2", + "jsr:@std/streams@^0.224.3" + ] + }, + "@std/io@0.224.1": { + "integrity": "73de242551a5c0965eb33e36b1fc7df4834ffbc836a1a643a410ccd11253d6be" + }, + "@std/json@0.224.1": { + "integrity": "2a18a8000707190e467f94b2732f6f88a3094db823765d8c58925bb5efeac29a" + }, + "@std/jsonc@0.224.1": { + "integrity": "1db6b207bf761e47bdbfb0a56a382daeb42c10f52d6e6dc84952641afa4e1735", + "dependencies": [ + "jsr:@std/assert@^0.226.0", + "jsr:@std/json@^0.224.1" + ] + }, + "@std/log@0.224.1": { + "integrity": "243688532289298670034915da5e2987cc544938c566c7d508afb7e06ec3fe9d", + "dependencies": [ + "jsr:@std/assert@^0.225.1", + "jsr:@std/fmt@^0.225.0", + "jsr:@std/fs@^0.229.0", + "jsr:@std/io@^0.224.0" + ] + }, + "@std/log@0.224.2": { + "integrity": "354fa2a93678e34e2c4b0238ac30a71a75ef645bde59742dc57ae4fce2cce46e", + "dependencies": [ + "jsr:@std/fmt@^0.225.4", + "jsr:@std/fs@^0.229.2", + "jsr:@std/io@^0.224.1" + ] + }, + "@std/media-types@0.224.1": { + "integrity": "9e69a5daed37c5b5c6d3ce4731dc191f80e67f79bed392b0957d1d03b87f11e1" + }, + "@std/media-types@1.0.0-rc.1": { + "integrity": "ff3cc8d5b536be2730fc4d446865007faf69bf4d46e7bea426d5e1d9c6ba9053" + }, + "@std/net@0.224.2": { + "integrity": "d5b45361e6df59eef9f6a202004fccb0944029f4db524710799d391711fac01f" + }, + "@std/net@0.224.3": { + "integrity": "a6257b9a35a4f299a0a9d4a4b76aef1f90ad05572374c5267c6c51a2ec41dfba" + }, + "@std/path@0.225.1": { + "integrity": "8c3220635a73730eb51fe43de9e10b79e2724a5bb8638b9355d35ae012fd9429", + "dependencies": [ + "jsr:@std/assert@^0.225.2" + ] + }, + "@std/path@0.225.2": { + "integrity": "0f2db41d36b50ef048dcb0399aac720a5348638dd3cb5bf80685bf2a745aa506", + "dependencies": [ + "jsr:@std/assert@^0.226.0" + ] + }, + "@std/path@1.0.0-rc.1": { + "integrity": "b8c00ae2f19106a6bb7cbf1ab9be52aa70de1605daeb2dbdc4f87a7cbaf10ff6" + }, + "@std/streams@0.224.4": { + "integrity": "0601626fbab009b4b4a7407009b4af2fe8e3edcd67630ac66ba7f23542b0d7e1" + }, + "@std/toml@0.224.1": { + "integrity": "c364b9ca3b18207223c4e2a1f652ef2970ff80967f7575ddf89b6b0565a17148", + "dependencies": [ + "jsr:@std/collections@^1.0.0-rc.1" + ] + }, + "@std/yaml@0.224.1": { + "integrity": "cbb444acccce7ea34b9ef6678bff84c18eba89b790e52dd098def8dae313f0b2" + } + }, + "npm": { + "@js-temporal/polyfill@0.4.4": { + "integrity": "sha512-2X6bvghJ/JAoZO52lbgyAPFj8uCflhTo2g7nkFzEQdXd/D8rEeD4HtmTEpmtGCva260fcd66YNXBOYdnmHqSOg==", + "dependencies": { + "jsbi": "jsbi@4.3.0", + "tslib": "tslib@2.6.3" + } + }, + "@types/estree@1.0.5": { + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dependencies": {} + }, + "@types/prop-types@15.7.12": { + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dependencies": {} + }, + "@types/react-dom@18.3.0": { + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dependencies": { + "@types/react": "@types/react@18.3.3" + } + }, + "@types/react@18.3.3": { + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dependencies": { + "@types/prop-types": "@types/prop-types@15.7.12", + "csstype": "csstype@3.1.3" + } + }, + "argparse@2.0.1": { + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dependencies": {} + }, + "csstype@3.1.3": { + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dependencies": {} + }, + "entities@4.5.0": { + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dependencies": {} + }, + "estree-walker@3.0.3": { + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": { + "@types/estree": "@types/estree@1.0.5" + } + }, + "js-tokens@4.0.0": { + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dependencies": {} + }, + "jsbi@4.3.0": { + "integrity": "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==", + "dependencies": {} + }, + "linkify-it@5.0.0": { + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dependencies": { + "uc.micro": "uc.micro@2.1.0" + } + }, + "loose-envify@1.4.0": { + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "js-tokens@4.0.0" + } + }, + "markdown-it-attrs@4.1.6_markdown-it@14.1.0": { + "integrity": "sha512-O7PDKZlN8RFMyDX13JnctQompwrrILuz2y43pW2GagcwpIIElkAdfeek+erHfxUOlXWPsjFeWmZ8ch1xtRLWpA==", + "dependencies": { + "markdown-it": "markdown-it@14.1.0" + } + }, + "markdown-it-deflist@3.0.0": { + "integrity": "sha512-OxPmQ/keJZwbubjiQWOvKLHwpV2wZ5I3Smc81OjhwbfJsjdRrvD5aLTQxmZzzePeO0kbGzAo3Krk4QLgA8PWLg==", + "dependencies": {} + }, + "markdown-it@14.1.0": { + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dependencies": { + "argparse": "argparse@2.0.1", + "entities": "entities@4.5.0", + "linkify-it": "linkify-it@5.0.0", + "mdurl": "mdurl@2.0.0", + "punycode.js": "punycode.js@2.3.1", + "uc.micro": "uc.micro@2.1.0" + } + }, + "mdurl@2.0.0": { + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dependencies": {} + }, + "meriyah@4.4.2": { + "integrity": "sha512-fENZIbs4tscI3IGRGtPrCoW4H4oGzVQrQCVCGRv+92kFXKkvxr52ZNR684ICvDC/UBWg9ioGc2X6pMnWOtRYwA==", + "dependencies": {} + }, + "punycode.js@2.3.1": { + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dependencies": {} + }, + "react-dom@18.3.1_react@18.3.1": { + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "loose-envify@1.4.0", + "react": "react@18.3.1", + "scheduler": "scheduler@0.23.2" + } + }, + "react@18.3.1": { + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "loose-envify@1.4.0" + } + }, + "scheduler@0.23.2": { + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "loose-envify@1.4.0" + } + }, + "tslib@2.6.3": { + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dependencies": {} + }, + "uc.micro@2.1.0": { + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dependencies": {} + }, + "unidecode@1.1.0": { + "integrity": "sha512-GIp57N6DVVJi8dpeIU6/leJGdv7W65ZSXFLFiNmxvexXkc0nXdqUvhA/qL9KqBKsILxMwg5MnmYNOIDJLb5JVA==", + "dependencies": {} + } + } + }, + "remote": { + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/adapters/lume.ts": "e33373886b9920515a0f0da9c9c4d38974a66e447a65925ca522be41e7491af6", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/cms.ts": "a423a22c4005c319918131841517a263dc2a89875ed4421c9b122656033cd3a4", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/collection.ts": "a6cf60685b0661b47b3ea610b5108a85b86f2ebd6629e4a73bfc73fe67fe93da", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/document.ts": "e5b346e28c3bced6109dc4b9ca1238789ed9f8a757466ceab984af126707a562", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/git.ts": "ebcb06df6c89ad74dc3194d78c5a6bb88c54305e8f79b177c1f3151296760e98", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/routes/auth.ts": "bf1a5c5a9b7d6896762077f9b005d3b49f706adb1efb0b938f2ec6c228f56ea8", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/routes/collection.ts": "c20244bf31699e9410984842bcfca20fbd0c924f58eaf6f3f9d65727a08011f6", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/routes/document.ts": "3f1fba5502ec459b48ff8872252300af7dfda1ef95d5b8d6e85891aebdf3a825", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/routes/files.ts": "7833e118804fa400f4a917e92c8de17d71af6ec7b3a50be12fb6b4edf23d529a", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/routes/index.ts": "d140a7577b88ab06a1a401e1a91334c6e56b8988adc6635443db822a5bf214e9", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/routes/versions.tsx": "dcfd34b50fb0be72078915ae484a6c23868366c0afcbdc88d7cb4c1910c161c1", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/breadcrumb.ts": "4252e88ab5aec21ce7f460cdb7cd29fd17a88cdd676817a0c09a9a15cad4d290", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/collection/create.ts": "b7496d3df3552921e049637bd03a896e28bfc2b898ae9af4fb70d7a4800c4324", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/collection/edit.ts": "6b626033d48c3f7676623ed37dd1b416d291db4d6c739fddec4d7bdbcfa2c627", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/collection/list.ts": "a186a70150ad5765901abfced5bac631c96c85d0b648837d1fb0a04f80642b32", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/document/edit.ts": "f49039d20d4fd6d89acb4e8924adeb12874605d6d88be03da8c9c7fda1a856cf", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/index.ts": "8ab7e1fd7deac4fcab87cc389cb244223d9e2e6b731912c9a4ca2365a4b7d54b", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/layout.ts": "66eba11ad9d466164ec7dd35aadb4640e82a3e51a4c27d3b47e40641879ebcfd", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/notfound.ts": "c89b3b113a6cd847b7dfa6155688c01e8e53754e5f0548149971ae5da5c439cd", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/tree.ts": "b99e66347519305d243cd4e4fbd04150e5ade1a6f51e9d0b6c383beacc90f966", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/uploads/list.ts": "45205bdb2118e881490b8038cbcbd58dbc0e214985706ab49da3d45ef5abadbb", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/templates/uploads/view.ts": "ad5cc54795b0a1afbfb3447a5df62865de4650c3c7de12a7984fae6f6b5b865a", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/upload.ts": "9d68f3274bc480be0f5ffc4fc65b7c2354c5b269f70c1579dad9aaa964111728", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/utils/data.ts": "8c4c01cb04c1cf62e251bdab2dbc1efc3abb00f26732cef12c52fc817ae59874", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/utils/env.ts": "723cb01d9509e0942a32ff568314b5ac27152c94e0070dc0cd6a706c74f33a62", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/utils/event.ts": "a7915a3e6bf7b34c166ee3aefc8ca5aab1631de50e0d851f78d0e8c8d0c766d8", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/utils/path.ts": "a210f4dc0b040aa5fd6cf170640b79bd83315920ed7cd55b3382130b87e33487", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/core/utils/string.ts": "53c8f487947f89c3f5eacdafbfa7cf7c6bc6bd4321506bc62112bc7d96b9eb65", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/deps/hono.ts": "d94bf5bf49ac38473549002b5f507b90c1126415edf43a059f7ff4f2e417a1d3", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/deps/std.ts": "6244f187951ff5c1f60b7418bd5b03458ca4db399e6ee8027b2fc42a706288cd", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/fields/core.ts": "cda0db8222b001c11a5c65d30ff340cd211afd467527951b4041b85b0c43cd95", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/mod.ts": "8c0e794889d779e84137f4d3b9673f5a5a1083777afdffa571d0a7af54ddceac", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/storage/fs.ts": "2d45319ce0ece128c6a86dbff4f18d392d07a641c0bf1b8d616b0ae4d63fec92", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/storage/transformers/front_matter.ts": "d357436c8fccf5aec59ec1ab63af08118863dd8d1f74cb5950dfde3700fa7c9e", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/storage/transformers/json.ts": "eb5d664be2042cc266a4fc737bbeeb1b4eb586e2beab8ca1965b07c2b066ee68", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/storage/transformers/mod.ts": "d828136358c98c93b45b5a1f1c7f383f9788ec47ede04bcb03de8ee0b19c2b3c", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/storage/transformers/yaml.ts": "87ce4b914a91ecec833558c29a5bbe8ca33f5cdf05141ba5e9c4e497aace561c", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.0/types.ts": "adde55f4ab5b670888991433f4e1a1f97900fc8f67cb2c9882c9a8e679f70a9b", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/adapters/lume.ts": "e33373886b9920515a0f0da9c9c4d38974a66e447a65925ca522be41e7491af6", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/cms.ts": "a423a22c4005c319918131841517a263dc2a89875ed4421c9b122656033cd3a4", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/collection.ts": "a6cf60685b0661b47b3ea610b5108a85b86f2ebd6629e4a73bfc73fe67fe93da", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/document.ts": "e5b346e28c3bced6109dc4b9ca1238789ed9f8a757466ceab984af126707a562", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/git.ts": "ebcb06df6c89ad74dc3194d78c5a6bb88c54305e8f79b177c1f3151296760e98", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/routes/auth.ts": "bf1a5c5a9b7d6896762077f9b005d3b49f706adb1efb0b938f2ec6c228f56ea8", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/routes/collection.ts": "c20244bf31699e9410984842bcfca20fbd0c924f58eaf6f3f9d65727a08011f6", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/routes/document.ts": "3f1fba5502ec459b48ff8872252300af7dfda1ef95d5b8d6e85891aebdf3a825", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/routes/files.ts": "7833e118804fa400f4a917e92c8de17d71af6ec7b3a50be12fb6b4edf23d529a", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/routes/index.ts": "d140a7577b88ab06a1a401e1a91334c6e56b8988adc6635443db822a5bf214e9", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/routes/versions.tsx": "dcfd34b50fb0be72078915ae484a6c23868366c0afcbdc88d7cb4c1910c161c1", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/breadcrumb.ts": "4252e88ab5aec21ce7f460cdb7cd29fd17a88cdd676817a0c09a9a15cad4d290", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/collection/create.ts": "b7496d3df3552921e049637bd03a896e28bfc2b898ae9af4fb70d7a4800c4324", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/collection/edit.ts": "6b626033d48c3f7676623ed37dd1b416d291db4d6c739fddec4d7bdbcfa2c627", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/collection/list.ts": "a186a70150ad5765901abfced5bac631c96c85d0b648837d1fb0a04f80642b32", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/document/edit.ts": "f49039d20d4fd6d89acb4e8924adeb12874605d6d88be03da8c9c7fda1a856cf", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/index.ts": "8ab7e1fd7deac4fcab87cc389cb244223d9e2e6b731912c9a4ca2365a4b7d54b", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/layout.ts": "66eba11ad9d466164ec7dd35aadb4640e82a3e51a4c27d3b47e40641879ebcfd", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/notfound.ts": "c89b3b113a6cd847b7dfa6155688c01e8e53754e5f0548149971ae5da5c439cd", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/tree.ts": "b99e66347519305d243cd4e4fbd04150e5ade1a6f51e9d0b6c383beacc90f966", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/uploads/list.ts": "45205bdb2118e881490b8038cbcbd58dbc0e214985706ab49da3d45ef5abadbb", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/templates/uploads/view.ts": "ad5cc54795b0a1afbfb3447a5df62865de4650c3c7de12a7984fae6f6b5b865a", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/upload.ts": "9d68f3274bc480be0f5ffc4fc65b7c2354c5b269f70c1579dad9aaa964111728", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/utils/data.ts": "8c4c01cb04c1cf62e251bdab2dbc1efc3abb00f26732cef12c52fc817ae59874", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/utils/env.ts": "723cb01d9509e0942a32ff568314b5ac27152c94e0070dc0cd6a706c74f33a62", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/utils/event.ts": "a7915a3e6bf7b34c166ee3aefc8ca5aab1631de50e0d851f78d0e8c8d0c766d8", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/utils/path.ts": "a210f4dc0b040aa5fd6cf170640b79bd83315920ed7cd55b3382130b87e33487", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/core/utils/string.ts": "53c8f487947f89c3f5eacdafbfa7cf7c6bc6bd4321506bc62112bc7d96b9eb65", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/deps/hono.ts": "6f7a4d97201a60e1551e932a9766926321df0f2886fcbe6321a23824f902ea0f", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/deps/std.ts": "a63e76f3ff270c5556f7c98a2eb1bfebeb2b1c0e8eca29aba3a12b71976d8b69", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/fields/core.ts": "cda0db8222b001c11a5c65d30ff340cd211afd467527951b4041b85b0c43cd95", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/mod.ts": "8c0e794889d779e84137f4d3b9673f5a5a1083777afdffa571d0a7af54ddceac", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/storage/fs.ts": "2d45319ce0ece128c6a86dbff4f18d392d07a641c0bf1b8d616b0ae4d63fec92", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/storage/transformers/front_matter.ts": "d357436c8fccf5aec59ec1ab63af08118863dd8d1f74cb5950dfde3700fa7c9e", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/storage/transformers/json.ts": "eb5d664be2042cc266a4fc737bbeeb1b4eb586e2beab8ca1965b07c2b066ee68", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/storage/transformers/mod.ts": "d828136358c98c93b45b5a1f1c7f383f9788ec47ede04bcb03de8ee0b19c2b3c", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/storage/transformers/yaml.ts": "87ce4b914a91ecec833558c29a5bbe8ca33f5cdf05141ba5e9c4e497aace561c", + "https://cdn.jsdelivr.net/gh/lumeland/cms@v0.5.1/types.ts": "adde55f4ab5b670888991433f4e1a1f97900fc8f67cb2c9882c9a8e679f70a9b", + "https://deno.land/std@0.170.0/_util/asserts.ts": "d0844e9b62510f89ce1f9878b046f6a57bf88f208a10304aab50efcb48365272", + "https://deno.land/std@0.170.0/_util/os.ts": "8a33345f74990e627b9dfe2de9b040004b08ea5146c7c9e8fe9a29070d193934", + "https://deno.land/std@0.170.0/encoding/base64.ts": "8605e018e49211efc767686f6f687827d7f5fd5217163e981d8d693105640d7a", + "https://deno.land/std@0.170.0/fmt/colors.ts": "03ad95e543d2808bc43c17a3dd29d25b43d0f16287fe562a0be89bf632454a12", + "https://deno.land/std@0.170.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", + "https://deno.land/std@0.170.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", + "https://deno.land/std@0.170.0/path/_util.ts": "d16be2a16e1204b65f9d0dfc54a9bc472cafe5f4a190b3c8471ec2016ccd1677", + "https://deno.land/std@0.170.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", + "https://deno.land/std@0.170.0/path/glob.ts": "81cc6c72be002cd546c7a22d1f263f82f63f37fe0035d9726aa96fc8f6e4afa1", + "https://deno.land/std@0.170.0/path/mod.ts": "cf7cec7ac11b7048bb66af8ae03513e66595c279c65cfa12bfc07d9599608b78", + "https://deno.land/std@0.170.0/path/posix.ts": "b859684bc4d80edfd4cad0a82371b50c716330bed51143d6dcdbe59e6278b30c", + "https://deno.land/std@0.170.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", + "https://deno.land/std@0.170.0/path/win32.ts": "7cebd2bda6657371adc00061a1d23fdd87bcdf64b4843bb148b0b24c11b40f69", + "https://deno.land/std@0.224.0/assert/assert.ts": "09d30564c09de846855b7b071e62b5974b001bb72a4b797958fe0660e7849834", + "https://deno.land/std@0.224.0/assert/assertion_error.ts": "ba8752bd27ebc51f723702fac2f54d3e94447598f54264a6653d6413738a8917", + "https://deno.land/std@0.224.0/dotenv/mod.ts": "0180eaeedaaf88647318811cdaa418cc64dc51fb08354f91f5f480d0a1309f7d", + "https://deno.land/std@0.224.0/dotenv/parse.ts": "09977ff88dfd1f24f9973a338f0f91bbdb9307eb5ff6085446e7c423e4c7ba0c", + "https://deno.land/std@0.224.0/dotenv/stringify.ts": "275da322c409170160440836342eaa7cf012a1d11a7e700d8ca4e7f2f8aa4615", + "https://deno.land/std@0.224.0/html/entities.ts": "fd5ac9d459355a377baea118f4e808a1268808fd9138b319c90f11024e2f1718", + "https://deno.land/std@0.224.0/html/mod.ts": "047624f883874f4b9781da872f9579a615fb5418af30663c9ce0c65074ace87f", + "https://deno.land/std@0.224.0/path/_common/assert_path.ts": "dbdd757a465b690b2cc72fc5fb7698c51507dec6bfafce4ca500c46b76ff7bd8", + "https://deno.land/std@0.224.0/path/_common/basename.ts": "569744855bc8445f3a56087fd2aed56bdad39da971a8d92b138c9913aecc5fa2", + "https://deno.land/std@0.224.0/path/_common/common.ts": "ef73c2860694775fe8ffcbcdd387f9f97c7a656febf0daa8c73b56f4d8a7bd4c", + "https://deno.land/std@0.224.0/path/_common/constants.ts": "dc5f8057159f4b48cd304eb3027e42f1148cf4df1fb4240774d3492b5d12ac0c", + "https://deno.land/std@0.224.0/path/_common/dirname.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8", + "https://deno.land/std@0.224.0/path/_common/format.ts": "92500e91ea5de21c97f5fe91e178bae62af524b72d5fcd246d6d60ae4bcada8b", + "https://deno.land/std@0.224.0/path/_common/from_file_url.ts": "d672bdeebc11bf80e99bf266f886c70963107bdd31134c4e249eef51133ceccf", + "https://deno.land/std@0.224.0/path/_common/glob_to_reg_exp.ts": "6cac16d5c2dc23af7d66348a7ce430e5de4e70b0eede074bdbcf4903f4374d8d", + "https://deno.land/std@0.224.0/path/_common/normalize.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8", + "https://deno.land/std@0.224.0/path/_common/normalize_string.ts": "33edef773c2a8e242761f731adeb2bd6d683e9c69e4e3d0092985bede74f4ac3", + "https://deno.land/std@0.224.0/path/_common/relative.ts": "faa2753d9b32320ed4ada0733261e3357c186e5705678d9dd08b97527deae607", + "https://deno.land/std@0.224.0/path/_common/strip_trailing_separators.ts": "7024a93447efcdcfeaa9339a98fa63ef9d53de363f1fbe9858970f1bba02655a", + "https://deno.land/std@0.224.0/path/_common/to_file_url.ts": "7f76adbc83ece1bba173e6e98a27c647712cab773d3f8cbe0398b74afc817883", + "https://deno.land/std@0.224.0/path/_interface.ts": "8dfeb930ca4a772c458a8c7bbe1e33216fe91c253411338ad80c5b6fa93ddba0", + "https://deno.land/std@0.224.0/path/_os.ts": "8fb9b90fb6b753bd8c77cfd8a33c2ff6c5f5bc185f50de8ca4ac6a05710b2c15", + "https://deno.land/std@0.224.0/path/basename.ts": "7ee495c2d1ee516ffff48fb9a93267ba928b5a3486b550be73071bc14f8cc63e", + "https://deno.land/std@0.224.0/path/common.ts": "03e52e22882402c986fe97ca3b5bb4263c2aa811c515ce84584b23bac4cc2643", + "https://deno.land/std@0.224.0/path/constants.ts": "0c206169ca104938ede9da48ac952de288f23343304a1c3cb6ec7625e7325f36", + "https://deno.land/std@0.224.0/path/dirname.ts": "85bd955bf31d62c9aafdd7ff561c4b5fb587d11a9a5a45e2b01aedffa4238a7c", + "https://deno.land/std@0.224.0/path/extname.ts": "593303db8ae8c865cbd9ceec6e55d4b9ac5410c1e276bfd3131916591b954441", + "https://deno.land/std@0.224.0/path/format.ts": "6ce1779b0980296cf2bc20d66436b12792102b831fd281ab9eb08fa8a3e6f6ac", + "https://deno.land/std@0.224.0/path/from_file_url.ts": "911833ae4fd10a1c84f6271f36151ab785955849117dc48c6e43b929504ee069", + "https://deno.land/std@0.224.0/path/glob_to_regexp.ts": "7f30f0a21439cadfdae1be1bf370880b415e676097fda584a63ce319053b5972", + "https://deno.land/std@0.224.0/path/is_absolute.ts": "4791afc8bfd0c87f0526eaa616b0d16e7b3ab6a65b62942e50eac68de4ef67d7", + "https://deno.land/std@0.224.0/path/is_glob.ts": "a65f6195d3058c3050ab905705891b412ff942a292bcbaa1a807a74439a14141", + "https://deno.land/std@0.224.0/path/join.ts": "ae2ec5ca44c7e84a235fd532e4a0116bfb1f2368b394db1c4fb75e3c0f26a33a", + "https://deno.land/std@0.224.0/path/join_globs.ts": "5b3bf248b93247194f94fa6947b612ab9d3abd571ca8386cf7789038545e54a0", + "https://deno.land/std@0.224.0/path/mod.ts": "f6bd79cb08be0e604201bc9de41ac9248582699d1b2ee0ab6bc9190d472cf9cd", + "https://deno.land/std@0.224.0/path/normalize.ts": "4155743ccceeed319b350c1e62e931600272fad8ad00c417b91df093867a8352", + "https://deno.land/std@0.224.0/path/normalize_glob.ts": "cc89a77a7d3b1d01053b9dcd59462b75482b11e9068ae6c754b5cf5d794b374f", + "https://deno.land/std@0.224.0/path/parse.ts": "77ad91dcb235a66c6f504df83087ce2a5471e67d79c402014f6e847389108d5a", + "https://deno.land/std@0.224.0/path/posix/_util.ts": "1e3937da30f080bfc99fe45d7ed23c47dd8585c5e473b2d771380d3a6937cf9d", + "https://deno.land/std@0.224.0/path/posix/basename.ts": "d2fa5fbbb1c5a3ab8b9326458a8d4ceac77580961b3739cd5bfd1d3541a3e5f0", + "https://deno.land/std@0.224.0/path/posix/common.ts": "26f60ccc8b2cac3e1613000c23ac5a7d392715d479e5be413473a37903a2b5d4", + "https://deno.land/std@0.224.0/path/posix/constants.ts": "93481efb98cdffa4c719c22a0182b994e5a6aed3047e1962f6c2c75b7592bef1", + "https://deno.land/std@0.224.0/path/posix/dirname.ts": "76cd348ffe92345711409f88d4d8561d8645353ac215c8e9c80140069bf42f00", + "https://deno.land/std@0.224.0/path/posix/extname.ts": "e398c1d9d1908d3756a7ed94199fcd169e79466dd88feffd2f47ce0abf9d61d2", + "https://deno.land/std@0.224.0/path/posix/format.ts": "185e9ee2091a42dd39e2a3b8e4925370ee8407572cee1ae52838aed96310c5c1", + "https://deno.land/std@0.224.0/path/posix/from_file_url.ts": "951aee3a2c46fd0ed488899d024c6352b59154c70552e90885ed0c2ab699bc40", + "https://deno.land/std@0.224.0/path/posix/glob_to_regexp.ts": "76f012fcdb22c04b633f536c0b9644d100861bea36e9da56a94b9c589a742e8f", + "https://deno.land/std@0.224.0/path/posix/is_absolute.ts": "cebe561ad0ae294f0ce0365a1879dcfca8abd872821519b4fcc8d8967f888ede", + "https://deno.land/std@0.224.0/path/posix/is_glob.ts": "8a8b08c08bf731acf2c1232218f1f45a11131bc01de81e5f803450a5914434b9", + "https://deno.land/std@0.224.0/path/posix/join.ts": "7fc2cb3716aa1b863e990baf30b101d768db479e70b7313b4866a088db016f63", + "https://deno.land/std@0.224.0/path/posix/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25", + "https://deno.land/std@0.224.0/path/posix/mod.ts": "2301fc1c54a28b349e20656f68a85f75befa0ee9b6cd75bfac3da5aca9c3f604", + "https://deno.land/std@0.224.0/path/posix/normalize.ts": "baeb49816a8299f90a0237d214cef46f00ba3e95c0d2ceb74205a6a584b58a91", + "https://deno.land/std@0.224.0/path/posix/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6", + "https://deno.land/std@0.224.0/path/posix/parse.ts": "09dfad0cae530f93627202f28c1befa78ea6e751f92f478ca2cc3b56be2cbb6a", + "https://deno.land/std@0.224.0/path/posix/relative.ts": "3907d6eda41f0ff723d336125a1ad4349112cd4d48f693859980314d5b9da31c", + "https://deno.land/std@0.224.0/path/posix/resolve.ts": "08b699cfeee10cb6857ccab38fa4b2ec703b0ea33e8e69964f29d02a2d5257cf", + "https://deno.land/std@0.224.0/path/posix/to_file_url.ts": "7aa752ba66a35049e0e4a4be5a0a31ac6b645257d2e031142abb1854de250aaf", + "https://deno.land/std@0.224.0/path/posix/to_namespaced_path.ts": "28b216b3c76f892a4dca9734ff1cc0045d135532bfd9c435ae4858bfa5a2ebf0", + "https://deno.land/std@0.224.0/path/relative.ts": "ab739d727180ed8727e34ed71d976912461d98e2b76de3d3de834c1066667add", + "https://deno.land/std@0.224.0/path/resolve.ts": "a6f977bdb4272e79d8d0ed4333e3d71367cc3926acf15ac271f1d059c8494d8d", + "https://deno.land/std@0.224.0/path/to_file_url.ts": "88f049b769bce411e2d2db5bd9e6fd9a185a5fbd6b9f5ad8f52bef517c4ece1b", + "https://deno.land/std@0.224.0/path/to_namespaced_path.ts": "b706a4103b104cfadc09600a5f838c2ba94dbcdb642344557122dda444526e40", + "https://deno.land/std@0.224.0/path/windows/_util.ts": "d5f47363e5293fced22c984550d5e70e98e266cc3f31769e1710511803d04808", + "https://deno.land/std@0.224.0/path/windows/basename.ts": "6bbc57bac9df2cec43288c8c5334919418d784243a00bc10de67d392ab36d660", + "https://deno.land/std@0.224.0/path/windows/common.ts": "26f60ccc8b2cac3e1613000c23ac5a7d392715d479e5be413473a37903a2b5d4", + "https://deno.land/std@0.224.0/path/windows/constants.ts": "5afaac0a1f67b68b0a380a4ef391bf59feb55856aa8c60dfc01bd3b6abb813f5", + "https://deno.land/std@0.224.0/path/windows/dirname.ts": "33e421be5a5558a1346a48e74c330b8e560be7424ed7684ea03c12c21b627bc9", + "https://deno.land/std@0.224.0/path/windows/extname.ts": "165a61b00d781257fda1e9606a48c78b06815385e7d703232548dbfc95346bef", + "https://deno.land/std@0.224.0/path/windows/format.ts": "bbb5ecf379305b472b1082cd2fdc010e44a0020030414974d6029be9ad52aeb6", + "https://deno.land/std@0.224.0/path/windows/from_file_url.ts": "ced2d587b6dff18f963f269d745c4a599cf82b0c4007356bd957cb4cb52efc01", + "https://deno.land/std@0.224.0/path/windows/glob_to_regexp.ts": "e45f1f89bf3fc36f94ab7b3b9d0026729829fabc486c77f414caebef3b7304f8", + "https://deno.land/std@0.224.0/path/windows/is_absolute.ts": "4a8f6853f8598cf91a835f41abed42112cebab09478b072e4beb00ec81f8ca8a", + "https://deno.land/std@0.224.0/path/windows/is_glob.ts": "8a8b08c08bf731acf2c1232218f1f45a11131bc01de81e5f803450a5914434b9", + "https://deno.land/std@0.224.0/path/windows/join.ts": "8d03530ab89195185103b7da9dfc6327af13eabdcd44c7c63e42e27808f50ecf", + "https://deno.land/std@0.224.0/path/windows/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25", + "https://deno.land/std@0.224.0/path/windows/mod.ts": "2301fc1c54a28b349e20656f68a85f75befa0ee9b6cd75bfac3da5aca9c3f604", + "https://deno.land/std@0.224.0/path/windows/normalize.ts": "78126170ab917f0ca355a9af9e65ad6bfa5be14d574c5fb09bb1920f52577780", + "https://deno.land/std@0.224.0/path/windows/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6", + "https://deno.land/std@0.224.0/path/windows/parse.ts": "08804327b0484d18ab4d6781742bf374976de662f8642e62a67e93346e759707", + "https://deno.land/std@0.224.0/path/windows/relative.ts": "3e1abc7977ee6cc0db2730d1f9cb38be87b0ce4806759d271a70e4997fc638d7", + "https://deno.land/std@0.224.0/path/windows/resolve.ts": "8dae1dadfed9d46ff46cc337c9525c0c7d959fb400a6308f34595c45bdca1972", + "https://deno.land/std@0.224.0/path/windows/to_file_url.ts": "40e560ee4854fe5a3d4d12976cef2f4e8914125c81b11f1108e127934ced502e", + "https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c", + "https://deno.land/x/astring@v1.8.6/src/astring.js": "457e5fd0b72da2a365c33059c8846d9cb37dc5e5f1010332d13afae540323da0", + "https://deno.land/x/cliffy@v0.25.7/_utils/distance.ts": "02af166952c7c358ac83beae397aa2fbca4ad630aecfcd38d92edb1ea429f004", + "https://deno.land/x/cliffy@v0.25.7/ansi/ansi.ts": "7f43d07d31dd7c24b721bb434c39cbb5132029fa4be3dd8938873065f65e5810", + "https://deno.land/x/cliffy@v0.25.7/ansi/ansi_escapes.ts": "885f61f343223f27b8ec69cc138a54bea30542924eacd0f290cd84edcf691387", + "https://deno.land/x/cliffy@v0.25.7/ansi/chain.ts": "31fb9fcbf72fed9f3eb9b9487270d2042ccd46a612d07dd5271b1a80ae2140a0", + "https://deno.land/x/cliffy@v0.25.7/ansi/colors.ts": "5f71993af5bd1aa0a795b15f41692d556d7c89584a601fed75997df844b832c9", + "https://deno.land/x/cliffy@v0.25.7/ansi/cursor_position.ts": "d537491e31d9c254b208277448eff92ff7f55978c4928dea363df92c0df0813f", + "https://deno.land/x/cliffy@v0.25.7/ansi/deps.ts": "0f35cb7e91868ce81561f6a77426ea8bc55dc15e13f84c7352f211023af79053", + "https://deno.land/x/cliffy@v0.25.7/ansi/mod.ts": "bb4e6588e6704949766205709463c8c33b30fec66c0b1846bc84a3db04a4e075", + "https://deno.land/x/cliffy@v0.25.7/ansi/tty.ts": "8fb064c17ead6cdf00c2d3bc87a9fd17b1167f2daa575c42b516f38bdb604673", + "https://deno.land/x/cliffy@v0.25.7/command/_errors.ts": "a9bd23dc816b32ec96c9b8f3057218241778d8c40333b43341138191450965e5", + "https://deno.land/x/cliffy@v0.25.7/command/_utils.ts": "9ab3d69fabab6c335b881b8a5229cbd5db0c68f630a1c307aff988b6396d9baf", + "https://deno.land/x/cliffy@v0.25.7/command/command.ts": "a2b83c612acd65c69116f70dec872f6da383699b83874b70fcf38cddf790443f", + "https://deno.land/x/cliffy@v0.25.7/command/completions/_bash_completions_generator.ts": "43b4abb543d4dc60233620d51e69d82d3b7c44e274e723681e0dce2a124f69f9", + "https://deno.land/x/cliffy@v0.25.7/command/completions/_fish_completions_generator.ts": "d0289985f5cf0bd288c05273bfa286b24c27feb40822eb7fd9d7fee64e6580e8", + "https://deno.land/x/cliffy@v0.25.7/command/completions/_zsh_completions_generator.ts": "14461eb274954fea4953ee75938821f721da7da607dc49bcc7db1e3f33a207bd", + "https://deno.land/x/cliffy@v0.25.7/command/completions/bash.ts": "053aa2006ec327ccecacb00ba28e5eb836300e5c1bec1b3cfaee9ddcf8189756", + "https://deno.land/x/cliffy@v0.25.7/command/completions/complete.ts": "58df61caa5e6220ff2768636a69337923ad9d4b8c1932aeb27165081c4d07d8b", + "https://deno.land/x/cliffy@v0.25.7/command/completions/fish.ts": "9938beaa6458c6cf9e2eeda46a09e8cd362d4f8c6c9efe87d3cd8ca7477402a5", + "https://deno.land/x/cliffy@v0.25.7/command/completions/mod.ts": "aeef7ec8e319bb157c39a4bab8030c9fe8fa327b4c1e94c9c1025077b45b40c0", + "https://deno.land/x/cliffy@v0.25.7/command/completions/zsh.ts": "8b04ab244a0b582f7927d405e17b38602428eeb347a9968a657e7ea9f40e721a", + "https://deno.land/x/cliffy@v0.25.7/command/deprecated.ts": "bbe6670f1d645b773d04b725b8b8e7814c862c9f1afba460c4d599ffe9d4983c", + "https://deno.land/x/cliffy@v0.25.7/command/deps.ts": "275b964ce173770bae65f6b8ebe9d2fd557dc10292cdd1ed3db1735f0d77fa1d", + "https://deno.land/x/cliffy@v0.25.7/command/help/_help_generator.ts": "f7c349cb2ddb737e70dc1f89bcb1943ca9017a53506be0d4138e0aadb9970a49", + "https://deno.land/x/cliffy@v0.25.7/command/help/mod.ts": "09d74d3eb42d21285407cda688074c29595d9c927b69aedf9d05ff3f215820d3", + "https://deno.land/x/cliffy@v0.25.7/command/mod.ts": "d0a32df6b14028e43bb2d41fa87d24bc00f9662a44e5a177b3db02f93e473209", + "https://deno.land/x/cliffy@v0.25.7/command/type.ts": "24e88e3085e1574662b856ccce70d589959648817135d4469fab67b9cce1b364", + "https://deno.land/x/cliffy@v0.25.7/command/types.ts": "ae02eec0ed7a769f7dba2dd5d3a931a61724b3021271b1b565cf189d9adfd4a0", + "https://deno.land/x/cliffy@v0.25.7/command/types/action_list.ts": "33c98d449617c7a563a535c9ceb3741bde9f6363353fd492f90a74570c611c27", + "https://deno.land/x/cliffy@v0.25.7/command/types/boolean.ts": "3879ec16092b4b5b1a0acb8675f8c9250c0b8a972e1e4c7adfba8335bd2263ed", + "https://deno.land/x/cliffy@v0.25.7/command/types/child_command.ts": "f1fca390c7fbfa7a713ca15ef55c2c7656bcbb394d50e8ef54085bdf6dc22559", + "https://deno.land/x/cliffy@v0.25.7/command/types/command.ts": "325d0382e383b725fd8d0ef34ebaeae082c5b76a1f6f2e843fee5dbb1a4fe3ac", + "https://deno.land/x/cliffy@v0.25.7/command/types/enum.ts": "2178345972adf7129a47e5f02856ca3e6852a91442a1c78307dffb8a6a3c6c9f", + "https://deno.land/x/cliffy@v0.25.7/command/types/file.ts": "8618f16ac9015c8589cbd946b3de1988cc4899b90ea251f3325c93c46745140e", + "https://deno.land/x/cliffy@v0.25.7/command/types/integer.ts": "29864725fd48738579d18123d7ee78fed37515e6dc62146c7544c98a82f1778d", + "https://deno.land/x/cliffy@v0.25.7/command/types/number.ts": "aeba96e6f470309317a16b308c82e0e4138a830ec79c9877e4622c682012bc1f", + "https://deno.land/x/cliffy@v0.25.7/command/types/string.ts": "e4dadb08a11795474871c7967beab954593813bb53d9f69ea5f9b734e43dc0e0", + "https://deno.land/x/cliffy@v0.25.7/command/upgrade/mod.ts": "17e2df3b620905583256684415e6c4a31e8de5c59066eb6d6c9c133919292dc4", + "https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider.ts": "d6fb846043232cbd23c57d257100c7fc92274984d75a5fead0f3e4266dc76ab8", + "https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider/deno_land.ts": "24f8d82e38c51e09be989f30f8ad21f9dd41ac1bb1973b443a13883e8ba06d6d", + "https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider/github.ts": "99e1b133dd446c6aa79f69e69c46eb8bc1c968dd331c2a7d4064514a317c7b59", + "https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider/nest_land.ts": "0e07936cea04fa41ac9297f32d87f39152ea873970c54cb5b4934b12fee1885e", + "https://deno.land/x/cliffy@v0.25.7/command/upgrade/upgrade_command.ts": "3640a287d914190241ea1e636774b1b4b0e1828fa75119971dd5304784061e05", + "https://deno.land/x/cliffy@v0.25.7/flags/_errors.ts": "f1fbb6bfa009e7950508c9d491cfb4a5551027d9f453389606adb3f2327d048f", + "https://deno.land/x/cliffy@v0.25.7/flags/_utils.ts": "340d3ecab43cde9489187e1f176504d2c58485df6652d1cdd907c0e9c3ce4cc2", + "https://deno.land/x/cliffy@v0.25.7/flags/_validate_flags.ts": "16eb5837986c6f6f7620817820161a78d66ce92d690e3697068726bbef067452", + "https://deno.land/x/cliffy@v0.25.7/flags/deprecated.ts": "a72a35de3cc7314e5ebea605ca23d08385b218ef171c32a3f135fb4318b08126", + "https://deno.land/x/cliffy@v0.25.7/flags/flags.ts": "68a9dfcacc4983a84c07ba19b66e5e9fccd04389fad215210c60fb414cc62576", + "https://deno.land/x/cliffy@v0.25.7/flags/mod.ts": "b21c2c135cd2437cc16245c5f168a626091631d6d4907ad10db61c96c93bdb25", + "https://deno.land/x/cliffy@v0.25.7/flags/types.ts": "7452ea5296758fb7af89930349ce40d8eb9a43b24b3f5759283e1cb5113075fd", + "https://deno.land/x/cliffy@v0.25.7/flags/types/boolean.ts": "4c026dd66ec9c5436860dc6d0241427bdb8d8e07337ad71b33c08193428a2236", + "https://deno.land/x/cliffy@v0.25.7/flags/types/integer.ts": "b60d4d590f309ddddf066782d43e4dc3799f0e7d08e5ede7dc62a5ee94b9a6d9", + "https://deno.land/x/cliffy@v0.25.7/flags/types/number.ts": "610936e2d29de7c8c304b65489a75ebae17b005c6122c24e791fbed12444d51e", + "https://deno.land/x/cliffy@v0.25.7/flags/types/string.ts": "e89b6a5ce322f65a894edecdc48b44956ec246a1d881f03e97bbda90dd8638c5", + "https://deno.land/x/cliffy@v0.25.7/keycode/key_code.ts": "c4ab0ffd102c2534962b765ded6d8d254631821bf568143d9352c1cdcf7a24be", + "https://deno.land/x/cliffy@v0.25.7/keycode/key_codes.ts": "917f0a2da0dbace08cf29bcfdaaa2257da9fe7e705fff8867d86ed69dfb08cfe", + "https://deno.land/x/cliffy@v0.25.7/keycode/mod.ts": "292d2f295316c6e0da6955042a7b31ab2968ff09f2300541d00f05ed6c2aa2d4", + "https://deno.land/x/cliffy@v0.25.7/mod.ts": "e3515ccf6bd4e4ac89322034e07e2332ed71901e4467ee5bc9d72851893e167b", + "https://deno.land/x/cliffy@v0.25.7/prompt/_generic_input.ts": "737cff2de02c8ce35250f5dd79c67b5fc176423191a2abd1f471a90dd725659e", + "https://deno.land/x/cliffy@v0.25.7/prompt/_generic_list.ts": "79b301bf09eb19f0d070d897f613f78d4e9f93100d7e9a26349ef0bfaa7408d2", + "https://deno.land/x/cliffy@v0.25.7/prompt/_generic_prompt.ts": "8630ce89a66d83e695922df41721cada52900b515385d86def597dea35971bb2", + "https://deno.land/x/cliffy@v0.25.7/prompt/_generic_suggestions.ts": "2a8b619f91e8f9a270811eff557f10f1343a444a527b5fc22c94de832939920c", + "https://deno.land/x/cliffy@v0.25.7/prompt/_utils.ts": "676cca30762656ed1a9bcb21a7254244278a23ffc591750e98a501644b6d2df3", + "https://deno.land/x/cliffy@v0.25.7/prompt/checkbox.ts": "e5a5a9adbb86835dffa2afbd23c6f7a8fe25a9d166485388ef25aba5dc3fbf9e", + "https://deno.land/x/cliffy@v0.25.7/prompt/confirm.ts": "94c8e55de3bbcd53732804420935c432eab29945497d1c47c357d236a89cb5f6", + "https://deno.land/x/cliffy@v0.25.7/prompt/deps.ts": "4c38ab18e55a792c9a136c1c29b2b6e21ea4820c45de7ef4cf517ce94012c57d", + "https://deno.land/x/cliffy@v0.25.7/prompt/figures.ts": "26af0fbfe21497220e4b887bb550fab997498cde14703b98e78faf370fbb4b94", + "https://deno.land/x/cliffy@v0.25.7/prompt/input.ts": "ee45532e0a30c2463e436e08ae291d79d1c2c40872e17364c96d2b97c279bf4d", + "https://deno.land/x/cliffy@v0.25.7/prompt/list.ts": "6780427ff2a932a48c9b882d173c64802081d6cdce9ff618d66ba6504b6abc50", + "https://deno.land/x/cliffy@v0.25.7/prompt/mod.ts": "195aed14d10d279914eaa28c696dec404d576ca424c097a5bc2b4a7a13b66c89", + "https://deno.land/x/cliffy@v0.25.7/prompt/number.ts": "015305a76b50138234dde4fd50eb886c6c7c0baa1b314caf811484644acdc2cf", + "https://deno.land/x/cliffy@v0.25.7/prompt/prompt.ts": "0e7f6a1d43475ee33fb25f7d50749b2f07fc0bcddd9579f3f9af12d05b4a4412", + "https://deno.land/x/cliffy@v0.25.7/prompt/secret.ts": "58745f5231fb2c44294c4acf2511f8c5bfddfa1e12f259580ff90dedea2703d6", + "https://deno.land/x/cliffy@v0.25.7/prompt/select.ts": "1e982eae85718e4e15a3ee10a5ae2233e532d7977d55888f3a309e8e3982b784", + "https://deno.land/x/cliffy@v0.25.7/prompt/toggle.ts": "842c3754a40732f2e80bcd4670098713e402e64bd930e6cab2b787f7ad4d931a", + "https://deno.land/x/cliffy@v0.25.7/table/border.ts": "2514abae4e4f51eda60a5f8c927ba24efd464a590027e900926b38f68e01253c", + "https://deno.land/x/cliffy@v0.25.7/table/cell.ts": "1d787d8006ac8302020d18ec39f8d7f1113612c20801b973e3839de9c3f8b7b3", + "https://deno.land/x/cliffy@v0.25.7/table/deps.ts": "5b05fa56c1a5e2af34f2103fd199e5f87f0507549963019563eae519271819d2", + "https://deno.land/x/cliffy@v0.25.7/table/layout.ts": "46bf10ae5430cf4fbb92f23d588230e9c6336edbdb154e5c9581290562b169f4", + "https://deno.land/x/cliffy@v0.25.7/table/mod.ts": "e74f69f38810ee6139a71132783765feb94436a6619c07474ada45b465189834", + "https://deno.land/x/cliffy@v0.25.7/table/row.ts": "5f519ba7488d2ef76cbbf50527f10f7957bfd668ce5b9169abbc44ec88302645", + "https://deno.land/x/cliffy@v0.25.7/table/table.ts": "ec204c9d08bb3ff1939c5ac7412a4c9ed7d00925d4fc92aff9bfe07bd269258d", + "https://deno.land/x/cliffy@v0.25.7/table/utils.ts": "187bb7dcbcfb16199a5d906113f584740901dfca1007400cba0df7dcd341bc29", + "https://deno.land/x/deno_dom@v0.1.47/build/deno-wasm/deno-wasm.js": "d6841a06342eb6a2798ef28de79ad69c0f2fa349fa04d3ca45e5fcfbf50a9340", + "https://deno.land/x/deno_dom@v0.1.47/deno-dom-wasm.ts": "0669396686fb207f1354af33df6aabe2189b4eceafdb1bf7f3d6bbb2637b6b03", + "https://deno.land/x/deno_dom@v0.1.47/src/api.ts": "0ff5790f0a3eeecb4e00b7d8fbfa319b165962cf6d0182a65ba90f158d74f7d7", + "https://deno.land/x/deno_dom@v0.1.47/src/constructor-lock.ts": "0e7b297e8b9cf921a3b0d3a692ec5fb462c5afc47ec554292e20090b9e16b40a", + "https://deno.land/x/deno_dom@v0.1.47/src/deserialize.ts": "1cf4096678d8afed8ed28dbad690504c4d2c28149ba768b26eacd1416873425b", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/document-fragment.ts": "1c7352a3c816587ed7fad574b42636198f680f17abc3836fcfe7799b31e7718f", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/document.ts": "0b07049fd614c1d460240d1bf3e051084a58105e54887af90f45bc615965f1c6", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/dom-parser.ts": "784ee0e766d4a01e14420f328053fd3a0016c6b40ee442edc3ae80f5d9777927", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/element.ts": "d1a006e4f7cd1eb050838a96ba93a254e5cf4136236c6454ab6e8ffedcf395fd", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/elements/html-template-element.ts": "740b97a5378c9a14cccf3429299846eda240b613013e2d2d7f20b393897453c2", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/html-collection.ts": "eedc0b097612ef420d975df6924850a36a4829b35aafa4c92078609a15a52f08", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/node-list.ts": "aa5d4c2297fadfb1b392ffa0e5c33a6fb8c198e8875bb853c2fc3fc49807701d", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/node.ts": "4ee9bc98f1d5b31a9a36674a9f3e1d6e25b9125b1532c42f84c4624816fe8435", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/selectors/custom-api.ts": "852696bd58e534bc41bd3be9e2250b60b67cd95fd28ed16b1deff1d548531a71", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/selectors/nwsapi-types.ts": "c43b36c36acc5d32caabaa54fda8c9d239b2b0fcbce9a28efb93c84aa1021698", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/selectors/nwsapi.js": "985d7d8fc1eabbb88946b47a1c44c1b2d4aa79ff23c21424219f1528fa27a2ff", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/selectors/selectors.ts": "83eab57be2290fb48e3130533448c93c6c61239f2a2f3b85f1917f80ca0fdc75", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/selectors/sizzle-types.ts": "78149e2502409989ce861ed636b813b059e16bc267bb543e7c2b26ef43e4798b", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/selectors/sizzle.js": "c3aed60c1045a106d8e546ac2f85cc82e65f62d9af2f8f515210b9212286682a", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/utils-types.ts": "96db30e3e4a75b194201bb9fa30988215da7f91b380fca6a5143e51ece2a8436", + "https://deno.land/x/deno_dom@v0.1.47/src/dom/utils.ts": "4c6206516fb8f61f37a209c829e812c4f5a183e46d082934dd14c91bde939263", + "https://deno.land/x/deno_dom@v0.1.47/src/parser.ts": "e06b2300d693e6ae7564e53dfa5c9a9e97fdb8c044c39c52c8b93b5d60860be3", + "https://deno.land/x/lume@v2.2.1/cli.ts": "71f6e24caf5eb661fb1b903ed6a914718a08ee6711daa689dc61fa5e5a37c54c", + "https://deno.land/x/lume@v2.2.1/cli/build.ts": "4a280da27631beca8f57a459a3bd6a9d4f83316d95d3886a3bc43a65af857cd6", + "https://deno.land/x/lume@v2.2.1/cli/cms.ts": "ba10b3f1cc44f5ec172c72c6bbe1da99bac97c0e2c0f214d1aa8e1a4ce200464", + "https://deno.land/x/lume@v2.2.1/cli/create.ts": "f4173fd79c6a97480839e1bd47a0ec8c79de1f24d2e92c83baad637c476c9c01", + "https://deno.land/x/lume@v2.2.1/cli/run.ts": "6f60a8c03b085ed71e67c595d02428259526db6095f41389d3933d98433e9f0c", + "https://deno.land/x/lume@v2.2.1/cli/upgrade.ts": "a11e7c9024f78c2e7376c57b4a99e389dbf490769779d2d37a4a3ccd6ef27d9e", + "https://deno.land/x/lume@v2.2.1/core/component_loader.ts": "da80bf80a168d0b91b59eb3449fbf62627d8bf67879df34e71970616d47ce2ec", + "https://deno.land/x/lume@v2.2.1/core/data_loader.ts": "8698a9e9b1aac27147dc835ba89a0e30828c81338eceae86630607d78f146215", + "https://deno.land/x/lume@v2.2.1/core/events.ts": "e4fd1786eb7dd4a041d7d922779b9edf1ee89e51fd17ba5e756f380879ccb557", + "https://deno.land/x/lume@v2.2.1/core/file.ts": "ddbb9ff4a98c5efeccf2beb3f98d68e376d9c1018862b64e9f1e12d676bfae21", + "https://deno.land/x/lume@v2.2.1/core/formats.ts": "24d9f5ccf384b2474f457cc0d3855e6ad411ded0d6acf4afe36547ba93fc706f", + "https://deno.land/x/lume@v2.2.1/core/fs.ts": "28adb1bc12e8d4005a1d7a2ff44a6e1d1e805e1d70262299876f6e7343959018", + "https://deno.land/x/lume@v2.2.1/core/loaders/binary.ts": "bb1e1cf3faac49f6007dc6814168dc0f633da17356db18e68862e4b2a87a3f33", + "https://deno.land/x/lume@v2.2.1/core/loaders/json.ts": "632e840340edf7d79091fb37474a1cbf86dd2d218090fb6f6c0420f5f5e9c2ce", + "https://deno.land/x/lume@v2.2.1/core/loaders/mod.ts": "148404b9a9112361918177fcec1456e3e1ccc59baa3812043b6b3dffebbd958d", + "https://deno.land/x/lume@v2.2.1/core/loaders/module.ts": "abcb210fa6724b83407407cd0f7ef90462b35a2017bc135a3d124dd7f38843f6", + "https://deno.land/x/lume@v2.2.1/core/loaders/text.ts": "42860fc3482651fa6cfba18a734bb548d6e6e1163bf1015c2abc447ab150acbd", + "https://deno.land/x/lume@v2.2.1/core/loaders/toml.ts": "72ddfef2deea62815c28e27faa2c5356e09b3109e9547e47a6defea3d3332452", + "https://deno.land/x/lume@v2.2.1/core/loaders/yaml.ts": "241dc41fbe51b92e38dc748eda614c35d80fb8c63a6d40253453c6bb78c9c47e", + "https://deno.land/x/lume@v2.2.1/core/processors.ts": "ce9b97307740723afd86d1773e946981a96769189ba6acd649b412e48552045d", + "https://deno.land/x/lume@v2.2.1/core/renderer.ts": "54d33353f6b0c32e2957691429db1d57f16905b3eed36aa64de64bff2fd738a6", + "https://deno.land/x/lume@v2.2.1/core/scopes.ts": "dbdf93d7a9cead84833779e974f190b1379356ec7c0ccd34aa92f917c2cdd2f9", + "https://deno.land/x/lume@v2.2.1/core/scripts.ts": "286969b120d2290ba57a7fdd9b37e587aacf4e4162d92f51f1f1e9e18c864f30", + "https://deno.land/x/lume@v2.2.1/core/searcher.ts": "cf580b0d9d81de0287c7345a8d50c0af4945e0800e623c6e8be0620486edf5c2", + "https://deno.land/x/lume@v2.2.1/core/server.ts": "f0446cbe56b6d8e04517cb0b994f1f3b8d4f5a5cd2bdbafa2a7aa671520cc012", + "https://deno.land/x/lume@v2.2.1/core/site.ts": "574a4c503d27988119d6ad94f64b8c1f4d947488770a0af0312157942ff4b877", + "https://deno.land/x/lume@v2.2.1/core/slugifier.ts": "70427c98d32533171933304d34867c15d6b7bcfd48c7d1e0347184b8c4fb8b8e", + "https://deno.land/x/lume@v2.2.1/core/source.ts": "5b866c68c7275e9fd195c0461b2f7c8907bf3772b4bd4bbe332b21613623a8ae", + "https://deno.land/x/lume@v2.2.1/core/utils/cli_options.ts": "0e48094ef8b89502c53fa597e01238c2ca972f65d2b9b219cca42a3988cba3c6", + "https://deno.land/x/lume@v2.2.1/core/utils/concurrent.ts": "cb0775b3d95f3faa356aa3a3e489dccef8807ed93cc4f84fcf5bc81e87c29504", + "https://deno.land/x/lume@v2.2.1/core/utils/data_values.ts": "40cc18575c35d64797b06fb8638920f54d22c650c50e8760756a7ccbaa37da75", + "https://deno.land/x/lume@v2.2.1/core/utils/date.ts": "b989369496b9a6fba04cf1dee7f58f157911ae273aa3ca16abf9a047e4e091c2", + "https://deno.land/x/lume@v2.2.1/core/utils/digest.ts": "445b387983391af73269686292a65bb677119a25a327776885ff1242a9397ad8", + "https://deno.land/x/lume@v2.2.1/core/utils/dom.ts": "d406fb5c48ceb012286d0aff66ef635261eda666de2ce07538c0cf9366b8fecd", + "https://deno.land/x/lume@v2.2.1/core/utils/env.ts": "d2440f14ad27e65b0a42b35a52f59ccce0430dd52950bd5df103bb1c9ba1a4a7", + "https://deno.land/x/lume@v2.2.1/core/utils/generator.ts": "1e664e9fd4c469e38a0acf5c94fd49dac4f38cb6334563ea4b7fc498b5958877", + "https://deno.land/x/lume@v2.2.1/core/utils/log.ts": "c04df547a673aaecaaeb1f5d90f2a973c1cca9e4545353e94b3cd0074a8ec2b4", + "https://deno.land/x/lume@v2.2.1/core/utils/lume_config.ts": "344bafe9bdd5b69b44d3106de90cbd822dcc21f2916261dddde7eb2b94f336b1", + "https://deno.land/x/lume@v2.2.1/core/utils/lume_version.ts": "96ce8c0144b5adbc170f388b60be706244d1bd100413e748e9cf23878838c87c", + "https://deno.land/x/lume@v2.2.1/core/utils/merge_data.ts": "f4771c4f027b17487bf9a33bc2b04701a97f0578fd4a7feb31809cc119e5ee63", + "https://deno.land/x/lume@v2.2.1/core/utils/net.ts": "7827473a96b28950ab8083582a1f810e56ab265c28196494d9d714f1e0c17e8a", + "https://deno.land/x/lume@v2.2.1/core/utils/object.ts": "e00ee6e91264064772c87e69e128a09ba0e30c2c41be4a5302881f59f456fc31", + "https://deno.land/x/lume@v2.2.1/core/utils/page_date.ts": "096b21d1832c74bc338c8d8d8762f1f5106259b73e6b2caa72fb50986d4f1f5b", + "https://deno.land/x/lume@v2.2.1/core/utils/page_url.ts": "99da7e9e2b8ba0aebb4412ef7d4e1c89bc47ac4c59e34db4a9a4f4108812f4ca", + "https://deno.land/x/lume@v2.2.1/core/utils/path.ts": "a7bae3ad1ff3c9d1d838b044c9d4d4a0410f657cde493f090241345429e833f2", + "https://deno.land/x/lume@v2.2.1/core/utils/read.ts": "a19647855ae100d54a0eb879551548114f195b9f680bcc301d1f3951dc91a011", + "https://deno.land/x/lume@v2.2.1/core/watcher.ts": "2487018b7b860fec08194b6b46ca3793852e2bf72ac9479ef513624b085becdc", + "https://deno.land/x/lume@v2.2.1/core/writer.ts": "47a8aeae457e7162a7ae89303c5ed98551ba0f4d2cad3e1d6e3da6dce24a4fae", + "https://deno.land/x/lume@v2.2.1/deps/cli.ts": "28cbbf8b16472940de50e844474cc44f7aedff7c31963d3e2efc93f1f2eb6736", + "https://deno.land/x/lume@v2.2.1/deps/cliffy.ts": "faff0c2ca187ec9fd1ad8660141f85b9d05b5c36bab25b40eb5038c02590a310", + "https://deno.land/x/lume@v2.2.1/deps/colors.ts": "1c249ff668b7814caab1688f5781d3a32957613caa5bbcb3aef90a4667ec9a99", + "https://deno.land/x/lume@v2.2.1/deps/crypto.ts": "b02a4e2d950675a71eee2d4982c775fbaac17ee7c200d2addc35cb72e38dafae", + "https://deno.land/x/lume@v2.2.1/deps/dom.ts": "7f47d1462127c62ecc8571434fe55639a5a3936ecb8b38476cf560e2b1283da2", + "https://deno.land/x/lume@v2.2.1/deps/front_matter.ts": "5e5bc49e1be519fa3eb52f7a69a61e2d99a9b5f14fa59f1019c99c14b6c688c3", + "https://deno.land/x/lume@v2.2.1/deps/fs.ts": "a853d90b80715e98136a5bd901a961782e5f106e3e6598206b3b4b370c3226a2", + "https://deno.land/x/lume@v2.2.1/deps/hex.ts": "bd514b5645e7744b13fba8e4312c9619469e5b81f0df34ffa3940821a4fac8de", + "https://deno.land/x/lume@v2.2.1/deps/http.ts": "ac6f6d0e9e8394fdb4493a4480add904a453d07271b4b6ae19a307e92c98af92", + "https://deno.land/x/lume@v2.2.1/deps/init.ts": "05d45af66ebdfe63e43540618f51ece8f99d98dc49de890f10eeb43abe9ed0f3", + "https://deno.land/x/lume@v2.2.1/deps/jsonc.ts": "dc72751839df8bae67bb13b7418f434802df5e704238b0d8ca1846751e8fdffb", + "https://deno.land/x/lume@v2.2.1/deps/log.ts": "780db1d7175f2dbafe12b31dc24bd7165d7d97249a3e557e13476c64e88d8313", + "https://deno.land/x/lume@v2.2.1/deps/markdown_it.ts": "5da22a23e59f86bb7f0a0aa7c9cb9012a2444b8c3a0896d92a07492626a8c21f", + "https://deno.land/x/lume@v2.2.1/deps/path.ts": "c4a37bd4d0533a1065a485ad1d5ddc5d71d1bb274806e3e1e7a81b9e634d5066", + "https://deno.land/x/lume@v2.2.1/deps/react.ts": "e78c2f0ef668ce2d79ddc040964f76a350ba8703dcc7473f567444e2d5478f14", + "https://deno.land/x/lume@v2.2.1/deps/temporal.ts": "1958b134c4186b0ab39316fa33ba19d1a4203e2ea445080429d60d296b91a552", + "https://deno.land/x/lume@v2.2.1/deps/toml.ts": "e7ca77ce70c66d1f2678a98ab5870d7ec9b62fbeede81ef8dbef4f60f4988181", + "https://deno.land/x/lume@v2.2.1/deps/unidecode.ts": "e476000bf9278edd64eb79a426ec68ac45e1c691a114ee07f9b89b4d30ffca1c", + "https://deno.land/x/lume@v2.2.1/deps/vento.ts": "bfc4a47b4a24bcd114026dee2055a772f1e715a74c71abf355e9400b8e6ce479", + "https://deno.land/x/lume@v2.2.1/deps/xml.ts": "12206fd907e9594f72c5981ddea3c1c82533a113959975e77d132c7923594247", + "https://deno.land/x/lume@v2.2.1/deps/yaml.ts": "6704702a7dcb63697a8cea8b417a26601e0a496c9a00face5aee49c930a4926b", + "https://deno.land/x/lume@v2.2.1/middlewares/logger.ts": "84fb60e1631cd839053eaaba7b3b802eab7d320dfd1b940d982aa1ae5951a85c", + "https://deno.land/x/lume@v2.2.1/middlewares/no_cache.ts": "c576ae2323c8b5657681721377c806672d5e1811d8cf35fba5efebc2645b37ae", + "https://deno.land/x/lume@v2.2.1/middlewares/no_cors.ts": "9e0344efcc9a541e7b6845250d0a19101ce5762d6668710a38a28d550e1eeb42", + "https://deno.land/x/lume@v2.2.1/middlewares/not_found.ts": "0fcd2da81a9573faf3f6f650f8e126ab5600bf0dd0b49b211303274b5d9afa4e", + "https://deno.land/x/lume@v2.2.1/middlewares/reload.ts": "c9999bdd52e18e85a1634659506542ce0e942cc91b69e3fc9887cabf23ca4592", + "https://deno.land/x/lume@v2.2.1/middlewares/reload_client.js": "34d75e01503fae8180796de882af42b1125fac88f22a010a99d5548de1ba7d72", + "https://deno.land/x/lume@v2.2.1/mod.ts": "0f7afe1e73472bee8fb6dc21d616f9c055a1cffd3a3744f2005b8a6ccfbf8aed", + "https://deno.land/x/lume@v2.2.1/plugins/feed.ts": "c3702523ae8507d7d20c5f91635c0dc76e09610aaf1db7cc6af2da484cb7c9e0", + "https://deno.land/x/lume@v2.2.1/plugins/json.ts": "f6429bbd865e3666ef3385fd205fcc92df02ca2c0f74f20baa5c0798a81e1642", + "https://deno.land/x/lume@v2.2.1/plugins/jsx.ts": "20ece4ddd348089dd407f184f462f8824b342aef461117257166fd81323f18da", + "https://deno.land/x/lume@v2.2.1/plugins/markdown.ts": "b0f224dcffa0abeb30af178d7ec21f50515c2a7ccd42a3347aac3bea53c4ca27", + "https://deno.land/x/lume@v2.2.1/plugins/modules.ts": "19a66398a5494f506458e48b8443a7c4700b7577e8fcc0818c39b1d0530c8950", + "https://deno.land/x/lume@v2.2.1/plugins/paginate.ts": "e86617ec1ad491c86bc4866db41f070a6b393e8c2ac94ed28a51ca309f88477d", + "https://deno.land/x/lume@v2.2.1/plugins/search.ts": "8ec3a8f082b8ff1532bbe8f8bf76dfaa2d0feab7c2ec5c824d0ccc044c26f640", + "https://deno.land/x/lume@v2.2.1/plugins/toml.ts": "60191e1e8fd0922def0b3f0eaad13988217511571a54659481759db4b0ca4f82", + "https://deno.land/x/lume@v2.2.1/plugins/url.ts": "3d298886cb16e1110d427d2f257de6c2ae0da3cd7076b6abcbbd41e7536ed094", + "https://deno.land/x/lume@v2.2.1/plugins/vento.ts": "03b2121ca5e14b589d9add0a390e0c0c4e591436617ef899011440325c878392", + "https://deno.land/x/lume@v2.2.1/plugins/yaml.ts": "21b1604304240d4de42b2ba0fcfd81b8330fcff8b365a1ee4ff164de6ef3de75", + "https://deno.land/x/lume@v2.2.1/types.ts": "516bec311f10083c5b1d8109e8afd17f02b49cc62c45dca53706f286cb855dba", + "https://deno.land/x/vento@v0.12.6/deps.ts": "430b31ecdc02c40c02168e8e5de7939b9f1c82335eda0fafcad7d8a04f20cb21", + "https://deno.land/x/vento@v0.12.6/mod.ts": "1c226f165e6c995bcb0f68b7d78623c263ea7bc3e0dae131617fd053703bc742", + "https://deno.land/x/vento@v0.12.6/plugins/echo.ts": "f7c064fb6d34b29852f46f6e01583ed87656dcbbc5cae51c8f29198d6951d0cf", + "https://deno.land/x/vento@v0.12.6/plugins/escape.ts": "605511d54319fb07d63428e16b6ece96f04f8abafc97d9f8e6643d9c1579fb42", + "https://deno.land/x/vento@v0.12.6/plugins/export.ts": "ef54811ed0205aaeef6ad09557c94b8ae98e1457234898da5a1c5461a7dcf424", + "https://deno.land/x/vento@v0.12.6/plugins/for.ts": "7cfd603cc5ef0a46011b6c8a2cdca25c84945faa29baf56a0a1396f856852397", + "https://deno.land/x/vento@v0.12.6/plugins/function.ts": "cdf610a98493e4a093c53473abdad7d47cbcff40aa8362d280e39910620cb8d6", + "https://deno.land/x/vento@v0.12.6/plugins/if.ts": "9de295f8675cacaec7866ad21068b6b089bfcadf72d3c62e1df50ca378c04279", + "https://deno.land/x/vento@v0.12.6/plugins/import.ts": "406204ab9d785db206da5d5cbcffa9a111cef2a39a19574e630cdea89b0691c5", + "https://deno.land/x/vento@v0.12.6/plugins/include.ts": "feeb3621517759d45ed3b62d581084baf08f943a1a0689c1f28e59bac3bc04e2", + "https://deno.land/x/vento@v0.12.6/plugins/js.ts": "4ce7742b9454c64c19a20b1f8e43ced54d776c89fe4d698ae68c896034f5bb3f", + "https://deno.land/x/vento@v0.12.6/plugins/layout.ts": "b7428ddb0db60338050837ff8f41db1cccbf650bf44bba72eea5a1f62c1729db", + "https://deno.land/x/vento@v0.12.6/plugins/set.ts": "9b20f4f699f592b159fe81994ee5902d29417228ca1b66ff96df86803d39e701", + "https://deno.land/x/vento@v0.12.6/plugins/trim.ts": "708dedbf068c4a9a0f568505fcfce84370530a4e4333254571d4fc2e4f652529", + "https://deno.land/x/vento@v0.12.6/plugins/unescape.ts": "92d5cd2f5c256cc50f3cde2b14efb49dd40518b2bd74ad6f1a695a80210496ea", + "https://deno.land/x/vento@v0.12.6/src/environment.ts": "6fa89a131b884147ab473412e0631f9925c14975b97777b5549a74b5fcdd2ccf", + "https://deno.land/x/vento@v0.12.6/src/js.ts": "c4ac5e2b2cd2995523d3167c5708c424686fd30d2d3951ff965a76dbdfb74e37", + "https://deno.land/x/vento@v0.12.6/src/loader.ts": "eb01b0dca7ea8bcdcdfd30b1f90f2fad28fb7f2cfd943900322a85bfaa86130c", + "https://deno.land/x/vento@v0.12.6/src/tokenizer.ts": "acafb05ca528a27cb99bb1c34765362fc0a4dc2982848dd4b7983e27dcb17d69", + "https://deno.land/x/vento@v0.12.6/src/transformer.ts": "587a0b107a2bd1437a3093c4c44c07e4fdf3abfaaf8e845767b69bd34a039154", + "https://deno.land/x/xml@5.4.6/_types.ts": "7787e8e2f204c4919bd75374a76ad897010ab491369290905f64fc562a7affc0", + "https://deno.land/x/xml@5.4.6/mod.ts": "b59e5c0dd9fe7ed597c21c39aacf089aa82fe5c5eaad3f411a43a9c104359f4e", + "https://deno.land/x/xml@5.4.6/parse.ts": "70334eee74b738d8c4cf1f44b3a05834c3f0ba4dc4e09eea84a2286fd86bcf89", + "https://deno.land/x/xml@5.4.6/stringify.ts": "b507f85351aef662892a0d79204e1e5e7ce234a10f91b058fc22f9ec72a55862", + "https://deno.land/x/xml@5.4.6/wasm_xml_parser/wasm_xml_parser.js": "9db1be8ed275be5e3847f0b17d204ba40e5f50e5716adf6b821da6be39ea2097" + } +} diff --git a/index.md b/index.md new file mode 100644 index 0000000..e69de29 diff --git a/list-games.md b/list-games.md new file mode 100644 index 0000000..e69de29