Skip to content

Commit 7e37398

Browse files
committed
fix: guard JSON.parse with try/catch
1 parent eb4f78c commit 7e37398

4 files changed

Lines changed: 25 additions & 7 deletions

File tree

app/components/Settings/AccentColorPicker.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
<script setup lang="ts">
2+
import type { UserPreferences } from '#shared/schemas/userPreferences'
3+
24
const { accentColors, selectedAccentColor, setAccentColor } = useAccentColor()
35
46
onPrehydrate(el => {
5-
const preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}')
7+
let preferences: UserPreferences = {}
68
const defaultId = 'sky'
9+
try {
10+
preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}')
11+
} catch {}
712
const id = preferences.accentColorId
813
if (id) {
914
const input = el.querySelector<HTMLInputElement>(`input[value="${id}"]`)

app/components/Settings/BgThemePicker.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
<script setup lang="ts">
2+
import type { UserPreferences } from '#shared/schemas/userPreferences'
3+
24
const { backgroundThemes, selectedBackgroundTheme, setBackgroundTheme } = useBackgroundTheme()
35
46
onPrehydrate(el => {
5-
const preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}')
7+
let preferences: UserPreferences = {}
68
const defaultId = 'neutral'
9+
try {
10+
preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}')
11+
} catch {}
712
const id = preferences.preferredBackgroundTheme
813
if (id) {
914
const input = el.querySelector<HTMLInputElement>(`input[value="${id}"]`)

app/composables/useUserLocalSettings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
interface UserLocalSettings {
1+
export interface UserLocalSettings {
22
sidebar: {
33
collapsed: string[]
44
animateSparkline: boolean

app/utils/prehydrate.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { UserPreferences } from '#shared/schemas/userPreferences'
2+
import type { UserLocalSettings } from '~/composables/useUserLocalSettings'
3+
14
/**
25
* Initialize user preferences before hydration to prevent flash/layout shift.
36
* This sets CSS custom properties and data attributes that CSS can use
@@ -24,7 +27,10 @@ export function initPreferencesOnPrehydrate() {
2427
const validPMs = new Set(['npm', 'pnpm', 'yarn', 'bun', 'deno', 'vlt'])
2528

2629
// Read user preferences from localStorage
27-
const preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}')
30+
let preferences: UserPreferences = {}
31+
try {
32+
preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}')
33+
} catch {}
2834

2935
const accentColorId = preferences.accentColorId
3036
if (accentColorId && accentColorIds.has(accentColorId)) {
@@ -58,8 +64,10 @@ export function initPreferencesOnPrehydrate() {
5864
// Set data attribute for CSS-based visibility
5965
document.documentElement.dataset.pm = pm
6066

61-
// Read sidebar preferences from separate localStorage key
62-
const sidebar = JSON.parse(localStorage.getItem('npmx-sidebar-preferences') || '{}')
63-
document.documentElement.dataset.collapsed = sidebar.collapsed?.join(' ') ?? ''
67+
let localSettings: Partial<UserLocalSettings> = {}
68+
try {
69+
localSettings = JSON.parse(localStorage.getItem('npmx-settings') || '{}')
70+
} catch {}
71+
document.documentElement.dataset.collapsed = localSettings.sidebar?.collapsed?.join(' ') ?? ''
6472
})
6573
}

0 commit comments

Comments
 (0)