Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ html.light .shiki {
}
}

/* Settings-based configuration for code ligatures. On by default. */
:root[data-code-ligatures='false'] code {
font-variant-ligatures: none;
}

/* Inline code in package descriptions */
p > span > code,
.line-clamp-2 code {
Expand Down
33 changes: 33 additions & 0 deletions app/composables/useSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export interface AppSettings {
autoOpenURL: boolean
}
codeContainerFull: boolean
/** Enable/disable ligatures in code */
codeLigatures: boolean
sidebar: {
collapsed: string[]
}
Expand All @@ -65,6 +67,7 @@ const DEFAULT_SETTINGS: AppSettings = {
autoOpenURL: false,
},
codeContainerFull: false,
codeLigatures: true,
sidebar: {
collapsed: [],
},
Expand Down Expand Up @@ -253,3 +256,33 @@ export function useCodeContainer() {
toggleCodeContainer,
}
}

export const useCodeLigatures = createSharedComposable(function useCodeLigatures() {
const { settings } = useSettings()

const codeLigatures = computed(() => settings.value.codeLigatures)

if (import.meta.client) {
// Sync the data attribute on root to the setting
watch(
codeLigatures,
value => {
if (value) {
delete document.documentElement.dataset.codeLigatures
} else {
document.documentElement.dataset.codeLigatures = 'false'
}
},
{ immediate: true },
)
}

function toggleCodeLigatures() {
settings.value.codeLigatures = !settings.value.codeLigatures
}

return {
codeLigatures,
toggleCodeLigatures,
}
})
11 changes: 11 additions & 0 deletions app/pages/settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { locale: currentLocale, locales, setLocale: setNuxti18nLocale } = useI18n
const colorMode = useColorMode()
const { currentLocaleStatus, isSourceLocale } = useI18nStatus()
const keyboardShortcutsEnabled = useKeyboardShortcuts()
const { toggleCodeLigatures } = useCodeLigatures()

// Escape to go back (but not when focused on form elements or modal is open)
onKeyStroke(
Expand Down Expand Up @@ -143,6 +144,16 @@ const setLocale: typeof setNuxti18nLocale = newLocale => {
:description="$t('settings.enable_graph_pulse_loop_description')"
v-model="settings.enableGraphPulseLooping"
/>

<!-- Divider -->
<div class="border-t border-border my-4" />

<!-- Code ligatures toggle -->
<SettingsToggle
:label="$t('settings.enable_code_ligatures')"
:modelValue="settings.codeLigatures"
@update:modelValue="() => toggleCodeLigatures()"
/>
</div>
</section>

Expand Down
5 changes: 5 additions & 0 deletions app/utils/prehydrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,10 @@ export function initPreferencesOnPrehydrate() {
if (settings.keyboardShortcuts === false) {
document.documentElement.dataset.kbdShortcuts = 'false'
}

// Code font ligatures (default: true)
if (settings.codeLigatures === false) {
document.documentElement.dataset.codeLigatures = 'false'
}
})
}
3 changes: 2 additions & 1 deletion i18n/locales/cs-CZ.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@
"black": "Černá"
},
"keyboard_shortcuts_enabled": "Povolit klávesové zkratky",
"keyboard_shortcuts_enabled_description": "Klávesové zkratky lze zakázat, pokud se střetávají s jinými zkratkami prohlížeče nebo systému"
"keyboard_shortcuts_enabled_description": "Klávesové zkratky lze zakázat, pokud se střetávají s jinými zkratkami prohlížeče nebo systému",
"enable_code_ligatures": "Zapnout ligatury v kódu"
},
"i18n": {
"missing_keys": "{count} chybějící překlad | {count} chybějící překlady | {count} chybějících překladů",
Expand Down
3 changes: 2 additions & 1 deletion i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@
"black": "Black"
},
"keyboard_shortcuts_enabled": "Enable keyboard shortcuts",
"keyboard_shortcuts_enabled_description": "Keyboard shortcuts can be disabled if they conflict with other browser or system shortcuts"
"keyboard_shortcuts_enabled_description": "Keyboard shortcuts can be disabled if they conflict with other browser or system shortcuts",
"enable_code_ligatures": "Enable ligatures in code"
},
"i18n": {
"missing_keys": "{count} missing translation | {count} missing translations",
Expand Down
3 changes: 3 additions & 0 deletions i18n/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,9 @@
},
"keyboard_shortcuts_enabled_description": {
"type": "string"
},
"enable_code_ligatures": {
"type": "string"
}
},
"additionalProperties": false
Expand Down
28 changes: 28 additions & 0 deletions test/nuxt/composables/use-settings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,31 @@ describe('useSettings - keyboardShortcuts', () => {
})
})
})

describe('useSettings - codeLigatures', () => {
beforeEach(() => {
vi.resetModules()
})

it('has a default value of true', async () => {
const { useSettings } = await import('~/composables/useSettings')
const codeLigatures = useSettings().settings.value.codeLigatures
expect(codeLigatures).toBe(true)
})

describe('useCodeLigatures', () => {
it('has a default value of true', async () => {
const { useCodeLigatures } = await import('~/composables/useSettings')
const codeLigatures = useCodeLigatures().codeLigatures
expect(codeLigatures.value).toBe(true)
})

it('updates after toggle', async () => {
const { useCodeLigatures } = await import('~/composables/useSettings')
const { codeLigatures, toggleCodeLigatures } = useCodeLigatures()
expect(codeLigatures.value).toBe(true)
toggleCodeLigatures()
expect(codeLigatures.value).toBe(false)
})
})
})
Loading