Merge branch 'main' into fvsch/fix-header-overflow-hidden

pull/3331/head
TAKAHASHI Shuuji 2025-09-03 19:58:26 +09:00 zatwierdzone przez GitHub
commit 2554ed6a71
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
20 zmienionych plików z 2996 dodań i 1796 usunięć

Wyświetl plik

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
# workaround for npm registry key change
# ref. `pnpm@10.1.0` / `pnpm@9.15.4` cannot be installed due to key id mismatch · Issue #612 · nodejs/corepack
# - https://github.com/nodejs/corepack/issues/612#issuecomment-2629496091

Wyświetl plik

@ -16,7 +16,7 @@ jobs:
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Docker meta
id: metal
uses: docker/metadata-action@v5

Wyświetl plik

@ -12,7 +12,7 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0

Wyświetl plik

@ -19,6 +19,6 @@ jobs:
name: Semantic Pull Request
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5.5.3
uses: amannn/action-semantic-pull-request@v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Wyświetl plik

@ -45,7 +45,7 @@ One could put Elk behind popular reverse proxies with SSL Handling like Traefik,
1. got into new source dir: ```cd elk```
1. create local storage directory for settings: ```mkdir elk-storage```
1. adjust permissions of storage dir: ```sudo chown 911:911 ./elk-storage```
1. start container: ```docker-compose up --build -d```
1. start container: ```docker compose up --build -d```
> [!NOTE]
> The provided Dockerfile creates a container which will eventually run Elk as non-root user and create a persistent named Docker volume upon first start (if that volume does not yet exist). This volume is always created with root permission. Failing to change the permissions of ```/elk/data``` inside this volume to UID:GID 911 (as specified for Elk in the Dockerfile) will prevent Elk from storing it's config for user accounts. You either have to fix the permission in the created named volume, or mount a directory with the correct permission to ```/elk/data``` into the container.

Wyświetl plik

@ -1,6 +1,6 @@
<script setup lang="ts">
const { as = 'div', active } = defineProps<{
as: any
as?: string
active: boolean
}>()

Wyświetl plik

@ -29,7 +29,7 @@ const emit = defineEmits<{
const { t } = useI18n()
const { threadItems, threadIsActive, publishThread } = threadComposer ?? useThreadComposer(draftKey)
const { threadItems, threadIsActive, publishThread, threadIsSending } = threadComposer ?? useThreadComposer(draftKey)
const draft = computed({
get: () => threadItems.value[draftItemIndex],
@ -577,18 +577,18 @@ const detectLanguage = useDebounceFn(async () => {
<button
v-if="!threadIsActive || isFinalItemOfThread"
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit class="publish-button"
:aria-disabled="isPublishDisabled || isExceedingCharacterLimit" aria-describedby="publish-tooltip"
:disabled="isPublishDisabled || isExceedingCharacterLimit"
:aria-disabled="isPublishDisabled || isExceedingCharacterLimit || threadIsSending" aria-describedby="publish-tooltip"
:disabled="isPublishDisabled || isExceedingCharacterLimit || threadIsSending"
@click="publish"
>
<span v-if="isSending" block animate-spin preserve-3d>
<span v-if="isSending || threadIsSending" block animate-spin preserve-3d>
<div block i-ri:loader-2-fill />
</span>
<span v-if="failedMessages.length" block>
<div block i-carbon:face-dizzy-filled />
</span>
<template v-if="threadIsActive">
<span>{{ $t('action.publish_thread') }} </span>
<span>{{ !threadIsSending ? $t('action.publish_thread') : $t('state.publishing') }} </span>
</template>
<template v-else>
<span v-if="draft.editingStatus">{{ $t('action.save_changes') }}</span>

Wyświetl plik

@ -104,11 +104,12 @@ export function parseMastodonHTML(
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/`/g, '&#96;')
.replace(/\*/g, '&ast;')
const classes = lang ? ` class="language-${lang}"` : ''
return `><pre><code${classes}>${code}</code></pre>`
})
.replace(/`([^`\n]*)`/g, (_1, raw) => {
return raw ? `<code>${htmlToText(raw).replace(/</g, '&lt;').replace(/>/g, '&gt;')}</code>` : ''
return raw ? `<code>${htmlToText(raw).replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\*/g, '&ast;')}</code>` : ''
})
}

Wyświetl plik

@ -95,9 +95,9 @@ export async function toggleMuteAccount(relationship: mastodon.v1.Relationship,
relationship!.muting = !relationship!.muting
relationship = relationship!.muting
? await client.value.v1.accounts.$select(account.id).mute({
duration,
notifications,
})
duration,
notifications,
})
: await client.value.v1.accounts.$select(account.id).unmute()
}

Wyświetl plik

@ -11,6 +11,8 @@ export function useThreadComposer(draftKey: string, initial?: () => DraftItem) {
*/
const threadIsActive = computed<boolean>(() => draftItems.value.length > 1)
const threadIsSending = ref(false)
/**
* Add an item to the thread
*/
@ -44,6 +46,7 @@ export function useThreadComposer(draftKey: string, initial?: () => DraftItem) {
async function publishThread() {
const allFailedMessages: Array<string> = []
const isAReplyThread = Boolean(draftItems.value[0].params.inReplyToId)
threadIsSending.value = true
let lastPublishedStatus: mastodon.v1.Status | null = null
let amountPublished = 0
@ -72,6 +75,7 @@ export function useThreadComposer(draftKey: string, initial?: () => DraftItem) {
}
// Remove all published items from the thread
draftItems.value.splice(0, amountPublished)
threadIsSending.value = false
// If we have errors, return them
if (allFailedMessages.length > 0)
@ -90,5 +94,6 @@ export function useThreadComposer(draftKey: string, initial?: () => DraftItem) {
addThreadItem,
removeThreadItem,
publishThread,
threadIsSending,
}
}

Wyświetl plik

@ -10,6 +10,6 @@ catch (err) {
<template>
<MainContent text-base grid gap-3 m3>
<img rounded-3 :src="instance.thumbnail.url">
<img v-if="instance !== undefined" rounded-3 :src="instance.thumbnail.url">
</MainContent>
</template>

Wyświetl plik

@ -13,6 +13,6 @@
},
"devDependencies": {
"@nuxt-themes/docus": "^1.15.1",
"nuxt": "^3.17.6"
"nuxt": "^3.18.1"
}
}

Wyświetl plik

@ -7,6 +7,8 @@
"route_loaded": "Page {0} chargée"
},
"account": {
"authorize": "Autoriser l'abonnement",
"authorized": "Vous avez autorisé la demande",
"avatar_description": "Avatar de {0}",
"blocked_by": "Ce compte vous a bloqué",
"blocked_domains": "Domaines bloqués",
@ -25,6 +27,7 @@
"follows_you": "@:account.follow_back",
"go_to_profile": "Aller à son profil",
"joined": "a rejoint",
"lock": "Verrouiller",
"moved_title": "a indiqué que son nouveau compte est désormais :",
"muted_users": "Comptes masqués",
"muting": "Masqué·e",
@ -37,7 +40,10 @@
"profile_description": "En-tête du profil de {0}",
"profile_personal_note": "Note personnelle",
"profile_unavailable": "Profil non accessible",
"reject": "Rejeter l'abonnement",
"rejected": "Vous avez rejeté la demande",
"request_follow": "Demander à suivre",
"requested": "{0} a demandé à vous suivre",
"unblock": "Débloquer",
"unfollow": "Ne plus suivre",
"unmute": "Réafficher",
@ -52,6 +58,7 @@
"boost": "Partager",
"boost_count": "{0}",
"boosted": "Partagé",
"clear": "Effacer",
"clear_publish_failed": "Effacer les erreurs de publication",
"clear_save_failed": "Effacer les erreurs de sauvegarde",
"clear_upload_failed": "Effacer les erreurs de téléversement de fichier",
@ -66,8 +73,10 @@
"favourited": "J'aime",
"more": "Plus",
"next": "Suivant",
"open_image_preview_dialog": "Ouvrir le dialogue d'aperçu de l'image",
"prev": "Précédent",
"publish": "Publier",
"publish_thread": "Publier le fil",
"reply": "Répondre",
"reply_count": "{0}",
"reset": "Réinitialiser",
@ -115,12 +124,14 @@
"block_account": {
"cancel": "Annuler",
"confirm": "Bloquer",
"description": "Voulez-vous vraiment bloquer {0} ?"
"description": "Voulez-vous vraiment bloquer {0} ?",
"title": "Bloquer le compte"
},
"block_domain": {
"cancel": "Annuler",
"confirm": "Bloquer",
"description": "Voulez-vous vraiment bloquer {0} ?"
"description": "Voulez-vous vraiment bloquer {0} ?",
"title": "Bloquer le domaine"
},
"common": {
"cancel": "Non",
@ -129,27 +140,37 @@
"delete_list": {
"cancel": "Annuler",
"confirm": "Supprimer",
"description": "Voulez-vous vraiment supprimer la liste \"{0}\" ?"
"description": "Voulez-vous vraiment supprimer la liste \"{0}\" ?",
"title": "Supprimer la liste"
},
"delete_posts": {
"cancel": "Annuler",
"confirm": "Supprimer",
"description": "Voulez-vous vraiment supprimer ce message ?"
"description": "Voulez-vous vraiment supprimer ce message ?",
"title": "Supprimer le message"
},
"mute_account": {
"cancel": "Annuler",
"confirm": "Mettre en sourdine",
"description": "Voulez-vous vraiment mettre en sourdine {0} ?"
"days": "jour|jour|jour",
"description": "Voulez-vous vraiment mettre en sourdine {0} ?",
"hours": "heures|heures|heures",
"minute": "minutes|minutes|minutes",
"notifications": "Mettre en sourdine les notifications",
"specify_duration": "Spécifier la durée de la mise en sourdine",
"title": "Mettre en sourdine le compte"
},
"show_reblogs": {
"cancel": "Annuler",
"confirm": "Afficher",
"description": "Voulez-vous vraiment afficher les partages de {0} ?"
"description": "Voulez-vous vraiment afficher les partages de {0} ?",
"title": "Afficher les partages"
},
"unfollow": {
"cancel": "Annuler",
"confirm": "Se désabonner",
"description": "Voulez-vous vraiment vous désabonner ?"
"description": "Voulez-vous vraiment vous désabonner ?",
"title": "Se désabonner"
}
},
"conversation": {
@ -202,9 +223,12 @@
"error": "Il y a eu une erreur lors de la création de la liste",
"error_prefix": "Erreur :",
"list_title_placeholder": "Nom de la liste",
"manage": "Gérer les listes",
"modify_account": "Modifier les listes de ce compte",
"remove_account": "Supprimer ce compte de listes",
"save": "Enregistrer les changements"
"save": "Enregistrer les changements",
"search_following_desc": "Chercher des personnes que vous suivez",
"search_following_placeholder": "Chercher parmi les personnes que vous suivez"
},
"magic_keys": {
"dialog_header": "Raccourcis clavier",
@ -214,14 +238,26 @@
"command_mode": "Mode commande",
"compose": "Composer",
"favourite": "J'aime",
"search": "Rechercher",
"show_new_items": "Afficher les nouveaux éléments",
"title": "Actions"
},
"media": {
"title": "Média"
},
"navigation": {
"go_to_bookmarks": "Signets",
"go_to_conversations": "Conversations",
"go_to_explore": "Explorer",
"go_to_favourites": "Favoris",
"go_to_federated": "Fédérés",
"go_to_home": "Accueil",
"go_to_lists": "Listes",
"go_to_local": "Local",
"go_to_notifications": "Notifications",
"go_to_profile": "Profil",
"go_to_search": "Rechercher",
"go_to_settings": "Paramètres",
"next_status": "Message suivant",
"previous_status": "Message précédent",
"shortcut_help": "Aide sur les raccourcis",
@ -276,13 +312,16 @@
"built_at": "Dernière compilation {0}",
"compose": "Composer",
"conversations": "Conversations",
"docs": "Documentation",
"explore": "Explorer",
"favourites": "Aimés",
"federated": "Fédérés",
"hashtags": "Hashtags",
"home": "Accueil",
"list": "Liste",
"lists": "Listes",
"local": "Local",
"more_menu": "Plus d'options",
"muted_users": "Comptes masqués",
"notifications": "Notifications",
"privacy": "Données privées",
@ -297,10 +336,12 @@
"zen_mode": "Mode Zen"
},
"notification": {
"and": "et",
"favourited_post": "a aimé votre message",
"followed_you": "vous suit",
"followed_you_count": "{0} personnes vous suivent|{0} personne vous suit|{0} personnes vous suivent",
"missing_type": "MISSING notification.type:",
"others": "{0} personnes|{0} personne|{0} personnes",
"reblogged_post": "a relayé votre message",
"reported": "{0} a signalé {1}",
"request_to_follow": "vous demande de le suivre",
@ -417,6 +458,8 @@
"label": "Paramètres de compte"
},
"interface": {
"bottom_nav": "Navigation inférieure",
"bottom_nav_instructions": "Choisissez jusqu'à cinq boutons de navigation inférieure favoris. Doit inclure le bouton \"Plus d'options\".",
"color_mode": "Couleur de thème",
"dark_mode": "Mode sombre",
"default": " (par défaut)",
@ -428,6 +471,7 @@
},
"language": {
"display_language": "Langue d'affichage",
"how_to_contribute": "Comment contribuer ?",
"label": "Langue",
"post_language": "Langue de publication",
"status": "État de la traduction : {0}/{1} ({2} %)",
@ -495,6 +539,8 @@
},
"notifications_settings": "Notifications",
"preferences": {
"embedded_media": "Lecteur multimédia intégré",
"embedded_media_description": "Affichez un lecteur intégré au lieu de la carte d'aperçu normale lors de l'expansion des liens de streaming de supports partagés.",
"enable_autoplay": "Activer la lecture automatique",
"enable_data_saving": "Activer l'économie de données",
"enable_data_saving_description": "Economise les données en évitant le chargement automatique des médias.",
@ -507,13 +553,16 @@
"hide_boost_count": "Masquer les compteurs de partages",
"hide_favorite_count": "Masquer les compteurs de favoris",
"hide_follower_count": "Masquer les compteurs d'abonné·e·s",
"hide_gif_indi_on_posts": "Masquer l'indicateur de gif sur les messages",
"hide_news": "Masquer les actualités",
"hide_reply_count": "Masquer les compteurs de réponses",
"hide_translation": "Masquer traduction",
"hide_username_emojis": "Masquer les emojis sur le nom d'utilisateur",
"hide_username_emojis_description": "Masque les emojis des noms d'utilisateur dans la timeline. \nLes emojis seront toujours visibles sur leurs profils.",
"label": "Préférences",
"optimize_for_low_performance_device": "Optimiser pour un dispositif à faible performance",
"title": "Fonctionnalités expérimentales",
"unmute_videos": "Son de vidéo par défaut",
"use_star_favorite_icon": "Utiliser l'icône de l'étoile en favoris",
"user_picker": "User Picker",
"user_picker_description": "Affiche tous les avatars des comptes connectés en bas à gauche afin que vous puissiez basculer rapidement entre eux.",
@ -556,7 +605,11 @@
},
"state": {
"attachments_exceed_server_limit": "Le nombre de pièces jointes a dépassé la limite par message.",
"attachments_limit_audio_error": "Taille maximum d'audio dépassée : {0}",
"attachments_limit_error": "Limite par publication dépassée",
"attachments_limit_image_error": "Taille maximum d'image dépassée : {0}",
"attachments_limit_unknown_error": "Taille maximum de fichier dépassée : {0}",
"attachments_limit_video_error": "Taille maximum de vidéo dépassée : {0}",
"edited": "(Édité)",
"editing": "Édition",
"loading": "Chargement...",
@ -573,15 +626,18 @@
},
"boosted_by": "Partagé par",
"edited": "Edité {0}",
"embedded_warning": "Lire ceci peut révéler votre adresse IP à d'autres.",
"favourited_by": "Aimé par",
"filter_hidden_phrase": "Filtré par",
"filter_show_anyway": "Montrer coûte que coûte",
"gif": "GIF",
"img_alt": {
"ALT": "ALT",
"desc": "Description",
"dismiss": "Fermer",
"read": "Lire la description de {0}"
},
"pinned": "Messages épinglés",
"poll": {
"count": "{0} votes",
"ends": "se clôt {0}",
@ -663,6 +719,7 @@
"year_past": "il y a 0 année|l'année dernière|il y a {n} années"
},
"timeline": {
"no_posts": "Pas de messages ici !",
"show_new_items": "Voir le nouveau message|Voir les {v} nouveaux messages",
"view_older_posts": "Les messages plus anciens d'autres instances peuvent ne pas être affichés."
},
@ -675,6 +732,7 @@
"add_emojis": "Ajouter des émoticônes",
"add_media": "Ajouter des images, une vidéo ou un fichier audio",
"add_publishable_content": "Ajouter du contenu à publier",
"add_thread_item": "Ajouter un message au fil",
"change_content_visibility": "Ajuster la confidentialité du message",
"change_language": "Changer la langue",
"emoji": "Emoji",
@ -684,6 +742,8 @@
"open_editor_tools": "Outils d'édition",
"pick_an_icon": "Choisir une icône",
"publish_failed": "Fermez les messages ayant échoué en haut de l'éditeur pour republier les messages",
"remove_thread_item": "Supprimer le message du fil",
"start_thread": "Commencer un fil",
"toggle_bold": "Appliquer/retirer le gras",
"toggle_code_block": "Ajouter un bloc de code",
"toggle_italic": "Appliquer/retirer l'italique"

Wyświetl plik

@ -1,5 +1,4 @@
import type { Ref } from 'vue'
import type { UnwrapNestedRefs } from 'vue'
import type { Ref, UnwrapNestedRefs } from 'vue'
export interface PwaInjection {
isInstalled: boolean

Wyświetl plik

@ -68,7 +68,7 @@
"@vueuse/motion": "2.2.6",
"@vueuse/nuxt": "^13.2.0",
"blurhash": "^2.0.5",
"browser-fs-access": "^0.35.0",
"browser-fs-access": "^0.38.0",
"cheerio": "^1.0.0",
"chroma-js": "^3.0.0",
"emoji-mart": "^5.5.2",
@ -117,7 +117,7 @@
"ws": "^8.15.1"
},
"devDependencies": {
"@antfu/eslint-config": "^4.13.1",
"@antfu/eslint-config": "^5.2.1",
"@antfu/ni": "^24.4.0",
"@types/chroma-js": "^3.1.1",
"@types/file-saver": "^2.0.7",
@ -127,21 +127,21 @@
"@types/wicg-file-system-access": "^2023.10.6",
"@types/ws": "^8.18.1",
"@unlazy/nuxt": "^0.12.4",
"@unocss/eslint-config": "^66.3.2",
"@unocss/eslint-config": "^66.4.2",
"@vue/test-utils": "2.4.6",
"bumpp": "^10.2.0",
"bumpp": "^10.2.3",
"consola": "^3.4.2",
"eslint": "^9.27.0",
"eslint": "^9.34.0",
"eslint-plugin-format": "^1.0.1",
"flat": "^6.0.1",
"fs-extra": "^11.3.0",
"fs-extra": "^11.3.1",
"lint-staged": "^15.5.2",
"nuxt": "^3.17.6",
"prettier": "^3.5.3",
"sharp": "^0.34.2",
"nuxt": "^3.18.1",
"prettier": "^3.6.2",
"sharp": "^0.34.3",
"sharp-ico": "^0.1.5",
"simple-git-hooks": "^2.13.0",
"tsx": "^4.20.3",
"simple-git-hooks": "^2.13.1",
"tsx": "^4.20.5",
"typescript": "^5.4.4",
"vitest": "3.2.4",
"vue-tsc": "^2.1.6"
@ -152,8 +152,8 @@
}
},
"resolutions": {
"nuxt-component-meta": "0.12.1",
"unstorage": "^1.16.0",
"nuxt-component-meta": "0.13.1",
"unstorage": "^1.17.0",
"vitest": "3.2.4",
"vue": "^3.5.4"
},

28
page-lifecycle.d.ts vendored
Wyświetl plik

@ -1,17 +1,17 @@
declare module 'page-lifecycle/dist/lifecycle.mjs' {
type PageLifecycleState = 'active' | 'passive' | 'hidden' | 'frozen' | 'terminated'
type PageLifecycleState = 'active' | 'passive' | 'hidden' | 'frozen' | 'terminated'
interface PageLifecycleEvent extends Event {
newState: PageLifecycleState
oldState: PageLifecycleState
}
interface PageLifecycle extends EventTarget {
get state(): PageLifecycleState
get pageWasDiscarded(): boolean
addUnsavedChanges: (id: symbol | any) => void
removeUnsavedChanges: (id: symbol | any) => void
addEventListener: (type: string, listener: (evt: PageLifecycleEvent) => void) => void
}
const lifecycle: PageLifecycle
export default lifecycle
interface PageLifecycleEvent extends Event {
newState: PageLifecycleState
oldState: PageLifecycleState
}
interface PageLifecycle extends EventTarget {
get state(): PageLifecycleState
get pageWasDiscarded(): boolean
addUnsavedChanges: (id: symbol | any) => void
removeUnsavedChanges: (id: symbol | any) => void
addEventListener: (type: string, listener: (evt: PageLifecycleEvent) => void) => void
}
const lifecycle: PageLifecycle
export default lifecycle
}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -60,7 +60,7 @@ async function fetchAppInfo(origin: string, server: string) {
},
body: {
client_name: APP_NAME + (env !== 'release' ? ` (${env})` : ''),
website: 'https://elk.zone',
website: origin,
redirect_uris: getRedirectURI(origin, server),
scopes: 'read write follow push',
},

Wyświetl plik

@ -1,5 +1,12 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`content-rich > asterisk paris in code block 1`] = `"<p><pre class="code-block">1 * 2 * 3</pre></p>"`;
exports[`content-rich > asterisk paris in inline code 1`] = `
"<p><code>1 * 2 * 3</code></p>
"
`;
exports[`content-rich > block with backticks 1`] = `"<p><pre class="code-block">[(\`number string) (\`tag string)]</pre></p>"`;
exports[`content-rich > block with injected html, with a known language 1`] = `

Wyświetl plik

@ -186,6 +186,16 @@ describe('content-rich', () => {
`)
expect(formatted).toMatchSnapshot()
})
it ('asterisk paris in inline code', async () => {
const { formatted } = await render('<p>`1 * 2 * 3`</p>')
expect(formatted).toMatchSnapshot()
})
it ('asterisk paris in code block', async () => {
const { formatted } = await render('<p>```<br />1 * 2 * 3<br />```</p>')
expect(formatted).toMatchSnapshot()
})
})
describe('editor', () => {