init
This commit is contained in:
parent
f070359a42
commit
b7f49d099d
18 changed files with 393 additions and 109 deletions
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 sup39
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
11
README.md
Normal file
11
README.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# botw-lang-cmp
|
||||
A tool to compare cutscene times among languages in Breath of the Wild
|
||||
|
||||
## CREADITS
|
||||
[Time data](https://github.com/sup39/botw-lang-cmp/src/db.json) is based on [Cephla's document](https://docs.google.com/document/d/1H0gqxqR2AZqc-MEDUoftJHn_FteyBBm_Zcowieev5ek/edit?usp=sharing), which is based on [Swiffy22's video](https://youtu.be/yVaZdsgjWz8).
|
||||
|
||||
## TODO
|
||||
- [ ] Rename cutscenes
|
||||
- [ ] Add more presets
|
||||
- [ ] Complete Japanese translation
|
||||
- [ ] Memorize settings with localStorage
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"name": "nya",
|
||||
"name": "botw-lang-cmp",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"author": "sup39 <dev@sup39.dev>",
|
||||
"repository": "https://github.com/sup39/botw-lang-cmp",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sup39/eslint-config-typescript": "^0.1.2",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
|
@ -14,6 +16,7 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"sass": "^1.56.0",
|
||||
"typescript": "^4.4.2",
|
||||
"web-vitals": "^2.1.0"
|
||||
},
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<meta name="theme-color" content="#2ee5b8" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
content="A tool to compare cutscene times among languages in Breath of the Wild"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
|
@ -24,7 +24,7 @@
|
|||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>BotW Language Comparison</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
|
38
src/App.css
38
src/App.css
|
@ -1,38 +0,0 @@
|
|||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
6
src/App.module.sass
Normal file
6
src/App.module.sass
Normal file
|
@ -0,0 +1,6 @@
|
|||
.SettingsRoot
|
||||
> div
|
||||
display: flex
|
||||
margin-bottom: 0.5em
|
||||
span
|
||||
margin-right: 0.25em
|
|
@ -1,9 +0,0 @@
|
|||
import React from 'react';
|
||||
import {render, screen} from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
170
src/App.tsx
170
src/App.tsx
|
@ -1,26 +1,156 @@
|
|||
import React from 'react';
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import db from './db.json';
|
||||
import {i18nLabels, defaultLang, $lang0, setLang} from './i18n';
|
||||
import {events, i18nEventNames, presets} from './events';
|
||||
import styles from './App.module.sass';
|
||||
|
||||
const langs = [
|
||||
'English',
|
||||
'French (Canada)',
|
||||
'French (France)',
|
||||
'German',
|
||||
'Italian',
|
||||
'Japanese',
|
||||
'Russian',
|
||||
'Spanish (Latin)',
|
||||
'Spanish (Spain)',
|
||||
] as const;
|
||||
const dbEntries = Object.entries(db);
|
||||
|
||||
const f2f = (f: number) => {
|
||||
let sign = '';
|
||||
if (f < 0) {
|
||||
sign = '-';
|
||||
f = -f;
|
||||
}
|
||||
const sf = String(f%30)+'f';
|
||||
const s = f/30|0;
|
||||
if (s === 0) return sign+sf;
|
||||
const ssf = `${s%30}:${sf.padStart(3, '0')}`;
|
||||
const m = s/60|0;
|
||||
if (m === 0) return sign+ssf;
|
||||
return `${sign}${m}:${ssf.padStart(6, '0')}`;
|
||||
};
|
||||
const f2s = (f: number) => {
|
||||
let sign = '';
|
||||
if (f < 0) {
|
||||
sign = '-';
|
||||
f = -f;
|
||||
}
|
||||
const s = f/30;
|
||||
const m = s/60|0;
|
||||
const ss = (s-m*60).toFixed(3);
|
||||
return sign+(m ? `${m}:${ss.padStart(6, '0')}` : ss);
|
||||
};
|
||||
|
||||
export const RadioGroup = ({name, value: val, values, onChange, ...props}: {
|
||||
values: (string | [value: string, label: string])[]
|
||||
} & React.ComponentProps<'input'>) => <>{values.map(o => {
|
||||
const [value, label] = typeof o === 'string' ? [o, o] : o;
|
||||
return <div key={value} {...props}>
|
||||
<input type='radio' name={name} value={value} checked={val===value}
|
||||
onChange={onChange} />
|
||||
<span>{label}</span>
|
||||
</div>;
|
||||
})}</>;
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/App.tsx</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
</header>
|
||||
</div>
|
||||
const [selected, setSelected] = useState(
|
||||
Object.fromEntries(events.map(l => [l, false])),
|
||||
);
|
||||
const [timeFormat, setTimeFormat] = useState('s');
|
||||
const f2t = timeFormat === 'f' ? f2f : f2s;
|
||||
|
||||
const [$lang, set$lang] = useState($lang0);
|
||||
useEffect(() => setLang($lang), [$lang]);
|
||||
|
||||
const eventNames = i18nEventNames[
|
||||
($lang in i18nEventNames) ? $lang : defaultLang
|
||||
];
|
||||
const L = (id: keyof typeof i18nLabels) =>
|
||||
i18nLabels[id][$lang] ?? i18nLabels[id][defaultLang];
|
||||
|
||||
const selectedTimes = dbEntries.filter(([event]) => selected[event]);
|
||||
const l2tEntries = langs.map(
|
||||
lang => [lang, selectedTimes.reduce(
|
||||
(sum, [_event, times]) => sum+times[lang],
|
||||
0,
|
||||
)] as const,
|
||||
).sort(([_a, tA], [_b, tB]) => tA-tB);
|
||||
const tMin = Math.min(...l2tEntries.map(([_, t]) => t));
|
||||
|
||||
return <div>
|
||||
<details>
|
||||
<summary>CREADITS</summary>
|
||||
<div>
|
||||
<p>This tool is made by sup39 with MIT license. The source code can be found <a href='https://github.com/sup39/botw-lang-cmp'>here</a>.</p>
|
||||
<p><a href='https://github.com/sup39/botw-lang-cmp/src/db.json'>Time data</a> is based on <a href='https://docs.google.com/document/d/1H0gqxqR2AZqc-MEDUoftJHn_FteyBBm_Zcowieev5ek/edit?usp=sharing'>Cephla's document</a>, which is based on <a href='https://youtu.be/yVaZdsgjWz8'>Swiffy22's video</a>.</p>
|
||||
</div>
|
||||
</details>
|
||||
<h2>Time Comparison</h2>
|
||||
<section>
|
||||
<table className="time">
|
||||
<thead><tr>
|
||||
<th>Language</th>
|
||||
<th>Time</th>
|
||||
<th>Diff</th>
|
||||
</tr></thead>
|
||||
<tbody>{l2tEntries.map(([lang, t]) => <tr key={lang}>
|
||||
<td>{lang}</td>
|
||||
<td>{f2t(t)}</td>
|
||||
<td>{(t>tMin?'+':'±')+f2t(t-tMin)}</td>
|
||||
</tr>)}</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Settings</h3>
|
||||
<div className={styles.SettingsRoot}>
|
||||
<div>
|
||||
<span>{L('displayLang')}</span>
|
||||
<select value={$lang} onChange={e=>set$lang(e.target.value)}>
|
||||
<option value='en-US'>English</option>
|
||||
<option value='ja-JP'>日本語</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<span>{L('timeFormat')}</span>
|
||||
<RadioGroup name='timeFormat' value={timeFormat}
|
||||
values={[['s', 'ms'], 'f']}
|
||||
onChange={e => setTimeFormat(e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Preset</h3>
|
||||
<div>
|
||||
<select
|
||||
defaultValue=''
|
||||
onChange={e => {
|
||||
const sels = presets[e.target.value];
|
||||
if (sels == null) return;
|
||||
setSelected(sels);
|
||||
}}
|
||||
>
|
||||
<option value=''>==== Choose a preset ====</option>
|
||||
{Object.keys(presets).map(
|
||||
name => <option key={name} value={name}>{name}</option>,
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Cutscenes</h3>
|
||||
<div>
|
||||
{events.map(id => <div key={id} className='option-ctn'>
|
||||
<input
|
||||
type='checkbox' checked={selected[id]}
|
||||
onChange={e => setSelected(o => ({...o, [id]: e.target.checked}))}
|
||||
/>
|
||||
<span>{eventNames[id]}</span>
|
||||
</div>)}
|
||||
</div>
|
||||
</section>
|
||||
</div>;
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
1
src/db.json
Normal file
1
src/db.json
Normal file
File diff suppressed because one or more lines are too long
90
src/events.ts
Normal file
90
src/events.ts
Normal file
|
@ -0,0 +1,90 @@
|
|||
import type {I18N} from './i18n';
|
||||
|
||||
type EEvent = (typeof events)[number];
|
||||
export const events = [
|
||||
'Sheikah Slate Get',
|
||||
'Out Of SoR',
|
||||
'Head For The Point On Your SS',
|
||||
'First Divine Beast Introduction',
|
||||
'All Divine Beasts Completion',
|
||||
'Lomei Labyrinth Island Introduction',
|
||||
'South Lomei Labyrinth Introduction',
|
||||
'North Lomei Labyrinth Introduction',
|
||||
'Thyphlo Ruins Introduction',
|
||||
'Eventide Island Introduction',
|
||||
'Eventide Island Completion',
|
||||
'All Shrines Completion',
|
||||
'(EX) Trial Of The Sword Invitation',
|
||||
'(EX) Naboris Re-Entry Introduction',
|
||||
'(EX) Medoh Re-Entry Introduction',
|
||||
'(EX) Ruta Re-Entry Introduction',
|
||||
'(EX) Rudania Re-Entry Introduction',
|
||||
'Impa',
|
||||
'All 13 Memories',
|
||||
"Ta'loh Naeg",
|
||||
'Thundra Plateau Completion',
|
||||
'(EX) Introduction',
|
||||
'(EX) Obtaining The One Hit Obliterator',
|
||||
'(EX) One Hit Obliterator Completion',
|
||||
'(EX) Trial Of The Sword Completion',
|
||||
'(EX) Single Shrine Completion',
|
||||
'(EX) Vah Naboris Kass Song',
|
||||
'(EX) Vah Medoh Kass Song',
|
||||
'(EX) Vah Ruta Kass Song',
|
||||
'(EX) Vah Rudania Kass Song',
|
||||
'(EX) All Champion Songs',
|
||||
'(EX) SoR Revisit Instructions',
|
||||
'(EX) Final Trial Introduction',
|
||||
'(EX) Final Trial Completion',
|
||||
'(EX) Maz Koshia Battle Completion',
|
||||
"(EX) The Champion's Ballad",
|
||||
] as const;
|
||||
|
||||
type TEventNameMap = {[event in EEvent]: string};
|
||||
const eventNameDefault =
|
||||
Object.fromEntries(events.map(e => [e, e])) as TEventNameMap;
|
||||
export const i18nEventNames: I18N<TEventNameMap> = {
|
||||
'en-US': {
|
||||
...eventNameDefault,
|
||||
// 0:10
|
||||
'Sheikah Slate Get': 'Sheikah Slate Get: "That is a Sheikah Slate."',
|
||||
// 0:27
|
||||
'Out Of SoR': 'Out of SoR: "Hold the Sheikah Slate up to the pedstal.""',
|
||||
// 12:05
|
||||
'Head For The Point On Your SS': '"Head for the point marked on the map in your Sheikah Slate."',
|
||||
// 1:06
|
||||
'First Divine Beast Introduction': 'First Divine Beast Introduction: "That Divine Beast was taken over by Ganon 100 years ago"',
|
||||
// 1:46
|
||||
'All Divine Beasts Completion': 'All Divine Beasts Completion: "Thanks to you, all of the Divine Beasts have returned to us and the spirits of the Champions are free."',
|
||||
},
|
||||
'ja-JP': {
|
||||
...eventNameDefault,
|
||||
'Sheikah Slate Get': 'シーカーストーン入手「それはシーカーストーン…」',
|
||||
'Out Of SoR': '回生の祠を出る直前「シーカーストーンをかざすのです…」',
|
||||
'Head For The Point On Your SS': '「シーカーストーンのマップに示された場所へ向かうのです…」',
|
||||
'First Divine Beast Introduction': '最初の神獣イントロ「あれが今から100年前ガノンに奪われてしまった神獣です…」',
|
||||
'All Divine Beasts Completion': '四神獣クリア直後「ありがとう…貴方のおかげで全ての神獣と英傑達の魂が解放されました」',
|
||||
},
|
||||
};
|
||||
|
||||
type Preset = {[event in (typeof events)[number]]?: boolean};
|
||||
// type Preset = (typeof events)[number][];
|
||||
export const presets: {[name: string]: Preset} = Object.fromEntries([
|
||||
['Any%', [
|
||||
'Sheikah Slate Get',
|
||||
'Head For The Point On Your SS',
|
||||
]],
|
||||
['All Dungeons', [
|
||||
'Sheikah Slate Get',
|
||||
'Head For The Point On Your SS',
|
||||
'First Divine Beast Introduction',
|
||||
'All Divine Beasts Completion',
|
||||
]],
|
||||
['Dog%', [
|
||||
'Sheikah Slate Get',
|
||||
'Head For The Point On Your SS',
|
||||
'First Divine Beast Introduction',
|
||||
]],
|
||||
].map(([k, sels]) => [k, Object.fromEntries(events.map(event => [
|
||||
event, sels.includes(event),
|
||||
]))]));
|
25
src/i18n.ts
Normal file
25
src/i18n.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
export const defaultLang = 'en-US';
|
||||
|
||||
export const lskey$lang = '$lang';
|
||||
export const $lang0 = localStorage.getItem(lskey$lang) ?? defaultLang;
|
||||
export function setLang($lang: string) {
|
||||
localStorage.setItem(lskey$lang, $lang);
|
||||
document.documentElement.lang = $lang;
|
||||
}
|
||||
|
||||
// assert label of defaultLang is specified
|
||||
export type I18N<T> =
|
||||
{[lang: string]: T} & {[lang in typeof defaultLang]: T};
|
||||
|
||||
const _i18nLabels = {
|
||||
'displayLang': {
|
||||
'en-US': 'Display Language',
|
||||
'ja-JP': '表示言語',
|
||||
},
|
||||
'timeFormat': {
|
||||
'en-US': 'Time Format',
|
||||
'ja-JP': 'タイムフォーマット',
|
||||
},
|
||||
};
|
||||
export const i18nLabels: {[id in keyof typeof _i18nLabels]: I18N<string>}
|
||||
= _i18nLabels;
|
|
@ -1,13 +0,0 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
32
src/index.sass
Normal file
32
src/index.sass
Normal file
|
@ -0,0 +1,32 @@
|
|||
@import './sup39.sass'
|
||||
|
||||
body
|
||||
margin: 1em
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif
|
||||
-webkit-font-smoothing: antialiased
|
||||
-moz-osx-font-smoothing: grayscale
|
||||
background-color: #282c34
|
||||
color: white
|
||||
|
||||
code
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace
|
||||
|
||||
table, th, td
|
||||
border-collapse: collapse
|
||||
border: 1px solid #777
|
||||
th, td
|
||||
padding: 0.25em
|
||||
table.time
|
||||
td:nth-child(2),
|
||||
td:nth-child(3)
|
||||
text-align: right
|
||||
min-width: 4.5em
|
||||
font-variant-numeric: tabular-nums
|
||||
|
||||
section
|
||||
margin-bottom: 1em
|
||||
|
||||
div.option-ctn
|
||||
display: flex
|
||||
align-items: flex-start
|
||||
margin-bottom: 4px
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import './index.sass';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
// import reportWebVitals from './reportWebVitals';
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement,
|
||||
|
@ -16,4 +16,4 @@ root.render(
|
|||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
// reportWebVitals();
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import {ReportHandler} from 'web-vitals';
|
||||
|
||||
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({getCLS, getFID, getFCP, getLCP, getTTFB}) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
|
@ -1,5 +0,0 @@
|
|||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
31
src/sup39.sass
Normal file
31
src/sup39.sass
Normal file
|
@ -0,0 +1,31 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 sup39
|
||||
|
||||
a, .link
|
||||
color: #72E5DB
|
||||
text-decoration: none
|
||||
cursor: pointer
|
||||
a:hover, .link:hover
|
||||
color: #72E5DB
|
||||
text-decoration: underline
|
||||
a:active, .link:active
|
||||
color: #A0E5DF
|
||||
text-decoration: underline
|
||||
|
||||
details
|
||||
border: 1px solid
|
||||
padding: 0.5em 1em
|
||||
margin-block-start: 0.5em
|
||||
margin-block-end: 0.5em
|
||||
> summary
|
||||
padding: 4px 0.5em
|
||||
margin: -0.5em -1em -0.5em
|
||||
cursor: pointer
|
||||
details[open]
|
||||
padding-bottom: 0
|
||||
> summary
|
||||
border-bottom: 1px solid
|
||||
margin: -0.5em -1em 0
|
||||
> ul, > ol
|
||||
padding-inline-start: 1.5em
|
||||
|
18
yarn.lock
18
yarn.lock
|
@ -3078,7 +3078,7 @@ check-types@^11.1.1:
|
|||
resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f"
|
||||
integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==
|
||||
|
||||
chokidar@^3.4.2, chokidar@^3.5.3:
|
||||
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.2, chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
|
@ -4975,6 +4975,11 @@ immer@^9.0.7:
|
|||
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.16.tgz#8e7caab80118c2b54b37ad43e05758cdefad0198"
|
||||
integrity sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==
|
||||
|
||||
immutable@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
|
||||
integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==
|
||||
|
||||
import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
|
@ -7832,6 +7837,15 @@ sass-loader@^12.3.0:
|
|||
klona "^2.0.4"
|
||||
neo-async "^2.6.2"
|
||||
|
||||
sass@^1.56.0:
|
||||
version "1.56.0"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.56.0.tgz#134032075a3223c8d49cb5c35e091e5ba1de8e0a"
|
||||
integrity sha512-WFJ9XrpkcnqZcYuLRJh5qiV6ibQOR4AezleeEjTjMsCocYW59dEG19U3fwTTXxzi2Ed3yjPBp727hbbj53pHFw==
|
||||
dependencies:
|
||||
chokidar ">=3.0.0 <4.0.0"
|
||||
immutable "^4.0.0"
|
||||
source-map-js ">=0.6.2 <2.0.0"
|
||||
|
||||
sax@~1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
|
@ -8038,7 +8052,7 @@ source-list-map@^2.0.0, source-list-map@^2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
|
||||
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
||||
|
||||
source-map-js@^1.0.1, source-map-js@^1.0.2:
|
||||
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
|
Loading…
Reference in a new issue