From d1c84a84123c77dede05c023b3697a432b56122c Mon Sep 17 00:00:00 2001 From: Ryan <43447928+Rmiller5466@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:05:59 -0500 Subject: [PATCH 01/11] fix: prompts disappearing on copy / move / upload (#3537) --------- Co-authored-by: Ryan Miller Co-authored-by: Oleg Lobanov --- frontend/src/api/files.ts | 8 +++++--- frontend/src/components/Sidebar.vue | 2 +- frontend/src/components/prompts/Prompts.vue | 11 ++--------- frontend/src/components/prompts/Upload.vue | 2 -- frontend/src/stores/layout.ts | 12 +++++++++++- frontend/src/types/layout.d.ts | 1 + frontend/src/utils/upload.ts | 4 ++++ frontend/src/views/files/FileListing.vue | 2 -- 8 files changed, 24 insertions(+), 18 deletions(-) diff --git a/frontend/src/api/files.ts b/frontend/src/api/files.ts index a36de03f..928f5282 100644 --- a/frontend/src/api/files.ts +++ b/frontend/src/api/files.ts @@ -1,7 +1,8 @@ -import { createURL, fetchURL, removePrefix } from "./utils"; -import { baseURL } from "@/utils/constants"; import { useAuthStore } from "@/stores/auth"; +import { useLayoutStore } from "@/stores/layout"; +import { baseURL } from "@/utils/constants"; import { upload as postTus, useTus } from "./tus"; +import { createURL, fetchURL, removePrefix } from "./utils"; export async function fetch(url: string) { url = removePrefix(url); @@ -156,6 +157,7 @@ function moveCopy( overwrite = false, rename = false ) { + const layoutStore = useLayoutStore(); const promises = []; for (const item of items) { @@ -166,7 +168,7 @@ function moveCopy( }&destination=${to}&override=${overwrite}&rename=${rename}`; promises.push(resourceAction(url, "PATCH")); } - + layoutStore.closeHovers(); return Promise.all(promises); } diff --git a/frontend/src/components/Sidebar.vue b/frontend/src/components/Sidebar.vue index d88d2d2f..543818ad 100644 --- a/frontend/src/components/Sidebar.vue +++ b/frontend/src/components/Sidebar.vue @@ -101,7 +101,7 @@ href="https://github.com/filebrowser/filebrowser" >File Browser - {{ ' ' }} {{ version }} + {{ " " }} {{ version }} {{ $t("sidebar.help") }} diff --git a/frontend/src/components/prompts/Prompts.vue b/frontend/src/components/prompts/Prompts.vue index 4ecde794..71e4e753 100644 --- a/frontend/src/components/prompts/Prompts.vue +++ b/frontend/src/components/prompts/Prompts.vue @@ -3,7 +3,7 @@ diff --git a/frontend/src/css/fonts.css b/frontend/src/css/fonts.css index c32e1e01..2e65cff6 100644 --- a/frontend/src/css/fonts.css +++ b/frontend/src/css/fonts.css @@ -63,8 +63,8 @@ local("Roboto"), local("Roboto-Regular"), url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2"); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, - U+A720-A7FF; + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, + U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -142,8 +142,8 @@ local("Roboto Medium"), local("Roboto-Medium"), url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2"); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, - U+A720-A7FF; + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, + U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -221,8 +221,8 @@ local("Roboto Bold"), local("Roboto-Bold"), url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2"); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, - U+A720-A7FF; + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, + U+2C60-2C7F, U+A720-A7FF; } @font-face { diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts index a16a0a6a..f0b0304b 100644 --- a/frontend/src/i18n/index.ts +++ b/frontend/src/i18n/index.ts @@ -142,7 +142,7 @@ export const i18n = createI18n({ export const isRtl = (locale?: string) => { // see below - // @ts-ignore + // @ts-expect-error incorrect type when legacy return rtlLanguages.includes(locale || i18n.global.locale.value); }; @@ -150,7 +150,7 @@ export function setLocale(locale: string) { dayjs.locale(locale); // according to doc u only need .value if legacy: false but they lied // https://vue-i18n.intlify.dev/guide/essentials/scope.html#local-scope-1 - //@ts-ignore + // @ts-expect-error incorrect type when legacy i18n.global.locale.value = locale; } diff --git a/frontend/src/utils/auth.ts b/frontend/src/utils/auth.ts index a83719ce..b868d90f 100644 --- a/frontend/src/utils/auth.ts +++ b/frontend/src/utils/auth.ts @@ -24,7 +24,7 @@ export async function validateLogin() { await renew(localStorage.getItem("jwt")); } } catch (error) { - console.warn("Invalid JWT token in storage"); // eslint-disable-line + console.warn("Invalid JWT token in storage"); throw error; } } diff --git a/frontend/src/utils/buttons.ts b/frontend/src/utils/buttons.ts index 6a8ac249..30ed74f2 100644 --- a/frontend/src/utils/buttons.ts +++ b/frontend/src/utils/buttons.ts @@ -4,7 +4,7 @@ function loading(button: string) { ); if (el === undefined || el === null) { - console.log("Error getting button " + button); // eslint-disable-line + console.log("Error getting button " + button); return; } @@ -30,7 +30,7 @@ function done(button: string) { ); if (el === undefined || el === null) { - console.log("Error getting button " + button); // eslint-disable-line + console.log("Error getting button " + button); return; } @@ -51,7 +51,7 @@ function success(button: string) { ); if (el === undefined || el === null) { - console.log("Error getting button " + button); // eslint-disable-line + console.log("Error getting button " + button); return; } diff --git a/frontend/src/utils/clipboard.ts b/frontend/src/utils/clipboard.ts index 136f1ad4..23bb7895 100644 --- a/frontend/src/utils/clipboard.ts +++ b/frontend/src/utils/clipboard.ts @@ -1,39 +1,36 @@ // Based on code by the following links: // https://stackoverflow.com/a/74528564 // https://web.dev/articles/async-clipboard -export function copy(text: string) { + +interface ClipboardArgs { + text?: string; + data?: ClipboardItems; +} + +interface ClipboardOpts { + permission?: boolean; +} + +export function copy(data: ClipboardArgs, opts?: ClipboardOpts) { return new Promise((resolve, reject) => { if ( // Clipboard API requires secure context window.isSecureContext && - typeof navigator.clipboard !== "undefined" && - // @ts-ignore - navigator.permissions !== "undefined" + typeof navigator.clipboard !== "undefined" ) { - navigator.permissions - // @ts-ignore - .query({ name: "clipboard-write" }) - .then((permission) => { - if (permission.state === "granted" || permission.state === "prompt") { - // simple writeText should work for all modern browsers - navigator.clipboard.writeText(text).then(resolve).catch(reject); - } else { - reject(new Error("Permission not granted!")); - } - }) - .catch((e) => { - // Firefox doesn't support clipboard-write permission - if (navigator.userAgent.indexOf("Firefox") != -1) { - navigator.clipboard.writeText(text).then(resolve).catch(reject); - } else { - reject(e); - } - }); + if (opts?.permission) { + getPermission("clipboard-write") + .then(() => writeToClipboard(data).then(resolve).catch(reject)) + .catch(reject); + } else { + writeToClipboard(data).then(resolve).catch(reject); + } } else if ( document.queryCommandSupported && - document.queryCommandSupported("copy") + document.queryCommandSupported("copy") && + data.text // old method only supports text ) { - const textarea = createTemporaryTextarea(text); + const textarea = createTemporaryTextarea(data.text); const body = document.activeElement || document.body; try { body.appendChild(textarea); @@ -54,6 +51,35 @@ export function copy(text: string) { }); } +function getPermission(name: string) { + return new Promise((resolve, reject) => { + typeof navigator.permissions !== "undefined" && + navigator.permissions + // @ts-expect-error chrome specific api + .query({ name }) + .then((permission) => { + if (permission.state === "granted" || permission.state === "prompt") { + resolve(); + } else { + reject(new Error("Permission denied!")); + } + }); + }); +} + +function writeToClipboard(data: ClipboardArgs) { + if (data.text) { + return navigator.clipboard.writeText(data.text); + } + if (data.data) { + return navigator.clipboard.write(data.data); + } + + return new Promise((resolve, reject) => { + reject(new Error("No data was supplied!")); + }); +} + const styles = { fontSize: "12pt", position: "fixed", @@ -69,10 +95,10 @@ const styles = { background: "transparent", }; -const createTemporaryTextarea = (text: string) => { +function createTemporaryTextarea(text: string) { const textarea = document.createElement("textarea"); textarea.value = text; textarea.setAttribute("readonly", ""); Object.assign(textarea.style, styles); return textarea; -}; +} diff --git a/frontend/src/utils/css.ts b/frontend/src/utils/css.ts index d727786b..aca6c62a 100644 --- a/frontend/src/utils/css.ts +++ b/frontend/src/utils/css.ts @@ -6,13 +6,16 @@ export default function getRule(rules: string[]) { let result = null; const find = Array.prototype.find; - find.call(document.styleSheets, (styleSheet) => { - result = find.call(styleSheet.cssRules, (cssRule) => { + find.call(document.styleSheets, (styleSheet: CSSStyleSheet) => { + result = find.call(styleSheet.cssRules, (cssRule: CSSRule) => { let found = false; - if (cssRule instanceof window.CSSStyleRule) { + // faster than checking instanceof for every element + if (cssRule.constructor.name === "CSSStyleRule") { for (let i = 0; i < rules.length; i++) { - if (cssRule.selectorText.toLowerCase() === rules[i]) { + if ( + (cssRule as CSSStyleRule).selectorText.toLowerCase() === rules[i] + ) { found = true; } } @@ -24,5 +27,5 @@ export default function getRule(rules: string[]) { return result != null; }); - return result; + return result as CSSStyleRule | null; } diff --git a/frontend/src/views/Share.vue b/frontend/src/views/Share.vue index 53f0cfb1..40b940b5 100644 --- a/frontend/src/views/Share.vue +++ b/frontend/src/views/Share.vue @@ -325,6 +325,7 @@ const token = ref(""); const audio = ref(); const tag = ref(false); +const $showError = inject("$showError")!; const $showSuccess = inject("$showSuccess")!; const { t } = useI18n({}); @@ -463,9 +464,9 @@ const download = () => { if (req.value === null) return false; layoutStore.closeHovers(); - let files: string[] = []; + const files: string[] = []; - for (let i of fileStore.selected) { + for (const i of fileStore.selected) { files.push(req.value.items[i].path); } @@ -488,13 +489,23 @@ const linkSelected = () => { }; const copyToClipboard = (text: string) => { - copy(text).then( + copy({ text }).then( () => { // clipboard successfully set $showSuccess(t("success.linkCopied")); }, () => { // clipboard write failed + copy({ text }, { permission: true }).then( + () => { + // clipboard successfully set + $showSuccess(t("success.linkCopied")); + }, + (e) => { + // clipboard write failed + $showError(e); + } + ); } ); }; diff --git a/frontend/src/views/files/Editor.vue b/frontend/src/views/files/Editor.vue index 7e4d7a9b..9e9b6b68 100644 --- a/frontend/src/views/files/Editor.vue +++ b/frontend/src/views/files/Editor.vue @@ -108,7 +108,7 @@ onMounted(() => { showPrintMargin: false, readOnly: fileStore.req?.type === "textImmutable", theme: "ace/theme/chrome", - mode: modelist.getModeForPath(fileStore.req?.name).mode, + mode: modelist.getModeForPath(fileStore.req!.name).mode, wrap: true, enableBasicAutocompletion: true, enableLiveAutocompletion: true, @@ -173,7 +173,7 @@ const close = () => { fileStore.updateRequest(null); - let uri = url.removeLastDir(route.path) + "/"; + const uri = url.removeLastDir(route.path) + "/"; router.push({ path: uri }); }; diff --git a/frontend/src/views/files/FileListing.vue b/frontend/src/views/files/FileListing.vue index ec75aec5..8fa48f72 100644 --- a/frontend/src/views/files/FileListing.vue +++ b/frontend/src/views/files/FileListing.vue @@ -523,12 +523,12 @@ const keyEvent = (event: KeyboardEvent) => { break; case "a": event.preventDefault(); - for (let file of items.value.files) { + for (const file of items.value.files) { if (fileStore.selected.indexOf(file.index) === -1) { fileStore.selected.push(file.index); } } - for (let dir of items.value.dirs) { + for (const dir of items.value.dirs) { if (fileStore.selected.indexOf(dir.index) === -1) { fileStore.selected.push(dir.index); } @@ -551,9 +551,9 @@ const copyCut = (event: Event | KeyboardEvent): void => { if (fileStore.req === null) return; - let items = []; + const items = []; - for (let i of fileStore.selected) { + for (const i of fileStore.selected) { items.push({ from: fileStore.req.items[i].url, name: fileStore.req.items[i].name, @@ -575,9 +575,9 @@ const paste = (event: Event) => { if ((event.target as HTMLElement).tagName?.toLowerCase() === "input") return; // TODO router location should it be - let items: any[] = []; + const items: any[] = []; - for (let item of clipboardStore.items) { + for (const item of clipboardStore.items) { const from = item.from.endsWith("/") ? item.from.slice(0, -1) : item.from; const to = route.path + encodeURIComponent(item.name); items.push({ from, to, name: item.name }); @@ -614,7 +614,7 @@ const paste = (event: Event) => { return; } - let conflict = upload.checkConflict(items, fileStore.req!.items); + const conflict = upload.checkConflict(items, fileStore.req!.items); let overwrite = false; let rename = false; @@ -640,14 +640,13 @@ const paste = (event: Event) => { const colunmsResize = () => { // Update the columns size based on the window width. - let items_ = css(["#listing.mosaic .item", ".mosaic#listing .item"]); + const items_ = css(["#listing.mosaic .item", ".mosaic#listing .item"]); if (items_ === null) return; let columns = Math.floor( (document.querySelector("main")?.offsetWidth ?? 0) / columnWidth.value ); if (columns === 0) columns = 1; - // @ts-ignore never type error items_.style.width = `calc(${100 / columns}% - 1em)`; }; @@ -677,11 +676,10 @@ const dragEnter = () => { // When the user starts dragging an item, put every // file on the listing with 50% opacity. - let items = document.getElementsByClassName("item"); + const items = document.getElementsByClassName("item"); - // @ts-ignore - Array.from(items).forEach((file: HTMLElement) => { - file.style.opacity = "0.5"; + Array.from(items).forEach((file: Element) => { + (file as HTMLElement).style.opacity = "0.5"; }); }; @@ -698,7 +696,7 @@ const drop = async (event: DragEvent) => { dragCounter.value = 0; resetOpacity(); - let dt = event.dataTransfer; + const dt = event.dataTransfer; let el: HTMLElement | null = event.target as HTMLElement; if (fileStore.req === null || dt === null || dt.files.length <= 0) return; @@ -709,7 +707,7 @@ const drop = async (event: DragEvent) => { } } - let files: UploadList = (await upload.scanFiles(dt)) as UploadList; + const files: UploadList = (await upload.scanFiles(dt)) as UploadList; let items = fileStore.req.items; let path = route.path.endsWith("/") ? route.path : route.path + "/"; @@ -729,7 +727,7 @@ const drop = async (event: DragEvent) => { } } - let conflict = upload.checkConflict(files, items); + const conflict = upload.checkConflict(files, items); if (conflict) { layoutStore.showHover({ @@ -753,10 +751,10 @@ const drop = async (event: DragEvent) => { }; const uploadInput = (event: Event) => { - let files = (event.currentTarget as HTMLInputElement)?.files; + const files = (event.currentTarget as HTMLInputElement)?.files; if (files === null) return; - let folder_upload = !!files[0].webkitRelativePath; + const folder_upload = !!files[0].webkitRelativePath; const uploadFiles: UploadList = []; for (let i = 0; i < files.length; i++) { @@ -771,8 +769,8 @@ const uploadInput = (event: Event) => { }); } - let path = route.path.endsWith("/") ? route.path : route.path + "/"; - let conflict = upload.checkConflict(uploadFiles, fileStore.req!.items); + const path = route.path.endsWith("/") ? route.path : route.path + "/"; + const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items); if (conflict) { layoutStore.showHover({ @@ -796,7 +794,7 @@ const uploadInput = (event: Event) => { }; const resetOpacity = () => { - let items = document.getElementsByClassName("item"); + const items = document.getElementsByClassName("item"); Array.from(items).forEach((file: Element) => { (file as HTMLElement).style.opacity = "1"; @@ -822,7 +820,6 @@ const sort = async (by: string) => { try { if (authStore.user?.id) { - // @ts-ignore await users.update({ id: authStore.user?.id, sorting: { by, asc } }, [ "sorting", ]); @@ -873,10 +870,10 @@ const download = () => { confirm: (format: any) => { layoutStore.closeHovers(); - let files = []; + const files = []; if (fileStore.selectedCount > 0 && fileStore.req !== null) { - for (let i of fileStore.selected) { + for (const i of fileStore.selected) { files.push(fileStore.req.items[i].url); } } else { @@ -899,13 +896,12 @@ const switchView = async () => { const data = { id: authStore.user?.id, - viewMode: modes[authStore.user?.viewMode ?? "list"] || "list", + viewMode: (modes[authStore.user?.viewMode ?? "list"] || + "list") as ViewModeType, }; - // @ts-ignore users.update(data, ["viewMode"]).catch($showError); - // @ts-ignore authStore.updateUser(data); setItemWeight(); diff --git a/frontend/src/views/files/Preview.vue b/frontend/src/views/files/Preview.vue index a4f2cfb7..4fd3d2c8 100644 --- a/frontend/src/views/files/Preview.vue +++ b/frontend/src/views/files/Preview.vue @@ -353,7 +353,7 @@ const updatePreview = async () => { autoPlay.value = false; } - let dirs = route.fullPath.split("/"); + const dirs = route.fullPath.split("/"); name.value = decodeURIComponent(dirs[dirs.length - 1]); if (!listing.value) { @@ -422,7 +422,7 @@ const toggleNavigation = throttle(function () { const close = () => { fileStore.updateRequest(null); - let uri = url.removeLastDir(route.path) + "/"; + const uri = url.removeLastDir(route.path) + "/"; router.push({ path: uri }); }; diff --git a/frontend/src/views/settings/Global.vue b/frontend/src/views/settings/Global.vue index 0b055ee2..5bbaec7f 100644 --- a/frontend/src/views/settings/Global.vue +++ b/frontend/src/views/settings/Global.vue @@ -282,7 +282,7 @@ const formattedChunkSize = computed({ // Define funcs const capitalize = (name: string, where: string | RegExp = "_") => { if (where === "caps") where = /(?=[A-Z])/; - let split = name.split(where); + const split = name.split(where); name = ""; for (let i = 0; i < split.length; i++) { @@ -294,7 +294,7 @@ const capitalize = (name: string, where: string | RegExp = "_") => { const save = async () => { if (settings.value === null) return false; - let newSettings: ISettings = { + const newSettings: ISettings = { ...settings.value, shell: settings.value?.shell @@ -376,7 +376,7 @@ onMounted(async () => { try { layoutStore.loading = true; const original: ISettings = await api.get(); - let newSettings: ISettings = { ...original, commands: {} }; + const newSettings: ISettings = { ...original, commands: {} }; const keys = Object.keys(original.commands) as Array; for (const key of keys) { diff --git a/frontend/src/views/settings/Shares.vue b/frontend/src/views/settings/Shares.vue index 478d595c..e1076ec9 100644 --- a/frontend/src/views/settings/Shares.vue +++ b/frontend/src/views/settings/Shares.vue @@ -87,12 +87,12 @@ onMounted(async () => { layoutStore.loading = true; try { - let newLinks = await api.list(); + const newLinks = await api.list(); if (authStore.user?.perm.admin) { - let userMap = new Map(); - for (let user of await users.getAll()) + const userMap = new Map(); + for (const user of await users.getAll()) userMap.set(user.id, user.username); - for (let link of newLinks) { + for (const link of newLinks) { if (link.userID && userMap.has(link.userID)) link.username = userMap.get(link.userID); } @@ -108,13 +108,23 @@ onMounted(async () => { }); const copyToClipboard = (text: string) => { - copy(text).then( + copy({ text }).then( () => { // clipboard successfully set $showSuccess(t("success.linkCopied")); }, () => { // clipboard write failed + copy({ text }, { permission: true }).then( + () => { + // clipboard successfully set + $showSuccess(t("success.linkCopied")); + }, + (e) => { + // clipboard write failed + $showError(e); + } + ); } ); }; diff --git a/frontend/src/views/settings/User.vue b/frontend/src/views/settings/User.vue index f12d5997..a0da68ce 100644 --- a/frontend/src/views/settings/User.vue +++ b/frontend/src/views/settings/User.vue @@ -90,7 +90,7 @@ const fetchData = async () => { try { if (isNew.value) { - let { defaults, createUserDir: _createUserDir } = await settings.get(); + const { defaults, createUserDir: _createUserDir } = await settings.get(); createUserDir.value = _createUserDir; user.value = { ...defaults, From 1194cfe0097a70399c1f06cf0f514b9d70fa463c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2025 10:22:04 +0100 Subject: [PATCH 04/11] build(deps): bump golang.org/x/net from 0.23.0 to 0.33.0 (#3712) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.33.0. - [Commits](https://github.com/golang/net/compare/v0.23.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b6be3d7b..a58d5c24 100644 --- a/go.mod +++ b/go.mod @@ -64,7 +64,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/net v0.23.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 7254e9b5..4e451c05 100644 --- a/go.sum +++ b/go.sum @@ -190,8 +190,8 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 252f0a753323f7981fde1da22f2e08cdb69b531b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=84=B1=EB=AF=BC?= Date: Thu, 30 Jan 2025 18:24:44 +0900 Subject: [PATCH 05/11] chore: update ko.json (#3688) --- frontend/src/i18n/ko.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index 046a712b..722da2d2 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -9,7 +9,7 @@ "create": "생성", "delete": "삭제", "download": "다운로드", - "hideDotfiles": "", + "hideDotfiles": "숨김파일(dotfile)을 표시 안함", "info": "정보", "more": "더보기", "move": "이동", @@ -38,7 +38,7 @@ "download": { "downloadFile": "파일 다운로드", "downloadFolder": "폴더 다운로드", - "downloadSelected": "" + "downloadSelected": "선택 항목 다운로드" }, "errors": { "forbidden": "접근 권한이 없습니다.", @@ -120,8 +120,8 @@ "scheduleMessage": "이 글을 공개할 시간을 알려주세요.", "show": "보기", "size": "크기", - "upload": "", - "uploadMessage": "" + "upload": "업로드", + "uploadMessage": "업로드 옵션을 선택하세요." }, "search": { "images": "이미지", @@ -160,7 +160,7 @@ "executeOnShellDescription": "기본적으로 File Browser 는 바이너리를 명령어로 호출하여 실행합니다. 쉘을 통해 실행하기를 원한다면, Bash 또는 PowerShell 에 필요한 인수와 플래그를 설정하세요. 사용자 명령어와 이벤트 훅에 모두 적용됩니다.", "globalRules": "규칙에 대한 전역설정으로 모든 사용자에게 적용됩니다. 지정된 규칙은 사용자 설정을 덮어쓰기 합니다.", "globalSettings": "전역 설정", - "hideDotfiles": "", + "hideDotfiles": "숨김파일(dotfile)을 표시하지 않습니다.", "insertPath": "경로 입력", "insertRegex": "정규식 입력", "instanceName": "인스턴스 이름", @@ -171,7 +171,7 @@ "newUser": "새로운 사용자", "password": "비밀번호", "passwordUpdated": "비밀번호 수정 완료!", - "path": "", + "path": "경로", "perm": { "create": "파일이나 디렉토리 생성하기", "delete": "화일이나 디렉토리 삭제하기", @@ -190,13 +190,13 @@ "rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n", "scope": "범위", "settingsUpdated": "설정 수정됨!", - "shareDuration": "", - "shareManagement": "", - "singleClick": "", + "shareDuration": "공유 기간", + "shareManagement": "공유 내역 관리", + "singleClick": "한번 클릭으로 파일과 폴더를 열도록 합니다.", "themes": { - "dark": "", - "light": "", - "title": "" + "dark": "다크테마", + "light": "라이트테마", + "title": "테마" }, "user": "사용자", "userCommands": "명령어", From 045064f8b8bf9f86058e877448085e38da8b3f2e Mon Sep 17 00:00:00 2001 From: Eden Yemini Date: Thu, 30 Jan 2025 11:29:14 +0200 Subject: [PATCH 06/11] fix: add proper healthcheck for S6 containers (#3691) Co-authored-by: Oleg Lobanov --- Dockerfile.s6 | 11 ++++++++--- Dockerfile.s6.aarch64 | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Dockerfile.s6 b/Dockerfile.s6 index 63c43018..609a2634 100644 --- a/Dockerfile.s6 +++ b/Dockerfile.s6 @@ -2,15 +2,20 @@ FROM ghcr.io/linuxserver/baseimage-alpine:3.20 RUN apk --update add ca-certificates \ mailcap \ - curl + curl \ + jq + +COPY healthcheck.sh /healthcheck.sh +RUN chmod +x /healthcheck.sh # Make the script executable HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \ - CMD curl -f http://localhost/health || exit 1 + CMD /healthcheck.sh || exit 1 # copy local files COPY docker/root/ / +RUN ln -s /config/settings.json /.filebrowser.json COPY filebrowser /usr/bin/filebrowser # ports and volumes VOLUME /srv /config /database -EXPOSE 80 \ No newline at end of file +EXPOSE 80 diff --git a/Dockerfile.s6.aarch64 b/Dockerfile.s6.aarch64 index 752e3ed3..1e62391e 100644 --- a/Dockerfile.s6.aarch64 +++ b/Dockerfile.s6.aarch64 @@ -2,15 +2,20 @@ FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.20 RUN apk --update add ca-certificates \ mailcap \ - curl + curl \ + jq + +COPY healthcheck.sh /healthcheck.sh +RUN chmod +x /healthcheck.sh # Make the script executable HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \ - CMD curl -f http://localhost/health || exit 1 + CMD /healthcheck.sh || exit 1 # copy local files COPY docker/root/ / +RUN ln -s /config/settings.json /.filebrowser.json COPY filebrowser /usr/bin/filebrowser # ports and volumes VOLUME /srv /config /database -EXPOSE 80 \ No newline at end of file +EXPOSE 80 From bbdd313705b8d253f0c47ad717a6e47b2f46e719 Mon Sep 17 00:00:00 2001 From: elmodor Date: Thu, 30 Jan 2025 10:32:05 +0100 Subject: [PATCH 07/11] fix: disk usage refreshing (#3692) Co-authored-by: Oleg Lobanov --- frontend/src/components/Sidebar.vue | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Sidebar.vue b/frontend/src/components/Sidebar.vue index 595fd685..4d55cf0f 100644 --- a/frontend/src/components/Sidebar.vue +++ b/frontend/src/components/Sidebar.vue @@ -191,8 +191,13 @@ export default { logout: auth.logout, }, watch: { - isFiles(newValue) { - newValue && this.fetchUsage(); + $route: { + handler(to) { + if (to.path.includes("/files")) { + this.fetchUsage(); + } + }, + immediate: true, }, }, }; From 5300d00d2e7dbb80a252aff57e100113f02506c3 Mon Sep 17 00:00:00 2001 From: Arran Hobson Sayers <32173585+ahobsonsayers@users.noreply.github.com> Date: Thu, 30 Jan 2025 10:28:19 +0000 Subject: [PATCH 08/11] fix: Fix user creation on proxy auth (#3666) * Fix user creation on proxy auth * Refactoring --------- Co-authored-by: Oleg Lobanov --- auth/proxy.go | 66 ++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/auth/proxy.go b/auth/proxy.go index 9d140540..0e954309 100644 --- a/auth/proxy.go +++ b/auth/proxy.go @@ -23,39 +23,45 @@ func (a ProxyAuth) Auth(r *http.Request, usr users.Store, setting *settings.Sett username := r.Header.Get(a.Header) user, err := usr.Get(srv.Root, username) if errors.Is(err, fbErrors.ErrNotExist) { - randomPasswordBytes := make([]byte, 32) //nolint:gomnd - _, err = rand.Read(randomPasswordBytes) - if err != nil { - return nil, err - } + return a.createUser(usr, setting, srv, username) + } + return user, err +} - var hashedRandomPassword string - hashedRandomPassword, err = users.HashPwd(string(randomPasswordBytes)) - if err != nil { - return nil, err - } - - user = &users.User{ - Username: username, - Password: hashedRandomPassword, - LockPassword: true, - } - setting.Defaults.Apply(user) - - var userHome string - userHome, err = setting.MakeUserDir(user.Username, user.Scope, srv.Root) - if err != nil { - return nil, err - } - user.Scope = userHome - - err = usr.Save(user) - if err != nil { - return nil, err - } +func (a ProxyAuth) createUser(usr users.Store, setting *settings.Settings, srv *settings.Server, username string) (*users.User, error) { + const passwordSize = 32 + randomPasswordBytes := make([]byte, passwordSize) + _, err := rand.Read(randomPasswordBytes) + if err != nil { + return nil, err } - return user, err + var hashedRandomPassword string + hashedRandomPassword, err = users.HashPwd(string(randomPasswordBytes)) + if err != nil { + return nil, err + } + + user := &users.User{ + Username: username, + Password: hashedRandomPassword, + LockPassword: true, + } + setting.Defaults.Apply(user) + + var userHome string + userHome, err = setting.MakeUserDir(user.Username, user.Scope, srv.Root) + if err != nil { + return nil, err + } + user.Scope = userHome + + err = usr.Save(user) + if err != nil { + return nil, err + } + + return user, nil } // LoginPage tells that proxy auth doesn't require a login page. From ba797cda3135eddb9b7165dc5ceb932399cb54df Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Fri, 31 Jan 2025 09:32:34 +0100 Subject: [PATCH 09/11] build: fix go releaser --- .goreleaser.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 2fbdefc6..0e0a5d65 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -36,10 +36,10 @@ builds: archives: - name_template: "{{.Os}}-{{.Arch}}{{if .Arm}}v{{.Arm}}{{end}}-{{ .ProjectName }}" - format: tar.gz + formats: [ 'tar.gz' ] format_overrides: - goos: windows - format: zip + formats: [ 'zip' ] dockers: - @@ -139,6 +139,7 @@ dockers: - "filebrowser/filebrowser:v{{ .Major }}-amd64-s6" extra_files: - docker/root + - healthcheck.sh - dockerfile: Dockerfile.s6.aarch64 use: buildx @@ -157,6 +158,7 @@ dockers: - "filebrowser/filebrowser:v{{ .Major }}-arm64-s6" extra_files: - docker/root + - healthcheck.sh docker_manifests: - name_template: "filebrowser/filebrowser:latest" image_templates: From 3d6c5152fe22a4a47783253a3506a2930b7b6be3 Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Fri, 31 Jan 2025 09:48:22 +0100 Subject: [PATCH 10/11] chore(release): 2.32.0 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cc85562..2d414dcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,37 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.32.0](https://github.com/filebrowser/filebrowser/compare/v2.31.2...v2.32.0) (2025-01-31) + + +### Features + +* create user on proxy authentication if user does not exist ([#3569](https://github.com/filebrowser/filebrowser/issues/3569)) ([209acf2](https://github.com/filebrowser/filebrowser/commit/209acf2429b06e2e8d78218937c59fd7e7edd1be)) + + +### Bug Fixes + +* add proper healthcheck for S6 containers ([#3691](https://github.com/filebrowser/filebrowser/issues/3691)) ([045064f](https://github.com/filebrowser/filebrowser/commit/045064f8b8bf9f86058e877448085e38da8b3f2e)) +* disk usage refreshing ([#3692](https://github.com/filebrowser/filebrowser/issues/3692)) ([bbdd313](https://github.com/filebrowser/filebrowser/commit/bbdd313705b8d253f0c47ad717a6e47b2f46e719)) +* Fix user creation on proxy auth ([#3666](https://github.com/filebrowser/filebrowser/issues/3666)) ([5300d00](https://github.com/filebrowser/filebrowser/commit/5300d00d2e7dbb80a252aff57e100113f02506c3)) +* prompts disappearing on copy / move / upload ([#3537](https://github.com/filebrowser/filebrowser/issues/3537)) ([d1c84a8](https://github.com/filebrowser/filebrowser/commit/d1c84a84123c77dede05c023b3697a432b56122c)) + + +### Refactorings + +* Fix eslint warnings ([#3698](https://github.com/filebrowser/filebrowser/issues/3698)) ([0201f9c](https://github.com/filebrowser/filebrowser/commit/0201f9c5c4dd2a4d5a3503e59cdb8045e8d3a91f)), closes [#3407](https://github.com/filebrowser/filebrowser/issues/3407) + + +### Build + +* **deps:** bump cross-spawn from 7.0.3 to 7.0.6 in /tools ([#3601](https://github.com/filebrowser/filebrowser/issues/3601)) ([25372ed](https://github.com/filebrowser/filebrowser/commit/25372edb5c0e616e82b76b5f523633af57d347e0)) +* **deps:** bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 ([#3574](https://github.com/filebrowser/filebrowser/issues/3574)) ([2fdea73](https://github.com/filebrowser/filebrowser/commit/2fdea73430011846276a1cda52458f1d670f5ea7)) +* **deps:** bump golang.org/x/crypto from 0.26.0 to 0.31.0 ([#3634](https://github.com/filebrowser/filebrowser/issues/3634)) ([e92dbb4](https://github.com/filebrowser/filebrowser/commit/e92dbb4bb8b7894264fbf0a48a641712c3b68766)) +* **deps:** bump golang.org/x/net from 0.23.0 to 0.33.0 ([#3712](https://github.com/filebrowser/filebrowser/issues/3712)) ([1194cfe](https://github.com/filebrowser/filebrowser/commit/1194cfe0097a70399c1f06cf0f514b9d70fa463c)) +* **deps:** bump vue-i18n from 9.10.2 to 9.14.2 in /frontend ([#3618](https://github.com/filebrowser/filebrowser/issues/3618)) ([0659594](https://github.com/filebrowser/filebrowser/commit/065959451d3ba12019c6151274aa4e6904cdca99)) +* fix go releaser ([ba797cd](https://github.com/filebrowser/filebrowser/commit/ba797cda3135eddb9b7165dc5ceb932399cb54df)) +* update to node 22 and pnpm ([#3616](https://github.com/filebrowser/filebrowser/issues/3616)) ([d51a343](https://github.com/filebrowser/filebrowser/commit/d51a3438201274a1b826be1b775ca1035ade20c5)) + ### [2.31.2](https://github.com/filebrowser/filebrowser/compare/v2.31.1...v2.31.2) (2024-10-03) From 35d1c092434b80b22c89a614a02122e9f5965b39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 17:03:45 +0100 Subject: [PATCH 11/11] build(deps): bump vue-i18n from 11.0.1 to 11.1.2 in /frontend (#3786) Bumps [vue-i18n](https://github.com/intlify/vue-i18n/tree/HEAD/packages/vue-i18n) from 11.0.1 to 11.1.2. - [Release notes](https://github.com/intlify/vue-i18n/releases) - [Changelog](https://github.com/intlify/vue-i18n/blob/master/CHANGELOG.md) - [Commits](https://github.com/intlify/vue-i18n/commits/v11.1.2/packages/vue-i18n) --- updated-dependencies: - dependency-name: vue-i18n dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package.json | 2 +- frontend/pnpm-lock.yaml | 60 ++++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 7924117f..86c2f88d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -42,7 +42,7 @@ "videojs-mobile-ui": "^1.1.1", "vue": "^3.4.21", "vue-final-modal": "^4.5.4", - "vue-i18n": "^11.0.1", + "vue-i18n": "^11.1.2", "vue-lazyload": "^3.0.0", "vue-reader": "^1.2.17", "vue-router": "^4.3.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 6f3378d3..2cf5b620 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -81,8 +81,8 @@ importers: specifier: ^4.5.4 version: 4.5.5(@vueuse/core@12.5.0(typescript@5.6.3))(@vueuse/integrations@12.5.0(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3))(focus-trap@7.6.2)(vue@3.5.13(typescript@5.6.3)) vue-i18n: - specifier: ^11.0.1 - version: 11.0.1(vue@3.5.13(typescript@5.6.3)) + specifier: ^11.1.2 + version: 11.1.2(vue@3.5.13(typescript@5.6.3)) vue-lazyload: specifier: ^3.0.0 version: 3.0.0 @@ -98,7 +98,7 @@ importers: devDependencies: '@intlify/unplugin-vue-i18n': specifier: ^6.0.3 - version: 6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.19.0)(rollup@4.32.0)(typescript@5.6.3)(vue-i18n@11.0.1(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) + version: 6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.19.0)(rollup@4.32.0)(typescript@5.6.3)(vue-i18n@11.1.2(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) '@playwright/test': specifier: ^1.50.0 version: 1.50.0 @@ -930,24 +930,24 @@ packages: vue-i18n: optional: true - '@intlify/core-base@11.0.1': - resolution: {integrity: sha512-NAmhw1l/llM0HZRpagR/ChJTNymW4ll6/4EDSJML5c8L5Hl/+k6UyF8EIgE6DeHpfheQujkSRngauViHqq6jJQ==} + '@intlify/core-base@11.1.2': + resolution: {integrity: sha512-nmG512G8QOABsserleechwHGZxzKSAlggGf9hQX0nltvSwyKNVuB/4o6iFeG2OnjXK253r8p8eSDOZf8PgFdWw==} engines: {node: '>= 16'} '@intlify/message-compiler@11.0.0-rc.1': resolution: {integrity: sha512-TGw2uBfuTFTegZf/BHtUQBEKxl7Q/dVGLoqRIdw8lFsp9g/53sYn5iD+0HxIzdYjbWL6BTJMXCPUHp9PxDTRPw==} engines: {node: '>= 16'} - '@intlify/message-compiler@11.0.1': - resolution: {integrity: sha512-5RFH8x+Mn3mbjcHXnb6KCXGiczBdiQkWkv99iiA0JpKrNuTAQeW59Pjq/uObMB0eR0shnKYGTkIJxum+DbL3sw==} + '@intlify/message-compiler@11.1.2': + resolution: {integrity: sha512-T/xbNDzi+Yv0Qn2Dfz2CWCAJiwNgU5d95EhhAEf4YmOgjCKktpfpiUSmLcBvK1CtLpPQ85AMMQk/2NCcXnNj1g==} engines: {node: '>= 16'} '@intlify/shared@11.0.0-rc.1': resolution: {integrity: sha512-8tR1xe7ZEbkabTuE/tNhzpolygUn9OaYp9yuYAF4MgDNZg06C3Qny80bes2/e9/Wm3aVkPUlCw6WgU7mQd0yEg==} engines: {node: '>= 16'} - '@intlify/shared@11.0.1': - resolution: {integrity: sha512-lH164+aDDptHZ3dBDbIhRa1dOPQUp+83iugpc+1upTOWCnwyC1PVis6rSWNMMJ8VQxvtHQB9JMib48K55y0PvQ==} + '@intlify/shared@11.1.2': + resolution: {integrity: sha512-dF2iMMy8P9uKVHV/20LA1ulFLL+MKSbfMiixSmn6fpwqzvix38OIc7ebgnFbBqElvghZCW9ACtzKTGKsTGTWGA==} engines: {node: '>= 16'} '@intlify/unplugin-vue-i18n@6.0.3': @@ -2608,8 +2608,8 @@ packages: focus-trap: '>=7.2.0' vue: '>=3.2.0' - vue-i18n@11.0.1: - resolution: {integrity: sha512-pWAT8CusK8q9/EpN7V3oxwHwxWm6+Kp2PeTZmRGvdZTkUzMQDpbbmHp0TwQ8xw04XKm23cr6B4GL72y3W8Yekg==} + vue-i18n@11.1.2: + resolution: {integrity: sha512-MfdkdKGUHN+jkkaMT5Zbl4FpRmN7kfelJIwKoUpJ32ONIxdFhzxZiLTVaAXkAwvH3y9GmWpoiwjDqbPIkPIMFA==} engines: {node: '>= 16'} peerDependencies: vue: ^3.0.0 @@ -3576,7 +3576,7 @@ snapshots: '@humanwhocodes/retry@0.4.1': {} - '@intlify/bundle-utils@10.0.0(vue-i18n@11.0.1(vue@3.5.13(typescript@5.6.3)))': + '@intlify/bundle-utils@10.0.0(vue-i18n@11.1.2(vue@3.5.13(typescript@5.6.3)))': dependencies: '@intlify/message-compiler': 11.0.0-rc.1 '@intlify/shared': 11.0.0-rc.1 @@ -3588,33 +3588,33 @@ snapshots: source-map-js: 1.2.1 yaml-eslint-parser: 1.2.3 optionalDependencies: - vue-i18n: 11.0.1(vue@3.5.13(typescript@5.6.3)) + vue-i18n: 11.1.2(vue@3.5.13(typescript@5.6.3)) - '@intlify/core-base@11.0.1': + '@intlify/core-base@11.1.2': dependencies: - '@intlify/message-compiler': 11.0.1 - '@intlify/shared': 11.0.1 + '@intlify/message-compiler': 11.1.2 + '@intlify/shared': 11.1.2 '@intlify/message-compiler@11.0.0-rc.1': dependencies: '@intlify/shared': 11.0.0-rc.1 source-map-js: 1.2.1 - '@intlify/message-compiler@11.0.1': + '@intlify/message-compiler@11.1.2': dependencies: - '@intlify/shared': 11.0.1 + '@intlify/shared': 11.1.2 source-map-js: 1.2.1 '@intlify/shared@11.0.0-rc.1': {} - '@intlify/shared@11.0.1': {} + '@intlify/shared@11.1.2': {} - '@intlify/unplugin-vue-i18n@6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.19.0)(rollup@4.32.0)(typescript@5.6.3)(vue-i18n@11.0.1(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3))': + '@intlify/unplugin-vue-i18n@6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.19.0)(rollup@4.32.0)(typescript@5.6.3)(vue-i18n@11.1.2(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3))': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0) - '@intlify/bundle-utils': 10.0.0(vue-i18n@11.0.1(vue@3.5.13(typescript@5.6.3))) - '@intlify/shared': 11.0.1 - '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.0.1)(@vue/compiler-dom@3.5.13)(vue-i18n@11.0.1(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) + '@intlify/bundle-utils': 10.0.0(vue-i18n@11.1.2(vue@3.5.13(typescript@5.6.3))) + '@intlify/shared': 11.1.2 + '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.2)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.2(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) '@rollup/pluginutils': 5.1.4(rollup@4.32.0) '@typescript-eslint/scope-manager': 8.21.0 '@typescript-eslint/typescript-estree': 8.21.0(typescript@5.6.3) @@ -3628,7 +3628,7 @@ snapshots: unplugin: 1.16.1 vue: 3.5.13(typescript@5.6.3) optionalDependencies: - vue-i18n: 11.0.1(vue@3.5.13(typescript@5.6.3)) + vue-i18n: 11.1.2(vue@3.5.13(typescript@5.6.3)) transitivePeerDependencies: - '@vue/compiler-dom' - eslint @@ -3636,14 +3636,14 @@ snapshots: - supports-color - typescript - '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.0.1)(@vue/compiler-dom@3.5.13)(vue-i18n@11.0.1(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3))': + '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.2)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.2(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3))': dependencies: '@babel/parser': 7.26.7 optionalDependencies: - '@intlify/shared': 11.0.1 + '@intlify/shared': 11.1.2 '@vue/compiler-dom': 3.5.13 vue: 3.5.13(typescript@5.6.3) - vue-i18n: 11.0.1(vue@3.5.13(typescript@5.6.3)) + vue-i18n: 11.1.2(vue@3.5.13(typescript@5.6.3)) '@jridgewell/gen-mapping@0.3.5': dependencies: @@ -5283,10 +5283,10 @@ snapshots: focus-trap: 7.6.2 vue: 3.5.13(typescript@5.6.3) - vue-i18n@11.0.1(vue@3.5.13(typescript@5.6.3)): + vue-i18n@11.1.2(vue@3.5.13(typescript@5.6.3)): dependencies: - '@intlify/core-base': 11.0.1 - '@intlify/shared': 11.0.1 + '@intlify/core-base': 11.1.2 + '@intlify/shared': 11.1.2 '@vue/devtools-api': 6.6.4 vue: 3.5.13(typescript@5.6.3)