diff --git a/scrapper_web/.gitignore b/scrapper_web/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/scrapper_web/.gitignore
@@ -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?
diff --git a/scrapper_web/.vscode/extensions.json b/scrapper_web/.vscode/extensions.json
new file mode 100644
index 0000000..bdef820
--- /dev/null
+++ b/scrapper_web/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["svelte.svelte-vscode"]
+}
diff --git a/scrapper_web/README.md b/scrapper_web/README.md
new file mode 100644
index 0000000..69c2ac5
--- /dev/null
+++ b/scrapper_web/README.md
@@ -0,0 +1,47 @@
+# Svelte + Vite
+
+This template should help get you started developing with Svelte in Vite.
+
+## Recommended IDE Setup
+
+[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
+
+## Need an official Svelte framework?
+
+Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
+
+## Technical considerations
+
+**Why use this over SvelteKit?**
+
+- It brings its own routing solution which might not be preferable for some users.
+- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
+
+This template contains as little as possible to get started with Vite + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
+
+Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
+
+**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
+
+Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
+
+**Why include `.vscode/extensions.json`?**
+
+Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
+
+**Why enable `checkJs` in the JS template?**
+
+It is likely that most cases of changing variable types in runtime are likely to be accidental, rather than deliberate. This provides advanced typechecking out of the box. Should you like to take advantage of the dynamically-typed nature of JavaScript, it is trivial to change the configuration.
+
+**Why is HMR not preserving my local component state?**
+
+HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
+
+If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
+
+```js
+// store.js
+// An extremely simple external store
+import { writable } from 'svelte/store'
+export default writable(0)
+```
diff --git a/scrapper_web/index.html b/scrapper_web/index.html
new file mode 100644
index 0000000..26c29c4
--- /dev/null
+++ b/scrapper_web/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + Svelte
+
+
+
+
+
+
diff --git a/scrapper_web/jsconfig.json b/scrapper_web/jsconfig.json
new file mode 100644
index 0000000..2df8094
--- /dev/null
+++ b/scrapper_web/jsconfig.json
@@ -0,0 +1,33 @@
+{
+ "compilerOptions": {
+ "moduleResolution": "Node",
+ "target": "ESNext",
+ "module": "ESNext",
+ /**
+ * svelte-preprocess cannot figure out whether you have
+ * a value or a type, so tell TypeScript to enforce using
+ * `import type` instead of `import` for Types.
+ */
+ "importsNotUsedAsValues": "error",
+ "isolatedModules": true,
+ "resolveJsonModule": true,
+ /**
+ * To have warnings / errors of the Svelte compiler at the
+ * correct position, enable source maps by default.
+ */
+ "sourceMap": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ /**
+ * Typecheck JS in `.svelte` and `.js` files by default.
+ * Disable this if you'd like to use dynamic types.
+ */
+ "checkJs": false
+ },
+ /**
+ * Use global.d.ts instead of compilerOptions.types
+ * to avoid limiting type declarations.
+ */
+ "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
+}
diff --git a/scrapper_web/package.json b/scrapper_web/package.json
new file mode 100644
index 0000000..b66da50
--- /dev/null
+++ b/scrapper_web/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "scrapper_web",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "wasm-pack build ./scrapper -t web && vite build",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "@sveltejs/vite-plugin-svelte": "^2.0.2",
+ "@tailwindcss/forms": "^0.5.3",
+ "autoprefixer": "^10.4.13",
+ "cssnano": "^5.1.14",
+ "cssnano-preset-advanced": "^5.3.9",
+ "daisyui": "^2.50.0",
+ "filedrop-svelte": "^0.1.2",
+ "postcss": "^8.4.21",
+ "svelte": "^3.55.1",
+ "svelte-preprocess": "^5.0.1",
+ "tailwindcss": "^3.2.4",
+ "vite": "^4.1.0",
+ "vite-plugin-wasm-pack": "^0.1.12"
+ }
+}
\ No newline at end of file
diff --git a/scrapper_web/pnpm-lock.yaml b/scrapper_web/pnpm-lock.yaml
new file mode 100644
index 0000000..739e35e
--- /dev/null
+++ b/scrapper_web/pnpm-lock.yaml
@@ -0,0 +1,1777 @@
+lockfileVersion: 5.4
+
+specifiers:
+ '@sveltejs/vite-plugin-svelte': ^2.0.2
+ '@tailwindcss/forms': ^0.5.3
+ autoprefixer: ^10.4.13
+ cssnano: ^5.1.14
+ cssnano-preset-advanced: ^5.3.9
+ daisyui: ^2.50.0
+ filedrop-svelte: ^0.1.2
+ postcss: ^8.4.21
+ svelte: ^3.55.1
+ svelte-preprocess: ^5.0.1
+ tailwindcss: ^3.2.4
+ vite: ^4.1.0
+ vite-plugin-wasm-pack: ^0.1.12
+
+devDependencies:
+ '@sveltejs/vite-plugin-svelte': 2.0.2_svelte@3.55.1+vite@4.1.1
+ '@tailwindcss/forms': 0.5.3_tailwindcss@3.2.6
+ autoprefixer: 10.4.13_postcss@8.4.21
+ cssnano: 5.1.14_postcss@8.4.21
+ cssnano-preset-advanced: 5.3.9_postcss@8.4.21
+ daisyui: 2.50.0_gbtt6ss3tbiz4yjtvdr6fbrj44
+ filedrop-svelte: 0.1.2
+ postcss: 8.4.21
+ svelte: 3.55.1
+ svelte-preprocess: 5.0.1_pehl75e5jsy22vp33udjja4soi
+ tailwindcss: 3.2.6_postcss@8.4.21
+ vite: 4.1.1
+ vite-plugin-wasm-pack: 0.1.12
+
+packages:
+
+ /@esbuild/android-arm/0.16.17:
+ resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64/0.16.17:
+ resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64/0.16.17:
+ resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64/0.16.17:
+ resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64/0.16.17:
+ resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64/0.16.17:
+ resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64/0.16.17:
+ resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm/0.16.17:
+ resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64/0.16.17:
+ resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32/0.16.17:
+ resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64/0.16.17:
+ resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el/0.16.17:
+ resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64/0.16.17:
+ resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64/0.16.17:
+ resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x/0.16.17:
+ resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64/0.16.17:
+ resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64/0.16.17:
+ resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64/0.16.17:
+ resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64/0.16.17:
+ resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64/0.16.17:
+ resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32/0.16.17:
+ resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64/0.16.17:
+ resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@jridgewell/sourcemap-codec/1.4.14:
+ resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
+ dev: true
+
+ /@nodelib/fs.scandir/2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat/2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk/1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.15.0
+ dev: true
+
+ /@sveltejs/vite-plugin-svelte/2.0.2_svelte@3.55.1+vite@4.1.1:
+ resolution: {integrity: sha512-xCEan0/NNpQuL0l5aS42FjwQ6wwskdxC3pW1OeFtEKNZwRg7Evro9lac9HesGP6TdFsTv2xMes5ASQVKbCacxg==}
+ engines: {node: ^14.18.0 || >= 16}
+ peerDependencies:
+ svelte: ^3.54.0
+ vite: ^4.0.0
+ dependencies:
+ debug: 4.3.4
+ deepmerge: 4.3.0
+ kleur: 4.1.5
+ magic-string: 0.27.0
+ svelte: 3.55.1
+ svelte-hmr: 0.15.1_svelte@3.55.1
+ vite: 4.1.1
+ vitefu: 0.2.4_vite@4.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@tailwindcss/forms/0.5.3_tailwindcss@3.2.6:
+ resolution: {integrity: sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1'
+ dependencies:
+ mini-svg-data-uri: 1.4.4
+ tailwindcss: 3.2.6_postcss@8.4.21
+ dev: true
+
+ /@trysound/sax/0.2.0:
+ resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
+ engines: {node: '>=10.13.0'}
+ dev: true
+
+ /@types/node/18.13.0:
+ resolution: {integrity: sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==}
+ dev: true
+
+ /@types/pug/2.0.6:
+ resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==}
+ dev: true
+
+ /@types/sass/1.43.1:
+ resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==}
+ dependencies:
+ '@types/node': 18.13.0
+ dev: true
+
+ /acorn-node/1.8.2:
+ resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==}
+ dependencies:
+ acorn: 7.4.1
+ acorn-walk: 7.2.0
+ xtend: 4.0.2
+ dev: true
+
+ /acorn-walk/7.2.0:
+ resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==}
+ engines: {node: '>=0.4.0'}
+ dev: true
+
+ /acorn/7.4.1:
+ resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /ansi-styles/4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /anymatch/3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /arg/5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ dev: true
+
+ /autoprefixer/10.4.13_postcss@8.4.21:
+ resolution: {integrity: sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ browserslist: 4.21.5
+ caniuse-lite: 1.0.30001450
+ fraction.js: 4.2.0
+ normalize-range: 0.1.2
+ picocolors: 1.0.0
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /balanced-match/1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /binary-extensions/2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /boolbase/1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+ dev: true
+
+ /brace-expansion/1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /braces/3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
+ /browserslist/4.21.5:
+ resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001450
+ electron-to-chromium: 1.4.288
+ node-releases: 2.0.10
+ update-browserslist-db: 1.0.10_browserslist@4.21.5
+ dev: true
+
+ /buffer-crc32/0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+ dev: true
+
+ /camelcase-css/2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /caniuse-api/3.0.0:
+ resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
+ dependencies:
+ browserslist: 4.21.5
+ caniuse-lite: 1.0.30001450
+ lodash.memoize: 4.1.2
+ lodash.uniq: 4.5.0
+ dev: true
+
+ /caniuse-lite/1.0.30001450:
+ resolution: {integrity: sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==}
+ dev: true
+
+ /chalk/4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chokidar/3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /color-convert/2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name/1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /color-string/1.9.1:
+ resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
+ dependencies:
+ color-name: 1.1.4
+ simple-swizzle: 0.2.2
+ dev: true
+
+ /color/4.2.3:
+ resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
+ engines: {node: '>=12.5.0'}
+ dependencies:
+ color-convert: 2.0.1
+ color-string: 1.9.1
+ dev: true
+
+ /colord/2.9.3:
+ resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
+ dev: true
+
+ /commander/7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+ dev: true
+
+ /concat-map/0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /css-declaration-sorter/6.3.1_postcss@8.4.21:
+ resolution: {integrity: sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==}
+ engines: {node: ^10 || ^12 || >=14}
+ peerDependencies:
+ postcss: ^8.0.9
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /css-select/4.3.0:
+ resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 6.1.0
+ domhandler: 4.3.1
+ domutils: 2.8.0
+ nth-check: 2.1.1
+ dev: true
+
+ /css-selector-tokenizer/0.8.0:
+ resolution: {integrity: sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==}
+ dependencies:
+ cssesc: 3.0.0
+ fastparse: 1.1.2
+ dev: true
+
+ /css-tree/1.1.3:
+ resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==}
+ engines: {node: '>=8.0.0'}
+ dependencies:
+ mdn-data: 2.0.14
+ source-map: 0.6.1
+ dev: true
+
+ /css-what/6.1.0:
+ resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /cssesc/3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /cssnano-preset-advanced/5.3.9_postcss@8.4.21:
+ resolution: {integrity: sha512-njnh4pp1xCsibJcEHnWZb4EEzni0ePMqPuPNyuWT4Z+YeXmsgqNuTPIljXFEXhxGsWs9183JkXgHxc1TcsahIg==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ autoprefixer: 10.4.13_postcss@8.4.21
+ cssnano-preset-default: 5.2.13_postcss@8.4.21
+ postcss: 8.4.21
+ postcss-discard-unused: 5.1.0_postcss@8.4.21
+ postcss-merge-idents: 5.1.1_postcss@8.4.21
+ postcss-reduce-idents: 5.2.0_postcss@8.4.21
+ postcss-zindex: 5.1.0_postcss@8.4.21
+ dev: true
+
+ /cssnano-preset-default/5.2.13_postcss@8.4.21:
+ resolution: {integrity: sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ css-declaration-sorter: 6.3.1_postcss@8.4.21
+ cssnano-utils: 3.1.0_postcss@8.4.21
+ postcss: 8.4.21
+ postcss-calc: 8.2.4_postcss@8.4.21
+ postcss-colormin: 5.3.0_postcss@8.4.21
+ postcss-convert-values: 5.1.3_postcss@8.4.21
+ postcss-discard-comments: 5.1.2_postcss@8.4.21
+ postcss-discard-duplicates: 5.1.0_postcss@8.4.21
+ postcss-discard-empty: 5.1.1_postcss@8.4.21
+ postcss-discard-overridden: 5.1.0_postcss@8.4.21
+ postcss-merge-longhand: 5.1.7_postcss@8.4.21
+ postcss-merge-rules: 5.1.3_postcss@8.4.21
+ postcss-minify-font-values: 5.1.0_postcss@8.4.21
+ postcss-minify-gradients: 5.1.1_postcss@8.4.21
+ postcss-minify-params: 5.1.4_postcss@8.4.21
+ postcss-minify-selectors: 5.2.1_postcss@8.4.21
+ postcss-normalize-charset: 5.1.0_postcss@8.4.21
+ postcss-normalize-display-values: 5.1.0_postcss@8.4.21
+ postcss-normalize-positions: 5.1.1_postcss@8.4.21
+ postcss-normalize-repeat-style: 5.1.1_postcss@8.4.21
+ postcss-normalize-string: 5.1.0_postcss@8.4.21
+ postcss-normalize-timing-functions: 5.1.0_postcss@8.4.21
+ postcss-normalize-unicode: 5.1.1_postcss@8.4.21
+ postcss-normalize-url: 5.1.0_postcss@8.4.21
+ postcss-normalize-whitespace: 5.1.1_postcss@8.4.21
+ postcss-ordered-values: 5.1.3_postcss@8.4.21
+ postcss-reduce-initial: 5.1.1_postcss@8.4.21
+ postcss-reduce-transforms: 5.1.0_postcss@8.4.21
+ postcss-svgo: 5.1.0_postcss@8.4.21
+ postcss-unique-selectors: 5.1.1_postcss@8.4.21
+ dev: true
+
+ /cssnano-utils/3.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /cssnano/5.1.14_postcss@8.4.21:
+ resolution: {integrity: sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ cssnano-preset-default: 5.2.13_postcss@8.4.21
+ lilconfig: 2.0.6
+ postcss: 8.4.21
+ yaml: 1.10.2
+ dev: true
+
+ /csso/4.2.0:
+ resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==}
+ engines: {node: '>=8.0.0'}
+ dependencies:
+ css-tree: 1.1.3
+ dev: true
+
+ /daisyui/2.50.0_gbtt6ss3tbiz4yjtvdr6fbrj44:
+ resolution: {integrity: sha512-KiqRvqMXi9rgoH84M8D69gXPg6x+cbdiaHqm8pFHOsXXN1rTl/+OcCKkSnkEwTtIge9VJVDGU6l4B8/n+Juc5g==}
+ peerDependencies:
+ autoprefixer: ^10.0.2
+ postcss: ^8.1.6
+ dependencies:
+ autoprefixer: 10.4.13_postcss@8.4.21
+ color: 4.2.3
+ css-selector-tokenizer: 0.8.0
+ postcss: 8.4.21
+ postcss-js: 4.0.1_postcss@8.4.21
+ tailwindcss: 3.2.6_postcss@8.4.21
+ transitivePeerDependencies:
+ - ts-node
+ dev: true
+
+ /debug/4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /deepmerge/4.3.0:
+ resolution: {integrity: sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /defined/1.0.1:
+ resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==}
+ dev: true
+
+ /detect-indent/6.1.0:
+ resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /detective/5.2.1:
+ resolution: {integrity: sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==}
+ engines: {node: '>=0.8.0'}
+ hasBin: true
+ dependencies:
+ acorn-node: 1.8.2
+ defined: 1.0.1
+ minimist: 1.2.7
+ dev: true
+
+ /didyoumean/1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+ dev: true
+
+ /dlv/1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+ dev: true
+
+ /dom-serializer/1.4.1:
+ resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 4.3.1
+ entities: 2.2.0
+ dev: true
+
+ /domelementtype/2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+ dev: true
+
+ /domhandler/4.3.1:
+ resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
+ engines: {node: '>= 4'}
+ dependencies:
+ domelementtype: 2.3.0
+ dev: true
+
+ /domutils/2.8.0:
+ resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
+ dependencies:
+ dom-serializer: 1.4.1
+ domelementtype: 2.3.0
+ domhandler: 4.3.1
+ dev: true
+
+ /electron-to-chromium/1.4.288:
+ resolution: {integrity: sha512-8s9aJf3YiokIrR+HOQzNOGmEHFXVUQzXM/JaViVvKdCkNUjS+lEa/uT7xw3nDVG/IgfxiIwUGkwJ6AR1pTpYsQ==}
+ dev: true
+
+ /entities/2.2.0:
+ resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
+ dev: true
+
+ /es6-promise/3.3.1:
+ resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
+ dev: true
+
+ /esbuild/0.16.17:
+ resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/android-arm': 0.16.17
+ '@esbuild/android-arm64': 0.16.17
+ '@esbuild/android-x64': 0.16.17
+ '@esbuild/darwin-arm64': 0.16.17
+ '@esbuild/darwin-x64': 0.16.17
+ '@esbuild/freebsd-arm64': 0.16.17
+ '@esbuild/freebsd-x64': 0.16.17
+ '@esbuild/linux-arm': 0.16.17
+ '@esbuild/linux-arm64': 0.16.17
+ '@esbuild/linux-ia32': 0.16.17
+ '@esbuild/linux-loong64': 0.16.17
+ '@esbuild/linux-mips64el': 0.16.17
+ '@esbuild/linux-ppc64': 0.16.17
+ '@esbuild/linux-riscv64': 0.16.17
+ '@esbuild/linux-s390x': 0.16.17
+ '@esbuild/linux-x64': 0.16.17
+ '@esbuild/netbsd-x64': 0.16.17
+ '@esbuild/openbsd-x64': 0.16.17
+ '@esbuild/sunos-x64': 0.16.17
+ '@esbuild/win32-arm64': 0.16.17
+ '@esbuild/win32-ia32': 0.16.17
+ '@esbuild/win32-x64': 0.16.17
+ dev: true
+
+ /escalade/3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /fast-glob/3.2.12:
+ resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
+ /fastparse/1.1.2:
+ resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==}
+ dev: true
+
+ /fastq/1.15.0:
+ resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /file-selector/0.2.4:
+ resolution: {integrity: sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA==}
+ engines: {node: '>= 10'}
+ dependencies:
+ tslib: 2.5.0
+ dev: true
+
+ /filedrop-svelte/0.1.2:
+ resolution: {integrity: sha512-S0Z+zCO2dy/g3tRjswD8pLEcorj78olkLWvhKEp511gwHUI6x+uWjXacuvFmRQnjbCCPByXzGlC5Asb9nPzUKw==}
+ dependencies:
+ file-selector: 0.2.4
+ pretty-bytes: 6.1.0
+ dev: true
+
+ /fill-range/7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /fraction.js/4.2.0:
+ resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
+ dev: true
+
+ /fs-extra/10.1.0:
+ resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ graceful-fs: 4.2.10
+ jsonfile: 6.1.0
+ universalify: 2.0.0
+ dev: true
+
+ /fs.realpath/1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents/2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind/1.1.1:
+ resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
+ dev: true
+
+ /glob-parent/5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob-parent/6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob/7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /graceful-fs/4.2.10:
+ resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
+ dev: true
+
+ /has-flag/4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has/1.0.3:
+ resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ function-bind: 1.1.1
+ dev: true
+
+ /inflight/1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits/2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /is-arrayish/0.3.2:
+ resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
+ dev: true
+
+ /is-binary-path/2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-core-module/2.11.0:
+ resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==}
+ dependencies:
+ has: 1.0.3
+ dev: true
+
+ /is-extglob/2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-glob/4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-number/7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /jsonfile/6.1.0:
+ resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+ dependencies:
+ universalify: 2.0.0
+ optionalDependencies:
+ graceful-fs: 4.2.10
+ dev: true
+
+ /kleur/4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /lilconfig/2.0.6:
+ resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /lodash.memoize/4.1.2:
+ resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
+ dev: true
+
+ /lodash.uniq/4.5.0:
+ resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
+ dev: true
+
+ /magic-string/0.27.0:
+ resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.14
+ dev: true
+
+ /mdn-data/2.0.14:
+ resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
+ dev: true
+
+ /merge2/1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromatch/4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /min-indent/1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /mini-svg-data-uri/1.4.4:
+ resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
+ hasBin: true
+ dev: true
+
+ /minimatch/3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimist/1.2.7:
+ resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
+ dev: true
+
+ /mkdirp/0.5.6:
+ resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
+ hasBin: true
+ dependencies:
+ minimist: 1.2.7
+ dev: true
+
+ /ms/2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /nanoid/3.3.4:
+ resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /narrowing/1.5.0:
+ resolution: {integrity: sha512-DUu4XdKgkfAPTAL28k79pdnshDE2W5T24QAnidSPo2F/W1TX6CjNzmEeXQfE5O1lxQvC0GYI6ZRDsLcyzugEYA==}
+ dev: true
+
+ /node-releases/2.0.10:
+ resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==}
+ dev: true
+
+ /normalize-path/3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /normalize-range/0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /normalize-url/6.1.0:
+ resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /nth-check/2.1.1:
+ resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+ dependencies:
+ boolbase: 1.0.0
+ dev: true
+
+ /object-hash/3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /once/1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /path-is-absolute/1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-parse/1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /picocolors/1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ dev: true
+
+ /picomatch/2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /pify/2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /postcss-calc/8.2.4_postcss@8.4.21:
+ resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==}
+ peerDependencies:
+ postcss: ^8.2.2
+ dependencies:
+ postcss: 8.4.21
+ postcss-selector-parser: 6.0.11
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-colormin/5.3.0_postcss@8.4.21:
+ resolution: {integrity: sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ browserslist: 4.21.5
+ caniuse-api: 3.0.0
+ colord: 2.9.3
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-convert-values/5.1.3_postcss@8.4.21:
+ resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ browserslist: 4.21.5
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-discard-comments/5.1.2_postcss@8.4.21:
+ resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /postcss-discard-duplicates/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /postcss-discard-empty/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /postcss-discard-overridden/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /postcss-discard-unused/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-selector-parser: 6.0.11
+ dev: true
+
+ /postcss-import/14.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.1
+ dev: true
+
+ /postcss-js/4.0.1_postcss@8.4.21:
+ resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.4.21
+ dev: true
+
+ /postcss-load-config/3.1.4_postcss@8.4.21:
+ resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
+ engines: {node: '>= 10'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ dependencies:
+ lilconfig: 2.0.6
+ postcss: 8.4.21
+ yaml: 1.10.2
+ dev: true
+
+ /postcss-merge-idents/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ cssnano-utils: 3.1.0_postcss@8.4.21
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-merge-longhand/5.1.7_postcss@8.4.21:
+ resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ stylehacks: 5.1.1_postcss@8.4.21
+ dev: true
+
+ /postcss-merge-rules/5.1.3_postcss@8.4.21:
+ resolution: {integrity: sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ browserslist: 4.21.5
+ caniuse-api: 3.0.0
+ cssnano-utils: 3.1.0_postcss@8.4.21
+ postcss: 8.4.21
+ postcss-selector-parser: 6.0.11
+ dev: true
+
+ /postcss-minify-font-values/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-minify-gradients/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ colord: 2.9.3
+ cssnano-utils: 3.1.0_postcss@8.4.21
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-minify-params/5.1.4_postcss@8.4.21:
+ resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ browserslist: 4.21.5
+ cssnano-utils: 3.1.0_postcss@8.4.21
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-minify-selectors/5.2.1_postcss@8.4.21:
+ resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-selector-parser: 6.0.11
+ dev: true
+
+ /postcss-nested/6.0.0_postcss@8.4.21:
+ resolution: {integrity: sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+ dependencies:
+ postcss: 8.4.21
+ postcss-selector-parser: 6.0.11
+ dev: true
+
+ /postcss-normalize-charset/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /postcss-normalize-display-values/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-normalize-positions/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-normalize-repeat-style/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-normalize-string/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-normalize-timing-functions/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-normalize-unicode/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ browserslist: 4.21.5
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-normalize-url/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ normalize-url: 6.1.0
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-normalize-whitespace/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-ordered-values/5.1.3_postcss@8.4.21:
+ resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ cssnano-utils: 3.1.0_postcss@8.4.21
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-reduce-idents/5.2.0_postcss@8.4.21:
+ resolution: {integrity: sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-reduce-initial/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ browserslist: 4.21.5
+ caniuse-api: 3.0.0
+ postcss: 8.4.21
+ dev: true
+
+ /postcss-reduce-transforms/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /postcss-selector-parser/6.0.11:
+ resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+ dev: true
+
+ /postcss-svgo/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-value-parser: 4.2.0
+ svgo: 2.8.0
+ dev: true
+
+ /postcss-unique-selectors/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ postcss-selector-parser: 6.0.11
+ dev: true
+
+ /postcss-value-parser/4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+ dev: true
+
+ /postcss-zindex/5.1.0_postcss@8.4.21:
+ resolution: {integrity: sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ postcss: 8.4.21
+ dev: true
+
+ /postcss/8.4.21:
+ resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.4
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /pretty-bytes/6.1.0:
+ resolution: {integrity: sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+ dev: true
+
+ /queue-microtask/1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /quick-lru/5.1.1:
+ resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /read-cache/1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+ dependencies:
+ pify: 2.3.0
+ dev: true
+
+ /readdirp/3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /resolve/1.22.1:
+ resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.11.0
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /reusify/1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rimraf/2.7.1:
+ resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /rollup/3.14.0:
+ resolution: {integrity: sha512-o23sdgCLcLSe3zIplT9nQ1+r97okuaiR+vmAPZPTDYB7/f3tgWIYNyiQveMsZwshBT0is4eGax/HH83Q7CG+/Q==}
+ engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /run-parallel/1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /sander/0.5.1:
+ resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
+ dependencies:
+ es6-promise: 3.3.1
+ graceful-fs: 4.2.10
+ mkdirp: 0.5.6
+ rimraf: 2.7.1
+ dev: true
+
+ /simple-swizzle/0.2.2:
+ resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+ dependencies:
+ is-arrayish: 0.3.2
+ dev: true
+
+ /sorcery/0.11.0:
+ resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==}
+ hasBin: true
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.14
+ buffer-crc32: 0.2.13
+ minimist: 1.2.7
+ sander: 0.5.1
+ dev: true
+
+ /source-map-js/1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map/0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /stable/0.1.8:
+ resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
+ deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
+ dev: true
+
+ /strip-indent/3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ min-indent: 1.0.1
+ dev: true
+
+ /stylehacks/5.1.1_postcss@8.4.21:
+ resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==}
+ engines: {node: ^10 || ^12 || >=14.0}
+ peerDependencies:
+ postcss: ^8.2.15
+ dependencies:
+ browserslist: 4.21.5
+ postcss: 8.4.21
+ postcss-selector-parser: 6.0.11
+ dev: true
+
+ /supports-color/7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag/1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /svelte-hmr/0.15.1_svelte@3.55.1:
+ resolution: {integrity: sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==}
+ engines: {node: ^12.20 || ^14.13.1 || >= 16}
+ peerDependencies:
+ svelte: '>=3.19.0'
+ dependencies:
+ svelte: 3.55.1
+ dev: true
+
+ /svelte-preprocess/5.0.1_pehl75e5jsy22vp33udjja4soi:
+ resolution: {integrity: sha512-0HXyhCoc9rsW4zGOgtInylC6qj259E1hpFnJMJWTf+aIfeqh4O/QHT31KT2hvPEqQfdjmqBR/kO2JDkkciBLrQ==}
+ engines: {node: '>= 14.10.0'}
+ requiresBuild: true
+ peerDependencies:
+ '@babel/core': ^7.10.2
+ coffeescript: ^2.5.1
+ less: ^3.11.3 || ^4.0.0
+ postcss: ^7 || ^8
+ postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0
+ pug: ^3.0.0
+ sass: ^1.26.8
+ stylus: ^0.55.0
+ sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0
+ svelte: ^3.23.0
+ typescript: ^3.9.5 || ^4.0.0
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ coffeescript:
+ optional: true
+ less:
+ optional: true
+ postcss:
+ optional: true
+ postcss-load-config:
+ optional: true
+ pug:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ typescript:
+ optional: true
+ dependencies:
+ '@types/pug': 2.0.6
+ '@types/sass': 1.43.1
+ detect-indent: 6.1.0
+ magic-string: 0.27.0
+ postcss: 8.4.21
+ sorcery: 0.11.0
+ strip-indent: 3.0.0
+ svelte: 3.55.1
+ dev: true
+
+ /svelte/3.55.1:
+ resolution: {integrity: sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /svgo/2.8.0:
+ resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ dependencies:
+ '@trysound/sax': 0.2.0
+ commander: 7.2.0
+ css-select: 4.3.0
+ css-tree: 1.1.3
+ csso: 4.2.0
+ picocolors: 1.0.0
+ stable: 0.1.8
+ dev: true
+
+ /tailwindcss/3.2.6_postcss@8.4.21:
+ resolution: {integrity: sha512-BfgQWZrtqowOQMC2bwaSNe7xcIjdDEgixWGYOd6AL0CbKHJlvhfdbINeAW76l1sO+1ov/MJ93ODJ9yluRituIw==}
+ engines: {node: '>=12.13.0'}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.0.9
+ dependencies:
+ arg: 5.0.2
+ chokidar: 3.5.3
+ color-name: 1.1.4
+ detective: 5.2.1
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.2.12
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ lilconfig: 2.0.6
+ micromatch: 4.0.5
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.0.0
+ postcss: 8.4.21
+ postcss-import: 14.1.0_postcss@8.4.21
+ postcss-js: 4.0.1_postcss@8.4.21
+ postcss-load-config: 3.1.4_postcss@8.4.21
+ postcss-nested: 6.0.0_postcss@8.4.21
+ postcss-selector-parser: 6.0.11
+ postcss-value-parser: 4.2.0
+ quick-lru: 5.1.1
+ resolve: 1.22.1
+ transitivePeerDependencies:
+ - ts-node
+ dev: true
+
+ /to-regex-range/5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /tslib/2.5.0:
+ resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
+ dev: true
+
+ /universalify/2.0.0:
+ resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
+ engines: {node: '>= 10.0.0'}
+ dev: true
+
+ /update-browserslist-db/1.0.10_browserslist@4.21.5:
+ resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.21.5
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: true
+
+ /util-deprecate/1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ dev: true
+
+ /vite-plugin-wasm-pack/0.1.12:
+ resolution: {integrity: sha512-WliYvQp9HXluir4OKGbngkcKxtYtifU11cqLurRRJGsl770Sjr1iIkp5RuvU3IC1poT4A57Z2/YgAKI2Skm7ZA==}
+ dependencies:
+ chalk: 4.1.2
+ fs-extra: 10.1.0
+ narrowing: 1.5.0
+ dev: true
+
+ /vite/4.1.1:
+ resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': '>= 14'
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ esbuild: 0.16.17
+ postcss: 8.4.21
+ resolve: 1.22.1
+ rollup: 3.14.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /vitefu/0.2.4_vite@4.1.1:
+ resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+ dependencies:
+ vite: 4.1.1
+ dev: true
+
+ /wrappy/1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /xtend/4.0.2:
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+ engines: {node: '>=0.4'}
+ dev: true
+
+ /yaml/1.10.2:
+ resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
+ engines: {node: '>= 6'}
+ dev: true
diff --git a/scrapper_web/postcss.config.cjs b/scrapper_web/postcss.config.cjs
new file mode 100644
index 0000000..059077c
--- /dev/null
+++ b/scrapper_web/postcss.config.cjs
@@ -0,0 +1,11 @@
+let cssnano_plugin = {};
+if (process.env.NODE_ENV === "production") {
+ cssnano_plugin = { cssnano: { preset: "advanced" } };
+}
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ ...cssnano_plugin,
+ },
+};
diff --git a/scrapper_web/public/vite.svg b/scrapper_web/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/scrapper_web/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/scrapper_web/scrapper/.gitignore b/scrapper_web/scrapper/.gitignore
new file mode 100644
index 0000000..6985cf1
--- /dev/null
+++ b/scrapper_web/scrapper/.gitignore
@@ -0,0 +1,14 @@
+# Generated by Cargo
+# will have compiled files and executables
+debug/
+target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+# MSVC Windows builds of rustc generate these, which store debugging information
+*.pdb
diff --git a/scrapper_web/scrapper/Cargo.toml b/scrapper_web/scrapper/Cargo.toml
new file mode 100644
index 0000000..ee8e4d6
--- /dev/null
+++ b/scrapper_web/scrapper/Cargo.toml
@@ -0,0 +1,31 @@
+[package]
+name = "scrapper"
+version = "0.1.0"
+authors = []
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib", "rlib"]
+
+[profile.release]
+lto = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+aes = "0.8.2"
+anyhow = "1.0.69"
+binrw = "0.11.1"
+cbc = "0.1.2"
+console_error_panic_hook = "0.1.7"
+derivative = "2.2.0"
+js-sys = "0.3.61"
+pelite = "0.10.0"
+serde = { version = "1.0.152", features = ["derive"] }
+serde-wasm-bindgen = "0.4.5"
+wasm-bindgen = "0.2.83"
+wasm-bindgen-file-reader = "1.0.0"
+web-sys = { version = "0.3.61", features = ["File", "BlobPropertyBag", "Blob", "Url"] }
+
+[package.metadata.wasm-pack.profile.release]
+wasm-opt = ["-O4"]
diff --git a/scrapper_web/scrapper/README.md b/scrapper_web/scrapper/README.md
new file mode 100644
index 0000000..a923c54
--- /dev/null
+++ b/scrapper_web/scrapper/README.md
@@ -0,0 +1,23 @@
+# scrapper
+
+## Usage
+
+[rsw-rs doc](https://github.com/lencx/rsw-rs)
+
+```bash
+# install rsw
+cargo install rsw
+
+# --- help ---
+# rsw help
+rsw -h
+# new help
+rsw new -h
+
+# --- usage ---
+# dev
+rsw watch
+
+# production
+rsw build
+```
diff --git a/scrapper_web/scrapper/src/lib.rs b/scrapper_web/scrapper/src/lib.rs
new file mode 100644
index 0000000..fda2f4b
--- /dev/null
+++ b/scrapper_web/scrapper/src/lib.rs
@@ -0,0 +1,155 @@
+use binrw::{binread, BinReaderExt};
+use serde::Serialize;
+use std::collections::BTreeMap;
+use std::io::{Read, Seek, SeekFrom};
+use wasm_bindgen::prelude::*;
+use wasm_bindgen_file_reader::WebSysFile;
+use web_sys::{Blob, File};
+
+type JsResult = Result;
+
+#[binread]
+#[derive(Serialize, Debug)]
+struct ScrapFile {
+ #[br(temp)]
+ name_len: u32,
+ #[br(count = name_len)]
+ #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())]
+ path: String,
+ size: u32,
+ offset: u32,
+}
+
+#[binread]
+#[br(magic = b"BFPK", little)]
+#[derive(Serialize, Debug)]
+struct PackedHeader {
+ version: u32,
+ #[br(temp)]
+ num_files: u32,
+ #[br(count= num_files)]
+ files: Vec,
+}
+
+#[derive(Serialize, Debug)]
+#[serde(tag = "type", rename_all = "snake_case")]
+enum DirectoryTree {
+ File {
+ size: u32,
+ offset: u32,
+ file_index: u8,
+ },
+ Directory {
+ entries: BTreeMap,
+ },
+}
+
+#[wasm_bindgen(inspectable)]
+pub struct MultiPack {
+ files: Vec<(String,WebSysFile)>,
+ tree: DirectoryTree,
+}
+
+fn blob_url(buffer: &[u8]) -> JsResult {
+ let uint8arr =
+ js_sys::Uint8Array::new(&unsafe { js_sys::Uint8Array::view(buffer) }.into());
+ let array = js_sys::Array::new();
+ array.push(&uint8arr.buffer());
+ let blob = Blob::new_with_u8_array_sequence_and_options(
+ &array,
+ web_sys::BlobPropertyBag::new().type_("application/octet-stream"),
+ )
+ .unwrap();
+ web_sys::Url::create_object_url_with_blob(&blob)
+}
+
+#[wasm_bindgen]
+impl MultiPack {
+ #[wasm_bindgen(constructor)]
+ pub fn parse(files: Vec) -> Self {
+ let mut tree = DirectoryTree::default();
+ let mut web_files = vec![];
+ for (file_index, file) in files.into_iter().enumerate() {
+ let file_name = file.name();
+ let mut fh = WebSysFile::new(file);
+ let header = fh.read_le::().unwrap();
+ tree.merge(&header.files, file_index.try_into().unwrap());
+ web_files.push((file_name,fh));
+ }
+ Self {
+ tree,
+ files: web_files,
+ }
+ }
+
+ #[wasm_bindgen]
+ pub fn tree(&self) -> JsValue {
+ serde_wasm_bindgen::to_value(&self.tree).unwrap()
+ }
+
+ #[wasm_bindgen]
+ pub fn download(
+ &mut self,
+ file_index: u8,
+ offset: u32,
+ size: u32,
+ ) -> Result {
+ let Some((_,file)) = self.files.get_mut(file_index as usize) else {
+ return Err("File not found".into());
+ };
+ let mut buffer = vec![0u8; size as usize];
+ file.seek(SeekFrom::Start(offset as u64))
+ .map_err(|e| format!("Failed to seek file: {e}"))?;
+ file.read(&mut buffer)
+ .map_err(|e| format!("Failed to read from file: {e}"))?;
+ Ok(blob_url(&buffer)?.into())
+ }
+}
+
+impl Default for DirectoryTree {
+ fn default() -> Self {
+ Self::Directory {
+ entries: Default::default(),
+ }
+ }
+}
+
+impl DirectoryTree {
+ fn add_child(&mut self, name: &str, node: Self) -> &mut Self {
+ match self {
+ Self::File { .. } => panic!("Can't add child to file!"),
+ Self::Directory {
+ entries
+ } => entries.entry(name.to_owned()).or_insert(node),
+ }
+ }
+
+ fn merge(&mut self, files: &[ScrapFile], file_index: u8) {
+ for file in files {
+ let mut folder = &mut *self;
+ let path: Vec<_> = file.path.split('/').collect();
+ if let Some((filename, path)) = path.as_slice().split_last() {
+ for part in path {
+ let DirectoryTree::Directory { entries } = folder else {
+ unreachable!();
+ };
+ folder = entries.entry(part.to_string()).or_default();
+ }
+ folder.add_child(
+ filename,
+ DirectoryTree::File {
+ size: file.size,
+ offset: file.offset,
+ file_index,
+ },
+ );
+ }
+ }
+ }
+}
+
+#[wasm_bindgen(start)]
+pub fn main() -> Result<(), JsValue> {
+ console_error_panic_hook::set_once();
+ Ok(())
+}
diff --git a/scrapper_web/src/App.svelte b/scrapper_web/src/App.svelte
new file mode 100644
index 0000000..70adfa0
--- /dev/null
+++ b/scrapper_web/src/App.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
Scrapland .packed explorer
+
+
+
+
+
diff --git a/scrapper_web/src/app.pcss b/scrapper_web/src/app.pcss
new file mode 100644
index 0000000..19ea342
--- /dev/null
+++ b/scrapper_web/src/app.pcss
@@ -0,0 +1,109 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+.card {
+ padding: 2em;
+}
+
+#app {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+li {
+ text-align: left;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
+
+.lds-dual-ring {
+ display: inline-block;
+ width: 80px;
+ height: 80px;
+}
+.lds-dual-ring:after {
+ content: " ";
+ display: block;
+ width: 64px;
+ height: 64px;
+ margin: 8px;
+ border-radius: 50%;
+ border: 6px solid #fff;
+ border-color: #fff transparent #fff transparent;
+ animation: lds-dual-ring 1.2s linear infinite;
+}
+@keyframes lds-dual-ring {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
diff --git a/scrapper_web/src/lib/Explorer.svelte b/scrapper_web/src/lib/Explorer.svelte
new file mode 100644
index 0000000..5a7b44b
--- /dev/null
+++ b/scrapper_web/src/lib/Explorer.svelte
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+{#if tree}
+ {#each [...tree.entries] as [name, child]}
+
+ {/each}
+{/if}
diff --git a/scrapper_web/src/lib/TreeView.svelte b/scrapper_web/src/lib/TreeView.svelte
new file mode 100644
index 0000000..f2699f6
--- /dev/null
+++ b/scrapper_web/src/lib/TreeView.svelte
@@ -0,0 +1,56 @@
+
+
+
+
+
+ {#if tree.type == "directory" && tree.entries}
+
+ {#if expanded}
+ [-]
+ {:else}
+ [+]
+ {/if}
+ {label}
+
+ {#if tree.entries && expanded}
+ {#each [...tree.entries] as [name, child]}
+
+ {/each}
+ {/if}
+ {:else}
+
+
+ {label}
+
+ {/if}
+
+
+
+
diff --git a/scrapper_web/src/main.js b/scrapper_web/src/main.js
new file mode 100644
index 0000000..e7acd1d
--- /dev/null
+++ b/scrapper_web/src/main.js
@@ -0,0 +1,6 @@
+import './app.pcss'
+import App from './App.svelte'
+
+export default new App({
+ target: document.getElementById('app'),
+});
diff --git a/scrapper_web/src/scrapper.worker.js b/scrapper_web/src/scrapper.worker.js
new file mode 100644
index 0000000..a1146b1
--- /dev/null
+++ b/scrapper_web/src/scrapper.worker.js
@@ -0,0 +1,28 @@
+import wasm, { MultiPack } from "scrapper";
+
+async function initialize() {
+ await wasm();
+ let pack;
+ let handlers = {
+ parse(data) {
+ pack = new MultiPack(data);
+ return pack.tree();
+ },
+ download(data) {
+ if (pack) {
+ let { label, file_index, offset, size } = data;
+ return [label, pack.download(file_index, offset, size)];
+ }
+ },
+ };
+ self.onmessage = (event) => {
+ for (var [name, func] of Object.entries(handlers)) {
+ let data = event.data[name];
+ if (data) {
+ postMessage(Object.fromEntries([[name, func(data)]]));
+ }
+ }
+ };
+}
+
+initialize();
diff --git a/scrapper_web/src/vite-env.d.ts b/scrapper_web/src/vite-env.d.ts
new file mode 100644
index 0000000..4078e74
--- /dev/null
+++ b/scrapper_web/src/vite-env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/scrapper_web/svelte.config.js b/scrapper_web/svelte.config.js
new file mode 100644
index 0000000..66fa030
--- /dev/null
+++ b/scrapper_web/svelte.config.js
@@ -0,0 +1,6 @@
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
+export default {
+ // Consult https://svelte.dev/docs#compile-time-svelte-preprocess
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+}
diff --git a/scrapper_web/tailwind.config.cjs b/scrapper_web/tailwind.config.cjs
new file mode 100644
index 0000000..ad70a37
--- /dev/null
+++ b/scrapper_web/tailwind.config.cjs
@@ -0,0 +1,36 @@
+module.exports = {
+ content: ["./src/**/*.{svelte,js,ts}"],
+ plugins: [require("@tailwindcss/forms"),require("daisyui")],
+ theme: {
+ container: {
+ center: true,
+ },
+ },
+ daisyui: {
+ styled: true,
+ themes: true,
+ base: true,
+ utils: true,
+ logs: true,
+ rtl: false,
+ prefix: "",
+ darkTheme: "scraptool",
+ themes: [
+ {
+ scraptool: {
+ primary: "#F28C18",
+ secondary: "#b45309",
+ accent: "#22d3ee",
+ neutral: "#1B1D1D",
+ "base-100": "#212121",
+ info: "#2463EB",
+ success: "#16A249",
+ warning: "#DB7706",
+ error: "#DC2828",
+ // "--rounded-box": "0.4rem",
+ // "--rounded-btn": "0.2rem"
+ },
+ },
+ ],
+ },
+};
diff --git a/scrapper_web/vite.config.js b/scrapper_web/vite.config.js
new file mode 100644
index 0000000..6935bc3
--- /dev/null
+++ b/scrapper_web/vite.config.js
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vite'
+import { svelte } from '@sveltejs/vite-plugin-svelte'
+import wasmPack from 'vite-plugin-wasm-pack';
+import preprocess from 'svelte-preprocess';
+
+export default defineConfig({
+ plugins: [wasmPack("./scrapper/"),svelte({
+ preprocess: preprocess({ postcss: true })
+ })]
+});
diff --git a/tools/ghidra_scripts/mark_up_py.py b/tools/ghidra_scripts/mark_up_py.py
new file mode 100644
index 0000000..5dc9d71
--- /dev/null
+++ b/tools/ghidra_scripts/mark_up_py.py
@@ -0,0 +1,125 @@
+import time
+try:
+ import ghidra_bridge
+ has_bridge=True
+except ImportError:
+ has_bridge=False
+
+from contextlib import contextmanager
+
+if has_bridge:
+ import ghidra_bridge
+ b = ghidra_bridge.GhidraBridge(namespace=globals(), hook_import=True)
+ @contextmanager
+ def transaction():
+ start()
+ try:
+ yield
+ except Exception as e:
+ end(False)
+ raise e
+ end(True)
+else:
+ @contextmanager
+ def transaction():
+ yield
+
+import ghidra.program.model.symbol.SymbolType as SymbolType
+import ghidra.program.model.symbol.SourceType as SourceType
+from ghidra.app.cmd.label import CreateNamespacesCmd
+from ghidra.program.model.data.DataUtilities import createData
+from ghidra.program.model.data.DataUtilities import ClearDataMode
+from ghidra.program.model.listing.CodeUnit import PLATE_COMMENT
+
+listing = currentProgram.getListing()
+dtm = currentProgram.getDataTypeManager()
+py_mod = dtm.getDataType("/PyModuleDef")
+py_meth = dtm.getDataType("/PyMethodDef")
+
+NULL=toAddr(0)
+
+def make_namespace(parts):
+ ns_cmd = CreateNamespacesCmd("::".join(parts), SourceType.USER_DEFINED)
+ ns_cmd.applyTo(currentProgram)
+ return ns_cmd.getNamespace()
+
+def create_data(addr,dtype):
+ return createData(currentProgram,addr,dtype,0,False,ClearDataMode.CLEAR_ALL_CONFLICT_DATA)
+
+def create_str(addr):
+ if addr.equals(NULL):
+ return None
+ str_len = (findBytes(addr, b"\0").offset - addr.offset) + 1
+ clearListing(addr, addr.add(str_len))
+ return createAsciiString(addr)
+
+def get_call_obj(addr):
+ func = getFunctionContaining(addr)
+ if func is None:
+ disassemble(addr)
+ func = createFunction(addr,None)
+ call_obj = {"this": None, "stack": []}
+ for inst in currentProgram.listing.getInstructions(func.body, True):
+ affected_objs = [r.toString() for r in inst.resultObjects.tolist()]
+ inst_name = inst.getMnemonicString()
+ if inst_name == "PUSH":
+ val=inst.getScalar(0)
+ if val is not None:
+ call_obj["stack"].insert(0, toAddr(val.getValue()).toString())
+ elif inst_name == "MOV" and "ECX" in affected_objs:
+ this = inst.getScalar(1)
+ if this is not None:
+ call_obj["this"] = toAddr(this.getValue()).toString()
+ elif inst_name == "CALL":
+ break
+ func=func.symbol.address
+ return func, call_obj
+
+def data_to_dict(data):
+ ret={}
+ for idx in range(data.dataType.getNumComponents()):
+ name=data.dataType.getComponent(idx).getFieldName()
+ value=data.getComponent(idx).getValue()
+ ret[name]=value
+ return ret
+
+def try_create_str(addr):
+ ret=create_str(addr)
+ if ret:
+ return ret.getValue()
+
+with transaction():
+ PyInitModule=getSymbolAt(toAddr("006f31c0"))
+ for ref in getReferencesTo(PyInitModule.address).tolist():
+ func,args=get_call_obj(ref.fromAddress)
+ print(func,args)
+ module_name=create_str(toAddr(args['stack'][0])).getValue()
+ methods=toAddr(args['stack'][1])
+ module_doc=create_str(toAddr(args['stack'][2]))
+ if module_doc:
+ module_doc=module_doc.getValue()
+ print(methods,module_name,module_doc)
+ mod_ns = make_namespace(["Python", module_name])
+ createLabel(func, "__init__", mod_ns, True, SourceType.USER_DEFINED)
+ if module_doc:
+ listing.getCodeUnitAt(func).setComment(PLATE_COMMENT,module_doc)
+ while True:
+ mod_data=data_to_dict(create_data(methods,py_meth))
+ if mod_data['name'] is None:
+ clearListing(methods, methods.add(16))
+ break
+ mod_data['name']=try_create_str(mod_data['name'])
+ try:
+ mod_data['doc']=try_create_str(mod_data['doc'])
+ except:
+ mod_data['doc']=None
+ print(mod_data)
+ createLabel(mod_data['ml_method'], mod_data['name'], mod_ns, True, SourceType.USER_DEFINED)
+ if mod_data['doc']:
+ listing.getCodeUnitAt(mod_data['ml_method']).setComment(PLATE_COMMENT,module_doc)
+ methods=methods.add(16)
+ try:
+ if getBytes(methods,4).tolist()==[0,0,0,0]:
+ break
+ except:
+ break
\ No newline at end of file
diff --git a/tools/remaster/scrap_parse/.gitignore b/tools/remaster/scrap_parse/.gitignore
new file mode 100644
index 0000000..758f49c
--- /dev/null
+++ b/tools/remaster/scrap_parse/.gitignore
@@ -0,0 +1,177 @@
+# Generated by Cargo
+# will have compiled files and executables
+debug/
+target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+# MSVC Windows builds of rustc generate these, which store debugging information
+*.pdb
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
+*.pkl.gz
\ No newline at end of file
diff --git a/tools/remaster/scrap_parse/Cargo.lock b/tools/remaster/scrap_parse/Cargo.lock
index 90147a3..533cb1d 100644
--- a/tools/remaster/scrap_parse/Cargo.lock
+++ b/tools/remaster/scrap_parse/Cargo.lock
@@ -8,6 +8,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+[[package]]
+name = "aho-corasick"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -18,10 +27,59 @@ dependencies = [
]
[[package]]
-name = "anyhow"
-version = "1.0.69"
+name = "anstream"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
+checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is-terminal",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
name = "array-init"
@@ -56,7 +114,7 @@ dependencies = [
"owo-colors",
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
@@ -66,16 +124,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
-name = "bumpalo"
-version = "3.12.0"
+name = "block-buffer"
+version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
[[package]]
name = "bytemuck"
-version = "1.13.0"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
@@ -91,9 +164,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.23"
+version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
dependencies = [
"iana-time-zone",
"js-sys",
@@ -106,50 +179,46 @@ dependencies = [
]
[[package]]
-name = "chrono-humanize"
-version = "0.2.2"
+name = "clap"
+version = "4.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32dce1ea1988dbdf9f9815ff11425828523bd2a134ec0805d2ac8af26ee6096e"
+checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62"
dependencies = [
- "chrono",
+ "clap_builder",
+ "clap_derive",
+ "once_cell",
]
[[package]]
-name = "clap"
-version = "4.1.6"
+name = "clap_builder"
+version = "4.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
+checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749"
dependencies = [
+ "anstream",
+ "anstyle",
"bitflags",
- "clap_derive",
"clap_lex",
- "is-terminal",
- "once_cell",
"strsim",
- "termcolor",
]
[[package]]
name = "clap_derive"
-version = "4.1.0"
+version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
+checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
dependencies = [
"heck",
- "proc-macro-error",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.15",
]
[[package]]
name = "clap_lex"
-version = "0.3.1"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
-dependencies = [
- "os_str_bytes",
-]
+checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
[[package]]
name = "codespan-reporting"
@@ -161,6 +230,12 @@ dependencies = [
"unicode-width",
]
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
[[package]]
name = "configparser"
version = "3.0.2"
@@ -172,9 +247,18 @@ dependencies = [
[[package]]
name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
+dependencies = [
+ "libc",
+]
[[package]]
name = "crc32fast"
@@ -186,10 +270,20 @@ dependencies = [
]
[[package]]
-name = "cxx"
-version = "1.0.91"
+name = "crypto-common"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "cxx"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
dependencies = [
"cc",
"cxxbridge-flags",
@@ -199,9 +293,9 @@ dependencies = [
[[package]]
name = "cxx-build"
-version = "1.0.91"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690"
+checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
dependencies = [
"cc",
"codespan-reporting",
@@ -209,24 +303,54 @@ dependencies = [
"proc-macro2",
"quote",
"scratch",
- "syn",
+ "syn 2.0.15",
]
[[package]]
name = "cxxbridge-flags"
-version = "1.0.91"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf"
+checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
[[package]]
name = "cxxbridge-macro"
-version = "1.0.91"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892"
+checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "dirs"
+version = "5.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b"
+dependencies = [
+ "libc",
+ "redox_users",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -237,13 +361,13 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "errno"
-version = "0.2.8"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
- "winapi",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -272,6 +396,27 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541"
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
[[package]]
name = "hashbrown"
version = "0.12.3"
@@ -292,16 +437,16 @@ checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "iana-time-zone"
-version = "0.1.53"
+version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
- "winapi",
+ "windows",
]
[[package]]
@@ -316,9 +461,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "1.9.2"
+version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
@@ -327,31 +472,38 @@ dependencies = [
[[package]]
name = "io-lifetimes"
-version = "1.0.5"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
+ "hermit-abi",
"libc",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
name = "is-terminal"
-version = "0.4.3"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
-name = "itoa"
-version = "1.0.5"
+name = "iter-read"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+checksum = "c397ca3ea05ad509c4ec451fea28b4771236a376ca1c69fd5143aae0cf8f93c4"
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "js-sys"
@@ -363,10 +515,35 @@ dependencies = [
]
[[package]]
-name = "libc"
-version = "0.2.139"
+name = "keyvalues-parser"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+checksum = "7d990301996c856ea07a84bc291e76f1273db52683663efc05c8d355976897e5"
+dependencies = [
+ "pest",
+ "pest_derive",
+ "thiserror",
+]
+
+[[package]]
+name = "keyvalues-serde"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da419ac133bb3ddf0dbf9c12fcc0ce01d994fcb65f6f1713faf15cc689320b5f"
+dependencies = [
+ "keyvalues-parser",
+ "once_cell",
+ "paste",
+ "regex",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.142"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
[[package]]
name = "link-cplusplus"
@@ -379,9 +556,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
-version = "0.1.4"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
+checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf"
[[package]]
name = "log"
@@ -392,6 +569,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
[[package]]
name = "miniz_oxide"
version = "0.6.2"
@@ -419,7 +602,24 @@ checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "nom"
+version = "1.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
+
+[[package]]
+name = "num-bigint"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
]
[[package]]
@@ -441,18 +641,18 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "obj"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "059c95245738cdc7b40078cdd51a23200252a4c0a0a6dd005136152b3f467a4a"
+
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
-[[package]]
-name = "os_str_bytes"
-version = "6.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
-
[[package]]
name = "owo-colors"
version = "3.5.0"
@@ -460,47 +660,110 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
+name = "paste"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
+
+[[package]]
+name = "pest"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122"
dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn",
- "version_check",
+ "thiserror",
+ "ucd-trie",
]
[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
+name = "pest_derive"
+version = "2.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15"
dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e"
+dependencies = [
+ "pest",
+ "pest_meta",
"proc-macro2",
"quote",
- "version_check",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha2",
]
[[package]]
name = "proc-macro2"
-version = "1.0.51"
+version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.23"
+version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+
[[package]]
name = "rhexdump"
version = "0.1.1"
@@ -509,23 +772,32 @@ checksum = "c5e9af64574935e39f24d1c0313a997c8b880ca0e087c888bc6af8af31579847"
[[package]]
name = "rustix"
-version = "0.36.8"
+version = "0.37.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
+checksum = "d9b864d3c18a5785a05953adeed93e2dca37ed30f18e69bba9f30079d51f363f"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
name = "ryu"
-version = "1.0.12"
+version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
[[package]]
name = "scrap_parse"
@@ -534,61 +806,112 @@ dependencies = [
"anyhow",
"binrw",
"chrono",
- "chrono-humanize",
"clap",
"configparser",
"flate2",
"fs-err",
"indexmap",
"modular-bitfield",
+ "obj",
"rhexdump",
"serde",
+ "serde-pickle",
"serde_json",
+ "steamlocate",
+ "walkdir",
]
[[package]]
name = "scratch"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
+checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
[[package]]
name = "serde"
-version = "1.0.152"
+version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
dependencies = [
"serde_derive",
]
[[package]]
-name = "serde_derive"
-version = "1.0.152"
+name = "serde-pickle"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "c762ad136a26407c6a80825813600ceeab5e613660d93d79a41f0ec877171e71"
+dependencies = [
+ "byteorder",
+ "iter-read",
+ "num-bigint",
+ "num-traits",
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.160"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.15",
]
[[package]]
name = "serde_json"
-version = "1.0.93"
+version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [
+ "indexmap",
"itoa",
"ryu",
"serde",
]
+[[package]]
+name = "sha2"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+[[package]]
+name = "steamlocate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec01c74611d14a808cb212d17c6e03f0e30736a15ed1d5736f8a53154cea3ae"
+dependencies = [
+ "dirs",
+ "keyvalues-parser",
+ "keyvalues-serde",
+ "serde",
+ "steamy-vdf",
+ "winreg",
+]
+
+[[package]]
+name = "steamy-vdf"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "533127ad49314bfe71c3d3fd36b3ebac3d24f40618092e70e1cfe8362c7fac79"
+dependencies = [
+ "nom",
+]
+
[[package]]
name = "strsim"
version = "0.10.0"
@@ -597,9 +920,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
-version = "1.0.107"
+version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
@@ -615,6 +949,26 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
[[package]]
name = "time"
version = "0.1.45"
@@ -622,15 +976,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
- "wasi",
+ "wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
[[package]]
-name = "unicode-ident"
-version = "1.0.6"
+name = "typenum"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "unicode-width"
@@ -638,18 +1004,40 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+[[package]]
+name = "walkdir"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
[[package]]
name = "wasm-bindgen"
version = "0.2.84"
@@ -671,7 +1059,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
"wasm-bindgen-shared",
]
@@ -693,7 +1081,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -735,68 +1123,153 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+[[package]]
+name = "windows"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
- "windows-targets",
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
]
[[package]]
name = "windows-targets"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
+name = "winreg"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a1a57ff50e9b408431e8f97d5456f2807f8eb2a2cd79b06068fc87f8ecf189"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
diff --git a/tools/remaster/scrap_parse/Cargo.toml b/tools/remaster/scrap_parse/Cargo.toml
index bdb3554..77904e2 100644
--- a/tools/remaster/scrap_parse/Cargo.toml
+++ b/tools/remaster/scrap_parse/Cargo.toml
@@ -9,13 +9,18 @@ edition = "2021"
anyhow = "1.0.69"
binrw = "0.11.1"
chrono = { version = "0.4.23", features = ["serde"] }
-chrono-humanize = "0.2.2"
+# chrono-humanize = "0.2.2"
clap = { version = "4.1.6", features = ["derive"] }
configparser = { version = "3.0.2", features = ["indexmap"] }
flate2 = "1.0.25"
fs-err = "2.9.0"
indexmap = { version = "1.9.2", features = ["serde"] }
+# memmap2 = "0.5.10"
modular-bitfield = "0.11.2"
rhexdump = "0.1.1"
serde = { version = "1.0.152", features = ["derive"] }
-serde_json = { version = "1.0.93", features = ["unbounded_depth"] }
+serde-pickle = "1.1.1"
+serde_json = { version = "1.0.95", features = ["preserve_order", "unbounded_depth"] }
+steamlocate = "1.1.0"
+walkdir = "2.3.3"
+obj = "0.10.2"
diff --git a/tools/remaster/scrap_parse/blender_plugin/__init__.py b/tools/remaster/scrap_parse/blender_plugin/__init__.py
new file mode 100644
index 0000000..84c8e51
--- /dev/null
+++ b/tools/remaster/scrap_parse/blender_plugin/__init__.py
@@ -0,0 +1,23 @@
+import pickle
+import subprocess as SP
+
+from . import packed_browser
+from . import level_import
+
+def scrap_bridge(*cmd):
+ cmd=["scrap_parse",*cmd]
+ proc=SP.Popen(cmd,stderr=None,stdin=None,stdout=SP.PIPE,shell=True,text=False)
+ stdout,stderr=proc.communicate()
+ code=proc.wait()
+ if code:
+ raise RuntimeError(str(stderr,"utf8"))
+ return pickle.loads(stdout)
+
+def register():
+ packed_browser.register()
+ level_import.regiser()
+
+def unregister():
+ packed_browser.unregister()
+ level_import.unregister()
+
diff --git a/tools/remaster/scrap_parse/blender_import.py b/tools/remaster/scrap_parse/blender_plugin/level_import.py
similarity index 87%
rename from tools/remaster/scrap_parse/blender_import.py
rename to tools/remaster/scrap_parse/blender_plugin/level_import.py
index eeae6cb..d0ef765 100644
--- a/tools/remaster/scrap_parse/blender_import.py
+++ b/tools/remaster/scrap_parse/blender_plugin/level_import.py
@@ -2,16 +2,16 @@ import bpy
import sys
import os
import re
-import json
import gzip
+import pickle
import argparse
-import shutil
from glob import glob
from mathutils import Vector
from pathlib import Path
import numpy as np
import itertools as ITT
from pprint import pprint
+# from .. import scrap_bridge
import bmesh
from bpy.props import StringProperty, BoolProperty
from bpy_extras.io_utils import ImportHelper
@@ -25,12 +25,6 @@ if "--" in sys.argv:
parser.add_argument("file_list", nargs="+")
cmdline = parser.parse_args(args)
-
-def fix_pos(xyz):
- x, y, z = xyz
- return x, z, y
-
-
class ScrapImporter(object):
def __init__(self, options):
self.unhandled = set()
@@ -39,16 +33,22 @@ class ScrapImporter(object):
self.model_scale = 1000.0
self.spawn_pos = {}
self.objects = {}
- print("Loading", filepath)
- with gzip.open(filepath, "r") as fh:
- data = json.load(fh)
+ # print("Loading", filepath)
+ # scrapland_path=scrap_bridge("find-scrapland")
+ # print(scrapland_path)
+ # packed_data=scrap_bridge("parse-packed",scrapland_path)
+ # print(packed_data)
+ # get_output(["scrap_parse","parse-file","--stdout",scrapland_path,"levels/temple"])
+ # raise NotImplementedError()
+ with gzip.open(filepath, "rb") as fh:
+ data = pickle.load(fh)
self.path = data.pop("path")
self.root = data.pop("root")
self.config = data.pop("config")
- self.dummies = data.pop("dummies")["DUM"]["dummies"]
+ self.dummies = data.pop("dummies")["dummies"]
self.moredummies = data.pop("moredummies")
- self.emi = data.pop("emi")["EMI"]
- self.sm3 = data.pop("sm3")["SM3"]
+ self.emi = data.pop("emi")
+ self.sm3 = data.pop("sm3")
def make_empty(self, name, pos, rot=None):
empty = bpy.data.objects.new(name, None)
@@ -119,7 +119,7 @@ class ScrapImporter(object):
bpy.context.scene.collection.objects.link(light)
def create_nodes(self):
- for node in self.sm3["scene"]["nodes"]:
+ for node in self.sm3["scene"].get("nodes",[]):
node_name = node["name"]
node = node.get("content", {})
if not node:
@@ -212,6 +212,8 @@ class ScrapImporter(object):
)
else:
folders = ITT.chain([start_folder], start_folder.parents)
+ folders=list(folders)
+ print(f"Looking for {path} in {folders}")
for folder in folders:
for suffix in file_extensions:
for dds in [".", "dds"]:
@@ -227,7 +229,7 @@ class ScrapImporter(object):
return list(filter(lambda i: (i.type, i.name) == (dtype, name), node.inputs))
- def build_material(self, mat_key, mat_def):
+ def build_material(self, mat_key, mat_def, map_def):
mat_props = dict(m.groups() for m in re.finditer(r"\(\+(\w+)(?::(\w*))?\)",mat_key))
for k,v in mat_props.items():
mat_props[k]=v or True
@@ -260,13 +262,13 @@ class ScrapImporter(object):
"Roughness": 0.0,
"Specular": 0.2,
}
- tex_slots=[
- "Base Color",
- "Metallic",
- None, # "Clearcoat" ? env map?
- "Normal",
- "Emission"
- ]
+ tex_slot_map={
+ "base": "Base Color",
+ "metallic":"Metallic",
+ "unk_1":None, # "Clearcoat" ? env map?
+ "bump":"Normal",
+ "glow":"Emission"
+ }
mat = bpy.data.materials.new(mat_key)
mat.use_nodes = True
@@ -275,7 +277,13 @@ class ScrapImporter(object):
imgs = {}
animated_textures={}
is_transparent = True
- for slot,tex in zip(tex_slots,mat_def["maps"]):
+ print(map_def)
+ if map_def[0]:
+ print("=== MAP[0]:",self.resolve_path(map_def[0]))
+ if map_def[2]:
+ print("=== MAP[2]:",self.resolve_path(map_def[2]))
+ for slot,tex in mat_def["maps"].items():
+ slot=tex_slot_map.get(slot)
if (slot is None) and tex:
self.unhandled.add(tex["texture"])
print(f"Don't know what to do with {tex}")
@@ -286,9 +294,7 @@ class ScrapImporter(object):
continue
tex_name = os.path.basename(tex_file)
if ".000." in tex_name:
- tex_files=glob(tex_file.replace(".000.",".*."))
- num_frames=len(tex_files)
- animated_textures[slot]=num_frames
+ animated_textures[slot]=len(glob(tex_file.replace(".000.",".*.")))
mat_props.update(overrides.get(tex_name,{}))
if any(
tex_name.find(fragment) != -1
@@ -297,7 +303,7 @@ class ScrapImporter(object):
continue
else:
is_transparent = False
- imgs[slot]=bpy.data.images.load(tex_file)
+ imgs[slot]=bpy.data.images.load(tex_file,check_existing=True)
for n in nodes:
nodes.remove(n)
out = nodes.new("ShaderNodeOutputMaterial")
@@ -311,7 +317,6 @@ class ScrapImporter(object):
settings.update(glass_settings)
for name, value in settings.items():
shader.inputs[name].default_value = value
- sockets_used = set()
for socket,img in imgs.items():
img_node = nodes.new("ShaderNodeTexImage")
img_node.name = img.name
@@ -369,17 +374,20 @@ class ScrapImporter(object):
node_tree.links.new(imgs["Base Color"].outputs["Color"],transp_shader.inputs["Color"])
shader_out=mix_shader.outputs["Shader"]
node_tree.links.new(shader_out, out.inputs["Surface"])
+ # try:
+ # bpy.ops.node.button()
+ # except:
+ # pass
return mat
def apply_maps(self, ob, m_mat, m_map):
mat_key, m_mat = m_mat
- map_key, m_map = m_map # TODO?: MAP
+ map_key, m_map = m_map
if mat_key == 0:
return
mat_name = m_mat.get("name", f"MAT:{mat_key:08X}")
- map_name = f"MAP:{map_key:08X}"
if mat_name not in bpy.data.materials:
- ob.active_material = self.build_material(mat_name, m_mat)
+ ob.active_material = self.build_material(mat_name, m_mat, m_map)
else:
ob.active_material = bpy.data.materials[mat_name]
@@ -424,17 +432,17 @@ class ScrapImporter(object):
ob = bpy.data.objects.new(name, me)
self.apply_maps(ob, m_mat, m_map)
bpy.context.scene.collection.objects.link(ob)
- self.objects.setdefault(name, []).append(ob)
+ self.objects.setdefault(name.split("(")[0], []).append(ob)
return ob
class Scrap_Load(Operator, ImportHelper):
- bl_idname = "scrap_utils.import_json"
- bl_label = "Import JSON"
+ bl_idname = "scrap_utils.import_pickle"
+ bl_label = "Import Pickle"
- filename_ext = ".json.gz"
- filter_glob: StringProperty(default="*.json.gz", options={"HIDDEN"})
+ filename_ext = ".pkl.gz"
+ filter_glob: StringProperty(default="*.pkl.gz", options={"HIDDEN"})
create_dummies: BoolProperty(
name="Import dummies",
@@ -447,25 +455,20 @@ class Scrap_Load(Operator, ImportHelper):
)
create_tracks: BoolProperty(
- name="Create track curves",
- default=True
+ name="Create track curves",
+ default=True
)
merge_objects: BoolProperty(
- name="Merge objects by name",
- default=False
+ name="Merge objects by name",
+ default=False
)
remove_dup_verts: BoolProperty(
- name="Remove overlapping vertices\nfor smoother meshes",
- default=True
+ name="Remove overlapping vertices\nfor smoother meshes",
+ default=True
)
- # remove_dup_verts: BoolProperty(
- # name="Remove overlapping vertices for smoother meshes",
- # default=False
- # )
-
def execute(self, context):
bpy.ops.preferences.addon_enable(module = "node_arrange")
@@ -488,7 +491,7 @@ def unregister():
if __name__ == "__main__":
if cmdline is None or not cmdline.file_list:
register()
- bpy.ops.scrap_utils.import_json("INVOKE_DEFAULT")
+ bpy.ops.scrap_utils.import_pickle("INVOKE_DEFAULT")
else:
for file in cmdline.file_list:
bpy.context.preferences.view.show_splash = False
diff --git a/tools/remaster/scrap_parse/blender_plugin/packed_browser.py b/tools/remaster/scrap_parse/blender_plugin/packed_browser.py
new file mode 100644
index 0000000..3981c53
--- /dev/null
+++ b/tools/remaster/scrap_parse/blender_plugin/packed_browser.py
@@ -0,0 +1,118 @@
+import sys
+from .. import scrap_bridge
+from bpy.props import (StringProperty, BoolProperty, CollectionProperty,
+ IntProperty)
+
+bl_info = {
+ "name": "Packed Archive File",
+ "blender": (2, 71, 0),
+ "location": "File > Import",
+ "description": "Import data from Scrapland .packed Archive",
+ "category": "Import-Export"}
+
+
+
+
+class ImportFilearchives(bpy.types.Operator):
+ """Import whole filearchives directory."""
+ bl_idname = "import_scene.packed"
+ bl_label = 'Import Scrapland .packed'
+
+ directory = StringProperty(name="'Scrapland' folder",
+ subtype="DIR_PATH", options={'HIDDEN'})
+ filter_folder = BoolProperty(default=True, options={'HIDDEN'})
+ filter_glob = StringProperty(default="", options={'HIDDEN'})
+
+ def invoke(self, context, event):
+ context.window_manager.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+ def execute(self, context):
+ # TODO: Validate filepath
+ bpy.ops.ui.packed_browser('INVOKE_DEFAULT',filepath=self.directory)
+ return {'FINISHED'}
+
+
+class PackedFile(bpy.types.PropertyGroup):
+ path = bpy.props.StringProperty()
+ packed_file = bpy.props.StringProperty()
+ selected = bpy.props.BoolProperty(name="")
+ offset = bpy.props.IntProperty()
+ size = bpy.props.IntProperty()
+
+
+archive = None
+class PackedBrowser(bpy.types.Operator):
+ bl_idname = "ui.packed_browser"
+ bl_label = "Packed Browser"
+ bl_options = {'INTERNAL'}
+
+ files = CollectionProperty(type=PackedFile)
+ selected_index = IntProperty(default=0)
+
+ def invoke(self, context, event):
+ scrapland_path=scrap_bridge("find-scrapland")
+ print(scrapland_path)
+ packed_data=scrap_bridge("parse-packed",scrapland_path)
+ print(packed_data)
+ self.packed_data=packed_data
+ return context.window_manager.invoke_props_dialog(self)
+
+ def draw(self, context):
+ if self.selected_index != -1:
+ print("new selected_index: " + str(self.selected_index))
+ self.files.clear()
+ for packed_name,files in self.archive:
+ for file in files:
+ entry = self.files.add()
+ entry.packed_file = packed_name
+ [entry.path,entry.offset,entry.size]=file
+ self.selected_index = -1
+ self.layout.template_list("PackedDirList", "", self, "current_dir", self, "selected_index")
+
+ def execute(self, context):
+ print("execute")
+ return {'FINISHED'}
+
+
+class PackedDirList(bpy.types.UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
+ operator = data
+ packed_entry = item
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.prop(packed_entry, "name", text="", emboss=False, icon_value=icon)
+ layout.prop(packed_entry, "selected")
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+def menu_func_import(self, context):
+ self.layout.operator(ImportFilearchives.bl_idname, text="Scrapland .packed")
+
+classes=[
+ PackedFile,
+ PackedDirList,
+ PackedBrowser,
+ ImportFilearchives,
+]
+
+def register():
+ for cls in classes:
+ bpy.utils.regiser_class(cls)
+ bpy.types.INFO_MT_file_import.append(menu_func_import)
+
+
+def unregister():
+ for cls in reversed(classes):
+ bpy.utils.unregister_class(cls)
+ bpy.types.INFO_MT_file_import.remove(menu_func_import)
+
+
+if __name__ == "__main__":
+ import imp
+ imp.reload(sys.modules[__name__])
+ for cls in classes:
+ bpy.utils.regiser_class(cls)
+
diff --git a/tools/remaster/scrap_parse/get_vertex_size.cpp b/tools/remaster/scrap_parse/get_vertex_size.cpp
new file mode 100644
index 0000000..783eec4
--- /dev/null
+++ b/tools/remaster/scrap_parse/get_vertex_size.cpp
@@ -0,0 +1,66 @@
+
+int _D3DXGetFVFVertexSize(uint fvf)
+
+{
+ uint uVar1;
+ uint uVar2;
+ uint uVar3;
+ int vert_size;
+
+ uVar1 = fvf & 0xe;
+ vert_size = 0;
+ if (uVar1 == 2) {
+ vert_size = 0xc;
+ }
+ else if ((uVar1 == 4) || (uVar1 == 6)) {
+ vert_size = 0x10;
+ }
+ else if (uVar1 == 8) {
+ vert_size = 0x14;
+ }
+ else if (uVar1 == 0xa) {
+ vert_size = 0x18;
+ }
+ else if (uVar1 == 0xc) {
+ vert_size = 0x1c;
+ }
+ else if (uVar1 == 0xe) {
+ vert_size = 0x20;
+ }
+ if ((fvf & 0x10) != 0) {
+ vert_size += 0xc;
+ }
+ if ((fvf & 0x20) != 0) {
+ vert_size += 4;
+ }
+ if ((fvf & 0x40) != 0) {
+ vert_size += 4;
+ }
+ if (fvf < '\0') {
+ vert_size += 4;
+ }
+ uVar1 = fvf >> 8 & 0xf;
+ uVar3 = fvf >> 16;
+ if (uVar3 == 0) {
+ vert_size += uVar1 * 8;
+ }
+ else {
+ for (; uVar1 != 0; uVar1 -= 1) {
+ uVar2 = uVar3 & 3;
+ if (uVar2 == 0) {
+ vert_size += 8;
+ }
+ else if (uVar2 == 1) {
+ vert_size += 0xc;
+ }
+ else if (uVar2 == 2) {
+ vert_size += 0x10;
+ }
+ else if (uVar2 == 3) {
+ vert_size += 4;
+ }
+ uVar3 >>= 2;
+ }
+ }
+ return vert_size;
+}
\ No newline at end of file
diff --git a/tools/remaster/scrap_parse/packed_loader.py b/tools/remaster/scrap_parse/packed_loader.py
deleted file mode 100644
index ffa6b34..0000000
--- a/tools/remaster/scrap_parse/packed_loader.py
+++ /dev/null
@@ -1,103 +0,0 @@
-bl_info = {
- "name": "Riot Archive File (RAF)",
- "blender": (2, 71, 0),
- "location": "File > Import",
- "description": "Import LoL data of an Riot Archive File",
- "category": "Import-Export"}
-
-
-import bpy
-from io_scene_lolraf import raf_utils
-from bpy.props import (StringProperty, BoolProperty, CollectionProperty,
- IntProperty)
-
-
-class ImportFilearchives(bpy.types.Operator):
- """Import whole filearchives directory."""
- bl_idname = "import_scene.rafs"
- bl_label = 'Import LoL filearchives'
-
- directory = StringProperty(name="'filearchives' folder",
- subtype="DIR_PATH", options={'HIDDEN'})
- filter_folder = BoolProperty(default=True, options={'HIDDEN'})
- filter_glob = StringProperty(default="", options={'HIDDEN'})
-
- def invoke(self, context, event):
- context.window_manager.fileselect_add(self)
- return {'RUNNING_MODAL'}
-
- def execute(self, context):
- # TODO: Validate filepath
- bpy.ops.ui.raf_browser('INVOKE_DEFAULT',filepath=self.directory)
- return {'FINISHED'}
-
-
-class RAFEntry(bpy.types.PropertyGroup):
- name = bpy.props.StringProperty()
- selected = bpy.props.BoolProperty(name="")
-
-
-archive = None
-class RAFBrowser(bpy.types.Operator):
- bl_idname = "ui.raf_browser"
- bl_label = "RAF-browser"
- bl_options = {'INTERNAL'}
-
- filepath = StringProperty()
- current_dir = CollectionProperty(type=RAFEntry)
- selected_index = IntProperty(default=0)
-
- def invoke(self, context, event):
- global archive
- archive = raf_utils.RAFArchive(self.filepath)
- return context.window_manager.invoke_props_dialog(self)
-
- def draw(self, context):
- if self.selected_index != -1:
- print("new selected_index: " + str(self.selected_index))
- global archive
- # TODO: change current directory of archive
- self.current_dir.clear()
- for dir in archive.current_dir():
- entry = self.current_dir.add()
- entry.name = dir
- self.selected_index = -1
- self.layout.template_list("RAFDirList", "", self, "current_dir", self, "selected_index")
-
- def execute(self, context):
- print("execute")
- return {'FINISHED'}
-
-
-class RAFDirList(bpy.types.UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
- operator = data
- raf_entry = item
-
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.prop(raf_entry, "name", text="", emboss=False, icon_value=icon)
- layout.prop(raf_entry, "selected")
- elif self.layout_type in {'GRID'}:
- layout.alignment = 'CENTER'
- layout.label(text="", icon_value=icon)
-
-
-def menu_func_import(self, context):
- self.layout.operator(ImportFilearchives.bl_idname, text="LoL Filearchives")
-
-
-def register():
- bpy.utils.register_module(__name__)
- bpy.types.INFO_MT_file_import.append(menu_func_import)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.INFO_MT_file_import.remove(menu_func_import)
-
-
-if __name__ == "__main__":
- import imp
- imp.reload(raf_utils)
- bpy.utils.register_module(__name__)
-
diff --git a/tools/remaster/scrap_parse/src/find_scrap.rs b/tools/remaster/scrap_parse/src/find_scrap.rs
new file mode 100644
index 0000000..4c69b3f
--- /dev/null
+++ b/tools/remaster/scrap_parse/src/find_scrap.rs
@@ -0,0 +1,15 @@
+use std::path::PathBuf;
+
+use steamlocate::SteamDir;
+use anyhow::{bail,Result};
+const APP_ID: u32 = 897610;
+
+pub(crate) fn get_executable() -> Result {
+ let Some(mut steam) = SteamDir::locate() else {
+ bail!("Failed to find steam folder");
+ };
+ let Some(app) = steam.app(&APP_ID) else {
+ bail!("App {APP_ID} is not installed!");
+ };
+ Ok(app.path.clone())
+}
\ No newline at end of file
diff --git a/tools/remaster/scrap_parse/src/main.rs b/tools/remaster/scrap_parse/src/main.rs
index 8d41f58..1dfaca3 100644
--- a/tools/remaster/scrap_parse/src/main.rs
+++ b/tools/remaster/scrap_parse/src/main.rs
@@ -5,6 +5,7 @@ use binrw::prelude::*;
use binrw::until_exclusive;
use chrono::{DateTime, NaiveDateTime, Utc};
use clap::Parser;
+use clap::Subcommand;
use configparser::ini::Ini;
use flate2::write::GzEncoder;
use flate2::Compression;
@@ -15,14 +16,37 @@ use modular_bitfield::specifiers::B2;
use modular_bitfield::specifiers::B4;
use modular_bitfield::BitfieldSpecifier;
use serde::Serialize;
-use serde_json::Map;
-use serde_json::Value;
use std::collections::HashMap;
use std::fmt::Debug;
use std::fs::File;
-use std::io::{BufReader, Read, Seek};
+use std::io::{BufReader, Cursor, Read, Seek};
use std::path::Path;
use std::path::PathBuf;
+use walkdir::WalkDir;
+
+mod find_scrap;
+
+type IniData = IndexMap>>;
+
+#[binread]
+#[derive(Serialize, Debug)]
+struct PackedFile{
+ path: PascalString,
+ size: u32,
+ offset: u32
+}
+
+#[binread]
+#[br(magic = b"BFPK")]
+#[derive(Serialize, Debug)]
+struct PackedHeader {
+ #[br(temp,assert(version==0))]
+ version: u32,
+ #[br(temp)]
+ num_files: u32,
+ #[br(count=num_files)]
+ files: Vec,
+}
#[binread]
#[derive(Serialize, Debug)]
@@ -141,6 +165,7 @@ struct IniSection {
#[br(magic = b"INI\0")]
#[derive(Debug)]
struct INI {
+ #[br(temp)]
size: u32,
#[br(temp)]
num_sections: u32,
@@ -153,13 +178,17 @@ impl Serialize for INI {
where
S: serde::Serializer,
{
+ use serde::ser::Error;
let blocks: Vec = self
.sections
.iter()
.flat_map(|s| s.sections.iter())
.map(|s| s.string.clone())
.collect();
- Ini::new().read(blocks.join("\n")).serialize(serializer)
+ Ini::new()
+ .read(blocks.join("\n"))
+ .map_err(Error::custom)?
+ .serialize(serializer)
}
}
@@ -227,7 +256,7 @@ enum Pos {
#[repr(u32)]
#[derive(Debug, Serialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FVF {
- reserved_1: bool,
+ reserved: bool,
pos: Pos,
normal: bool,
point_size: bool,
@@ -267,17 +296,17 @@ impl FVF {
}
}
- fn num_w(&self) -> usize {
- use Pos::*;
- match self.pos() {
- XYZ | XYZRHW => 0,
- XYZB1 => 1,
- XYZB2 => 2,
- XYZB3 => 3,
- XYZB4 => 4,
- XYZB5 => 5,
- }
- }
+ // fn num_w(&self) -> usize {
+ // use Pos::*;
+ // match self.pos() {
+ // XYZ | XYZRHW => 0,
+ // XYZB1 => 1,
+ // XYZB2 => 2,
+ // XYZB3 => 3,
+ // XYZB4 => 4,
+ // XYZB5 => 5,
+ // }
+ // }
}
fn vertex_size_from_id(fmt_id: u32) -> Result {
@@ -361,6 +390,7 @@ struct MD3D {
tris: Vec<[u16; 3]>,
mesh_data: LFVF,
unk_table_1: RawTable<2>,
+ rest: Unparsed<0x100>
// TODO:
// ==
// unk_t1_count: u32,
@@ -383,7 +413,7 @@ enum NodeData {
#[br(magic = 0x0u32)]
Null,
#[br(magic = 0xa1_00_00_01_u32)]
- TriangleMesh, // Empty?
+ TriangleMesh(Unparsed<0x10>), // TODO: Empty or unused?
#[br(magic = 0xa1_00_00_02_u32)]
Mesh(MD3D),
#[br(magic = 0xa2_00_00_04_u32)]
@@ -393,7 +423,7 @@ enum NodeData {
#[br(magic = 0xa4_00_00_10_u32)]
Ground(SUEL),
#[br(magic = 0xa5_00_00_20_u32)]
- SisPart(Unparsed<0x10>), // TODO: Particles
+ SistPart(Unparsed<0x10>), // TODO: Particles
#[br(magic = 0xa6_00_00_40_u32)]
Graphic3D(SPR3),
#[br(magic = 0xa6_00_00_80_u32)]
@@ -521,6 +551,16 @@ struct MAP {
unk_3: Option<[u8; 0xc]>,
}
+#[binread]
+#[derive(Debug, Serialize)]
+struct Textures {
+ base: Optional,
+ metallic: Optional,
+ unk_1: Optional,
+ bump: Optional,
+ glow: Optional
+}
+
#[binread]
#[br(magic = b"MAT\0")]
#[derive(Debug, Serialize)]
@@ -532,7 +572,7 @@ struct MAT {
name: Option,
unk_f: [RGBA; 7],
unk_data: [RGBA; 0x18 / 4],
- maps: [Optional; 5], // Base Color, Metallic?, ???, Normal, Emission
+ maps: Textures
}
#[binread]
@@ -556,9 +596,9 @@ struct SCN {
#[br(temp,assert(unk_3==1))]
unk_3: u32,
num_nodes: u32,
- #[br(count = num_nodes)] // 32
+ #[br(count = 1)] // 32
nodes: Vec,
- ani: Optional, // TODO:?
+ // ani: Optional, // TODO: ?
}
fn convert_timestamp(dt: u32) -> Result> {
@@ -682,11 +722,11 @@ struct CM3 {
#[binread]
#[derive(Debug, Serialize)]
struct Dummy {
+ has_next: u32,
name: PascalString,
pos: [f32; 3],
rot: [f32; 3],
info: Optional,
- has_next: u32,
}
#[binread]
@@ -697,7 +737,6 @@ struct DUM {
#[br(assert(version==1, "Invalid DUM version"))]
version: u32,
num_dummies: u32,
- unk_1: u32,
#[br(count=num_dummies)]
dummies: Vec,
}
@@ -826,13 +865,6 @@ enum Data {
EMI(EMI),
}
-#[derive(Parser, Debug)]
-#[command(author, version, about, long_about = None)]
-struct Args {
- root: PathBuf,
- path: PathBuf,
-}
-
fn parse_file(path: &PathBuf) -> Result {
let mut rest_size = 0;
let mut fh = BufReader::new(fs::File::open(path)?);
@@ -842,11 +874,11 @@ fn parse_file(path: &PathBuf) -> Result {
.unwrap_or(0)
.try_into()
.unwrap_or(u32::MAX);
- println!("Read {} bytes from {}", pos, path.display());
+ eprintln!("Read {} bytes from {}", pos, path.display());
let mut buffer = [0u8; 0x1000];
if let Ok(n) = fh.read(&mut buffer) {
if n != 0 {
- println!("Rest:\n{}", rhexdump::hexdump_offset(&buffer[..n], pos));
+ eprintln!("Rest:\n{}", rhexdump::hexdump_offset(&buffer[..n], pos));
}
};
while let Ok(n) = fh.read(&mut buffer) {
@@ -855,52 +887,182 @@ fn parse_file(path: &PathBuf) -> Result {
}
rest_size += n;
}
- println!("+{rest_size} unparsed bytes");
+ eprintln!("+{rest_size} unparsed bytes");
Ok(ret)
}
-fn load_ini(path: &PathBuf) -> IndexMap>> {
+fn load_ini(path: &PathBuf) -> IniData {
Ini::new().load(path).unwrap_or_default()
}
-fn load_data(root: &Path, path: &Path) -> Result {
- let full_path = &root.join(path);
- let emi_path = full_path.join("map").join("map3d.emi");
- let sm3_path = emi_path.with_extension("sm3");
- let dum_path = emi_path.with_extension("dum");
- let config_file = emi_path.with_extension("ini");
- let moredummies = emi_path.with_file_name("moredummies").with_extension("ini");
- let mut data = serde_json::to_value(HashMap::<(), ()>::default())?;
- data["config"] = serde_json::to_value(load_ini(&config_file))?;
- data["moredummies"] = serde_json::to_value(load_ini(&moredummies))?;
- data["emi"] = serde_json::to_value(parse_file(&emi_path)?)?;
- data["sm3"] = serde_json::to_value(parse_file(&sm3_path)?)?;
- data["dummies"] = serde_json::to_value(parse_file(&dum_path)?)?;
- data["path"] = serde_json::to_value(path)?;
- data["root"] = serde_json::to_value(root)?;
- Ok(data)
+#[derive(Serialize, Debug)]
+
+struct Level {
+ config: IniData,
+ moredummies: IniData,
+ emi: EMI,
+ sm3: SM3,
+ dummies: DUM,
+ path: PathBuf,
+ root: PathBuf,
}
-fn main() -> Result<()> {
- let args = Args::try_parse()?;
+impl Level {
+ fn load(root: &Path, path: &Path) -> Result {
+ let full_path = &root.join(path);
+ let emi_path = full_path.join("map").join("map3d.emi");
+ let sm3_path = emi_path.with_extension("sm3");
+ let dum_path = emi_path.with_extension("dum");
+ let config_file = emi_path.with_extension("ini");
+ let moredummies = emi_path.with_file_name("moredummies").with_extension("ini");
+ let config = load_ini(&config_file);
+ let moredummies = load_ini(&moredummies);
+ let Data::EMI(emi) = parse_file(&emi_path)? else {
+ bail!("Failed to parse EMI at {emi_path}", emi_path=emi_path.display());
+ };
+ let Data::SM3(sm3) = parse_file(&sm3_path)? else {
+ bail!("Failed to parse SM3 at {sm3_path}", sm3_path=sm3_path.display());
+ };
+ let Data::DUM(dummies) = parse_file(&dum_path)? else {
+ bail!("Failed to parse DUM at {dum_path}", dum_path=dum_path.display());
+ };
+ Ok(Level {
+ config,
+ moredummies,
+ emi,
+ sm3,
+ dummies,
+ path: path.into(),
+ root: root.into(),
+ })
+ }
+}
+
+#[derive(Subcommand, Debug)]
+enum Commands {
+ FindScrapland,
+ ParsePacked {
+ scrap_path: PathBuf,
+ },
+ ParseFile {
+ #[clap(long)]
+ /// Write to stdout
+ stdout: bool,
+ /// Scrapland root path
+ root: PathBuf,
+ /// Level to parse and convert
+ level: PathBuf,
+ },
+}
+
+#[derive(Parser, Debug)]
+#[command(author, version, about, long_about = None)]
+#[command(propagate_version = true)]
+struct Args {
+ #[arg(long,short)]
+ /// Write data as JSON
+ json: bool,
+ #[command(subcommand)]
+ command: Commands,
+}
+
+fn cmd_parse_packed(root: &Path) -> Result>> {
+ let mut packed_map = HashMap::new();
+ for entry in WalkDir::new(root).into_iter().filter_map(|e| e.ok()) {
+ let path = entry.path();
+ if path
+ .extension()
+ .map(|e| e.to_str() == Some("packed"))
+ .unwrap_or(false)
+ {
+ let path = entry.path().to_owned();
+ let header: PackedHeader = BufReader::new(File::open(&path)?).read_le()?;
+ packed_map.insert(path, header.files);
+ }
+ }
+ Ok(packed_map)
+}
+
+fn to_bytes(data: &T, json: bool) -> Result> where T: Serialize {
+ if json {
+ Ok(serde_json::to_vec_pretty(data)?)
+ } else {
+ Ok(serde_pickle::to_vec(data,Default::default())?)
+ }
+}
+
+fn cmd_parse_file(stdout: bool, root: &Path, path: &Path, json: bool) -> Result<()> {
let out_path = PathBuf::from(
- args.path
+ path
.components()
.last()
.unwrap()
.as_os_str()
.to_string_lossy()
.into_owned(),
- )
- .with_extension("json.gz");
- let full_path = &args.root.join(&args.path);
- let data = if full_path.is_dir() {
- load_data(&args.root, &args.path)?
+ );
+ let out_path = if json {
+ out_path.with_extension("json.gz")
} else {
- serde_json::to_value(parse_file(full_path)?)?
+ out_path.with_extension("pkl.gz")
+ };
+ let full_path = &root.join(path);
+ let data = if full_path.is_dir() {
+ let level = Level::load(root, path)?;
+ to_bytes(&level,json)?
+ } else {
+ let data = parse_file(full_path)?;
+ to_bytes(&data,json)?
+ };
+ let mut data = Cursor::new(data);
+ if stdout {
+ let mut stdout = std::io::stdout().lock();
+ std::io::copy(&mut data, &mut stdout)?;
+ } else {
+ let mut fh = GzEncoder::new(File::create(&out_path)?, Compression::best());
+ std::io::copy(&mut data, &mut fh)?;
+ eprintln!("Wrote {path}", path = out_path.display());
};
- let mut dumpfile = GzEncoder::new(File::create(&out_path)?, Compression::best());
- serde_json::to_writer_pretty(&mut dumpfile, &data)?;
- println!("Wrote {path}", path = out_path.display());
+ Ok(())
+}
+
+fn emi_to_obj(emi: EMI) -> ! {
+ // let mut obj_data = obj::ObjData::default();
+
+ // for mesh in emi.tri {
+ // for vert in mesh.data.verts_1.inner.map(|d| d.data).unwrap_or_default() {
+ // obj_data.position.push(vert.xyz);
+ // obj_data.normal.push(vert.normal.unwrap_or_default());
+ // obj_data.texture.push(vert.tex_1.unwrap_or_default().0.try_into().unwrap());
+ // }
+ // for vert in mesh.data.verts_2.inner.map(|d| d.data).unwrap_or_default() {
+ // obj_data.position.push(vert.xyz);
+ // obj_data.normal.push(vert.normal.unwrap_or_default());
+ // }
+ // }
+ todo!("EMI to OBJ converter");
+}
+
+fn main() -> Result<()> {
+ let args = Args::try_parse()?;
+ match args.command {
+ Commands::FindScrapland => {
+ let data = to_bytes(&find_scrap::get_executable()?,args.json)?;
+ let mut stdout = std::io::stdout().lock();
+ std::io::copy(&mut &data[..], &mut stdout)?;
+ }
+ Commands::ParsePacked { scrap_path } => {
+ let data = to_bytes(&cmd_parse_packed(&scrap_path)?,args.json)?;
+ let mut stdout = std::io::stdout().lock();
+ std::io::copy(&mut &data[..], &mut stdout)?;
+ }
+ Commands::ParseFile {
+ stdout,
+ root,
+ level,
+ } => {
+ cmd_parse_file(stdout, &root, &level, args.json)?;
+ }
+ }
Ok(())
}
diff --git a/tools/remaster/scrap_parse/src/pixel_shader.rs b/tools/remaster/scrap_parse/src/pixel_shader.rs
index 7bc87a3..1430524 100644
--- a/tools/remaster/scrap_parse/src/pixel_shader.rs
+++ b/tools/remaster/scrap_parse/src/pixel_shader.rs
@@ -1,3 +1,7 @@
+// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx9-graphics-reference-asm-ps-1-x
+//
+// ################################################
+//
// #[derive(Debug)]
// enum VecArg {
// Tex(f32,f32,f32,f32),