Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
SBence committed Jun 22, 2024
0 parents commit b37544d
Show file tree
Hide file tree
Showing 34 changed files with 2,925 additions and 0 deletions.
35 changes: 35 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module.exports = {
root: true,
env: { browser: true, es2021: true },
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/strict-type-checked",
"plugin:@typescript-eslint/stylistic-type-checked",
"plugin:react-hooks/recommended",
"prettier",
],
ignorePatterns: ["dist", ".eslintrc.cjs", "postcss.config.js"],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
project: ["./tsconfig.json", "./tsconfig.node.json"],
tsconfigRootDir: __dirname,
},
plugins: ["react-refresh"],
rules: {
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-misused-promises": [
"error",
{
checksVoidReturn: {
attributes: false, // TODO: Won't this silence needed errors?
},
},
],
},
};
64 changes: 64 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Deploy static content to Pages

on:
push:
branches: ["master"]

workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "*"
cache: "yarn"

- name: Install dependencies
run: yarn install

- name: Build project
run: yarn run build --base=/${{ github.event.repository.name }}/

- name: Setup Pages
uses: actions/configure-pages@v4

- name: Fix permissions
run: |
chmod -c -R +rX "_site/" | while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
done
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: "./dist"

deploy:
needs: build

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-latest

steps:
- name: Deploy to Pages
id: deployment
uses: actions/deploy-pages@v4
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
1 change: 1 addition & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
16 changes: 16 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Spicy Patcher</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

</html>
43 changes: 43 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "spicy-patcher",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"formatting:check": "yarn prettier --check .",
"formatting:apply": "yarn prettier --write ."
},
"dependencies": {
"@mantine/core": "^7.10.0",
"@mantine/dropzone": "^7.10.0",
"@mantine/form": "^7.10.0",
"@mantine/hooks": "^7.10.0",
"@mantine/notifications": "^7.10.2",
"@tabler/icons-react": "^3.5.0",
"jotai": "^2.8.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"postcss": "^8.4.38",
"postcss-preset-mantine": "^1.15.0",
"postcss-simple-vars": "^7.0.1",
"prettier": "^3.2.5",
"typescript": "^5.2.2",
"vite": "^5.2.0",
"vite-tsconfig-paths": "^4.3.2"
}
}
14 changes: 14 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default {
plugins: {
"postcss-preset-mantine": {},
"postcss-simple-vars": {
variables: {
"mantine-breakpoint-xs": "680px",
"mantine-breakpoint-sm": "980px",
"mantine-breakpoint-md": "1300px",
"mantine-breakpoint-lg": "1620px",
"mantine-breakpoint-xl": "1940px",
},
},
},
};
1 change: 1 addition & 0 deletions public/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added src/App.css
Empty file.
27 changes: 27 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import "./App.css";
import "@mantine/core/styles.css";
import "@mantine/notifications/styles.css";
import { Container, MantineProvider, Stack, Title } from "@mantine/core";
import MainForm from "./components/MainForm";
import { Notifications } from "@mantine/notifications";

function App() {
return (
<MantineProvider defaultColorScheme="auto">
<Notifications />
<Container size="xs">
<Stack h="100vh " justify="center">
<div>
<Title order={1}>Spicy Patcher</Title>
<Title order={2} style={{ color: "var(--mantine-color-dimmed)" }}>
Convert web patchers into Spice patches
</Title>
</div>
<MainForm />
</Stack>
</Container>
</MantineProvider>
);
}

export default App;
78 changes: 78 additions & 0 deletions src/components/GenerateButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Button } from "@mantine/core";
import { extractPatchersFromHtml } from "../utils/extractPatchersFromHtml";
import { webPatchersToSpice } from "../utils/webPatchersToSpice";
import downloadJson from "../utils/downloadJson";
import { useAtomValue } from "jotai";
import {
gameCodeAtom,
latestOnlyAtom,
minifyJsonAtom,
patchSourceAtom,
patcherFilesAtom,
patcherUrlAtom,
} from "@state";
import { useState } from "react";
import { notifications } from "@mantine/notifications";

function GenerateButton() {
const gameCode = useAtomValue(gameCodeAtom);
const patchSource = useAtomValue(patchSourceAtom);
const patcherUrl = useAtomValue(patcherUrlAtom);
const patcherFiles = useAtomValue(patcherFilesAtom);
const latestOnly = useAtomValue(latestOnlyAtom);
const minifyJson = useAtomValue(minifyJsonAtom);

const [isGenerating, setIsGenerating] = useState(false);

function generateButtonEnabled() {
const validUrl = patchSource == "url" && patcherUrl;
const validFile = patchSource == "file" && patcherFiles?.[0];
return !!(gameCode && (validUrl || validFile));
}

return (
<Button
disabled={!generateButtonEnabled()}
loading={isGenerating}
onClick={async () => {
setIsGenerating(true);

let patcherHtml: string | null = null;

switch (patchSource) {
case "url": {
const patcherHtmlRequest = await fetch(patcherUrl);
patcherHtml = await patcherHtmlRequest.text();
break;
}

case "file":
if (!patcherFiles?.[0]) throw new Error("No file uploaded");
patcherHtml = await patcherFiles[0].text();
break;

default:
throw new Error("Invalid patch source");
}

try {
const patchers = extractPatchersFromHtml(patcherHtml);
const patches = webPatchersToSpice(gameCode, patchers, latestOnly);
downloadJson("patches.json", patches, minifyJson);
} catch (error) {
notifications.show({
message:
error instanceof Error ? error.message : "An error has occurred",
color: "red",
});
}

setIsGenerating(false);
}}
>
Generate
</Button>
);
}

export default GenerateButton;
28 changes: 28 additions & 0 deletions src/components/MainForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Text, TextInput } from "@mantine/core";
import SourceSelector from "./SourceSelector";
import PatcherOptions from "./PatcherOptions";
import { useAtom } from "jotai";
import { gameCodeAtom } from "@state";
import GenerateButton from "./GenerateButton";

function MainForm() {
const [gameCode, setGameCode] = useAtom(gameCodeAtom);

return (
<>
<TextInput
label="Game code"
value={gameCode}
onChange={(event) => {
setGameCode(event.currentTarget.value);
}}
/>
<SourceSelector />
<Text size="sm">Options</Text>
<PatcherOptions />
<GenerateButton />
</>
);
}

export default MainForm;
29 changes: 29 additions & 0 deletions src/components/PatcherOptions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Checkbox, Stack } from "@mantine/core";
import { latestOnlyAtom, minifyJsonAtom } from "@state";
import { useAtom } from "jotai";

function PatcherOptions() {
const [latestOnly, setLatestOnly] = useAtom(latestOnlyAtom);
const [minifyJson, setMinifyJson] = useAtom(minifyJsonAtom);

return (
<Stack>
<Checkbox
label="Latest version only"
checked={latestOnly}
onChange={(event) => {
setLatestOnly(event.currentTarget.checked);
}}
/>
<Checkbox
label="Minify file"
checked={minifyJson}
onChange={(event) => {
setMinifyJson(event.currentTarget.checked);
}}
/>
</Stack>
);
}

export default PatcherOptions;
Loading

0 comments on commit b37544d

Please sign in to comment.