Declare prop types and clear the remaining web lint warnings

Every component now declares its prop types (vue/require-prop-types),
which was the bulk of what was left. The rest are one-off fixes:

- two <template> wrappers with no directive are removed (no-lone-template);
- the region dropdown's loop variable no longer shadows the region prop
  (no-template-shadow);
- the Splatfest winner bar renders the winning team's name as a real
  <span> inside the translated sentence instead of injecting markup with
  v-html (no-v-html).

The lint workflow's --max-warnings 0 now passes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Matt Isenhower
2026-09-05 10:36:51 -07:00
parent be6c23788f
commit 8827f59b44
15 changed files with 82 additions and 49 deletions

View File

@@ -54,7 +54,11 @@
<script>
export default {
props: ['title', 'link', 'googleId'],
props: {
title: String,
link: String,
googleId: String,
},
data() {
return {
isOpen: false,

View File

@@ -36,9 +36,9 @@
<script>
export default {
props: {
options: {},
value: {},
tag: { default: 'button' },
options: Array,
value: { type: [String, Number], default: null },
tag: { type: String, default: 'button' },
},
data() {
return {

View File

@@ -24,7 +24,9 @@ import { splatoonRegions } from '@/common/regions';
export default {
components: { Wrapper, SplatfestBox, SplatfestResultsBox },
props: ['region'],
props: {
region: String,
},
computed: {
festival() {
return this.$store.getters[`splatoon/splatfests/${this.region}/currentSplatfest`];

View File

@@ -78,7 +78,9 @@ export default {
return Vue.i18n.translate('splatfest.results_in', { time });
},
},
props: ['region'],
props: {
region: String,
},
computed: {
...mapGetters('splatoon', ['now']),
...mapGetters('splatoon/finalFest', {

View File

@@ -10,7 +10,7 @@
</div>
<div class="level-item">
<h2 class="title is-3 is-size-2-fullhd is-size-4-mobile font-splatoon1">
<template>{{ name }}</template>
{{ name }}
</h2>
</div>
</div>
@@ -21,7 +21,9 @@
import { mapGetters } from 'vuex';
export default {
props: ['mode'],
props: {
mode: String,
},
computed: {
...mapGetters('splatoon/splatfests', ['selectedRegionHasActiveSplatfest']),
name() {

View File

@@ -30,7 +30,9 @@
<script>
export default {
props: ['region'],
props: {
region: String,
},
computed: {
heroWins() {
return this.$store.getters[`splatoon/splatfests/${this.region}/heroWins`];

View File

@@ -81,7 +81,9 @@
import { mapGetters } from 'vuex';
export default {
props: ['merchandise'],
props: {
merchandise: Object,
},
computed: {
...mapGetters('splatoon', ['now']),
brandName() {

View File

@@ -33,8 +33,8 @@
<script>
export default {
props: {
weapon: {},
title: {},
weapon: Object,
title: String,
},
computed: {
displayTitle() {

View File

@@ -59,7 +59,9 @@ import ScheduleRow from './ScheduleRow.vue';
export default {
components: { GameModeHeader, Stage, ScheduleRow },
props: ['mode'],
props: {
mode: String,
},
computed: {
...mapGetters('splatoon', ['now']),
...mapGetters('splatoon/splatfests', [

View File

@@ -18,6 +18,8 @@ import ScheduleList from './ScheduleList.vue';
export default {
components: { Modal, GameModeHeader, ScheduleList },
props: ['mode'],
props: {
mode: String,
},
};
</script>

View File

@@ -8,27 +8,25 @@
<ScheduleRow :schedule="first" />
</div>
<template>
<div v-if="second">
<div class="is-size-5 title-squid font-splatoon1" style="margin-top: 10px">
{{ $t('times.next') }}
</div>
<ScheduleRow :schedule="second" />
<div v-if="second">
<div class="is-size-5 title-squid font-splatoon1" style="margin-top: 10px">
{{ $t('times.next') }}
</div>
<div v-if="others && others.length">
<div class="is-size-5 title-squid font-splatoon1" style="margin-top: 10px">
{{ $t('times.future') }}
</div>
<ScheduleRow :schedule="second" />
</div>
<ScheduleRow
v-for="schedule in others"
:key="schedule.start_time"
:schedule="schedule"
/>
<div v-if="others && others.length">
<div class="is-size-5 title-squid font-splatoon1" style="margin-top: 10px">
{{ $t('times.future') }}
</div>
</template>
<ScheduleRow
v-for="schedule in others"
:key="schedule.start_time"
:schedule="schedule"
/>
</div>
</div>
</template>
@@ -38,7 +36,9 @@ import ScheduleRow from './ScheduleRow.vue';
export default {
components: { ScheduleRow },
props: ['mode'],
props: {
mode: String,
},
computed: {
...mapGetters('splatoon', ['now']),
schedules() {

View File

@@ -17,13 +17,13 @@
trigger-class="button is-clear font-splatoon2"
>
<router-link
v-for="region in regions"
:key="region.key"
v-for="regionOption in regions"
:key="regionOption.key"
class="dropdown-item"
:to="region.route"
:to="regionOption.route"
exact
>
{{ region.name }}
{{ regionOption.name }}
</router-link>
</DropdownBase>
</div>
@@ -97,7 +97,9 @@ export default {
return Vue.i18n.translate('splatfest.results_in', { time });
},
},
props: ['region'],
props: {
region: String,
},
computed: {
...mapGetters('splatoon', ['now']),
regions() {

View File

@@ -44,7 +44,10 @@ export default {
return value.toString().slice(-2);
},
},
props: ['festival', 'type'],
props: {
festival: Object,
type: String,
},
computed: {
winner() {
return this.festival.results.summary[this.type] ? 'bravo' : 'alpha';

View File

@@ -1,10 +1,14 @@
<template>
<div class="festival-period" style="background-color: #333" v-html="teamWins" />
<div class="festival-period" style="background-color: #333">
<span v-if="winner">{{ winnerText.before }}<span :style="{ color: winnerColor }">{{ teamNames[winner] }}</span>{{ winnerText.after }}</span>
</div>
</template>
<script>
export default {
props: ['festival'],
props: {
festival: Object,
},
computed: {
teamNames() {
return {
@@ -12,14 +16,20 @@ export default {
bravo: this.$t(`splatnet.festivals.${this.festival.festival_id}.names.bravo_short`, this.festival.names.bravo_short),
};
},
teamWins() {
winner() {
if (!this.festival || !this.festival.results)
return;
return null;
let winner = this.festival.results.summary.total ? 'bravo' : 'alpha';
let team = `<span style="color: ${this.festival.colors[winner].css_rgb}">${this.teamNames[winner]}</span>`;
return this.$t('splatfest.team_name_wins', { team });
return this.festival.results.summary.total ? 'bravo' : 'alpha';
},
winnerColor() {
return this.festival.colors[this.winner].css_rgb;
},
// The translated sentence split around the team name, e.g. "Team " / " wins!"
winnerText() {
const placeholder = '\u0000';
const [before, after] = this.$t('splatfest.team_name_wins', { team: placeholder }).split(placeholder);
return { before, after };
},
},
};

View File

@@ -32,9 +32,9 @@ import SplatoonStages from '@/web/support/stages';
export default {
components: { Modal },
props: {
stage: {},
showTitle: { default: true },
clickable: { default: true },
stage: Object,
showTitle: { type: Boolean, default: true },
clickable: { type: Boolean, default: true },
isSalmonRun: Boolean,
},
data() {