Merge branch 'main' into shuuji3/chore/upgrade-masto-to-v7.2.0
# Conflicts: # package.json # pnpm-lock.yaml
This commit is contained in:
commit
94ac6a9ae2
56 changed files with 8576 additions and 10643 deletions
22
.github/workflows/provenance.yml
vendored
Normal file
22
.github/workflows/provenance.yml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
check-provenance:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check provenance downgrades
|
||||
uses: danielroe/provenance-action@41bcc969e579d9e29af08ba44fcbfdf95cee6e6c # v0.1.1
|
||||
with:
|
||||
fail-on-provenance-change: true
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ dist
|
|||
.output
|
||||
.pnpm-store
|
||||
.nuxt
|
||||
.data
|
||||
.env
|
||||
.DS_Store
|
||||
.idea/
|
||||
|
|
|
|||
4
.npmrc
4
.npmrc
|
|
@ -1,4 +0,0 @@
|
|||
shamefully-hoist=true
|
||||
shell-emulator=true
|
||||
ignore-workspace-root-check=true
|
||||
package-manager-strict=false
|
||||
|
|
@ -17,13 +17,12 @@ RUN apk add git --no-cache
|
|||
|
||||
# Prepare build deps ( ignore postinstall scripts for now )
|
||||
COPY package.json ./
|
||||
COPY .npmrc ./
|
||||
COPY pnpm-lock.yaml ./
|
||||
COPY patches ./patches
|
||||
RUN pnpm i --frozen-lockfile --ignore-scripts
|
||||
|
||||
# Copy all source files
|
||||
COPY . ./
|
||||
RUN pnpm nuxt prepare
|
||||
|
||||
# Run full install with every postinstall script ( This needs project file )
|
||||
RUN pnpm i --frozen-lockfile
|
||||
|
|
|
|||
19
app/augments.d.ts
vendored
Normal file
19
app/augments.d.ts
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
export {}
|
||||
|
||||
declare module '#app' {
|
||||
interface PageMeta {
|
||||
wideLayout?: boolean
|
||||
}
|
||||
|
||||
interface RuntimeNuxtHooks {
|
||||
'elk-logo:click': () => void
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface Process {
|
||||
mock?: Record<string, any>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ function handleFavouritedBoostedByClose() {
|
|||
>
|
||||
<ModalMediaPreview v-if="isMediaPreviewOpen" @close="closeMediaPreview()" />
|
||||
</ModalDialog>
|
||||
<ModalDialog v-model="isEditHistoryDialogOpen" max-w-125>
|
||||
<ModalDialog v-model="isEditHistoryDialogOpen" :focus-first-element="false" max-w-125>
|
||||
<StatusEditPreview v-if="statusEdit" :edit="statusEdit" />
|
||||
</ModalDialog>
|
||||
<ModalDialog v-model="isCommandPanelOpen" max-w-fit flex>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const {
|
|||
closeByMask = true,
|
||||
useVIf = true,
|
||||
keepAlive = false,
|
||||
focusFirstElement = true,
|
||||
} = defineProps<{
|
||||
// level of depth
|
||||
zIndex?: number
|
||||
|
|
@ -21,6 +22,8 @@ const {
|
|||
keepAlive?: boolean
|
||||
// The aria-labelledby id for the dialog.
|
||||
dialogLabelledBy?: string
|
||||
// Whether to focus on the first element when the modal opens.
|
||||
focusFirstElement?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
|
@ -45,6 +48,7 @@ const { activate } = useFocusTrap(elDialogRoot, {
|
|||
escapeDeactivates: true,
|
||||
preventScroll: true,
|
||||
returnFocusOnDeactivate: true,
|
||||
initialFocus: focusFirstElement ? undefined : false,
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export const shikiParser: Parser = (options) => {
|
|||
return promise ?? []
|
||||
|
||||
if (!parser)
|
||||
// @ts-expect-error will be fixed when shiki upgrades
|
||||
parser = createParser(highlighter)
|
||||
|
||||
return parser(options)
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ export default defineNuxtPlugin(async (nuxt) => {
|
|||
if (!supportLanguages.includes(lang.value))
|
||||
userSettings.value.language = getDefaultLanguage(supportLanguages)
|
||||
|
||||
if (lang.value !== i18n.locale)
|
||||
if (lang.value !== i18n.locale.value)
|
||||
await setLocale(userSettings.value.language as Locale)
|
||||
|
||||
watch([lang, isHydrated], () => {
|
||||
if (isHydrated.value && lang.value !== i18n.locale)
|
||||
if (isHydrated.value && lang.value !== i18n.locale.value)
|
||||
setLocale(lang.value)
|
||||
}, { immediate: true })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,13 +75,11 @@ export const countryLocaleVariants: Record<string, (LocaleObjectData & { country
|
|||
|
||||
const locales: LocaleObjectData[] = [
|
||||
{
|
||||
// @ts-expect-error en used as placeholder
|
||||
code: 'en',
|
||||
file: 'en.json',
|
||||
name: 'English',
|
||||
},
|
||||
{
|
||||
// @ts-expect-error ar used as placeholder
|
||||
code: 'ar',
|
||||
file: 'ar.json',
|
||||
name: 'العربية',
|
||||
|
|
@ -112,7 +110,6 @@ const locales: LocaleObjectData[] = [
|
|||
},
|
||||
} satisfies LocaleObjectData,
|
||||
{
|
||||
// @ts-expect-error ca used as placeholder
|
||||
code: 'ca',
|
||||
file: 'ca.json',
|
||||
name: 'Català',
|
||||
|
|
@ -153,7 +150,6 @@ const locales: LocaleObjectData[] = [
|
|||
name: 'Nederlands',
|
||||
},
|
||||
{
|
||||
// @ts-expect-error es used as placeholder
|
||||
code: 'es',
|
||||
file: 'es.json',
|
||||
name: 'Español',
|
||||
|
|
@ -207,7 +203,6 @@ const locales: LocaleObjectData[] = [
|
|||
},
|
||||
},
|
||||
{
|
||||
// @ts-expect-error pt used as placeholder
|
||||
code: 'pt',
|
||||
file: 'pt.json',
|
||||
name: 'Português',
|
||||
|
|
@ -283,7 +278,7 @@ function buildLocales() {
|
|||
acc.push(data)
|
||||
}
|
||||
return acc
|
||||
}, <LocaleObjectData[]>[])
|
||||
}, [] as LocaleObjectData[])
|
||||
|
||||
return useLocales.sort((a, b) => a.code.localeCompare(b.code))
|
||||
}
|
||||
|
|
@ -313,7 +308,7 @@ export const datetimeFormats = Object.values(currentLocales).reduce((acc, data)
|
|||
}
|
||||
|
||||
return acc
|
||||
}, <DateTimeFormats>{})
|
||||
}, {} as DateTimeFormats)
|
||||
|
||||
export const numberFormats = Object.values(currentLocales).reduce((acc, data) => {
|
||||
const numberFormats = data.numberFormats
|
||||
|
|
@ -345,7 +340,7 @@ export const numberFormats = Object.values(currentLocales).reduce((acc, data) =>
|
|||
}
|
||||
|
||||
return acc
|
||||
}, <NumberFormats>{})
|
||||
}, {} as NumberFormats)
|
||||
|
||||
export const pluralRules = Object.values(currentLocales).reduce((acc, data) => {
|
||||
const pluralRule = data.pluralRule
|
||||
|
|
@ -355,4 +350,4 @@ export const pluralRules = Object.values(currentLocales).reduce((acc, data) => {
|
|||
}
|
||||
|
||||
return acc
|
||||
}, <PluralizationRules>{})
|
||||
}, {} as PluralizationRules)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ services:
|
|||
volumes:
|
||||
# make sure this directory has the same ownership as the elk user from the Dockerfile
|
||||
# otherwise Elk will not be able to store configs for accounts
|
||||
# e.q. mkdir ./elk-storage; sudo chown 911:911 ./elk-storage
|
||||
# e.g., mkdir ./elk-storage; sudo chown 911:911 ./elk-storage
|
||||
- './elk-storage:/elk/data'
|
||||
ports:
|
||||
- 5314:5314
|
||||
|
|
|
|||
|
|
@ -1,35 +1,41 @@
|
|||
export default defineAppConfig({
|
||||
docus: {
|
||||
seo: {
|
||||
title: 'Elk',
|
||||
description: 'A nimble Mastodon web client.',
|
||||
image: 'https://docs.elk.zone/elk-screenshot.png',
|
||||
socials: {
|
||||
// twitter: 'elk_zone',
|
||||
github: 'elk-zone/elk',
|
||||
mastodon: {
|
||||
label: 'Mastodon',
|
||||
icon: 'IconMastodon',
|
||||
href: 'https://elk.zone/@elk@webtoo.ls',
|
||||
},
|
||||
},
|
||||
aside: {
|
||||
level: 0,
|
||||
exclude: [],
|
||||
description: 'A nimble Mastodon web client with modern features and elegant design.',
|
||||
},
|
||||
header: {
|
||||
logo: true,
|
||||
showLinkIcon: true,
|
||||
exclude: [],
|
||||
title: 'Elk',
|
||||
logo: {
|
||||
alt: 'Elk',
|
||||
light: '/logo.svg',
|
||||
dark: '/logo.svg',
|
||||
},
|
||||
footer: {
|
||||
iconLinks: [
|
||||
},
|
||||
socials: {
|
||||
github: 'https://github.com/elk-zone/elk',
|
||||
mastodon: 'https://elk.zone/@elk@webtoo.ls',
|
||||
},
|
||||
github: {
|
||||
url: 'https://github.com/elk-zone/elk',
|
||||
branch: 'main',
|
||||
rootDir: 'docs',
|
||||
},
|
||||
toc: {
|
||||
title: 'On this page',
|
||||
bottom: {
|
||||
title: 'Community',
|
||||
links: [
|
||||
{
|
||||
href: 'https://nuxt.com',
|
||||
icon: 'IconNuxtLabs',
|
||||
icon: 'i-ph-shooting-star-duotone',
|
||||
label: 'Star on GitHub',
|
||||
to: 'https://github.com/elk-zone/elk',
|
||||
target: '_blank',
|
||||
},
|
||||
{
|
||||
href: 'https://m.webtoo.ls/@elk',
|
||||
icon: 'IconMastodon',
|
||||
icon: 'i-simple-icons-mastodon',
|
||||
label: 'Follow on Mastodon',
|
||||
to: 'https://elk.zone/@elk@webtoo.ls',
|
||||
target: '_blank',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<template>
|
||||
<AppLayout>
|
||||
<NuxtPage />
|
||||
</AppLayout>
|
||||
</template>
|
||||
4
docs/app/assets/css/main.css
Normal file
4
docs/app/assets/css/main.css
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/* Elk brand colors for light and dark modes */
|
||||
:root {
|
||||
--ui-primary: #f0943c;
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import type { TranslationStatus } from '../../types'
|
||||
import type { TranslationStatus } from '../../../types'
|
||||
|
||||
const localesStatuses: TranslationStatus = await import('../../translation-status.json').then(m => m.default)
|
||||
const localesStatuses: TranslationStatus = await import('../../../translation-status.json').then(m => m.default)
|
||||
|
||||
const totalReference = localesStatuses.en.total
|
||||
const totalReference = localesStatuses.en!.total
|
||||
|
||||
type Tab = 'missing' | 'outdated'
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ const missingEntries = computed<string[]>(() => {
|
|||
if (hidden.value || !currentLocale.value || localeTab.value !== 'missing')
|
||||
return []
|
||||
|
||||
return localesStatuses[locale.value].missing
|
||||
return localesStatuses[locale.value]!.missing
|
||||
})
|
||||
|
||||
const outdatedEntries = computed<string[]>(() => {
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
title: Elk
|
||||
navigation: false
|
||||
layout: page
|
||||
---
|
||||
|
||||
::block-hero
|
||||
---
|
||||
cta:
|
||||
- Read more
|
||||
- /guide
|
||||
secondary:
|
||||
- Try it out →
|
||||
- https://elk.zone
|
||||
---
|
||||
|
||||
#title
|
||||
Elk
|
||||
|
||||
#description
|
||||
An in-progress, nimble Mastodon web client
|
||||
|
||||
#support
|
||||

|
||||
|
||||
#extra
|
||||
::list
|
||||
- markdown support
|
||||
- code blocks
|
||||
- reordering and connecting posts in timelines
|
||||
- multi account
|
||||
- GitHub HTML cards
|
||||
- and more...
|
||||
::
|
||||
|
||||
::
|
||||
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
title: Introduction
|
||||
description: Get started with Elk, the nimble Mastodon web client.
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
## What is Elk?
|
||||
|
|
@ -16,7 +21,7 @@ Elk provides some features not available through the standard Mastodon web app i
|
|||
|
||||
You can use Elk right in your browser.
|
||||
On a mobile device, you can install the app to your home screen right from your browser for easy access.
|
||||
(This is called a Progressive Web App, or [PWA](../80.pwa.md).)
|
||||
(This is called a Progressive Web App, or [PWA](../pwa.md).)
|
||||
|
||||
Want to try it out?
|
||||
Visit https://elk.zone, type in your Mastodon server address, then log in.
|
||||
|
|
@ -50,7 +55,7 @@ Using a client, you can
|
|||
- View, add, or participate in polls
|
||||
- Follow, unfollow, mute, and block accounts
|
||||
|
||||
::alert{type="info"}
|
||||
::callout{type="info"}
|
||||
**Note:** Not all clients provide all features.
|
||||
::
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: Features
|
||||
description: Discover the features that make Elk a delightful Mastodon client.
|
||||
---
|
||||
|
||||
# Features
|
||||
|
||||
::alert{type=warning}
|
||||
::callout{type=warning}
|
||||
🚧 This section is a work in progress. 🚧
|
||||
::
|
||||
|
||||
|
|
@ -23,7 +28,7 @@ Elk renders basic Markdown-like text markup in post texts as the expected HTML.
|
|||
- Use one asterisk (`*`) before and after a word or phrase to *italicize** the text.
|
||||
- Surround the text with two asterisks (`**word**`) to **bold** it.
|
||||
|
||||
::alert{type="warning"}
|
||||
::callout{type="warning"}
|
||||
Many apps do not support Markdown in posts.
|
||||
Mastodon itself does not support Markdown in posts.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
title: Contributing
|
||||
description: Learn how to contribute to Elk and help build the future of Mastodon clients.
|
||||
---
|
||||
|
||||
# Contributing
|
||||
|
||||
We're really excited that you're interested in contributing to Elk! Before submitting your contribution, please read through the following guide.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
title: Sponsoring
|
||||
description: Support the development of Elk by sponsoring the team.
|
||||
---
|
||||
|
||||
# Sponsoring
|
||||
|
||||
If you're enjoying the app, consider sponsoring our team:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
# Netlify and Cloudflare
|
||||
---
|
||||
title: Netlify and Cloudflare
|
||||
description: Deploy your own Elk instance.
|
||||
---
|
||||
|
||||
Want to host Elk for your Mastodon instance? You came to the right place!
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
title: Progressive Web App
|
||||
description: Learn about Elk's PWA capabilities and how to install it on your device.
|
||||
---
|
||||
|
||||
# PWA
|
||||
|
||||
Elk provides a PWA (Progressive Web App) that can be installed on your desktop/device. This allows you to use Elk as a native app on your device, and it will work offline.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
title: Privacy Policy
|
||||
description: Elk's privacy policy and data handling practices.
|
||||
---
|
||||
|
||||
# Privacy
|
||||
|
||||
> Last updated January 27, 2023
|
||||
|
|
@ -8,7 +13,7 @@ This privacy notice for Elk describes how we handle your information when you:
|
|||
|
||||
- Download and use our mobile or desktop application (Elk)
|
||||
|
||||
::alert{type=warning}
|
||||
::callout{type="warning"}
|
||||
Elk is [open source](https://github.com/elk-zone/elk) and other websites that link to this privacy notice may not be affiliated with Elk or bound by this policy.
|
||||
::
|
||||
|
||||
|
|
|
|||
158
docs/content/index.md
Executable file
158
docs/content/index.md
Executable file
|
|
@ -0,0 +1,158 @@
|
|||
---
|
||||
seo:
|
||||
title: "Elk - A Nimble Mastodon Web Client"
|
||||
description: A nimble Mastodon web client that provides a fresh and intuitive social media experience with modern features and elegant design.
|
||||
ogImage: https://docs.elk.zone/elk-screenshot.png
|
||||
---
|
||||
|
||||
::u-page-hero
|
||||
---
|
||||
orientation: horizontal
|
||||
---
|
||||
:::div{.hidden.lg:flex.items-center.justify-center}
|
||||
{.rounded-lg.shadow-lg}
|
||||
:::
|
||||
|
||||
#title
|
||||
A Nimble [Mastodon Web Client]{.text-primary}
|
||||
|
||||
#description
|
||||
Experience Mastodon like never before. Elk brings you a fresh, intuitive interface with modern features that make social networking delightful.
|
||||
|
||||
#links
|
||||
:::u-button
|
||||
---
|
||||
icon: i-ph-rocket-launch-duotone
|
||||
size: xl
|
||||
to: /guide
|
||||
---
|
||||
Read the docs
|
||||
:::
|
||||
|
||||
:::u-button
|
||||
---
|
||||
icon: i-ph-arrow-square-out-duotone
|
||||
size: xl
|
||||
variant: outline
|
||||
to: https://elk.zone
|
||||
target: _blank
|
||||
---
|
||||
Try it live
|
||||
:::
|
||||
::
|
||||
|
||||
::u-page-section
|
||||
#title
|
||||
Everything you need for the perfect [Mastodon experience]{.text-primary}
|
||||
|
||||
#features
|
||||
:::u-page-card
|
||||
---
|
||||
spotlight: true
|
||||
icon: i-ph-markdown-logo-duotone
|
||||
to: /guide/features
|
||||
---
|
||||
#title
|
||||
Rich Content Support
|
||||
|
||||
#description
|
||||
Full Markdown support with syntax highlighting, emoji reactions, and rich media previews that bring your posts to life.
|
||||
:::
|
||||
|
||||
:::u-page-card
|
||||
---
|
||||
spotlight: true
|
||||
icon: i-ic-twotone-view-timeline
|
||||
to: /guide/features
|
||||
---
|
||||
#title
|
||||
Smart Timeline Management
|
||||
|
||||
#description
|
||||
Reorder and connect posts in your timeline with intelligent grouping and enhanced notification management.
|
||||
:::
|
||||
|
||||
:::u-page-card
|
||||
---
|
||||
spotlight: true
|
||||
icon: i-ph-users-duotone
|
||||
to: /guide/features
|
||||
---
|
||||
#title
|
||||
Multi-Account Support
|
||||
|
||||
#description
|
||||
Seamlessly manage multiple Mastodon accounts with quick switching and unified notifications.
|
||||
:::
|
||||
|
||||
:::u-page-card
|
||||
---
|
||||
spotlight: true
|
||||
icon: i-ph-github-logo-duotone
|
||||
to: /guide/features
|
||||
---
|
||||
#title
|
||||
GitHub Integration
|
||||
|
||||
#description
|
||||
Beautiful HTML cards for GitHub links with repository previews and rich metadata display.
|
||||
:::
|
||||
|
||||
:::u-page-card
|
||||
---
|
||||
spotlight: true
|
||||
icon: i-ph-device-mobile-duotone
|
||||
to: /pwa
|
||||
---
|
||||
#title
|
||||
Progressive Web App
|
||||
|
||||
#description
|
||||
Install Elk on any device for a native-like experience with offline support and push notifications.
|
||||
:::
|
||||
|
||||
:::u-page-card
|
||||
---
|
||||
spotlight: true
|
||||
icon: i-ph-heart-duotone
|
||||
to: /guide/contributing
|
||||
---
|
||||
#title
|
||||
Open Source & Community Driven
|
||||
|
||||
#description
|
||||
Built with love by the community. Contribute to the future of federated social media.
|
||||
:::
|
||||
::
|
||||
|
||||
::u-page-section
|
||||
---
|
||||
orientation: horizontal
|
||||
---
|
||||
#title
|
||||
Ready to dive in?
|
||||
|
||||
#description
|
||||
Join thousands of users who have already discovered a better way to experience Mastodon. Get started in minutes with our comprehensive documentation.
|
||||
|
||||
#links
|
||||
:::u-button
|
||||
---
|
||||
icon: i-ph-book-open-duotone
|
||||
size: xl
|
||||
to: /guide
|
||||
---
|
||||
Read the docs
|
||||
:::
|
||||
|
||||
:::u-button
|
||||
---
|
||||
icon: i-ph-github-logo-duotone
|
||||
size: xl
|
||||
variant: outline
|
||||
to: https://github.com/elk-zone/elk
|
||||
target: _blank
|
||||
---
|
||||
View on GitHub
|
||||
:::
|
||||
::
|
||||
|
|
@ -1,5 +1,17 @@
|
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
extends: '@nuxt-themes/docus',
|
||||
extends: ['docus'],
|
||||
|
||||
css: ['~/assets/css/main.css'],
|
||||
|
||||
site: {
|
||||
name: 'Elk',
|
||||
url: 'https://docs.elk.zone',
|
||||
},
|
||||
|
||||
llms: {
|
||||
domain: 'https://docs.elk.zone',
|
||||
},
|
||||
|
||||
vite: {
|
||||
optimizeDeps: {
|
||||
|
|
|
|||
|
|
@ -3,16 +3,14 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "nuxi dev",
|
||||
"build": "nuxi build",
|
||||
"generate": "nuxi generate",
|
||||
"preview": "nuxi preview"
|
||||
"dev": "nuxt dev",
|
||||
"build": "nuxt build",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"theme-colors": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt-themes/docus": "^1.15.1",
|
||||
"nuxt": "^3.18.1"
|
||||
"better-sqlite3": "^12.4.1",
|
||||
"docus": "^4.0.0",
|
||||
"nuxt": "^4.1.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
import { defineTheme } from 'pinceau'
|
||||
import { getColors } from 'theme-colors'
|
||||
|
||||
const light = getColors('#995e1b')
|
||||
const primary = Object
|
||||
.entries(getColors('#d98018'))
|
||||
.reduce((acc, [key, value]) => {
|
||||
acc[key] = {
|
||||
initial: light[key]!,
|
||||
dark: value,
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<string | number, { initial: string, dark: string }>)
|
||||
|
||||
export default defineTheme({
|
||||
color: { primary },
|
||||
})
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { BuildInfo } from '#shared/types'
|
||||
import { createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||
import type { BuildInfo } from '../shared/types'
|
||||
import { createResolver, defineNuxtModule } from 'nuxt/kit'
|
||||
import { isCI } from 'std-env'
|
||||
import { getEnv, version } from '../config/env'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { lstat } from 'node:fs'
|
||||
import { createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||
import { createResolver, defineNuxtModule } from 'nuxt/kit'
|
||||
import { currentLocales } from '../config/i18n'
|
||||
|
||||
const virtual = 'virtual:emoji-mart-lang-importer'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
|
||||
import MagicString from 'magic-string'
|
||||
import { addVitePlugin, defineNuxtModule } from 'nuxt/kit'
|
||||
|
||||
export default defineNuxtModule({
|
||||
meta: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ManifestOptions } from 'vite-plugin-pwa'
|
||||
import { Buffer } from 'node:buffer'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { createResolver } from '@nuxt/kit'
|
||||
import { createResolver } from 'nuxt/kit'
|
||||
import { THEME_COLORS } from '../../app/constants/index'
|
||||
import { getEnv } from '../../config/env'
|
||||
import { currentLocales } from '../../config/i18n'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import type { VitePWANuxtOptions } from './types'
|
|||
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
||||
import { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||
import { addPlugin, createResolver, defineNuxtModule } from 'nuxt/kit'
|
||||
import { join, resolve } from 'pathe'
|
||||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { configurePWAOptions } from './config'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { BuildInfo } from './shared/types'
|
||||
import { createResolver, useNuxt } from '@nuxt/kit'
|
||||
import { resolveModulePath } from 'exsolve'
|
||||
import { createResolver, useNuxt } from 'nuxt/kit'
|
||||
import { isCI, isDevelopment, isWindows } from 'std-env'
|
||||
import { isPreview } from './config/env'
|
||||
import { currentLocales } from './config/i18n'
|
||||
|
|
@ -11,12 +11,10 @@ const { resolve } = createResolver(import.meta.url)
|
|||
const mockProxy = resolveModulePath('mocked-exports/proxy', { from: import.meta.url })
|
||||
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2024-09-11',
|
||||
future: {
|
||||
compatibilityVersion: 4,
|
||||
},
|
||||
compatibilityDate: '2025-07-11',
|
||||
typescript: {
|
||||
tsConfig: {
|
||||
include: ['../tests/nuxt'],
|
||||
exclude: ['../service-worker'],
|
||||
compilerOptions: {
|
||||
// TODO: enable this once we fix the issues
|
||||
|
|
@ -37,11 +35,6 @@ export default defineNuxtConfig({
|
|||
'@unlazy/nuxt',
|
||||
'@nuxt/test-utils/module',
|
||||
...(isDevelopment || isWindows) ? [] : ['nuxt-security'],
|
||||
'~~/modules/emoji-mart-translation',
|
||||
'~~/modules/purge-comments',
|
||||
'~~/modules/build-env',
|
||||
'~~/modules/pwa/index', // change to '@vite-pwa/nuxt' once released and remove pwa module
|
||||
'stale-dep/nuxt',
|
||||
],
|
||||
vue: {
|
||||
propsDestructure: true,
|
||||
|
|
@ -61,6 +54,9 @@ export default defineNuxtConfig({
|
|||
experimental: {
|
||||
payloadExtraction: false,
|
||||
renderJsonPayloads: true,
|
||||
// Temporary workaround to avoid hash mismatch issue
|
||||
// ref. https://github.com/elk-zone/elk/issues/3385#issuecomment-3335167005
|
||||
entryImportMap: false,
|
||||
},
|
||||
css: [
|
||||
'@unocss/reset/tailwind.css',
|
||||
|
|
@ -315,48 +311,19 @@ export default defineNuxtConfig({
|
|||
colorMode: { classSuffix: '' },
|
||||
i18n: {
|
||||
locales: currentLocales,
|
||||
lazy: true,
|
||||
strategy: 'no_prefix',
|
||||
detectBrowserLanguage: false,
|
||||
// relative to i18n dir on rootDir: not yet v4 compat layout
|
||||
langDir: '../locales',
|
||||
defaultLocale: 'en-US',
|
||||
experimental: {
|
||||
generatedLocaleFilePathFormat: 'relative',
|
||||
},
|
||||
vueI18n: '../config/i18n.config.ts',
|
||||
bundle: {
|
||||
optimizeTranslationDirective: false,
|
||||
},
|
||||
},
|
||||
pwa,
|
||||
staleDep: {
|
||||
packageManager: 'pnpm',
|
||||
},
|
||||
unlazy: {
|
||||
ssr: false,
|
||||
},
|
||||
})
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line ts/no-namespace
|
||||
namespace NodeJS {
|
||||
interface Process {
|
||||
mock?: Record<string, any>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module '#app' {
|
||||
interface PageMeta {
|
||||
wideLayout?: boolean
|
||||
}
|
||||
|
||||
interface RuntimeNuxtHooks {
|
||||
'elk-logo:click': () => void
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@nuxt/schema' {
|
||||
interface AppConfig {
|
||||
storage: any
|
||||
|
|
|
|||
104
package.json
104
package.json
|
|
@ -2,35 +2,35 @@
|
|||
"name": "@elk-zone/elk",
|
||||
"type": "module",
|
||||
"version": "0.16.0",
|
||||
"packageManager": "pnpm@10.15.1",
|
||||
"packageManager": "pnpm@10.17.1",
|
||||
"license": "MIT",
|
||||
"homepage": "https://elk.zone/",
|
||||
"main": "./nuxt.config.ts",
|
||||
"scripts": {
|
||||
"build": "nuxi build",
|
||||
"dev": "nuxi dev --port 5314",
|
||||
"dev:pwa": "VITE_DEV_PWA=true nuxi dev --port 5314",
|
||||
"dev:mocked": "nuxi dev --port 5314 --dotenv .env.mock",
|
||||
"dev:mocked:pwa": "VITE_DEV_PWA=true nuxi dev --port 5314 --dotenv .env.mock",
|
||||
"dev:mocked:pwa:ssl": "VITE_DEV_PWA=true nuxi dev --port 5314 --https --ssl-cert ./https-dev-config/localhost.crt --ssl-key ./https-dev-config/localhost.key --dotenv .env.mock",
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev --port 5314",
|
||||
"dev:pwa": "VITE_DEV_PWA=true nuxt dev --port 5314",
|
||||
"dev:mocked": "nuxt dev --port 5314 --dotenv .env.mock",
|
||||
"dev:mocked:pwa": "VITE_DEV_PWA=true nuxt dev --port 5314 --dotenv .env.mock",
|
||||
"dev:mocked:pwa:ssl": "VITE_DEV_PWA=true nuxt dev --port 5314 --https --ssl-cert ./https-dev-config/localhost.crt --ssl-key ./https-dev-config/localhost.key --dotenv .env.mock",
|
||||
"start": "PORT=5314 node .output/server/index.mjs",
|
||||
"start:https": "PORT=5314 node ./https-dev-config/local-https-server.mjs",
|
||||
"lint": "eslint --cache .",
|
||||
"lint:fix": "eslint --cache --fix .",
|
||||
"typecheck": "stale-dep && nuxi typecheck",
|
||||
"prepare": "ignore-dependency-scripts \"tsx scripts/prepare.ts\"",
|
||||
"generate": "nuxi generate",
|
||||
"test:unit": "stale-dep && vitest",
|
||||
"test:unit:ci": "stale-dep && vitest run",
|
||||
"test:typecheck": "stale-dep && vue-tsc --noEmit && vue-tsc --noEmit --project service-worker/tsconfig.json",
|
||||
"test": "nr test:unit",
|
||||
"test:ci": "nr test:unit:ci",
|
||||
"update:team:avatars": "tsx scripts/avatars.ts",
|
||||
"cleanup-translations": "tsx scripts/cleanup-translations.ts",
|
||||
"prepare-translation-status": "tsx scripts/prepare-translation-status.ts",
|
||||
"generate-pwa-icons": "tsx scripts/generate-pwa-icons.ts",
|
||||
"postinstall": "ignore-dependency-scripts \"stale-dep -u && simple-git-hooks && nuxi prepare && nr prepare-translation-status\"",
|
||||
"release": "stale-dep && bumpp && tsx scripts/release.ts"
|
||||
"typecheck": "nuxt typecheck",
|
||||
"prepare": "node scripts/prepare-translation-status.ts && node scripts/prepare.ts",
|
||||
"generate": "nuxt generate",
|
||||
"test:unit": "vitest",
|
||||
"test:unit:ci": "vitest run",
|
||||
"test:typecheck": "vue-tsc -b --noEmit",
|
||||
"test": "vitest",
|
||||
"test:ci": "vitest run",
|
||||
"update:team:avatars": "node scripts/avatars.ts",
|
||||
"cleanup-translations": "node scripts/cleanup-translations.ts",
|
||||
"prepare-translation-status": "node scripts/prepare-translation-status.ts",
|
||||
"generate-pwa-icons": "node scripts/generate-pwa-icons.ts",
|
||||
"postinstall": "simple-git-hooks && nuxt prepare",
|
||||
"release": "bumpp && node scripts/release.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emoji-mart/data": "^1.1.2",
|
||||
|
|
@ -38,15 +38,21 @@
|
|||
"@iconify-emoji/twemoji": "^1.0.2",
|
||||
"@iconify/json": "^2.2.170",
|
||||
"@iconify/utils": "^2.1.22",
|
||||
"@nuxt/devtools": "^2.4.1",
|
||||
"@nuxt/test-utils": "^3.19.0",
|
||||
"@intlify/core-base": "^11.1.12",
|
||||
"@intlify/message-compiler": "^11.1.12",
|
||||
"@intlify/shared": "^11.1.12",
|
||||
"@nuxt/devtools": "^2.6.5",
|
||||
"@nuxt/test-utils": "^3.19.2",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@nuxtjs/i18n": "^9.5.4",
|
||||
"@pinia/nuxt": "^0.11.0",
|
||||
"@nuxtjs/i18n": "^10.1.0",
|
||||
"@pinia/nuxt": "^0.11.2",
|
||||
"@tiptap/core": "2.2.4",
|
||||
"@tiptap/extension-bold": "2.2.4",
|
||||
"@tiptap/extension-character-count": "2.2.4",
|
||||
"@tiptap/extension-code": "2.2.4",
|
||||
"@tiptap/extension-code-block": "2.2.4",
|
||||
"@tiptap/extension-document": "2.2.4",
|
||||
"@tiptap/extension-hard-break": "2.2.4",
|
||||
"@tiptap/extension-history": "2.2.4",
|
||||
"@tiptap/extension-italic": "2.2.4",
|
||||
"@tiptap/extension-mention": "2.2.4",
|
||||
|
|
@ -57,16 +63,19 @@
|
|||
"@tiptap/starter-kit": "2.2.4",
|
||||
"@tiptap/suggestion": "2.2.4",
|
||||
"@tiptap/vue-3": "2.2.4",
|
||||
"@unocss/nuxt": "^66.1.2",
|
||||
"@unhead/schema": "^2.0.17",
|
||||
"@unlazy/nuxt": "^0.12.4",
|
||||
"@unocss/nuxt": "^66.5.2",
|
||||
"@upstash/redis": "^1.27.1",
|
||||
"@vercel/kv": "^3.0.0",
|
||||
"@vue-macros/nuxt": "^1.11.12",
|
||||
"@vue-macros/nuxt": "^1.13.5",
|
||||
"@vueuse/core": "^12.0.0",
|
||||
"@vueuse/gesture": "^2.0.0",
|
||||
"@vueuse/integrations": "^12.0.0",
|
||||
"@vueuse/math": "^12.0.0",
|
||||
"@vueuse/motion": "2.2.6",
|
||||
"@vueuse/nuxt": "^13.2.0",
|
||||
"@vueuse/nuxt": "^13.9.0",
|
||||
"@vueuse/shared": "^13.9.0",
|
||||
"blurhash": "^2.0.5",
|
||||
"browser-fs-access": "^0.38.0",
|
||||
"cheerio": "^1.0.0",
|
||||
|
|
@ -81,23 +90,25 @@
|
|||
"github-reserved-names": "^2.0.4",
|
||||
"happy-dom": "^16.0.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"ignore-dependency-scripts": "^1.0.1",
|
||||
"iso-639-1": "^3.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lru-cache": "^11.0.0",
|
||||
"magic-string": "^0.30.19",
|
||||
"masto": "^7.2.0",
|
||||
"mocked-exports": "^0.1.1",
|
||||
"node-emoji": "^2.1.3",
|
||||
"nuxt-security": "^2.2.0",
|
||||
"nuxt": "^4.1.2",
|
||||
"nuxt-security": "^2.4.0",
|
||||
"page-lifecycle": "^0.1.2",
|
||||
"pinia": "^3.0.2",
|
||||
"pathe": "^2.0.3",
|
||||
"pinia": "^3.0.3",
|
||||
"postcss-nested": "^7.0.0",
|
||||
"prosemirror-highlight": "^0.13.0",
|
||||
"prosemirror-state": "^1.4.3",
|
||||
"rollup-plugin-node-polyfills": "^0.2.1",
|
||||
"shiki": "^1.22.2",
|
||||
"simple-git": "^3.19.1",
|
||||
"slimeform": "^0.10.0",
|
||||
"stale-dep": "^0.8.0",
|
||||
"std-env": "^3.7.0",
|
||||
"string-length": "^5.0.1",
|
||||
"theme-vitesse": "^0.8.0",
|
||||
|
|
@ -106,16 +117,25 @@
|
|||
"ufo": "^1.5.3",
|
||||
"ultrahtml": "^1.5.3",
|
||||
"unimport": "^3.10.0",
|
||||
"unstorage": "^1.17.1",
|
||||
"vite": "^7.1.7",
|
||||
"vite-plugin-pwa": "^0.21.0",
|
||||
"vue": "^3.5.4",
|
||||
"vue-advanced-cropper": "^2.8.9",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"vue-virtual-scroller": "2.0.0-beta.8",
|
||||
"workbox-build": "^7.1.1",
|
||||
"workbox-cacheable-response": "^7.1.0",
|
||||
"workbox-expiration": "^7.1.0",
|
||||
"workbox-precaching": "^7.1.0",
|
||||
"workbox-routing": "^7.1.0",
|
||||
"workbox-strategies": "^7.1.0",
|
||||
"workbox-window": "^7.1.0",
|
||||
"ws": "^8.15.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^5.2.2",
|
||||
"@antfu/ni": "^24.4.0",
|
||||
"@antfu/eslint-config": "^5.4.1",
|
||||
"@antfu/ni": "^26.0.1",
|
||||
"@types/chroma-js": "^3.1.1",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/fnando__sparkline": "^0.3.7",
|
||||
|
|
@ -123,39 +143,31 @@
|
|||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/wicg-file-system-access": "^2023.10.6",
|
||||
"@types/ws": "^8.18.1",
|
||||
"@unlazy/nuxt": "^0.12.4",
|
||||
"@unocss/eslint-config": "^66.4.2",
|
||||
"@vue/test-utils": "2.4.6",
|
||||
"bumpp": "^10.2.3",
|
||||
"consola": "^3.4.2",
|
||||
"eslint": "^9.35.0",
|
||||
"eslint": "^9.36.0",
|
||||
"eslint-plugin-format": "^1.0.1",
|
||||
"flat": "^6.0.1",
|
||||
"fs-extra": "^11.3.1",
|
||||
"lint-staged": "^15.5.2",
|
||||
"nuxt": "^3.18.1",
|
||||
"lint-staged": "^16.1.6",
|
||||
"prettier": "^3.6.2",
|
||||
"sharp": "^0.34.3",
|
||||
"sharp-ico": "^0.1.5",
|
||||
"simple-git-hooks": "^2.13.1",
|
||||
"tsx": "^4.20.5",
|
||||
"typescript": "^5.4.4",
|
||||
"vitest": "3.2.4",
|
||||
"vue-tsc": "^2.1.6"
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"pinceau": "patches/pinceau.patch"
|
||||
}
|
||||
},
|
||||
"resolutions": {
|
||||
"nuxt-component-meta": "0.13.1",
|
||||
"nuxt-component-meta": "0.14.0",
|
||||
"unstorage": "^1.17.1",
|
||||
"vitest": "3.2.4",
|
||||
"vue": "^3.5.4"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "pnpm lint-staged"
|
||||
"pre-commit": "npx lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "eslint --fix"
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
diff --git a/dist/index.d.ts b/dist/index.d.ts
|
||||
index 612f1c7908c2e973870be08c6fba1515e6e2b9ca..445a3b0574c5388b624d537fc17cbf4a08973ded 100644
|
||||
--- a/dist/index.d.ts
|
||||
+++ b/dist/index.d.ts
|
||||
@@ -115,7 +115,7 @@ interface ModuleHooks {
|
||||
interface ModuleOptions extends PinceauOptions {
|
||||
}
|
||||
|
||||
-declare module '@vue/runtime-core' {
|
||||
+declare module 'vue' {
|
||||
interface ComponentCustomProperties {
|
||||
$dt: DtFunction;
|
||||
$pinceau: ComputedRef<string>;
|
||||
18455
pnpm-lock.yaml
18455
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -1,2 +1,21 @@
|
|||
packages:
|
||||
- docs
|
||||
|
||||
ignoreWorkspaceRootCheck: true
|
||||
|
||||
ignoredBuiltDependencies:
|
||||
- '@parcel/watcher'
|
||||
- '@tailwindcss/oxide'
|
||||
- esbuild
|
||||
- vue-demi
|
||||
|
||||
onlyBuiltDependencies:
|
||||
- better-sqlite3
|
||||
- sharp
|
||||
- simple-git-hooks
|
||||
|
||||
packageManagerStrict: false
|
||||
|
||||
shellEmulator: true
|
||||
|
||||
verifyDepsBeforeRun: install
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { writeFile } from 'node:fs/promises'
|
|||
import fs from 'fs-extra'
|
||||
import { ofetch } from 'ofetch'
|
||||
import { join, resolve } from 'pathe'
|
||||
import { elkTeamMembers } from '../app/composables/about'
|
||||
import { elkTeamMembers } from '../app/composables/about.ts'
|
||||
|
||||
const avatarsDir = resolve('./public/avatars/')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Buffer } from 'node:buffer'
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
import { createResolver } from '@nuxt/kit'
|
||||
import { flatten, unflatten } from 'flat'
|
||||
import { currentLocales } from '../config/i18n'
|
||||
import { createResolver } from 'nuxt/kit'
|
||||
import { currentLocales } from '../config/i18n.ts'
|
||||
|
||||
const resolver = createResolver(import.meta.url)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { ThemeColors } from '~/composables/settings'
|
||||
import type { ThemeColors } from '../app/composables/settings'
|
||||
import chroma from 'chroma-js'
|
||||
|
||||
// #cc7d24 -> hcl(67.14,62.19,59.56)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import type { ElkTranslationStatus } from '#shared/types/translation-status'
|
||||
import type { LocaleEntry } from '../docs/types'
|
||||
import type { ElkTranslationStatus } from '../shared/types/translation-status'
|
||||
import { Buffer } from 'node:buffer'
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
import { createResolver } from '@nuxt/kit'
|
||||
import { flatten } from 'flat'
|
||||
import { countryLocaleVariants, currentLocales } from '../config/i18n'
|
||||
import { createResolver } from 'nuxt/kit'
|
||||
import { countryLocaleVariants, currentLocales } from '../config/i18n.ts'
|
||||
|
||||
export const localeData: [code: string, file: string[], title: string][]
|
||||
= currentLocales.map((l: any) => [l.code, l.files ? l.files : [l.file!], l.name ?? l.code])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import process from 'node:process'
|
||||
import fs from 'fs-extra'
|
||||
import { emojiPrefix, iconifyEmojiPackage } from '../config/emojis'
|
||||
import { colorsMap } from './generate-themes'
|
||||
import { emojiPrefix, iconifyEmojiPackage } from '../config/emojis.ts'
|
||||
import { colorsMap } from './generate-themes.ts'
|
||||
|
||||
const dereference = process.platform === 'win32' ? true : undefined
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { stringifyQuery } from 'ufo'
|
||||
|
||||
import { defaultUserAgent } from '~~/server/utils/shared'
|
||||
import { defaultUserAgent, invalidateApp } from '~~/server/utils/shared'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
let { server, origin } = getRouterParams(event)
|
||||
|
|
@ -43,7 +43,51 @@ export default defineEventHandler(async (event) => {
|
|||
const url = `/signin/callback?${stringifyQuery({ server, token: result.access_token, vapid_key: app.vapid_key })}`
|
||||
await sendRedirect(event, url, 302)
|
||||
}
|
||||
catch (error: any) {
|
||||
// Check for invalid client error (OAuth app deleted)
|
||||
if (error?.data?.error === 'invalid_client'
|
||||
|| (error?.statusCode === 401 && error?.data?.error_description?.includes('Client authentication failed'))) {
|
||||
// Invalidate cached app and retry once
|
||||
await invalidateApp(origin, server)
|
||||
|
||||
try {
|
||||
const newApp = await getApp(origin, server)
|
||||
if (!newApp) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: `Failed to re-register app for server: ${server}`,
|
||||
})
|
||||
}
|
||||
|
||||
const retryResult: any = await $fetch(`https://${server}/oauth/token`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'user-agent': defaultUserAgent,
|
||||
},
|
||||
body: {
|
||||
client_id: newApp.client_id,
|
||||
client_secret: newApp.client_secret,
|
||||
redirect_uri: getRedirectURI(origin, server),
|
||||
grant_type: 'authorization_code',
|
||||
code,
|
||||
scope: 'read write follow push',
|
||||
},
|
||||
retry: 1,
|
||||
})
|
||||
|
||||
const url = `/signin/callback?${stringifyQuery({ server, token: retryResult.access_token, vapid_key: newApp.vapid_key })}`
|
||||
await sendRedirect(event, url, 302)
|
||||
return
|
||||
}
|
||||
catch {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'OAuth application recovery failed. Please try again.',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Other errors (network, invalid code, etc.)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'Could not complete log in.',
|
||||
|
|
|
|||
|
|
@ -111,6 +111,12 @@ export async function deleteApp(server: string) {
|
|||
await storage.removeItem(key)
|
||||
}
|
||||
|
||||
export async function invalidateApp(origin: string, server: string) {
|
||||
const host = origin.replace(/^https?:\/\//, '').replace(/\W/g, '-').replace(/\?.*$/, '')
|
||||
const key = `servers:v4:${server}:${host}.json`.toLowerCase()
|
||||
await storage.removeItem(key)
|
||||
}
|
||||
|
||||
export async function listServers() {
|
||||
const keys = await storage.getKeys('servers:v4:')
|
||||
const servers = new Set<string>()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"extends": "../.nuxt/tsconfig.app.json",
|
||||
"noEmit": true,
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext", "WebWorker", "DOM.Iterable"],
|
||||
"types": ["vite/client"]
|
||||
|
|
|
|||
1
service-worker/tsconfig.tsbuildinfo
Normal file
1
service-worker/tsconfig.tsbuildinfo
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"root":["./elk-sw.ts","./notification.ts","./share-target.ts","./types.ts","./web-push-notifications.ts"],"version":"5.9.2"}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/// <reference lib="WebWorker" />
|
||||
/// <reference types="vite/client" />
|
||||
import type { PushPayload } from '~~/service-worker/types'
|
||||
import type { PushPayload } from './types'
|
||||
import { ELK_PAGE_LIFECYCLE_FROZEN } from '../app/constants'
|
||||
import {
|
||||
closeDatabaseConnections,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { RouteLocationRaw } from '#vue-router'
|
||||
import type { mastodon } from 'masto'
|
||||
import type { RouteLocationRaw } from 'vue-router'
|
||||
import type { MarkNonNullable, Mutable } from './utils'
|
||||
|
||||
export interface AppInfo {
|
||||
|
|
@ -43,8 +43,6 @@ export interface GroupedLikeNotifications {
|
|||
|
||||
export type NotificationSlot = GroupedNotifications | GroupedLikeNotifications | mastodon.v1.Notification
|
||||
|
||||
export type TranslateFn = ReturnType<typeof useI18n>['t']
|
||||
|
||||
export interface DraftItem {
|
||||
editingStatus?: mastodon.v1.Status
|
||||
initialText?: string
|
||||
|
|
|
|||
|
|
@ -1,3 +1,20 @@
|
|||
{
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
"references": [
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.server.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.shared.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./service-worker/tsconfig.json"
|
||||
}
|
||||
],
|
||||
"files": []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
import { defineVitestConfig } from '@nuxt/test-utils/config'
|
||||
import { defineVitestProject } from '@nuxt/test-utils/config'
|
||||
import { isCI } from 'std-env'
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineVitestConfig({
|
||||
export default defineConfig({
|
||||
define: {
|
||||
'process.test': 'true',
|
||||
},
|
||||
test: {
|
||||
reporters: isCI ? ['default', 'hanging-process'] : ['default'],
|
||||
projects: [
|
||||
await defineVitestProject({
|
||||
test: {
|
||||
name: 'nuxt',
|
||||
setupFiles: [
|
||||
'./tests/setup.ts',
|
||||
],
|
||||
|
|
@ -19,4 +24,7 @@ export default defineVitestConfig({
|
|||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue