forked from Mirrors/elk
Merge branch 'main' of github.com:elk-zone/elk into feat/interface-font-selector-ui
This commit is contained in:
commit
799d157424
24 changed files with 189 additions and 117 deletions
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
|
@ -1 +1,2 @@
|
||||||
github: [antfu, patak-dev, sxzz, danielroe]
|
github: [elk-zone]
|
||||||
|
open_collective: elk
|
||||||
|
|
|
@ -4,9 +4,13 @@ Hi! We are really excited that you are interested in contributing to Elk. Before
|
||||||
|
|
||||||
Refer also to https://github.com/antfu/contribute.
|
Refer also to https://github.com/antfu/contribute.
|
||||||
|
|
||||||
## Set up your local development environment
|
### Online
|
||||||
|
|
||||||
The package manager used to install and link dependencies must be [pnpm](https://pnpm.io/) (Note: on Linux in a standard Node 16+ environment, you should follow the instructions to install via Node's `corepack` rather than using the `curl` command).
|
You can use [StackBlitz Codeflow](https://stackblitz.com/codeflow) to fix bugs or implement features. You'll also see a Codeflow button on PRs to review them without a local setup. Once the elk repo has been cloned in Codeflow, the dev server will start automatically and print the URL to open the App. You should receive a prompt in the bottom-right suggesting to open it in the Editor or in another Tab. To learn more, check out the [Codeflow docs](https://developer.stackblitz.com/codeflow/what-is-codeflow).
|
||||||
|
|
||||||
|
[![Open in Codeflow](https://developer.stackblitz.com/img/open_in_codeflow.svg)](https://pr.new/elk-zone/elk)
|
||||||
|
|
||||||
|
### Local Setup
|
||||||
|
|
||||||
To develop and test the Elk package:
|
To develop and test the Elk package:
|
||||||
|
|
||||||
|
@ -14,18 +18,33 @@ To develop and test the Elk package:
|
||||||
|
|
||||||
2. Ensure using the latest Node.js (16.x)
|
2. Ensure using the latest Node.js (16.x)
|
||||||
|
|
||||||
3. Elk uses pnpm v7, you must enable [Corepack](https://github.com/nodejs/corepack) by running `corepack enable`.
|
3. The package manager used to install and link dependencies must be [pnpm](https://pnpm.io/) v7. To use it you must first enable [Corepack](https://github.com/nodejs/corepack) by running `corepack enable`. (Note: on Linux in a standard Node 16+ environment, you should follow the instructions to install via Node's `corepack` rather than using the `curl` command)
|
||||||
|
|
||||||
4. Check out a branch where you can work and commit your changes:
|
4. Check out a branch where you can work and commit your changes:
|
||||||
```shell
|
```shell
|
||||||
git checkout -b my-new-branch
|
git checkout -b my-new-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Run `pnpm i` in Elk's root folder
|
1. Run `pnpm i` in Elk's root folder
|
||||||
|
|
||||||
6. Run `pnpm nuxi prepare` in Elk's root folder
|
2. Run `pnpm nuxi prepare` in Elk's root folder
|
||||||
|
|
||||||
7. Run `pnpm dev` in Elk's root folder to start dev server or `pnpm dev:mocked` to start dev server with `@elkdev@universeodon.com` user.
|
3. Run `pnpm dev` in Elk's root folder to start dev server or `pnpm dev:mocked` to start dev server with `@elkdev@universeodon.com` user.
|
||||||
|
|
||||||
|
We recommend installing [ni](https://github.com/antfu/ni#ni), that will use the right package manager in each of your projects. If `ni` is installed, you can instead run:
|
||||||
|
|
||||||
|
```
|
||||||
|
ni
|
||||||
|
nr dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
Elk uses [Vitest](https://vitest.dev). You can run the test suite with:
|
||||||
|
|
||||||
|
```
|
||||||
|
nr test
|
||||||
|
```
|
||||||
|
|
||||||
### Running PWA on dev server
|
### Running PWA on dev server
|
||||||
|
|
||||||
|
|
40
README.md
40
README.md
|
@ -1,11 +1,15 @@
|
||||||
# Elk
|
|
||||||
*A nimble Mastodon web client*
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://elk.zone" target="_blank" rel="noopener noreferrer">
|
<a href="https://elk.zone" target="_blank" rel="noopener noreferrer">
|
||||||
<img width="180" height="180" src="./elk.svg" alt="Elk logo">
|
<img width="160" height="160" src="./public/logo.svg" alt="Elk logo">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h1 align="center"/>Elk <sup><em>alpha</em></sup></h1>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
A nimble Mastodon web client
|
||||||
|
</p>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://chat.elk.zone"><img src="https://img.shields.io/badge/chat-discord-blue?style=flat&logo=discord" alt="discord chat"></a>
|
<a href="https://chat.elk.zone"><img src="https://img.shields.io/badge/chat-discord-blue?style=flat&logo=discord" alt="discord chat"></a>
|
||||||
|
@ -13,9 +17,15 @@
|
||||||
</p>
|
</p>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
# Elk is in early alpha ⚠️
|
<p align="center">
|
||||||
|
<a href="https://elk.zone/" target="_blank" rel="noopener noreferrer" >
|
||||||
|
<img src="./public/elk-og.png" alt="Elk screenshots" height="300">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
It is already quite usable, but it isn't ready for wide adoption yet. We recommend you to use it if you would like to help us build it. We appreciate your feedback and contributions. Check out the [Open Issues](https://github.com/elk-zone/elk/issues) and jump in the action. Join the [Elk discord server](https://chat.elk.zone) to chat with us and learn more about the project.
|
## ⚠️ Elk is in Alpha
|
||||||
|
|
||||||
|
It is already quite usable, but it isn't ready for wide adoption yet. We recommend you use it if you would like to help us build it. We appreciate your feedback and contributions. Check out the [Open Issues](https://github.com/elk-zone/elk/issues) and jump in the action. Join the [Elk discord server](https://chat.elk.zone) to chat with us and learn more about the project.
|
||||||
|
|
||||||
The client is deployed on:
|
The client is deployed on:
|
||||||
|
|
||||||
|
@ -24,9 +34,9 @@ The client is deployed on:
|
||||||
|
|
||||||
You can share screenshots on social media but we prefer you avoid sharing this URL directly until the app is more polished. Feel free to share the URL with your friends and invite others you think could be interested in helping to improve Elk.
|
You can share screenshots on social media but we prefer you avoid sharing this URL directly until the app is more polished. Feel free to share the URL with your friends and invite others you think could be interested in helping to improve Elk.
|
||||||
|
|
||||||
## Sponsors
|
## 💖 Sponsors
|
||||||
|
|
||||||
We want to thanks the generous sponsoring and help of:
|
We are grateful for the generous sponsorship and help of:
|
||||||
|
|
||||||
<a href="https://nuxtlabs.com/" target="_blank" rel="noopener noreferrer" >
|
<a href="https://nuxtlabs.com/" target="_blank" rel="noopener noreferrer" >
|
||||||
<img src="./images/nuxtlabs.svg" alt="NuxtLabs" height="85">
|
<img src="./images/nuxtlabs.svg" alt="NuxtLabs" height="85">
|
||||||
|
@ -37,7 +47,11 @@ We want to thanks the generous sponsoring and help of:
|
||||||
</a>
|
</a>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
And all the companies and individuals sponsoring Elk Team members. If you're enjoying the app, consider sponsoring our team:
|
And all the companies and individuals sponsoring Elk Team and the members. If you're enjoying the app, consider sponsoring us:
|
||||||
|
|
||||||
|
- [Elk Team's GitHub Sponsors](https://github.com/sponsors/elk-zone)
|
||||||
|
|
||||||
|
Or you can sponsor our core team members individually:
|
||||||
|
|
||||||
- [Anthony Fu](https://github.com/sponsors/antfu)
|
- [Anthony Fu](https://github.com/sponsors/antfu)
|
||||||
- [Daniel Roe](https://github.com/sponsors/danielroe)
|
- [Daniel Roe](https://github.com/sponsors/danielroe)
|
||||||
|
@ -46,11 +60,11 @@ And all the companies and individuals sponsoring Elk Team members. If you're enj
|
||||||
|
|
||||||
We would also appreciate sponsoring other contributors to the Elk project. If someone helps you solve an issue or implement a feature you wanted, supporting them would help make this project and OS more sustainable.
|
We would also appreciate sponsoring other contributors to the Elk project. If someone helps you solve an issue or implement a feature you wanted, supporting them would help make this project and OS more sustainable.
|
||||||
|
|
||||||
## Roadmap
|
## 📍 Roadmap
|
||||||
|
|
||||||
[Open board on Volta](https://volta.net/elk-zone/elk)
|
[Open board on Volta](https://volta.net/elk-zone/elk)
|
||||||
|
|
||||||
## Contributing
|
## 🧑💻 Contributing
|
||||||
|
|
||||||
We're really excited that you're interested in contributing to Elk! Before submitting your contribution, please read through the following guide.
|
We're really excited that you're interested in contributing to Elk! Before submitting your contribution, please read through the following guide.
|
||||||
|
|
||||||
|
@ -86,7 +100,7 @@ Elk uses [Vitest](https://vitest.dev). You can run the test suite with:
|
||||||
nr test
|
nr test
|
||||||
```
|
```
|
||||||
|
|
||||||
## Stack
|
## 🦄 Stack
|
||||||
|
|
||||||
- [Vite](https://vitejs.dev/) - Next Generation Frontend Tooling
|
- [Vite](https://vitejs.dev/) - Next Generation Frontend Tooling
|
||||||
- [Nuxt](https://nuxt.com/) - The Intuitive Web Framework
|
- [Nuxt](https://nuxt.com/) - The Intuitive Web Framework
|
||||||
|
@ -100,6 +114,6 @@ nr test
|
||||||
- [shiki](https://shiki.matsu.io/) - A beautiful Syntax Highlighter
|
- [shiki](https://shiki.matsu.io/) - A beautiful Syntax Highlighter
|
||||||
- [vite-plugin-pwa](https://github.com/vite-pwa/vite-plugin-pwa) - Prompt for update and push notifications
|
- [vite-plugin-pwa](https://github.com/vite-pwa/vite-plugin-pwa) - Prompt for update and push notifications
|
||||||
|
|
||||||
## License
|
## 📄 License
|
||||||
|
|
||||||
[MIT](./LICENSE) © 2022-PRESENT Elk contributors
|
[MIT](./LICENSE) © 2022-PRESENT Elk contributors
|
||||||
|
|
9
app.vue
9
app.vue
|
@ -2,6 +2,15 @@
|
||||||
setupPageHeader()
|
setupPageHeader()
|
||||||
provideGlobalCommands()
|
provideGlobalCommands()
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
if (process.server && !route.path.startsWith('/settings')) {
|
||||||
|
useHead({
|
||||||
|
meta: [
|
||||||
|
{ property: 'og:url', content: `https://main.elk.zone${route.path}` },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// We want to trigger rerendering the page when account changes
|
// We want to trigger rerendering the page when account changes
|
||||||
const key = computed(() => `${currentUser.value?.server ?? currentServer.value}:${currentUser.value?.account.id || ''}`)
|
const key = computed(() => `${currentUser.value?.server ?? currentServer.value}:${currentUser.value?.account.id || ''}`)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -26,6 +26,16 @@ function toggleDark() {
|
||||||
@click="userSettings.zenMode = !userSettings.zenMode"
|
@click="userSettings.zenMode = !userSettings.zenMode"
|
||||||
/>
|
/>
|
||||||
</CommonTooltip>
|
</CommonTooltip>
|
||||||
|
<CommonTooltip :content="$t('settings.about.sponsor_action')">
|
||||||
|
<NuxtLink
|
||||||
|
flex
|
||||||
|
text-lg
|
||||||
|
i-ri-heart-3-line hover="i-ri-heart-3-fill text-rose"
|
||||||
|
:aria-label="$t('settings.about.sponsor_action')"
|
||||||
|
href="https://github.com/sponsors/elk-zone"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
</CommonTooltip>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<i18n-t v-if="isHydrated" keypath="nav.built_at">
|
<i18n-t v-if="isHydrated" keypath="nav.built_at">
|
||||||
|
|
|
@ -62,7 +62,7 @@ useCommand({
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<div space-y-1>
|
<div flex="~ col gap-0.5">
|
||||||
<p>
|
<p>
|
||||||
<slot>
|
<slot>
|
||||||
<span>{{ text }}</span>
|
<span>{{ text }}</span>
|
||||||
|
|
31
components/settings/SettingsSponsorsList.vue
Normal file
31
components/settings/SettingsSponsorsList.vue
Normal file
File diff suppressed because one or more lines are too long
|
@ -55,7 +55,10 @@ export function parseMastodonHTML(
|
||||||
// Handle code blocks
|
// Handle code blocks
|
||||||
html = html
|
html = html
|
||||||
.replace(/>(```|~~~)(\w*)([\s\S]+?)\1/g, (_1, _2, lang: string, raw: string) => {
|
.replace(/>(```|~~~)(\w*)([\s\S]+?)\1/g, (_1, _2, lang: string, raw: string) => {
|
||||||
const code = htmlToText(raw).replace(/</g, '<').replace(/>/g, '>')
|
const code = htmlToText(raw)
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/`/, '`')
|
||||||
const classes = lang ? ` class="language-${lang}"` : ''
|
const classes = lang ? ` class="language-${lang}"` : ''
|
||||||
return `><pre><code${classes}>${code}</code></pre>`
|
return `><pre><code${classes}>${code}</code></pre>`
|
||||||
})
|
})
|
||||||
|
|
|
@ -37,6 +37,20 @@ export function onReactivated(hook: Function, target?: ComponentInternalInstance
|
||||||
// TODO: Workaround for Nuxt bug: https://github.com/elk-zone/elk/pull/199#issuecomment-1329771961
|
// TODO: Workaround for Nuxt bug: https://github.com/elk-zone/elk/pull/199#issuecomment-1329771961
|
||||||
export function useHeadFixed<T extends HeadAugmentations>(input: UseHeadInput<T>, options?: HeadEntryOptions): ActiveHeadEntry<UseHeadInput<T>> | void {
|
export function useHeadFixed<T extends HeadAugmentations>(input: UseHeadInput<T>, options?: HeadEntryOptions): ActiveHeadEntry<UseHeadInput<T>> | void {
|
||||||
const deactivated = useDeactivated()
|
const deactivated = useDeactivated()
|
||||||
|
if (input && typeof input === 'object' && !('value' in input)) {
|
||||||
|
const title = 'title' in input ? input.title : undefined
|
||||||
|
if (process.server && title) {
|
||||||
|
input.meta = input.meta || []
|
||||||
|
if (Array.isArray(input.meta)) {
|
||||||
|
input.meta.push(
|
||||||
|
{ property: 'og:title', content: (typeof input.title === 'function' ? input.title() : input.title) as string },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (title) {
|
||||||
|
(input as any).title = () => isHydrated.value ? typeof title === 'function' ? title() : title : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
return useHead(() => {
|
return useHead(() => {
|
||||||
if (deactivated.value)
|
if (deactivated.value)
|
||||||
return {}
|
return {}
|
||||||
|
|
|
@ -236,7 +236,13 @@
|
||||||
"settings": {
|
"settings": {
|
||||||
"about": {
|
"about": {
|
||||||
"label": "About",
|
"label": "About",
|
||||||
"meet_the_team": "Meet the team"
|
"meet_the_team": "Meet the team",
|
||||||
|
"sponsor_action": "Sponsor us",
|
||||||
|
"sponsor_action_desc": "To support the team developing Elk",
|
||||||
|
"sponsors": "Sponsors",
|
||||||
|
"sponsors_body_1": "Elk is made possible thanks the generous sponsoring and help of:",
|
||||||
|
"sponsors_body_2": "And all the companies and individuals sponsoring Elk Team and the members.",
|
||||||
|
"sponsors_body_3": "If you're enjoying the app, consider sponsoring us:"
|
||||||
},
|
},
|
||||||
"account_settings": {
|
"account_settings": {
|
||||||
"description": "Edit your account settings in Mastodon UI",
|
"description": "Edit your account settings in Mastodon UI",
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
toNodeListener,
|
toNodeListener,
|
||||||
} from 'h3'
|
} from 'h3'
|
||||||
import { createFetch } from 'ofetch'
|
import { createFetch } from 'ofetch'
|
||||||
import { parseURL } from 'ufo'
|
|
||||||
import {
|
import {
|
||||||
createCall,
|
createCall,
|
||||||
createFetch as createLocalFetch,
|
createFetch as createLocalFetch,
|
||||||
|
@ -26,13 +25,10 @@ const handlers = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const { protocol, host } = parseURL(window.location.href)
|
|
||||||
|
|
||||||
// @ts-expect-error undeclared global window property
|
// @ts-expect-error undeclared global window property
|
||||||
window.__NUXT__.config = {
|
window.__NUXT__.config = {
|
||||||
// @ts-expect-error undeclared global window property
|
// @ts-expect-error undeclared global window property
|
||||||
...window.__NUXT__.config,
|
...window.__NUXT__.config,
|
||||||
deployUrl: `${protocol}//${host}`,
|
|
||||||
storage: {},
|
storage: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,25 +71,11 @@ export default defineNuxtConfig({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
deployUrl: !isCI
|
|
||||||
? 'http://localhost:5314'
|
|
||||||
: isPreview
|
|
||||||
? process.env.DEPLOY_PRIME_URL
|
|
||||||
: 'https://elk.zone',
|
|
||||||
cloudflare: {
|
cloudflare: {
|
||||||
accountId: '',
|
accountId: '',
|
||||||
namespaceId: '',
|
namespaceId: '',
|
||||||
apiToken: '',
|
apiToken: '',
|
||||||
},
|
},
|
||||||
discord: {
|
|
||||||
inviteUrl: 'https://chat.elk.zone',
|
|
||||||
},
|
|
||||||
github: {
|
|
||||||
// oauth flow
|
|
||||||
clientId: '',
|
|
||||||
clientSecret: '',
|
|
||||||
inviteToken: '',
|
|
||||||
},
|
|
||||||
public: {
|
public: {
|
||||||
env: '', // set in build-env module
|
env: '', // set in build-env module
|
||||||
buildInfo: {} as BuildInfo, // set in build-env module
|
buildInfo: {} as BuildInfo, // set in build-env module
|
||||||
|
@ -132,6 +118,16 @@ export default defineNuxtConfig({
|
||||||
],
|
],
|
||||||
meta: [
|
meta: [
|
||||||
{ name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' },
|
{ name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' },
|
||||||
|
// open graph social image
|
||||||
|
{ property: 'og:title', content: 'Elk' },
|
||||||
|
{ property: 'og:description', content: 'A nimble Mastodon web client' },
|
||||||
|
{ property: 'og:type', content: 'website' },
|
||||||
|
{ property: 'og:image', content: 'https://main.elk.zone/elk-og.png' },
|
||||||
|
{ property: 'og:image:width', content: '3800' },
|
||||||
|
{ property: 'og:image:height', content: '1900' },
|
||||||
|
{ property: 'og:site_name', content: 'Elk' },
|
||||||
|
{ property: 'twitter:site', content: '@elk_zone' },
|
||||||
|
{ property: 'twitter:card', content: 'summary_large_image' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,7 +8,7 @@ const paginator = useMasto().v1.trends.listStatuses()
|
||||||
const hideNewsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_POSTS_TIPS, false)
|
const hideNewsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_POSTS_TIPS, false)
|
||||||
|
|
||||||
useHeadFixed({
|
useHeadFixed({
|
||||||
title: () => isHydrated.value ? `${t('tab.posts')} | ${t('nav.explore')}` : '',
|
title: () => `${t('tab.posts')} | ${t('nav.explore')}`,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ const paginator = useMasto().v1.trends.listLinks()
|
||||||
const hideNewsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_NEWS_TIPS, false)
|
const hideNewsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_NEWS_TIPS, false)
|
||||||
|
|
||||||
useHeadFixed({
|
useHeadFixed({
|
||||||
title: () => isHydrated.value ? `${t('tab.news')} | ${t('nav.explore')}` : '',
|
title: () => `${t('tab.news')} | ${t('nav.explore')}`,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ const paginator = masto.v1.trends.listTags({
|
||||||
const hideTagsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS, false)
|
const hideTagsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS, false)
|
||||||
|
|
||||||
useHeadFixed({
|
useHeadFixed({
|
||||||
title: () => isHydrated.value ? `${t('tab.hashtags')} | ${t('nav.explore')}` : '',
|
title: () => `${t('tab.hashtags')} | ${t('nav.explore')}`,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ const { t } = useI18n()
|
||||||
const paginator = useMasto().v2.suggestions.list({ limit: 20 })
|
const paginator = useMasto().v2.suggestions.list({ limit: 20 })
|
||||||
|
|
||||||
useHeadFixed({
|
useHeadFixed({
|
||||||
title: () => isHydrated.value ? `${t('tab.for_you')} | ${t('nav.explore')}` : '',
|
title: () => `${t('tab.for_you')} | ${t('nav.explore')}`,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
useHeadFixed({
|
useHeadFixed({
|
||||||
title: () => isHydrated.value ? `${t('tab.notifications_all')} | ${t('nav.notifications')}` : '',
|
title: () => `${t('tab.notifications_all')} | ${t('nav.notifications')}`,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
useHeadFixed({
|
useHeadFixed({
|
||||||
title: () => isHydrated.value ? `${t('tab.notifications_mention')} | ${t('nav.notifications')}` : '',
|
title: () => `${t('tab.notifications_mention')} | ${t('nav.notifications')}`,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ const handleShowCommit = () => {
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
:text="$t('nav.show_intro')"
|
:text="$t('nav.show_intro')"
|
||||||
icon="i-ri:article-line"
|
icon="i-ri:article-line"
|
||||||
cursor-pointer
|
cursor-pointer large
|
||||||
@click="openPreviewHelp"
|
@click="openPreviewHelp"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -62,27 +62,58 @@ const handleShowCommit = () => {
|
||||||
text="Mastodon"
|
text="Mastodon"
|
||||||
icon="i-ri:mastodon-line"
|
icon="i-ri:mastodon-line"
|
||||||
to="/m.webtoo.ls/@elk"
|
to="/m.webtoo.ls/@elk"
|
||||||
external target="_blank"
|
external large target="_blank"
|
||||||
/>
|
/>
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
text="Discord"
|
text="Discord"
|
||||||
icon="i-ri:discord-fill"
|
icon="i-ri:discord-fill"
|
||||||
to="https://chat.elk.zone"
|
to="https://chat.elk.zone"
|
||||||
external target="_blank"
|
external large target="_blank"
|
||||||
/>
|
/>
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
text="GitHub"
|
text="GitHub"
|
||||||
icon="i-ri:github-fill"
|
icon="i-ri:github-fill"
|
||||||
to="https://github.com/elk-zone"
|
to="https://github.com/elk-zone"
|
||||||
external target="_blank"
|
external large target="_blank"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div h-1px bg-border my2 />
|
<div h-1px bg-border my2 />
|
||||||
|
|
||||||
|
<p px5 py3 font-bold text-lg>
|
||||||
|
{{ $t('settings.about.sponsors') }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p px5 text-secondary>
|
||||||
|
{{ $t('settings.about.sponsors_body_1') }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<LazySettingsSponsorsList />
|
||||||
|
|
||||||
|
<p px5 mb1 text-secondary>
|
||||||
|
{{ $t('settings.about.sponsors_body_2') }}
|
||||||
|
</p>
|
||||||
|
<p px5 mb2 text-secondary>
|
||||||
|
{{ $t('settings.about.sponsors_body_3') }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<SettingsItem
|
||||||
|
:text="$t('settings.about.sponsor_action')"
|
||||||
|
to="https://github.com/sponsors/elk-zone"
|
||||||
|
:description="$t('settings.about.sponsor_action_desc')"
|
||||||
|
external large target="_blank"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<div i-ri-heart-3-fill text-rose rounded-full w-8 h-8 height="32" width="32" />
|
||||||
|
</template>
|
||||||
|
</SettingsItem>
|
||||||
|
|
||||||
|
<div h-1px bg-border my2 />
|
||||||
|
|
||||||
<template v-if="isHydrated">
|
<template v-if="isHydrated">
|
||||||
<p px5 py3 font-bold text-lg>
|
<p px5 py3 font-bold text-lg>
|
||||||
{{ $t('settings.about.meet_the_team') }}
|
{{ $t('settings.about.meet_the_team') }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
v-for="team in teams" :key="team.github"
|
v-for="team in teams" :key="team.github"
|
||||||
:text="team.display"
|
:text="team.display"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
/* eslint-disable no-alert */
|
||||||
import { fileOpen } from 'browser-fs-access'
|
import { fileOpen } from 'browser-fs-access'
|
||||||
import type { UserLogin } from '~/types'
|
import type { UserLogin } from '~/types'
|
||||||
|
|
||||||
|
|
BIN
public/elk-og.png
Normal file
BIN
public/elk-og.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 879 KiB |
|
@ -1,66 +0,0 @@
|
||||||
const query = (accessToken: string, query: string) =>
|
|
||||||
$fetch<{ data: any }>('https://api.github.com/graphql', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { Authorization: `Bearer ${accessToken}` },
|
|
||||||
body: { query },
|
|
||||||
})
|
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const { code } = getQuery(event)
|
|
||||||
|
|
||||||
const config = useRuntimeConfig()
|
|
||||||
|
|
||||||
if (!code) {
|
|
||||||
const redirect = `&redirect_uri=${config.deployUrl}/invite`
|
|
||||||
const loginURL = `https://github.com/login/oauth/authorize?client_id=${config.github.clientId}${redirect}`
|
|
||||||
await sendRedirect(event, loginURL)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const { access_token } = await $fetch<{ access_token: string }>(
|
|
||||||
'https://github.com/login/oauth/access_token',
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
body: {
|
|
||||||
client_id: config.github.clientId,
|
|
||||||
client_secret: config.github.clientSecret,
|
|
||||||
code,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!access_token) {
|
|
||||||
throw createError({
|
|
||||||
statusCode: 422,
|
|
||||||
statusMessage: 'Authorisation code invalid.',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = await query(access_token, '{ viewer { databaseId } }')
|
|
||||||
.then(r => r.data?.viewer.databaseId)
|
|
||||||
|
|
||||||
if (!id) {
|
|
||||||
throw createError({
|
|
||||||
statusCode: 422,
|
|
||||||
statusMessage: 'Access code invalid.',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
await $fetch(
|
|
||||||
'https://api.github.com/orgs/elk-zone/invitations',
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
body: { invitee_id: id, role: 'direct_member', team_ids: [7042932] },
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/vnd.github+json',
|
|
||||||
'Authorization': `Bearer ${config.github.inviteToken}`,
|
|
||||||
'X-GitHub-Api-Version': '2022-11-28',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return sendRedirect(
|
|
||||||
event,
|
|
||||||
config.discord.inviteUrl,
|
|
||||||
)
|
|
||||||
})
|
|
|
@ -1,5 +1,7 @@
|
||||||
// Vitest Snapshot v1
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
|
exports[`content-rich > block with backticks 1`] = `"<p><pre>[(\`number string) (\`tag string)]</pre></p>"`;
|
||||||
|
|
||||||
exports[`content-rich > code frame 1`] = `
|
exports[`content-rich > code frame 1`] = `
|
||||||
"<p>Testing code block</p><p></p><p><pre lang=\\"ts\\">import { useMouse, usePreferredDark } from '@vueuse/core'
|
"<p>Testing code block</p><p></p><p><pre lang=\\"ts\\">import { useMouse, usePreferredDark } from '@vueuse/core'
|
||||||
// tracks mouse position
|
// tracks mouse position
|
||||||
|
|
|
@ -20,6 +20,11 @@ describe('content-rich', () => {
|
||||||
expect(formatted).toMatchSnapshot()
|
expect(formatted).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it ('block with backticks', async () => {
|
||||||
|
const { formatted } = await render('<p>```<br />[(`number string) (`tag string)]<br />```</p>')
|
||||||
|
expect(formatted).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
it('group mention', async () => {
|
it('group mention', async () => {
|
||||||
const { formatted } = await render('<p><span class="h-card"><a href="https://lemmy.ml/c/pilipinas" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>pilipinas</span></a></span></p>', undefined, [{ id: '', username: 'pilipinas', url: 'https://lemmy.ml/c/pilipinas', acct: 'pilipinas@lemmy.ml' }])
|
const { formatted } = await render('<p><span class="h-card"><a href="https://lemmy.ml/c/pilipinas" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>pilipinas</span></a></span></p>', undefined, [{ id: '', username: 'pilipinas', url: 'https://lemmy.ml/c/pilipinas', acct: 'pilipinas@lemmy.ml' }])
|
||||||
expect(formatted).toMatchSnapshot('html')
|
expect(formatted).toMatchSnapshot('html')
|
||||||
|
|
Loading…
Reference in a new issue