Merge pull request #101 from misenhower/update-packages
Some checks are pending
Build frontend / build (22.x) (push) Waiting to run
Deploy / deploy-frontend (push) Waiting to run
Deploy / deploy-backend (push) Waiting to run
Fix code styles / build (push) Waiting to run

Update packages
This commit is contained in:
Matt Isenhower 2026-02-15 16:38:07 -08:00 committed by GitHub
commit 120f6e4dca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 8046 additions and 7077 deletions

View File

@ -1,69 +0,0 @@
/* eslint-env node */
const createAliasSetting = require('@vue/eslint-config-airbnb/createAliasSetting');
module.exports = {
'root': true,
'plugins': [
'@dword-design/import-alias',
],
'extends': [
'plugin:vue/vue3-recommended',
'eslint:recommended',
'plugin:import/recommended',
'plugin:jsdoc/recommended',
],
'rules': {
// ESLint
'indent': ['warn', 2, { 'SwitchCase': 1 }],
'comma-dangle': ['warn', 'always-multiline'],
'no-unused-vars': ['warn', { 'args': 'none' }],
'semi': 'warn',
'quotes': ['warn' , 'single'],
'object-curly-spacing': ['warn', 'always'],
// Vue
'vue/multi-word-component-names': 'off',
'vue/require-default-prop': 'off',
'vue/max-attributes-per-line': ['warn', { singleline: { max: 4 } }],
'vue/html-self-closing': ['warn', { html: { void: 'always' } }],
// Imports
'import/order': 'warn',
// JSDoc
'jsdoc/require-jsdoc': 'off',
'jsdoc/require-returns': 'off',
'jsdoc/require-param-description': 'off',
},
'globals': {
'__dirname': 'readonly',
'process': 'readonly',
'require': 'readonly',
'module': 'readonly',
'Buffer': 'readonly',
},
'overrides': [
{
'files': ['src/**'],
'rules': {
'@dword-design/import-alias/prefer-alias': ['warn', { 'alias': {
'@': './src',
} }],
},
},
],
'env': {
'vue/setup-compiler-macros': true,
},
'ignorePatterns': [
'src/assets/i18n/index.mjs', // "assert" syntax is currently unrecognized
],
'parserOptions': {
'ecmaVersion': 13,
},
settings: {
...createAliasSetting({
'@': './src',
}),
},
};

View File

@ -13,13 +13,13 @@ jobs:
strategy:
matrix:
node-version: [20.x]
node-version: [22.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

View File

@ -19,7 +19,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'
- name: Install dependencies
run: npm ci

View File

@ -12,10 +12,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'npm'
- run: npm ci
- run: npm run lint-fix

View File

@ -16,7 +16,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'
- name: Install dependencies
run: npm ci

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
22

View File

@ -1,6 +1,6 @@
import fs from 'fs/promises';
import path from 'path';
import mkdirp from 'mkdirp';
import { mkdirp } from './fs.mjs';
export default class ValueCache
{
constructor(key) {

View File

@ -1,5 +1,9 @@
import fs from 'fs/promises';
export function mkdirp(dir) {
return fs.mkdir(dir, { recursive: true });
}
export async function exists(file) {
try {
await fs.access(file);

View File

@ -1,11 +1,9 @@
import fs from 'fs/promises';
import path from 'path';
import mkdirp from 'mkdirp';
// eslint-disable-next-line import/no-unresolved
import PQueue from 'p-queue';
import prefixedConsole from '../common/prefixedConsole.mjs';
import { normalizeSplatnetResourcePath } from '../common/util.mjs';
import { exists } from '../common/fs.mjs';
import { exists, mkdirp } from '../common/fs.mjs';
const queue = new PQueue({ concurrency: 4 });

View File

@ -1,6 +1,6 @@
import fs from 'fs/promises';
import path from 'path';
import mkdirp from 'mkdirp';
import { mkdirp } from '../common/fs.mjs';
import jsonpath from 'jsonpath';
import get from 'lodash/get.js';
import set from 'lodash/set.js';

View File

@ -1,8 +1,7 @@
import fs from 'fs/promises';
import path from 'path';
import { Console } from 'node:console';
import mkdirp from 'mkdirp';
import jsonpath from 'jsonpath';
import { mkdirp } from '../../common/fs.mjs';
import ical from 'ical-generator';
import pFilter from 'p-filter';
import prefixedConsole from '../../common/prefixedConsole.mjs';
@ -11,6 +10,7 @@ import ImageProcessor from '../ImageProcessor.mjs';
import NsoClient from '../../splatnet/NsoClient.mjs';
import { locales, regionalLocales, defaultLocale } from '../../../src/common/i18n.mjs';
import { LocalizationProcessor } from '../LocalizationProcessor.mjs';
import jsonpath from 'jsonpath';
import { deriveId, getDateParts, getTopOfCurrentHour } from '../../common/util.mjs';
export default class DataUpdater
{
@ -241,7 +241,7 @@ export default class DataUpdater
async getiCalData(events, images) {
// Create a calendar object
const calendar = new ical({
const calendar = ical({
name: this.calendarName ?? this.name,
url: process.env.SITE_URL,
prodId: {
@ -257,14 +257,14 @@ export default class DataUpdater
// Add event entries
for (let event of events) {
calendar.createEvent(({
let calEvent = calendar.createEvent({
id: event.id,
summary: event.title,
start: event.start,
end: event.end,
url: event.url,
attachments: [event.imageUrl],
}));
});
calEvent.createAttachment(event.imageUrl);
const filename = images[event.imageUrl];
if (filename) {

View File

@ -1,6 +1,6 @@
import fs from 'fs/promises';
import jsonpath from 'jsonpath';
import pLimit from 'p-limit';
import jsonpath from 'jsonpath';
import { getFestId } from '../../common/util.mjs';
import ValueCache from '../../common/ValueCache.mjs';
import { regionTokens } from '../../splatnet/NsoClient.mjs';

View File

@ -13,7 +13,7 @@ import { sentryInit } from './common/sentry.mjs';
import { sync, syncUpload, syncDownload } from './sync/index.mjs';
consoleStamp(console);
dotenv.config();
dotenv.config({ quiet: true });
sentryInit();
const actions = {

View File

@ -1,5 +1,5 @@
import http from 'http';
import ecstatic from 'ecstatic';
import sirv from 'sirv';
export default class HttpServer
{
@ -16,7 +16,7 @@ export default class HttpServer
return resolve();
}
const handler = ecstatic({ root: './dist' });
const handler = sirv('./dist');
this.#server = http.createServer(handler);
this.#server.on('listening', () => resolve());
this.#server.listen();

View File

@ -1,5 +1,5 @@
import fs from 'fs/promises';
import mkdirp from 'mkdirp';
import { mkdirp } from '../../common/fs.mjs';
import Client from './Client.mjs';
export default class FileWriter extends Client {

View File

@ -1,5 +1,5 @@
import fs from 'fs/promises';
import mkdirp from 'mkdirp';
import { mkdirp } from '../../common/fs.mjs';
import Client from './Client.mjs';
export default class ImageWriter extends Client {

View File

@ -1,4 +1,3 @@
// eslint-disable-next-line import/no-unresolved
import CoralApi from 'nxapi/coral';
import { addUserAgent } from 'nxapi';
import pLimit from 'p-limit';

View File

@ -1,4 +1,4 @@
FROM node:20
FROM node:22
# App setup
WORKDIR /app

63
eslint.config.mjs Normal file
View File

@ -0,0 +1,63 @@
import js from '@eslint/js';
import pluginVue from 'eslint-plugin-vue';
import pluginJsdoc from 'eslint-plugin-jsdoc';
import importAlias from '@dword-design/eslint-plugin-import-alias';
import globals from 'globals';
export default [
js.configs.recommended,
...pluginVue.configs['flat/recommended'],
pluginJsdoc.configs['flat/recommended'],
// Global settings
{
languageOptions: {
ecmaVersion: 2022,
globals: {
...globals.browser,
...globals.node,
},
},
rules: {
// ESLint
'indent': ['warn', 2, { 'SwitchCase': 1 }],
'comma-dangle': ['warn', 'always-multiline'],
'no-unused-vars': ['warn', { 'args': 'none' }],
'semi': 'warn',
'quotes': ['warn', 'single'],
'object-curly-spacing': ['warn', 'always'],
// Vue
'vue/multi-word-component-names': 'off',
'vue/require-default-prop': 'off',
'vue/max-attributes-per-line': ['warn', { singleline: { max: 4 } }],
'vue/html-self-closing': ['warn', { html: { void: 'always' } }],
// JSDoc
'jsdoc/require-jsdoc': 'off',
'jsdoc/require-returns': 'off',
'jsdoc/require-param-description': 'off',
},
},
// Import alias for src files
{
files: ['src/**'],
plugins: {
'@dword-design/import-alias': importAlias.configs.recommended.plugins['@dword-design/import-alias'],
},
rules: {
'@dword-design/import-alias/prefer-alias': ['warn', { 'alias': {
'@': './src',
} }],
},
},
// Ignored files
{
ignores: [
'dist/**',
'src/assets/i18n/index.mjs',
],
},
];

14595
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
"dev": "vite",
"build": "vite build",
"preview": "vite preview --port 5050",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --ignore-path .gitignore",
"lint": "eslint .",
"lint-fix": "npm run lint -- --fix",
"cron": "node app/index.mjs cron",
"start": "npm run sync:download && npm run splatnet:quick && npm run social && npm run cron",
@ -25,46 +25,46 @@
"sync:download": "node app/index.mjs syncDownload"
},
"dependencies": {
"@atproto/api": "^0.11.2",
"@atproto/api": "^0.18.21",
"@aws-sdk/client-s3": "^3.341.0",
"@headlessui/vue": "^1.7.3",
"@heroicons/vue": "^2.0.12",
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
"@sentry/node": "^7.61.0",
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.2.0",
"@intlify/unplugin-vue-i18n": "^11.0.3",
"@sentry/node": "^10.38.0",
"console-stamp": "^3.0.6",
"cron": "^2.1.0",
"dotenv": "^16.0.2",
"ecstatic": "^4.1.4",
"ical-generator": "^3.6.0",
"jsonpath": "^1.1.1",
"cron": "^4.4.0",
"dotenv": "^17.3.1",
"ical-generator": "^10.0.0",
"jsonpath": "^1.2.1",
"lodash": "^4.17.21",
"masto": "^6.7.0",
"mkdirp": "^1.0.4",
"nxapi": "^1.6.1-next.170",
"masto": "^7.10.1",
"nxapi": "^1.6.1-next.248",
"p-filter": "^4.1.0",
"p-limit": "^6.1.0",
"p-queue": "^8.0.1",
"pinia": "^2.0.22",
"puppeteer-core": "^23.8.0",
"p-limit": "^7.3.0",
"p-queue": "^9.1.0",
"pinia": "^3.0.4",
"puppeteer-core": "^24.37.3",
"s3-sync-client": "^4.3.1",
"sharp": "^0.32.0",
"sharp": "^0.34.5",
"sirv": "^3.0.2",
"threads-api": "^1.4.0",
"twitter-api-v2": "^1.12.7",
"vue": "^3.2.39",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.5"
"twitter-api-v2": "^1.29.0",
"vue": "^3.5.28",
"vue-i18n": "^11.2.8",
"vue-router": "^5.0.2"
},
"devDependencies": {
"@dword-design/eslint-plugin-import-alias": "^5.0.0",
"@vitejs/plugin-vue": "^3.1.0",
"@vue/eslint-config-airbnb": "^8.0.0",
"autoprefixer": "^10.4.12",
"eslint": "^8.23.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsdoc": "^48.2.1",
"eslint-plugin-vue": "^9.5.1",
"postcss": "^8.4.16",
"tailwindcss": "^3.1.8",
"vite": "^3.1.3"
"@dword-design/eslint-plugin-import-alias": "^8.1.3",
"@eslint/js": "^9.39.2",
"@tailwindcss/vite": "^4.1.18",
"@vitejs/plugin-vue": "^6.0.4",
"eslint": "^9.39.2",
"eslint-plugin-jsdoc": "^62.5.5",
"eslint-plugin-vue": "^10.8.0",
"globals": "^17.3.0",
"tailwindcss": "^4.1.18",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vue-eslint-parser": "^10.4.0"
}
}

View File

@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@ -1,8 +1,51 @@
@import url('./fonts.css');
@import url('@/assets/css/fonts.css');
@tailwind base;
@tailwind components;
@tailwind utilities;
@import 'tailwindcss';
@custom-variant mobile (&:is(body.is-mobile *));
@custom-variant ss (&:is(body.for-screenshots *));
@theme {
--color-splatoon-blue: #603bff;
--color-splatoon-purple: #af50ff;
--color-splatoon-yellow: #eaff3d;
--color-splatoon-green: #6af7ce;
--color-splatoon-orange: #ff9750;
--color-splatoon-red: #ff505e;
--color-splatoon-brown: #7f413f;
--color-splatoon-battle-regular: #19d719;
--color-splatoon-battle-ranked: #f54910;
--color-splatoon-battle-xmatch: #0fdb9b;
--color-splatoon-battle-league: #f02d7d;
--color-splatoon-salmonRun: #ff5600;
--color-splatoon-bigRun: #b322ff;
--color-splatoon-eggstraWork: #be8800;
--font-splatoon1: var(--font-family-s1);
--font-splatoon2: var(--font-family-s2);
--drop-shadow-ruleIcon: 1px 1px 0 rgb(0, 0, 0);
}
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
}
body {
@apply text-zinc-100;

View File

@ -1,17 +1,17 @@
import deDE from './de-DE.json' assert { type: 'json' };
import enGB from './en-GB.json' assert { type: 'json' };
import enUS from './en-US.json' assert { type: 'json' };
import esES from './es-ES.json' assert { type: 'json' };
import esMX from './es-MX.json' assert { type: 'json' };
import frCA from './fr-CA.json' assert { type: 'json' };
import frFR from './fr-FR.json' assert { type: 'json' };
import itIT from './it-IT.json' assert { type: 'json' };
import jaJP from './ja-JP.json' assert { type: 'json' };
import koKR from './ko-KR.json' assert { type: 'json' };
import nlNL from './nl-NL.json' assert { type: 'json' };
import ruRU from './ru-RU.json' assert { type: 'json' };
import zhCN from './zh-CN.json' assert { type: 'json' };
import zhTW from './zh-TW.json' assert { type: 'json' };
import deDE from './de-DE.json' with { type: 'json' };
import enGB from './en-GB.json' with { type: 'json' };
import enUS from './en-US.json' with { type: 'json' };
import esES from './es-ES.json' with { type: 'json' };
import esMX from './es-MX.json' with { type: 'json' };
import frCA from './fr-CA.json' with { type: 'json' };
import frFR from './fr-FR.json' with { type: 'json' };
import itIT from './it-IT.json' with { type: 'json' };
import jaJP from './ja-JP.json' with { type: 'json' };
import koKR from './ko-KR.json' with { type: 'json' };
import nlNL from './nl-NL.json' with { type: 'json' };
import ruRU from './ru-RU.json' with { type: 'json' };
import zhCN from './zh-CN.json' with { type: 'json' };
import zhTW from './zh-TW.json' with { type: 'json' };
export default {
'de-DE': deDE,

View File

@ -1,7 +1,7 @@
<template>
<div class="flex justify-center text-xs">
<div class="flex space-x-2 bg-zinc-700 p-1 rounded">
<div class="bg-zinc-500 rounded font-semibold px-1">
<div class="flex space-x-2 bg-zinc-700 p-1 rounded-sm">
<div class="bg-zinc-500 rounded-sm font-semibold px-1">
Time Offset
</div>

View File

@ -10,7 +10,7 @@
leave-from="opacity-100"
leave-to="opacity-0"
>
<div class="fixed inset-0 bg-zinc-900/80 transition-opacity backdrop-blur-sm" />
<div class="fixed inset-0 bg-zinc-900/80 transition-opacity backdrop-blur-xs" />
</TransitionChild>
<div class="fixed inset-0 z-20" :class="noScroll ? 'overflow-hidden' : 'overflow-y-auto'">

View File

@ -19,18 +19,20 @@
</template>
<style scoped>
@reference "@/assets/css/base.css";
.router-link {
@apply text-zinc-300 px-4 py-1 bg-zinc-300 bg-opacity-20 rounded-full;
@apply text-zinc-300 px-4 py-1 bg-zinc-300/20 rounded-full;
}
.router-link:hover {
@apply text-zinc-50 bg-opacity-30;
@apply text-zinc-50 bg-zinc-300/30;
}
.router-link-active {
@apply text-zinc-100 bg-splatoon-blue bg-opacity-100;
@apply text-zinc-100 bg-splatoon-blue;
}
.router-link-active:hover {
@apply text-white bg-opacity-100;
@apply text-white;
}
</style>

View File

@ -6,12 +6,12 @@
<div class="font-splatoon1 lg:text-2xl xl:text-3xl text-shadow">
{{ $t(type.name) }}
</div>
<div v-if="type.badge" class="font-splatoon2 text-xs lg:text-sm xl:text-base bg-splatoon-blue rounded px-1 drop-shadow">
<div v-if="type.badge" class="font-splatoon2 text-xs lg:text-sm xl:text-base bg-splatoon-blue rounded-sm px-1 drop-shadow-sm">
{{ $t(type.badge) }}
</div>
</div>
<div class="bg-zinc-900 bg-opacity-70 backdrop-blur-sm pt-2 pb-6 px-2 mx-1 rounded-lg space-y-2">
<div class="bg-zinc-900/70 backdrop-blur-xs pt-2 pb-6 px-2 mx-1 rounded-lg space-y-2">
<div class="flex items-center justify-between font-splatoon2">
<div class="flex items-center space-x-2 text-sm lg:text-lg">
<template v-if="store.activeSchedule && store.activeSchedule.settings">
@ -24,13 +24,13 @@
</template>
<template v-else>
<div class="w-32 bg-zinc-600 rounded animate-pulse">
<div class="w-32 bg-zinc-600 rounded-sm animate-pulse">
&nbsp;
</div>
</template>
</div>
<div v-if="store.activeSchedule" class="justify-end text-xs lg:text-sm bg-zinc-100 bg-opacity-80 rounded text-black px-2">
<div v-if="store.activeSchedule" class="justify-end text-xs lg:text-sm bg-zinc-100/80 rounded-sm text-black px-2">
{{ $d(store.activeSchedule.startTime, 'time') }}
&ndash;
{{ $d(store.activeSchedule.endTime, 'time') }}
@ -52,7 +52,7 @@
</div>
<div v-if="nextSchedule && nextSchedule.settings" class="mx-2 space-y-2">
<SquidTape class="font-splatoon2 text-sm drop-shadow -rotate-6 -mx-2">
<SquidTape class="font-splatoon2 text-sm drop-shadow-sm -rotate-6 -mx-2">
<div class="px-2">
{{ $t('times.next') }}
</div>
@ -62,8 +62,8 @@
</div>
<div class="text-center pt-2">
<button class="bg-zinc-300 bg-opacity-50 hover:bg-opacity-70 px-2 py-1 rounded-full font-splatoon2 text-shadow" @click="open = true">
<span class="inline-block rotate-[25deg] text-red">&#57445;</span>
<button class="bg-zinc-300/50 hover:bg-zinc-300/70 px-2 py-1 rounded-full font-splatoon2 text-shadow" @click="open = true">
<span class="inline-block rotate-25 text-red">&#57445;</span>
{{ $t('schedule.all-upcoming') }}
</button>
</div>

View File

@ -8,7 +8,7 @@
<div class="font-splatoon1 lg:text-2xl xl:text-3xl text-shadow">
{{ $t(type.name) }}
</div>
<div v-if="type.badge" class="font-splatoon2 text-xs lg:text-sm xl:text-base bg-splatoon-blue rounded px-1 drop-shadow">
<div v-if="type.badge" class="font-splatoon2 text-xs lg:text-sm xl:text-base bg-splatoon-blue rounded-sm px-1 drop-shadow-sm">
{{ $t(type.badge) }}
</div>
</div>
@ -22,7 +22,7 @@
<div class="h-full overflow-y-auto pt-24 pb-8">
<template v-for="{ title, schedules } in sections" :key="title">
<div class="mt-6 mx-2 space-y-2 text-left">
<SquidTape class="font-splatoon2 text-sm drop-shadow -rotate-6 -mx-2">
<SquidTape class="font-splatoon2 text-sm drop-shadow-sm -rotate-6 -mx-2">
<div class="px-2">
{{ $t(title) }}
</div>

View File

@ -21,7 +21,7 @@
</div>
</div>
</div>
<div v-else class="sm:hidden bg-zinc-500 rounded animate-pulse w-32">
<div v-else class="sm:hidden bg-zinc-500 rounded-sm animate-pulse w-32">
&nbsp;
</div>
@ -55,13 +55,13 @@
</template>
<template v-else>
<div class="text-xs lg:text-lg bg-zinc-500 rounded animate-pulse">
<div class="text-xs lg:text-lg bg-zinc-500 rounded-sm animate-pulse">
&nbsp;
</div>
<div class="text-sm mx-8 bg-zinc-500 rounded animate-pulse">
<div class="text-sm mx-8 bg-zinc-500 rounded-sm animate-pulse">
&nbsp;
</div>
<div class="text-sm mx-4 bg-zinc-500 rounded animate-pulse">
<div class="text-sm mx-4 bg-zinc-500 rounded-sm animate-pulse">
&nbsp;
</div>
</template>

View File

@ -7,7 +7,7 @@
</div>
<div class="flex justify-center mx-2">
<div class="font-splatoon2 text-zinc-200 text-center text-shadow text-sm lg:text-lg bg-zinc-700 px-4 py-1 rounded-full bg-opacity-50 backdrop-blur-sm">
<div class="font-splatoon2 text-zinc-200 text-center text-shadow text-sm lg:text-lg bg-zinc-700/50 px-4 py-1 rounded-full backdrop-blur-xs">
{{ $t(`splatnet.festivals.${festival.__splatoon3ink_id}.title`, festival.title) }}
</div>
</div>

View File

@ -6,7 +6,7 @@
</div>
<template v-for="festival in festivals" :key="festival.id">
<div class="flex justify-center mx-2">
<div class="font-splatoon2 text-zinc-200 text-center text-shadow text-sm lg:text-lg bg-zinc-700 px-4 py-1 rounded-full bg-opacity-50 backdrop-blur-sm">
<div class="font-splatoon2 text-zinc-200 text-center text-shadow text-sm lg:text-lg bg-zinc-700/50 px-4 py-1 rounded-full backdrop-blur-xs">
{{ $t(`splatnet.festivals.${festival.__splatoon3ink_id}.title`, festival.title) }}
</div>
</div>

View File

@ -5,11 +5,11 @@
{{ $t('festival.results.title') }}
</div>
<div class="mx-2 px-1 bg-zinc-700 bg-opacity-50 backdrop-blur-sm rounded-lg">
<div class="mx-2 px-1 bg-zinc-700/50 backdrop-blur-xs rounded-lg">
<div class="flex justify-center md:justify-center py-2">
<div class="w-36 sm:mx-4 lg:-mx-1" />
<template v-for="team in festival.teams" :key="team.id">
<div class="w-12 mx-2 sm:w-20 flex justify-center py-1 rounded" :style="`background-color: ${toRgba(team.color)};`">
<div class="w-12 mx-2 sm:w-20 flex justify-center py-1 rounded-sm" :style="`background-color: ${toRgba(team.color)};`">
<img :src="team.image.url" class="w-6 h-6" />
</div>
</template>
@ -21,7 +21,7 @@
{{ $t(row.title) }}
</div>
<div class="flex bg-zinc-700 bg-opacity-70 rounded-full py-1">
<div class="flex bg-zinc-700/70 rounded-full py-1">
<div v-for="(result, i) in row.results" :key="i" class="w-16 lg:w-20 sm:mx-2">
<div :class="result.isTop ? 'text-splatoon-yellow' : 'text-zinc-300'">
{{ (result.ratio * 100).toFixed(2) }}%

View File

@ -67,6 +67,8 @@ function formatDate(date) {
</script>
<style scoped>
@reference "@/assets/css/base.css";
.bg-blue-pattern {
@apply bg-splatoon-blue;
background-image: url("@/assets/img/battle-bg-pattern-blue.jpg");

View File

@ -1,6 +1,6 @@
<template>
<button class="block relative" @click.prevent="open = true">
<div class="bg-zinc-700 aspect-[2/1] overflow-hidden" :class="imgClass">
<div class="bg-zinc-700 aspect-2/1 overflow-hidden" :class="imgClass">
<img v-if="lowRes" :src="lowRes" />
<div v-else class="bg-zinc-500 animate-pulse h-full" :class="imgClass">
&nbsp;
@ -17,7 +17,7 @@
left-1/2
-translate-x-1/2
translate-y-1/2
overflow-ellipsis
text-ellipsis
overflow-hidden
max-w-[85%]
whitespace-nowrap

View File

@ -6,12 +6,12 @@
<div class="font-splatoon1 lg:text-2xl xl:text-3xl text-shadow">
{{ $t(type.name) }}
</div>
<div v-if="type.badge" class="font-splatoon2 text-xs lg:text-sm xl:text-base bg-splatoon-blue rounded px-1 drop-shadow">
<div v-if="type.badge" class="font-splatoon2 text-xs lg:text-sm xl:text-base bg-splatoon-blue rounded-sm px-1 drop-shadow-sm">
{{ $t(type.badge) }}
</div>
</div>
<div class="bg-zinc-900 bg-opacity-70 backdrop-blur-sm pt-2 pb-6 px-2 mx-1 rounded-lg space-y-2">
<div class="bg-zinc-900/70 backdrop-blur-xs pt-2 pb-6 px-2 mx-1 rounded-lg space-y-2">
<div class="flex items-center justify-between font-splatoon2">
<div class="flex items-center space-x-2 text-sm lg:text-lg">
<div>
@ -27,7 +27,7 @@
</div>
</div>
<div v-if="tricolor.startTime && tricolor.endTime" class="justify-end text-xs lg:text-sm bg-zinc-100 bg-opacity-80 rounded text-black px-2">
<div v-if="tricolor.startTime && tricolor.endTime" class="justify-end text-xs lg:text-sm bg-zinc-100/80 rounded-sm text-black px-2">
{{ $d(tricolor.startTime, 'dateTimeShort') }}
&ndash;
{{ $d(tricolor.endTime, 'dateTimeShort') }}

View File

@ -13,7 +13,7 @@
</div>
</div>
<div class="bg-zinc-900 bg-opacity-70 backdrop-blur-sm pt-2 pb-1 px-2 mx-2 rounded-lg space-y-2">
<div class="bg-zinc-900/70 backdrop-blur-xs pt-2 pb-1 px-2 mx-2 rounded-lg space-y-2">
<div class="flex items-center justify-between font-splatoon2">
<div class="flex items-center space-x-2 text-sm lg:text-lg">
<template v-if="event">
@ -26,14 +26,14 @@
</template>
<template v-else>
<div class="w-32 bg-zinc-600 rounded animate-pulse">
<div class="w-32 bg-zinc-600 rounded-sm animate-pulse">
&nbsp;
</div>
</template>
</div>
<div v-if="event.activeTimePeriod">
<SquidTape class="font-splatoon2 text-sm drop-shadow rotate-6">
<SquidTape class="font-splatoon2 text-sm drop-shadow-sm rotate-6">
<div class="px-2">
{{ $t('events.now_open') }}
</div>
@ -66,7 +66,7 @@
<!-- Current/future time periods -->
<template v-if="event.currentTimePeriods?.length">
<SquidTape class="font-splatoon2 text-sm drop-shadow -rotate-6 -mx-2 mt-4">
<SquidTape class="font-splatoon2 text-sm drop-shadow-sm -rotate-6 -mx-2 mt-4">
<div class="px-2">
{{ event.activeTimePeriod ? $t('events.now') : $t('events.available') }}
</div>
@ -81,7 +81,7 @@
</div>
</div>
<div class="font-splatoon2 mx-2 p-2 text-zinc-200 bg-zinc-900 bg-opacity-50 backdrop-blur-sm rounded-lg whitespace-pre-line">
<div class="font-splatoon2 mx-2 p-2 text-zinc-200 bg-zinc-900/50 backdrop-blur-xs rounded-lg whitespace-pre-line">
{{ br2nl($t(`splatnet.events.${event.settings.leagueMatchEvent.id}.regulation`, event.settings.leagueMatchEvent.regulation)) }}
</div>
</div>

View File

@ -9,7 +9,7 @@
</div>
<div v-if="isCurrent" class="flex justify-end w-full">
<div class="hidden sm:block text-xs bg-zinc-100 bg-opacity-80 rounded text-black px-2">
<div class="hidden sm:block text-xs bg-zinc-100/80 rounded-sm text-black px-2">
<template v-if="isActive">
{{ $t('time.remaining', { time: formatDurationFromNow(event.activeTimePeriod.endTime) }) }}
</template>

View File

@ -7,7 +7,7 @@
</div>
<div class="flex flex-col items-center -space-y-2">
<SquidTape
class="font-splatoon2 text-sm text-black rounded-sm -rotate-2 z-10"
class="font-splatoon2 text-sm text-black rounded-xs -rotate-2 z-10"
bg="bg-splatoon-green"
squid-bg="bg-black"
border="border border-black"
@ -36,7 +36,7 @@
<GearCardHorizontal
v-for="gear in gears"
:key="gear.id"
class="bg-zinc-100 bg-opacity-20 backdrop-blur-sm border border-zinc-50 border-opacity-20 rounded-lg"
class="bg-zinc-100/20 backdrop-blur-xs border border-zinc-50/20 rounded-lg"
:gear="gear"
/>
</div>

View File

@ -56,7 +56,7 @@
<!-- Time left -->
<div class="absolute top-1 left-6">
<div class="inline-block text-xs bg-zinc-200 bg-opacity-30 rounded px-1 py-px font-semibold">
<div class="inline-block text-xs bg-zinc-200/30 rounded-sm px-1 py-px font-semibold">
{{ $t('time.left', { time: formatDurationHoursFromNow(props.gear.saleEndTime) }) }}
</div>
</div>

View File

@ -8,17 +8,17 @@
<!-- Details -->
<div class="grow min-w-0 flex flex-col justify-evenly space-y-2">
<div class="flex">
<div class="inline-block text-xs bg-zinc-200 bg-opacity-30 rounded px-1 py-px font-semibold">
<div class="inline-block text-xs bg-zinc-200/30 rounded-sm px-1 py-px font-semibold">
{{ $t('time.left', { time: formatDurationHoursFromNow(props.gear.saleEndTime) }) }}
</div>
</div>
<div class="flex items-center space-x-2">
<div class="bg-white h-6 aspect-square rounded">
<div class="bg-white h-6 aspect-square rounded-sm">
<img :src="gear.brand.image.url" :title="$t(`splatnet.brands.${gear.brand.id}.name`, gear.brand.name)" />
</div>
<div class="flex-1 font-splatoon2 text-shadow overflow-hidden overflow-ellipsis whitespace-nowrap">
<div class="flex-1 font-splatoon2 text-shadow overflow-hidden text-ellipsis whitespace-nowrap">
{{ $t(`splatnet.gear.${gear.__splatoon3ink_id}.name`, gear.name) }}
</div>
</div>
@ -49,7 +49,7 @@
<div v-if="false" class="absolute top-0 right-0 hidden mobile:block">
<a :href="shopUrl">
<SquidTape
class="font-splatoon2 text-sm text-black rounded-sm -rotate-2"
class="font-splatoon2 text-sm text-black rounded-xs -rotate-2"
bg="bg-splatoon-yellow"
squid-bg="bg-black"
border="border border-black"
@ -67,7 +67,7 @@
<div v-if="false" class="hidden mobile:block">
<a :href="shopUrl">
<SquidTape
class="font-splatoon2 text-sm text-black rounded-sm -rotate-2"
class="font-splatoon2 text-sm text-black rounded-xs -rotate-2"
bg="bg-splatoon-yellow"
squid-bg="bg-black"
border="border border-black"

View File

@ -15,7 +15,7 @@
<div class="pb-24 lg:pb-36">
<div class="text-center py-4">
<SquidTape
class="font-splatoon1 text-2xl text-black rounded-sm -rotate-2 z-10"
class="font-splatoon1 text-2xl text-black rounded-xs -rotate-2 z-10"
bg="bg-splatoon-orange"
squid-bg="bg-black"
border="border border-black"

View File

@ -23,7 +23,7 @@
<div
v-if="schedule.isBigRun"
class="bg-zinc-800 bg-opacity-80 text-sm text-white rounded-lg px-2 border-2 border-splatoon-bigRun"
class="bg-zinc-800/80 text-sm text-white rounded-lg px-2 border-2 border-splatoon-bigRun"
>
<img src="@/assets/img/modes/coop.bigrun.svg" :title="$t('salmonrun.bigrun')" class="w-4 inline-block" />
{{ $t('salmonrun.bigrun') }}
@ -44,7 +44,7 @@
{{ $t('salmonrun.weapons') }}
</div>
<div class="bg-zinc-900 bg-opacity-30 rounded-full backdrop-blur-sm px-2">
<div class="bg-zinc-900/30 rounded-full backdrop-blur-xs px-2">
<SalmonRunWeapons :weapons="schedule.settings.weapons" weapon-class="w-10 sm:w-14" />
</div>
</div>

View File

@ -16,7 +16,7 @@
<!-- Main content -->
<div class="md:w-2/3 mx-2 pb-2">
<div v-if="activeSchedule" class="mb-6 space-y-2">
<SquidTape class="font-splatoon2 text-sm drop-shadow -rotate-6 -mx-2">
<SquidTape class="font-splatoon2 text-sm drop-shadow-sm -rotate-6 -mx-2">
<div class="px-2">
{{ $t('times.now') }}
</div>
@ -25,8 +25,8 @@
<ExpandedSalmonRunRow :schedule="activeSchedule" :eggstra="eggstra" />
</div>
<div v-if="upcomingSchedules.length" class="py-1 bg-zinc-900 bg-opacity-70 rounded-lg backdrop-blur-sm">
<SquidTape class="font-splatoon2 text-sm drop-shadow -rotate-6 -mx-2">
<div v-if="upcomingSchedules.length" class="py-1 bg-zinc-900/70 rounded-lg backdrop-blur-xs">
<SquidTape class="font-splatoon2 text-sm drop-shadow-sm -rotate-6 -mx-2">
<div class="px-2">
{{ $t('times.future') }}
</div>

View File

@ -12,20 +12,20 @@
{{ $d(schedule.endTime, 'dateTimeShort') }}
</div>
<div class="hidden sm:block text-xs bg-zinc-100 bg-opacity-80 rounded text-black px-2">
<div class="hidden sm:block text-xs bg-zinc-100/80 rounded-sm text-black px-2">
{{ $t('time.in', { time: formatDurationFromNow(schedule.startTime, true) }) }}
</div>
</div>
<div class="flex items-center space-x-2">
<StageImage class="w-1/5" img-class="rounded" :stage="schedule.settings.coopStage" hide-label />
<StageImage class="w-1/5" img-class="rounded-sm" :stage="schedule.settings.coopStage" hide-label />
<div class="flex-1 text-sm text-zinc-300 text-shadow">
<KingSalmonid :schedule="schedule" class="inline-block align-middle drop-shadow-ruleIcon" size="w-5" />
{{ $t(`splatnet.stages.${schedule.settings.coopStage.id}.name`, schedule.settings.coopStage.name) }}
<span v-if="schedule.isBigRun" class="text-xs inline-block bg-splatoon-bigRun bg-opacity-80 text-white rounded px-2">
<span v-if="schedule.isBigRun" class="text-xs inline-block bg-splatoon-bigRun/80 text-white rounded-sm px-2">
{{ $t('salmonrun.bigrun') }}
</span>
</div>

View File

@ -4,7 +4,7 @@
<div>
<div class="flex flex-col items-center -mt-10 -space-y-2">
<SquidTape
class="font-splatoon2 text-2xl text-black rounded-sm -rotate-2 z-10"
class="font-splatoon2 text-2xl text-black rounded-xs -rotate-2 z-10"
bg="bg-splatoon-green"
squid-bg="bg-black"
border="border-2 border-black"

View File

@ -15,7 +15,7 @@
<div class="pb-24 lg:pb-36">
<div class="text-center pt-4">
<SquidTape
class="font-splatoon1 text-4xl text-black rounded-sm -rotate-2 z-10"
class="font-splatoon1 text-4xl text-black rounded-xs -rotate-2 z-10"
bg="bg-splatoon-orange"
squid-bg="bg-black"
border="border-2 border-black"

View File

@ -21,7 +21,7 @@
<div>
<div v-if="type.badge" class="flex items-center">
<img :src="type.img" class="h-8" />
<div v-if="type.badge" class="font-splatoon2 text-xl bg-splatoon-blue px-2 drop-shadow rounded">
<div v-if="type.badge" class="font-splatoon2 text-xl bg-splatoon-blue px-2 drop-shadow-sm rounded-sm">
{{ $t(type.badge) }}
</div>
</div>

View File

@ -26,7 +26,7 @@
<div>
<div v-if="type.badge" class="flex items-center">
<img :src="type.img" class="h-8" />
<div v-if="type.badge" class="font-splatoon2 text-xl bg-splatoon-blue px-2 drop-shadow rounded">
<div v-if="type.badge" class="font-splatoon2 text-xl bg-splatoon-blue px-2 drop-shadow-sm rounded-sm">
{{ $t(type.badge) }}
</div>
</div>

View File

@ -67,6 +67,8 @@ const isDev = import.meta.env.DEV;
</script>
<style scoped>
@reference "@/assets/css/base.css";
.footer-links a span {
@apply text-zinc-300;
}

View File

@ -4,7 +4,7 @@
<div class="h-16" />
<div class="h-12 m-4 bg-black bg-opacity-50 backdrop-blur-sm rounded-full absolute bottom-0 inset-x-0">
<div class="h-12 m-4 bg-black/50 backdrop-blur-xs rounded-full absolute bottom-0 inset-x-0">
<div class="flex justify-between h-full font-splatoon2 text-sm text-zinc-300">
<div class="flex justify-start items-center space-x-6 ml-4">
<div>
@ -74,6 +74,8 @@ const isDev = import.meta.env.DEV;
</script>
<style scoped>
@reference "@/assets/css/base.css";
.footer-links a span {
@apply text-zinc-300;
}

View File

@ -98,6 +98,8 @@ import ProductContainer from '@/components/ProductContainer.vue';
</script>
<style scoped>
@reference "@/assets/css/base.css";
.bg-octoarrow {
background-image: url('@/assets/img/octoarrow-transparent.png');
background-size: 200px;

View File

@ -1,7 +1,7 @@
<template>
<MainLayout :title="$t('events.title')">
<div class="grow flex items-center justify-center">
<div class="mx-4 md:mx-12 max-w-screen-2xl w-full my-6">
<div class="mx-4 md:mx-12 max-w-(--breakpoint-2xl) w-full my-6">
<div v-if="store.currentSchedules?.length" class="flex flex-col lg:flex-row items-center justify-center gap-10">
<div v-for="(event, i) in store.currentSchedules" :key="i" class="max-w-xl">
<ChallengeScheduleBox

View File

@ -96,6 +96,8 @@ const displaySocials = computed(() => {
</script>
<style scoped>
@reference "@/assets/css/base.css";
.bg-octoarrow {
background-image: url('@/assets/img/camo-transparent-bg.png');
background-size: 800px;

View File

@ -55,6 +55,8 @@
</template>
<style scoped>
@reference "@/assets/css/base.css";
a {
@apply underline;
}

View File

@ -1,47 +0,0 @@
const plugin = require('tailwindcss/plugin');
module.exports = {
content: [
'./index.html',
'./src/**/*.{vue,js,mjs}',
],
theme: {
extend: {
colors: {
splatoon: {
blue: '#603bff',
purple: '#af50ff',
yellow: '#eaff3d',
green: '#6af7ce',
orange: '#ff9750',
red: '#ff505e',
brown: '#7f413f',
battle: {
regular: '#19d719',
ranked: '#f54910',
xmatch: '#0fdb9b',
league: '#f02d7d',
},
salmonRun: '#ff5600',
bigRun: '#b322ff',
eggstraWork: '#be8800',
},
},
fontFamily: {
splatoon1: 'var(--font-family-s1)',
splatoon2: 'var(--font-family-s2)',
},
dropShadow: {
'ruleIcon': '1px 1px 0 rgb(0,0,0)',
},
},
},
plugins: [
plugin(function({ addVariant }) {
addVariant('mobile', 'body.is-mobile &');
addVariant('ss', 'body.for-screenshots &');
}),
],
};

View File

@ -3,7 +3,8 @@ import { fileURLToPath, URL } from 'url';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueI18n from '@intlify/vite-plugin-vue-i18n';
import tailwindcss from '@tailwindcss/vite';
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
const redirectToDist = [
'/assets/splatnet/',
@ -14,8 +15,9 @@ const redirectToDist = [
export default defineConfig({
plugins: [
vue(),
vueI18n({
include: resolve(__dirname, './src/assets/i18n/**'),
tailwindcss(),
VueI18nPlugin({
include: resolve(__dirname, './src/assets/i18n/*.json'),
}),
{
// Quick hack to redirect dynamic assets to the /dist/ directory