mirror of
https://github.com/nextcloud/server.git
synced 2026-06-10 17:23:59 -04:00
Merge pull request #57352 from nextcloud/fix/active-files
fix(files): properly handle currently active node and files action hotkeys
This commit is contained in:
commit
60a43694cc
43 changed files with 320 additions and 776 deletions
|
|
@ -1,9 +1,9 @@
|
|||
/**
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { Node, View } from '@nextcloud/files'
|
||||
import type { INode, IView } from '@nextcloud/files'
|
||||
import type { Capabilities } from '../types.ts'
|
||||
|
||||
import axios from '@nextcloud/axios'
|
||||
|
|
@ -17,10 +17,9 @@ import { useUserConfigStore } from '../store/userconfig.ts'
|
|||
export const isTrashbinEnabled = () => (getCapabilities() as Capabilities)?.files?.undelete === true
|
||||
|
||||
/**
|
||||
*
|
||||
* @param nodes
|
||||
*/
|
||||
export function canUnshareOnly(nodes: Node[]) {
|
||||
export function canUnshareOnly(nodes: INode[]) {
|
||||
return nodes.every((node) => node.attributes['is-mount-root'] === true
|
||||
&& node.attributes['mount-type'] === 'shared')
|
||||
}
|
||||
|
|
@ -29,7 +28,7 @@ export function canUnshareOnly(nodes: Node[]) {
|
|||
*
|
||||
* @param nodes
|
||||
*/
|
||||
export function canDisconnectOnly(nodes: Node[]) {
|
||||
export function canDisconnectOnly(nodes: INode[]) {
|
||||
return nodes.every((node) => node.attributes['is-mount-root'] === true
|
||||
&& node.attributes['mount-type'] === 'external')
|
||||
}
|
||||
|
|
@ -38,7 +37,7 @@ export function canDisconnectOnly(nodes: Node[]) {
|
|||
*
|
||||
* @param nodes
|
||||
*/
|
||||
export function isMixedUnshareAndDelete(nodes: Node[]) {
|
||||
export function isMixedUnshareAndDelete(nodes: INode[]) {
|
||||
if (nodes.length === 1) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -52,7 +51,7 @@ export function isMixedUnshareAndDelete(nodes: Node[]) {
|
|||
*
|
||||
* @param nodes
|
||||
*/
|
||||
export function isAllFiles(nodes: Node[]) {
|
||||
export function isAllFiles(nodes: INode[]) {
|
||||
return !nodes.some((node) => node.type !== FileType.File)
|
||||
}
|
||||
|
||||
|
|
@ -60,17 +59,18 @@ export function isAllFiles(nodes: Node[]) {
|
|||
*
|
||||
* @param nodes
|
||||
*/
|
||||
export function isAllFolders(nodes: Node[]) {
|
||||
export function isAllFolders(nodes: INode[]) {
|
||||
return !nodes.some((node) => node.type !== FileType.Folder)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display name for the delete action
|
||||
*
|
||||
* @param root0
|
||||
* @param root0.nodes
|
||||
* @param root0.view
|
||||
* @param context - The context
|
||||
* @param context.nodes - The nodes to delete
|
||||
* @param context.view - The current view
|
||||
*/
|
||||
export function displayName({ nodes, view }: { nodes: Node[], view: View }) {
|
||||
export function displayName({ nodes, view }: { nodes: INode[], view: IView }) {
|
||||
/**
|
||||
* If those nodes are all the root node of a
|
||||
* share, we can only unshare them.
|
||||
|
|
@ -143,7 +143,7 @@ export function shouldAskForConfirmation() {
|
|||
* @param nodes
|
||||
* @param view
|
||||
*/
|
||||
export async function askConfirmation(nodes: Node[], view: View) {
|
||||
export async function askConfirmation(nodes: INode[], view: IView) {
|
||||
const message = view.id === 'trashbin' || !isTrashbinEnabled()
|
||||
? n('files', 'You are about to permanently delete {count} item', 'You are about to permanently delete {count} items', nodes.length, { count: nodes.length })
|
||||
: n('files', 'You are about to delete {count} item', 'You are about to delete {count} items', nodes.length, { count: nodes.length })
|
||||
|
|
@ -170,7 +170,7 @@ export async function askConfirmation(nodes: Node[], view: View) {
|
|||
*
|
||||
* @param node
|
||||
*/
|
||||
export async function deleteNode(node: Node) {
|
||||
export async function deleteNode(node: INode) {
|
||||
await axios.delete(node.encodedSource)
|
||||
|
||||
// Let's delete even if it's moved to the trashbin
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import StarSvg from '@mdi/svg/svg/star.svg?raw'
|
|||
import axios from '@nextcloud/axios'
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { FileAction, Permission } from '@nextcloud/files'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { encodePath } from '@nextcloud/paths'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { isPublicShare } from '@nextcloud/sharing/public'
|
||||
|
|
|
|||
|
|
@ -54,4 +54,9 @@ export const action = new FileAction({
|
|||
},
|
||||
|
||||
order: -50,
|
||||
|
||||
hotkey: {
|
||||
key: 'D',
|
||||
description: t('files', 'Open the details sidebar'),
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -37,7 +37,11 @@ function hotkeyToString(hotkey: IHotkeyConfig): string {
|
|||
if (hotkey.shift) {
|
||||
parts.push('Shift')
|
||||
}
|
||||
parts.push(hotkey.key)
|
||||
if (hotkey.key.match(/^[a-z]$/)) {
|
||||
parts.push(hotkey.key.toUpperCase())
|
||||
} else {
|
||||
parts.push(hotkey.key)
|
||||
}
|
||||
return parts.join(' ')
|
||||
}
|
||||
</script>
|
||||
|
|
@ -71,7 +75,6 @@ function hotkeyToString(hotkey: IHotkeyConfig): string {
|
|||
|
||||
<NcHotkeyList :label="t('files', 'View')">
|
||||
<NcHotkey :label="t('files', 'Toggle grid view')" hotkey="V" />
|
||||
<NcHotkey :label="t('files', 'Open file sidebar')" hotkey="D" />
|
||||
<NcHotkey :label="t('files', 'Show those shortcuts')" hotkey="?" />
|
||||
</NcHotkeyList>
|
||||
</NcAppSettingsShortcutsSection>
|
||||
|
|
|
|||
|
|
@ -301,7 +301,11 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
if (this.fileId) {
|
||||
this.scrollToFile(this.fileId, false)
|
||||
const node = this.nodes.find((node) => node.fileid === this.fileId)
|
||||
if (node) {
|
||||
this.activeStore.activeNode = node
|
||||
this.scrollToFile(this.fileId, false)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -342,13 +346,7 @@ export default defineComponent({
|
|||
delete query.openfile
|
||||
delete query.opendetails
|
||||
|
||||
this.activeStore.activeNode = undefined
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null,
|
||||
{ ...this.$route.params, fileid: String(this.currentFolder.fileid ?? '') },
|
||||
query,
|
||||
true,
|
||||
)
|
||||
this.activeStore.activeNode = this.currentFolder
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -396,7 +394,7 @@ export default defineComponent({
|
|||
logger.debug('Ignore `openfile` query and replacing with `opendetails` for ' + node.path, { node })
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null,
|
||||
this.$route.params,
|
||||
window.OCP.Files.Router.params,
|
||||
{ ...this.$route.query, openfile: undefined, opendetails: '' },
|
||||
true, // silent update of the URL
|
||||
)
|
||||
|
|
@ -431,10 +429,29 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
onKeyDown(event: KeyboardEvent) {
|
||||
if (this.isEmpty) {
|
||||
return
|
||||
}
|
||||
|
||||
if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown'
|
||||
&& (!this.userConfig.grid_view || (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight'))
|
||||
) {
|
||||
// not an arrow key we handle
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.fileId || this.fileId === this.currentFolder.fileid) {
|
||||
// no active node so use either first or last node
|
||||
const index = event.key === 'ArrowUp' || event.key === 'ArrowLeft'
|
||||
? this.nodes.length - 1
|
||||
: 0
|
||||
this.setActiveNode(this.nodes[index] as NcNode & { fileid: number })
|
||||
}
|
||||
|
||||
const index = this.nodes.findIndex((node) => node.fileid === this.fileId) ?? 0
|
||||
// Up and down arrow keys
|
||||
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
|
||||
const columnCount = this.$refs.table?.columnCount ?? 1
|
||||
const index = this.nodes.findIndex((node) => node.fileid === this.fileId) ?? 0
|
||||
const nextIndex = event.key === 'ArrowUp' ? index - columnCount : index + columnCount
|
||||
if (nextIndex < 0 || nextIndex >= this.nodes.length) {
|
||||
return
|
||||
|
|
@ -450,7 +467,6 @@ export default defineComponent({
|
|||
|
||||
// if grid mode, left and right arrow keys
|
||||
if (this.userConfig.grid_view && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {
|
||||
const index = this.nodes.findIndex((node) => node.fileid === this.fileId) ?? 0
|
||||
const nextIndex = event.key === 'ArrowLeft' ? index - 1 : index + 1
|
||||
if (nextIndex < 0 || nextIndex >= this.nodes.length) {
|
||||
return
|
||||
|
|
@ -465,7 +481,7 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
|
||||
setActiveNode(node: NcNode & { fileid: number }) {
|
||||
async setActiveNode(node: NcNode & { fileid: number }) {
|
||||
logger.debug('Navigating to file ' + node.path, { node, fileid: node.fileid })
|
||||
this.scrollToFile(node.fileid)
|
||||
|
||||
|
|
@ -473,16 +489,13 @@ export default defineComponent({
|
|||
const query = { ...this.$route.query }
|
||||
delete query.openfile
|
||||
delete query.opendetails
|
||||
|
||||
this.activeStore.activeNode = node
|
||||
|
||||
// Silent update of the URL
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null,
|
||||
{ ...this.$route.params, fileid: String(node.fileid) },
|
||||
await this.$router.replace({
|
||||
...this.$route,
|
||||
query,
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
// set the new file as active
|
||||
this.activeStore.activeNode = node
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,18 +4,14 @@
|
|||
*/
|
||||
|
||||
import type { View } from '@nextcloud/files'
|
||||
import type { Mock } from 'vitest'
|
||||
import type { Location } from 'vue-router'
|
||||
|
||||
import axios from '@nextcloud/axios'
|
||||
import { File, Folder, Permission } from '@nextcloud/files'
|
||||
import { File, Folder, Permission, registerFileAction } from '@nextcloud/files'
|
||||
import { enableAutoDestroy, mount } from '@vue/test-utils'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { defineComponent, nextTick } from 'vue'
|
||||
import { action as deleteAction } from '../actions/deleteAction.ts'
|
||||
import { action as favoriteAction } from '../actions/favoriteAction.ts'
|
||||
import { action as renameAction } from '../actions/renameAction.ts'
|
||||
import { action as sidebarAction } from '../actions/sidebarAction.ts'
|
||||
import { useActiveStore } from '../store/active.ts'
|
||||
import { useFilesStore } from '../store/files.ts'
|
||||
import { getPinia } from '../store/index.ts'
|
||||
|
|
@ -63,10 +59,23 @@ const TestComponent = defineComponent({
|
|||
template: '<div />',
|
||||
})
|
||||
|
||||
beforeAll(() => {
|
||||
// @ts-expect-error mocking for tests
|
||||
window.OCP ??= {}
|
||||
// @ts-expect-error mocking for tests
|
||||
window.OCP.Files ??= {}
|
||||
// @ts-expect-error mocking for tests
|
||||
window.OCP.Files.Router ??= {
|
||||
...router,
|
||||
goToRoute: vi.fn(),
|
||||
}
|
||||
})
|
||||
|
||||
describe('HotKeysService testing', () => {
|
||||
const activeStore = useActiveStore(getPinia())
|
||||
|
||||
let initialState: HTMLInputElement
|
||||
let component: ReturnType<typeof mount>
|
||||
|
||||
enableAutoDestroy(afterEach)
|
||||
|
||||
|
|
@ -114,54 +123,15 @@ describe('HotKeysService testing', () => {
|
|||
})))
|
||||
document.body.appendChild(initialState)
|
||||
|
||||
mount(TestComponent)
|
||||
component = mount(TestComponent)
|
||||
})
|
||||
|
||||
it('Pressing d should open the sidebar once', () => {
|
||||
dispatchEvent({ key: 'd', code: 'KeyD' })
|
||||
// tests for register action handling
|
||||
|
||||
// Modifier keys should not trigger the action
|
||||
dispatchEvent({ key: 'd', code: 'KeyD', ctrlKey: true })
|
||||
dispatchEvent({ key: 'd', code: 'KeyD', altKey: true })
|
||||
dispatchEvent({ key: 'd', code: 'KeyD', shiftKey: true })
|
||||
dispatchEvent({ key: 'd', code: 'KeyD', metaKey: true })
|
||||
|
||||
expect(sidebarAction.enabled).toHaveReturnedWith(true)
|
||||
expect(sidebarAction.exec).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('Pressing F2 should rename the file', () => {
|
||||
dispatchEvent({ key: 'F2', code: 'F2' })
|
||||
|
||||
// Modifier keys should not trigger the action
|
||||
dispatchEvent({ key: 'F2', code: 'F2', ctrlKey: true })
|
||||
dispatchEvent({ key: 'F2', code: 'F2', altKey: true })
|
||||
dispatchEvent({ key: 'F2', code: 'F2', shiftKey: true })
|
||||
dispatchEvent({ key: 'F2', code: 'F2', metaKey: true })
|
||||
|
||||
expect(renameAction.enabled).toHaveReturnedWith(true)
|
||||
expect(renameAction.exec).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('Pressing s should toggle favorite', () => {
|
||||
(favoriteAction.enabled as Mock).mockReturnValue(true);
|
||||
(favoriteAction.exec as Mock).mockImplementationOnce(() => Promise.resolve(null))
|
||||
|
||||
vi.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve())
|
||||
dispatchEvent({ key: 's', code: 'KeyS' })
|
||||
|
||||
// Modifier keys should not trigger the action
|
||||
dispatchEvent({ key: 's', code: 'KeyS', ctrlKey: true })
|
||||
dispatchEvent({ key: 's', code: 'KeyS', altKey: true })
|
||||
dispatchEvent({ key: 's', code: 'KeyS', shiftKey: true })
|
||||
dispatchEvent({ key: 's', code: 'KeyS', metaKey: true })
|
||||
|
||||
expect(favoriteAction.exec).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('Pressing Delete should delete the file', async () => {
|
||||
// @ts-expect-error unit testing - private method access
|
||||
vi.spyOn(deleteAction._action, 'exec').mockResolvedValue(() => true)
|
||||
it('registeres actions', () => {
|
||||
component.destroy()
|
||||
registerFileAction(deleteAction)
|
||||
component = mount(TestComponent)
|
||||
|
||||
dispatchEvent({ key: 'Delete', code: 'Delete' })
|
||||
|
||||
|
|
@ -175,6 +145,8 @@ describe('HotKeysService testing', () => {
|
|||
expect(deleteAction.exec).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
// actions implemented by the composable
|
||||
|
||||
it('Pressing alt+up should go to parent directory', () => {
|
||||
expect(router.push).toHaveBeenCalledTimes(0)
|
||||
dispatchEvent({ key: 'ArrowUp', code: 'ArrowUp', altKey: true })
|
||||
|
|
@ -197,9 +169,8 @@ describe('HotKeysService testing', () => {
|
|||
it.each([
|
||||
['ctrlKey'],
|
||||
['altKey'],
|
||||
// those meta keys are still triggering...
|
||||
// ['shiftKey'],
|
||||
// ['metaKey']
|
||||
['shiftKey'],
|
||||
['metaKey'],
|
||||
])('Pressing v with modifier key %s should not toggle grid view', async (modifier: string) => {
|
||||
vi.spyOn(axios, 'put').mockImplementationOnce(() => Promise.resolve())
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
/**
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { getFileActions } from '@nextcloud/files'
|
||||
import { useHotKey } from '@nextcloud/vue/composables/useHotKey'
|
||||
import { dirname } from 'path'
|
||||
import { useRoute, useRouter } from 'vue-router/composables'
|
||||
import { action as deleteAction } from '../actions/deleteAction.ts'
|
||||
import { action as favoriteAction } from '../actions/favoriteAction.ts'
|
||||
import { action as renameAction } from '../actions/renameAction.ts'
|
||||
import { action as sidebarAction } from '../actions/sidebarAction.ts'
|
||||
import logger from '../logger.ts'
|
||||
import { useUserConfigStore } from '../store/userconfig.ts'
|
||||
import { executeAction } from '../utils/actionUtils.ts'
|
||||
|
|
@ -25,29 +23,24 @@ export function useHotKeys(): void {
|
|||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
// d opens the sidebar
|
||||
useHotKey('d', () => executeAction(sidebarAction), {
|
||||
stop: true,
|
||||
prevent: true,
|
||||
})
|
||||
const actions = getFileActions()
|
||||
for (const action of actions) {
|
||||
if (!action.hotkey) {
|
||||
continue
|
||||
}
|
||||
const key = action.hotkey.key.match(/^[a-z]$/)
|
||||
? action.hotkey.key.toUpperCase()
|
||||
: action.hotkey.key
|
||||
|
||||
// F2 renames the file
|
||||
useHotKey('F2', () => executeAction(renameAction), {
|
||||
stop: true,
|
||||
prevent: true,
|
||||
})
|
||||
|
||||
// s toggle favorite
|
||||
useHotKey('s', () => executeAction(favoriteAction), {
|
||||
stop: true,
|
||||
prevent: true,
|
||||
})
|
||||
|
||||
// Delete deletes the file
|
||||
useHotKey('Delete', () => executeAction(deleteAction), {
|
||||
stop: true,
|
||||
prevent: true,
|
||||
})
|
||||
logger.debug(`Register hotkey for action "${action.id}"`)
|
||||
useHotKey(key, () => executeAction(action), {
|
||||
stop: true,
|
||||
prevent: true,
|
||||
alt: action.hotkey.alt,
|
||||
ctrl: action.hotkey.ctrl,
|
||||
shift: action.hotkey.shift,
|
||||
})
|
||||
}
|
||||
|
||||
// alt+up go to parent directory
|
||||
useHotKey('ArrowUp', goToParentDir, {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import type { FileAction, IFolder, INode, IView } from '@nextcloud/files'
|
|||
import { subscribe } from '@nextcloud/event-bus'
|
||||
import { getNavigation } from '@nextcloud/files'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
import logger from '../logger.ts'
|
||||
|
||||
export const useActiveStore = defineStore('active', () => {
|
||||
|
|
@ -32,6 +32,21 @@ export const useActiveStore = defineStore('active', () => {
|
|||
*/
|
||||
const activeView = ref<IView>()
|
||||
|
||||
// Set the active node on the router params
|
||||
watch(activeNode, () => {
|
||||
if (typeof activeNode.value?.fileid !== 'number' || activeNode.value.fileid === activeFolder.value?.fileid) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.debug('Updating active fileid in URL query', { fileid: activeNode.value.fileid })
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null,
|
||||
{ ...window.OCP.Files.Router.params, fileid: String(activeNode.value.fileid) },
|
||||
{ ...window.OCP.Files.Router.query },
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
initialize()
|
||||
|
||||
/**
|
||||
|
|
@ -62,12 +77,10 @@ export const useActiveStore = defineStore('active', () => {
|
|||
*/
|
||||
function initialize() {
|
||||
const navigation = getNavigation()
|
||||
onChangedView(navigation.active)
|
||||
|
||||
// Make sure we only register the listeners once
|
||||
subscribe('files:node:deleted', onDeletedNode)
|
||||
|
||||
onChangedView(navigation.active)
|
||||
|
||||
// Or you can react to changes of the current active view
|
||||
navigation.addEventListener('updateActive', (event) => {
|
||||
onChangedView(event.detail)
|
||||
|
|
|
|||
|
|
@ -8,17 +8,17 @@ import type { INode, ISidebarContext } from '@nextcloud/files'
|
|||
import { subscribe } from '@nextcloud/event-bus'
|
||||
import { getSidebarActions, getSidebarTabs } from '@nextcloud/files'
|
||||
import { defineStore } from 'pinia'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { computed, readonly, ref, watch } from 'vue'
|
||||
import logger from '../logger.ts'
|
||||
import { useActiveStore } from './active.ts'
|
||||
import { useFilesStore } from './files.ts'
|
||||
|
||||
export const useSidebarStore = defineStore('sidebar', () => {
|
||||
const activeTab = ref<string>()
|
||||
const currentNode = ref<INode>()
|
||||
const isOpen = computed(() => !!currentNode.value)
|
||||
const isOpen = ref(false)
|
||||
|
||||
const activeStore = useActiveStore()
|
||||
const currentNode = computed(() => isOpen.value ? activeStore.activeNode : undefined)
|
||||
const hasContext = computed(() => !!(currentNode.value && activeStore.activeFolder && activeStore.activeView))
|
||||
const currentContext = computed<ISidebarContext | undefined>(() => {
|
||||
if (!hasContext.value) {
|
||||
|
|
@ -41,7 +41,6 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
* @param tabId - Optional ID of the tab to activate.
|
||||
*/
|
||||
function open(node: INode, tabId?: string) {
|
||||
const activeStore = useActiveStore()
|
||||
if (!(node && activeStore.activeFolder && activeStore.activeView)) {
|
||||
logger.debug('Cannot open sidebar because the active folder or view is not set.', {
|
||||
node,
|
||||
|
|
@ -64,14 +63,16 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
} else {
|
||||
activeTab.value = tabId ?? newTabs[0]?.id
|
||||
}
|
||||
currentNode.value = node
|
||||
logger.debug(`Opening sidebar for ${node.displayname}`, { node })
|
||||
activeStore.activeNode = node
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the sidebar.
|
||||
*/
|
||||
function close() {
|
||||
currentNode.value = undefined
|
||||
isOpen.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,7 +118,7 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
// update the current node if updated
|
||||
subscribe('files:node:updated', (node: INode) => {
|
||||
if (node.source === currentNode.value?.source) {
|
||||
currentNode.value = node
|
||||
activeStore.activeNode = node
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -144,8 +145,10 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
subscribe('files:list:updated', () => {
|
||||
if (!initialized) {
|
||||
initialized = true
|
||||
window.OCP.Files.Router._router.afterEach((to) => {
|
||||
if (to.query && !('opendetails' in to.query)) {
|
||||
window.OCP.Files.Router._router.afterEach((to, from) => {
|
||||
if ((from.query && ('opendetails' in from.query))
|
||||
&& (to.query && !('opendetails' in to.query))) {
|
||||
logger.debug('Closing sidebar because "opendetails" query parameter was removed from URL.')
|
||||
close()
|
||||
}
|
||||
})
|
||||
|
|
@ -153,37 +156,31 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
})
|
||||
|
||||
// watch open state and update URL query parameters
|
||||
watch(currentNode, (node) => {
|
||||
watch(isOpen, (isOpen) => {
|
||||
const params = { ...(window.OCP?.Files?.Router?.params ?? {}) }
|
||||
const query = { ...(window.OCP?.Files?.Router?.query ?? {}) }
|
||||
|
||||
if (!node && 'opendetails' in query) {
|
||||
logger.debug(`Sidebar current node changed: ${isOpen ? 'open' : 'closed'}`, { query, params, node: activeStore.activeNode })
|
||||
if (!isOpen && ('opendetails' in query)) {
|
||||
delete query.opendetails
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null,
|
||||
{ ...window.OCP.Files.Router.params },
|
||||
{
|
||||
...query,
|
||||
},
|
||||
params,
|
||||
query,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
if (node) {
|
||||
const fileid = String(node.fileid)
|
||||
if (!('opendetails' in query) || window.OCP.Files.Router.params.fileid !== fileid) {
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null,
|
||||
{
|
||||
...window.OCP.Files.Router.params,
|
||||
fileid,
|
||||
},
|
||||
{
|
||||
...query,
|
||||
opendetails: 'true',
|
||||
},
|
||||
true,
|
||||
)
|
||||
}
|
||||
if (isOpen && !('opendetails' in query)) {
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null,
|
||||
params,
|
||||
{
|
||||
...query,
|
||||
opendetails: 'true',
|
||||
},
|
||||
true,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -194,7 +191,7 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
currentNode,
|
||||
currentTabs,
|
||||
hasContext,
|
||||
isOpen,
|
||||
isOpen: readonly(isOpen),
|
||||
|
||||
open,
|
||||
close,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/**
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { INode } from '@nextcloud/files'
|
||||
import type { ActionContext, ActionContextSingle } from '@nextcloud/files'
|
||||
|
||||
import TagMultipleSvg from '@mdi/svg/svg/tag-multiple-outline.svg?raw'
|
||||
import { FileAction, Permission } from '@nextcloud/files'
|
||||
|
|
@ -15,10 +15,10 @@ import { defineAsyncComponent } from 'vue'
|
|||
/**
|
||||
* Spawn a dialog to add or remove tags from multiple nodes.
|
||||
*
|
||||
* @param nodes Nodes to modify tags for
|
||||
* @param nodes.nodes
|
||||
* @param context - The action context
|
||||
* @param context.nodes - Nodes to modify tags for
|
||||
*/
|
||||
async function execBatch({ nodes }: { nodes: INode[] }): Promise<(null | boolean)[]> {
|
||||
async function execBatch({ nodes }: ActionContext | ActionContextSingle): Promise<(null | boolean)[]> {
|
||||
const response = await new Promise<null | boolean>((resolve) => {
|
||||
spawnDialog(defineAsyncComponent(() => import('../components/SystemTagPicker.vue')), {
|
||||
nodes,
|
||||
|
|
@ -53,9 +53,15 @@ export const action = new FileAction({
|
|||
return !nodes.some((node) => (node.permissions & Permission.UPDATE) === 0)
|
||||
},
|
||||
|
||||
async exec({ nodes }) {
|
||||
return execBatch({ nodes })[0]
|
||||
async exec(context: ActionContextSingle) {
|
||||
const [result] = await execBatch(context)
|
||||
return result
|
||||
},
|
||||
|
||||
execBatch,
|
||||
|
||||
hotkey: {
|
||||
description: t('systemtags', 'Manage tags'),
|
||||
key: 't',
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/**
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { Node } from '@nextcloud/files'
|
||||
import type { INode } from '@nextcloud/files'
|
||||
import type { TagWithId } from '../types.ts'
|
||||
|
||||
import { subscribe } from '@nextcloud/event-bus'
|
||||
|
|
@ -44,11 +44,6 @@ export const action = new FileAction({
|
|||
},
|
||||
|
||||
order: 0,
|
||||
|
||||
hotkey: {
|
||||
description: t('files', 'Manage tags'),
|
||||
key: 'T',
|
||||
},
|
||||
})
|
||||
|
||||
// Subscribe to the events
|
||||
|
|
@ -62,7 +57,7 @@ subscribe('systemtags:tag:updated', updateTag)
|
|||
*
|
||||
* @param node - The updated node
|
||||
*/
|
||||
function updateSystemTagsHtml(node: Node) {
|
||||
function updateSystemTagsHtml(node: INode) {
|
||||
renderInline(node).then((systemTagsHtml) => {
|
||||
document.querySelectorAll(`[data-systemtags-fileid="${node.fileid}"]`).forEach((element) => {
|
||||
element.replaceWith(systemTagsHtml)
|
||||
|
|
@ -113,9 +108,10 @@ function updateSystemTagsColorAttribute(tag: TagWithId) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Render a single tag element
|
||||
*
|
||||
* @param tag
|
||||
* @param isMore
|
||||
* @param tag - The tag to render
|
||||
* @param isMore - Whether this is a "more" tag
|
||||
*/
|
||||
function renderTag(tag: string, isMore = false): HTMLElement {
|
||||
const tagElement = document.createElement('li')
|
||||
|
|
@ -143,10 +139,11 @@ function renderTag(tag: string, isMore = false): HTMLElement {
|
|||
}
|
||||
|
||||
/**
|
||||
* Render the inline system tags for a node
|
||||
*
|
||||
* @param node
|
||||
* @param node - The node to render the tags for
|
||||
*/
|
||||
async function renderInline(node: Node): Promise<HTMLElement> {
|
||||
async function renderInline(node: INode): Promise<HTMLElement> {
|
||||
// Ensure we have the system tags as an array
|
||||
const tags = getNodeSystemTags(node)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { registerFileSidebarAction } from './files_actions/filesSidebarAction.ts
|
|||
import { action as inlineSystemTagsAction } from './files_actions/inlineSystemTagsAction.ts'
|
||||
import { action as openInFilesAction } from './files_actions/openInFilesAction.ts'
|
||||
import { registerSystemTagsView } from './files_views/systemtagsView.ts'
|
||||
import { registerHotkeys } from './services/HotKeysService.ts'
|
||||
|
||||
registerDavProperty('nc:system-tags')
|
||||
registerFileAction(bulkSystemTagsAction)
|
||||
|
|
@ -19,7 +18,3 @@ registerFileAction(openInFilesAction)
|
|||
|
||||
registerSystemTagsView()
|
||||
registerFileSidebarAction()
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
registerHotkeys()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
import type { View } from '@nextcloud/files'
|
||||
|
||||
import { File, Folder, Permission } from '@nextcloud/files'
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useActiveStore } from '../../../files/src/store/active.ts'
|
||||
import { getPinia } from '../../../files/src/store/index.ts'
|
||||
import { action as bulkSystemTagsAction } from '../files_actions/bulkSystemTagsAction.ts'
|
||||
import { registerHotkeys } from './HotKeysService.ts'
|
||||
|
||||
let file: File
|
||||
const view = {
|
||||
id: 'files',
|
||||
name: 'Files',
|
||||
} as View
|
||||
|
||||
vi.mock('../files_actions/bulkSystemTagsAction.ts', { spy: true })
|
||||
|
||||
describe('HotKeysService testing', () => {
|
||||
const activeStore = useActiveStore(getPinia())
|
||||
|
||||
beforeAll(() => {
|
||||
registerHotkeys()
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
// Make sure the file is reset before each test
|
||||
file = new File({
|
||||
id: 2,
|
||||
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
|
||||
root: '/files/admin',
|
||||
owner: 'admin',
|
||||
mime: 'text/plain',
|
||||
permissions: Permission.ALL,
|
||||
})
|
||||
|
||||
const root = new Folder({
|
||||
id: 1,
|
||||
source: 'https://cloud.domain.com/remote.php/dav/files/admin/',
|
||||
root: '/files/admin',
|
||||
owner: 'admin',
|
||||
permissions: Permission.CREATE,
|
||||
})
|
||||
|
||||
// Setting the view first as it reset the active node
|
||||
activeStore.activeView = view
|
||||
activeStore.activeNode = file
|
||||
activeStore.activeFolder = root
|
||||
})
|
||||
|
||||
it('Pressing t should open the tag management dialog', () => {
|
||||
dispatchEvent({ key: 't', code: 'KeyT' })
|
||||
|
||||
// Modifier keys should not trigger the action
|
||||
dispatchEvent({ key: 't', code: 'KeyT', ctrlKey: true })
|
||||
dispatchEvent({ key: 't', code: 'KeyT', altKey: true })
|
||||
dispatchEvent({ key: 't', code: 'KeyT', shiftKey: true })
|
||||
dispatchEvent({ key: 't', code: 'KeyT', metaKey: true })
|
||||
|
||||
expect(bulkSystemTagsAction.enabled).toHaveReturnedWith(true)
|
||||
expect(bulkSystemTagsAction.exec).toHaveBeenCalledOnce()
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Helper to dispatch the correct event.
|
||||
*
|
||||
* @param init - KeyboardEvent options
|
||||
*/
|
||||
function dispatchEvent(init: KeyboardEventInit) {
|
||||
document.body.dispatchEvent(new KeyboardEvent('keydown', { ...init, bubbles: true }))
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import { useHotKey } from '@nextcloud/vue/composables/useHotKey'
|
||||
import { executeAction } from '../../../files/src/utils/actionUtils.ts'
|
||||
import { action as manageTagAction } from '../files_actions/bulkSystemTagsAction.ts'
|
||||
import logger from '../logger.ts'
|
||||
|
||||
/**
|
||||
* This register the hotkeys for the Files app.
|
||||
* As much as possible, we try to have all the hotkeys in one place.
|
||||
* Please make sure to add tests for the hotkeys after adding a new one.
|
||||
*/
|
||||
export function registerHotkeys() {
|
||||
// t opens the tag management dialog
|
||||
useHotKey('t', () => executeAction(manageTagAction), {
|
||||
stop: true,
|
||||
prevent: true,
|
||||
})
|
||||
|
||||
logger.debug('Hotkeys registered')
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ import type { User } from '@nextcloud/e2e-test-server/cypress'
|
|||
|
||||
const ACTION_COPY_MOVE = 'move-copy'
|
||||
|
||||
export const getRowForFileId = (fileid: number) => cy.get(`[data-cy-files-list-row-fileid="${fileid}"]`)
|
||||
export const getRowForFileId = (fileid: string | number) => cy.get(`[data-cy-files-list-row-fileid="${fileid}"]`)
|
||||
export const getRowForFile = (filename: string) => cy.get(`[data-cy-files-list-row-name="${CSS.escape(filename)}"]`)
|
||||
|
||||
export const getActionsForFileId = (fileid: number) => getRowForFileId(fileid).find('[data-cy-files-list-row-actions]')
|
||||
|
|
|
|||
113
cypress/e2e/files/hotkeys.cy.ts
Normal file
113
cypress/e2e/files/hotkeys.cy.ts
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { getRowForFileId } from './FilesUtils.ts'
|
||||
|
||||
describe('Files hotkey handling', () => {
|
||||
before(() => {
|
||||
cy.createRandomUser().then((user) => {
|
||||
cy.mkdir(user, '/abcd')
|
||||
cy.mkdir(user, '/zyx')
|
||||
cy.rm(user, '/welcome.txt')
|
||||
cy.login(user)
|
||||
})
|
||||
})
|
||||
|
||||
beforeEach(() => cy.visit('/apps/files'))
|
||||
|
||||
it('Pressing "arrow down" should go to first file', () => {
|
||||
cy.get('[data-cy-files-list]')
|
||||
.press(Cypress.Keyboard.Keys.DOWN)
|
||||
|
||||
cy.url()
|
||||
.should('match', /\/apps\/files\/files\/\d+/)
|
||||
.then((url) => new URL(url).pathname.split('/').at(-1))
|
||||
.then((fileId) => getRowForFileId(fileId)
|
||||
.should('exist')
|
||||
.and('have.attr', 'data-cy-files-list-row-name', 'abcd'))
|
||||
})
|
||||
|
||||
it('Pressing "arrow up" should go to first file', () => {
|
||||
cy.get('[data-cy-files-list]')
|
||||
.press(Cypress.Keyboard.Keys.UP)
|
||||
|
||||
cy.url()
|
||||
.should('match', /\/apps\/files\/files\/\d+/)
|
||||
.then((url) => new URL(url).pathname.split('/').at(-1))
|
||||
.then((fileId) => getRowForFileId(fileId)
|
||||
.should('exist')
|
||||
.and('have.attr', 'data-cy-files-list-row-name', 'zyx'))
|
||||
})
|
||||
|
||||
it('Pressing D should open the sidebar once', () => {
|
||||
activateFirstRow()
|
||||
cy.get('[data-cy-files-list]')
|
||||
.press('d')
|
||||
|
||||
cy.get('[data-cy-sidebar]')
|
||||
.should('exist')
|
||||
.and('be.visible')
|
||||
})
|
||||
|
||||
it('Pressing F2 should rename the file', () => {
|
||||
activateFirstRow()
|
||||
cy.get('[data-cy-files-list]')
|
||||
.should('exist')
|
||||
.then(($el) => {
|
||||
const el = $el.get(0)
|
||||
// manually dispatch as Cypress refuses to press F-keys for "security reasons"
|
||||
cy.log('Dispatching F2 keydown/keyup events')
|
||||
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'F2', code: 'F2', bubbles: true }))
|
||||
el.dispatchEvent(new KeyboardEvent('keyup', { key: 'F2', code: 'F2', bubbles: true }))
|
||||
el.dispatchEvent(new KeyboardEvent('keypress', { key: 'F2', code: 'F2', bubbles: true }))
|
||||
})
|
||||
|
||||
cy.get('[data-cy-files-list-row-name]')
|
||||
.first()
|
||||
.findByRole('textbox', { name: /Folder name/ })
|
||||
.should('exist')
|
||||
})
|
||||
|
||||
it('Pressing S should toggle favorite', () => {
|
||||
activateFirstRow()
|
||||
cy.get('[data-cy-files-list]')
|
||||
.press('s')
|
||||
|
||||
cy.get('[data-cy-files-list-row-name]')
|
||||
.first()
|
||||
.as('firstRow')
|
||||
.findByRole('img', { name: /Favorite/ })
|
||||
.should('exist')
|
||||
|
||||
cy.get('[data-cy-files-list]')
|
||||
.press('s')
|
||||
|
||||
cy.get('@firstRow')
|
||||
.findByRole('img', { name: /Favorite/ })
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('Pressing DELETE should delete the folder', () => {
|
||||
activateFirstRow()
|
||||
cy.get('td[data-cy-files-list-row-name]')
|
||||
.should('have.length', 2)
|
||||
|
||||
cy.get('[data-cy-files-list]')
|
||||
.press(Cypress.Keyboard.Keys.DELETE)
|
||||
|
||||
cy.get('td[data-cy-files-list-row-name]')
|
||||
.should('have.length', 1)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Activates the first row in the files list by simulating a press of the down arrow key.
|
||||
*/
|
||||
function activateFirstRow() {
|
||||
cy.get('[data-cy-files-list]')
|
||||
.press(Cypress.Keyboard.Keys.DOWN)
|
||||
cy.url()
|
||||
.should('match', /\/apps\/files\/files\/\d+/)
|
||||
}
|
||||
2
dist/2605-2605.js
vendored
2
dist/2605-2605.js
vendored
File diff suppressed because one or more lines are too long
1
dist/2605-2605.js.map.license
vendored
1
dist/2605-2605.js.map.license
vendored
|
|
@ -1 +0,0 @@
|
|||
2605-2605.js.license
|
||||
2
dist/3442-3442.js
vendored
Normal file
2
dist/3442-3442.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
dist/3442-3442.js.map.license
vendored
Symbolic link
1
dist/3442-3442.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
3442-3442.js.license
|
||||
4
dist/core-common.js
vendored
4
dist/core-common.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-common.js.map
vendored
2
dist/core-common.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files-init.js
vendored
4
dist/files-init.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files-init.js.map
vendored
2
dist/files-init.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files-main.js
vendored
4
dist/files-main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files-main.js.map
vendored
2
dist/files-main.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files-sidebar.js
vendored
4
dist/files-sidebar.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files-sidebar.js.map
vendored
2
dist/files-sidebar.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-init-public.js
vendored
4
dist/files_sharing-init-public.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-init-public.js.map
vendored
2
dist/files_sharing-init-public.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-init.js
vendored
4
dist/files_sharing-init.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-init.js.map
vendored
2
dist/files_sharing-init.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/settings-users-3239.js
vendored
4
dist/settings-users-3239.js
vendored
File diff suppressed because one or more lines are too long
2
dist/settings-users-3239.js.map
vendored
2
dist/settings-users-3239.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
dist/systemtags-init.js
vendored
4
dist/systemtags-init.js
vendored
File diff suppressed because one or more lines are too long
464
dist/systemtags-init.js.license
vendored
464
dist/systemtags-init.js.license
vendored
|
|
@ -5,59 +5,36 @@ SPDX-License-Identifier: BSD-3-Clause
|
|||
SPDX-License-Identifier: BSD-2-Clause
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
|
||||
SPDX-License-Identifier: (MIT AND BSD-3-Clause)
|
||||
SPDX-FileCopyrightText: string_decoder developers
|
||||
SPDX-FileCopyrightText: ripemd160 developers
|
||||
SPDX-FileCopyrightText: rhysd <lin90162@yahoo.co.jp>
|
||||
SPDX-FileCopyrightText: readable-stream developers
|
||||
SPDX-FileCopyrightText: qs developers
|
||||
SPDX-FileCopyrightText: p-queue developers
|
||||
SPDX-FileCopyrightText: omahlama
|
||||
SPDX-FileCopyrightText: jden <jason@denizac.org>
|
||||
SPDX-FileCopyrightText: inline-style-parser developers
|
||||
SPDX-FileCopyrightText: inherits developers
|
||||
SPDX-FileCopyrightText: escape-html developers
|
||||
SPDX-FileCopyrightText: defunctzombie
|
||||
SPDX-FileCopyrightText: debounce developers
|
||||
SPDX-FileCopyrightText: date-fns developers
|
||||
SPDX-FileCopyrightText: chenkai
|
||||
SPDX-FileCopyrightText: browserify-sign developers
|
||||
SPDX-FileCopyrightText: browserify-rsa developers
|
||||
SPDX-FileCopyrightText: atomiks
|
||||
SPDX-FileCopyrightText: Varun A P
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)
|
||||
SPDX-FileCopyrightText: T. Jameson Little <t.jameson.little@gmail.com>
|
||||
SPDX-FileCopyrightText: Stefan Thomas <justmoon@members.fsf.org> (http://www.justmoon.net)
|
||||
SPDX-FileCopyrightText: Sindre Sorhus
|
||||
SPDX-FileCopyrightText: Shuhei Kagawa
|
||||
SPDX-FileCopyrightText: Scott Cooper <scttcper@gmail.com>
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Raynos <raynos2@gmail.com>
|
||||
SPDX-FileCopyrightText: Perry Mitchell <perry@perrymitchell.net>
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorba.ch> (http://paul.vorba.ch)
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorb.de> (http://vorb.de)
|
||||
SPDX-FileCopyrightText: OpenJS Foundation and other contributors
|
||||
SPDX-FileCopyrightText: Olivier Scherrer <pode.fr@gmail.com>
|
||||
SPDX-FileCopyrightText: Nick Frasser (https://nfrasser.com)
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)
|
||||
SPDX-FileCopyrightText: Max <max@nextcloud.com>
|
||||
SPDX-FileCopyrightText: Matt Zabriskie
|
||||
SPDX-FileCopyrightText: Mathias Bynens
|
||||
SPDX-FileCopyrightText: Mathias Buus (@mafintosh)
|
||||
SPDX-FileCopyrightText: Mark <mark@remarkablemark.org>
|
||||
SPDX-FileCopyrightText: Kirill Fomichev <fanatid@ya.ru> (https://github.com/fanatid)
|
||||
SPDX-FileCopyrightText: Julian Gruber
|
||||
SPDX-FileCopyrightText: Joyent
|
||||
SPDX-FileCopyrightText: José F. Romaniello <jfromaniello@gmail.com> (http://joseoncode.com)
|
||||
SPDX-FileCopyrightText: Jordan Humphreys <jordan@zurb.com>
|
||||
SPDX-FileCopyrightText: Jordan Harband <ljharb@gmail.com>
|
||||
SPDX-FileCopyrightText: Jordan Harband
|
||||
SPDX-FileCopyrightText: Jordan Harbamd <ljharb@gmail.com>
|
||||
SPDX-FileCopyrightText: Jonas Schade <derzade@gmail.com>
|
||||
SPDX-FileCopyrightText: John Hiesey
|
||||
SPDX-FileCopyrightText: Jeff Sagal <sagalbot@gmail.com>
|
||||
SPDX-FileCopyrightText: James Halliday
|
||||
SPDX-FileCopyrightText: Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)
|
||||
SPDX-FileCopyrightText: Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)
|
||||
|
|
@ -66,46 +43,25 @@ SPDX-FileCopyrightText: Guillaume Chau
|
|||
SPDX-FileCopyrightText: GitHub Inc.
|
||||
SPDX-FileCopyrightText: Feross Aboukhadijeh
|
||||
SPDX-FileCopyrightText: Felix Boehm <me@feedic.com>
|
||||
SPDX-FileCopyrightText: Fedor Indutny <fedor@indutny.com>
|
||||
SPDX-FileCopyrightText: Fedor Indutny
|
||||
SPDX-FileCopyrightText: Evan You
|
||||
SPDX-FileCopyrightText: Eugene Sharygin <eush77@gmail.com>
|
||||
SPDX-FileCopyrightText: Eric Norris (https://github.com/ericnorris)
|
||||
SPDX-FileCopyrightText: Eduardo San Martin Morote
|
||||
SPDX-FileCopyrightText: Dylan Piercey <pierceydylan@gmail.com>
|
||||
SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 <mario@cure53.de> (https://cure53.de/)
|
||||
SPDX-FileCopyrightText: Dominic Tarr <dominic.tarr@gmail.com> (dominictarr.com)
|
||||
SPDX-FileCopyrightText: David Clark
|
||||
SPDX-FileCopyrightText: Daniel Cousens
|
||||
SPDX-FileCopyrightText: Christoph Wurst
|
||||
SPDX-FileCopyrightText: Calvin Metcalf <calvin.metcalf@gmail.com>
|
||||
SPDX-FileCopyrightText: Calvin Metcalf
|
||||
SPDX-FileCopyrightText: Borys Serebrov
|
||||
SPDX-FileCopyrightText: Ben Drucker
|
||||
SPDX-FileCopyrightText: Arnout Kazemier
|
||||
SPDX-FileCopyrightText: Antoni Andre <antoniandre.web@gmail.com>
|
||||
SPDX-FileCopyrightText: Anthony Fu <https://github.com/antfu>
|
||||
SPDX-FileCopyrightText: Anthony Fu <anthonyfu117@hotmail.com>
|
||||
SPDX-FileCopyrightText: Andrea Giammarchi
|
||||
SPDX-FileCopyrightText: Amit Gupta (https://solothought.com)
|
||||
SPDX-FileCopyrightText: Amit Gupta (https://amitkumargupta.work/)
|
||||
SPDX-FileCopyrightText: @nextcloud/dialogs developers
|
||||
SPDX-FileCopyrightText:
|
||||
|
||||
|
||||
This file is generated from multiple sources. Included packages:
|
||||
- @buttercup/fetch
|
||||
- version: 0.2.1
|
||||
- license: MIT
|
||||
- @ctrl/tinycolor
|
||||
- version: 3.6.1
|
||||
- license: MIT
|
||||
- @floating-ui/core
|
||||
- version: 1.7.3
|
||||
- license: MIT
|
||||
- @floating-ui/dom
|
||||
- version: 1.7.4
|
||||
- license: MIT
|
||||
- @floating-ui/utils
|
||||
- version: 0.2.10
|
||||
- license: MIT
|
||||
|
|
@ -121,45 +77,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/capabilities
|
||||
- version: 1.2.1
|
||||
- license: GPL-3.0-or-later
|
||||
- @ckpack/vue-color
|
||||
- version: 1.6.0
|
||||
- license: MIT
|
||||
- @nextcloud/paths
|
||||
- version: 2.4.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/browser-storage
|
||||
- version: 0.4.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/vue
|
||||
- version: 9.0.1
|
||||
- license: AGPL-3.0-or-later
|
||||
- @vueuse/core
|
||||
- version: 13.9.0
|
||||
- license: MIT
|
||||
- @vueuse/shared
|
||||
- version: 13.9.0
|
||||
- license: MIT
|
||||
- debounce
|
||||
- version: 2.2.0
|
||||
- license: MIT
|
||||
- rehype-react
|
||||
- version: 8.0.0
|
||||
- license: MIT
|
||||
- splitpanes
|
||||
- version: 4.0.4
|
||||
- license: MIT
|
||||
- vue-router
|
||||
- version: 4.6.3
|
||||
- license: MIT
|
||||
- vue-select
|
||||
- version: 4.0.0-beta.6
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 3.5.22
|
||||
- license: MIT
|
||||
- @nextcloud/dialogs
|
||||
- version: 7.1.0
|
||||
- license: AGPL-3.0-or-later
|
||||
- semver
|
||||
- version: 7.7.2
|
||||
- license: ISC
|
||||
|
|
@ -214,36 +131,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/vue
|
||||
- version: 8.35.0
|
||||
- license: AGPL-3.0-or-later
|
||||
- @ungap/structured-clone
|
||||
- version: 1.3.0
|
||||
- license: ISC
|
||||
- @vue/devtools-api
|
||||
- version: 6.6.4
|
||||
- license: MIT
|
||||
- @vue/reactivity
|
||||
- version: 3.5.22
|
||||
- license: MIT
|
||||
- @vue/runtime-core
|
||||
- version: 3.5.22
|
||||
- license: MIT
|
||||
- @vue/runtime-dom
|
||||
- version: 3.5.22
|
||||
- license: MIT
|
||||
- @vue/shared
|
||||
- version: 3.5.22
|
||||
- license: MIT
|
||||
- @vueuse/core
|
||||
- version: 11.3.0
|
||||
- license: MIT
|
||||
- @vueuse/shared
|
||||
- version: 11.3.0
|
||||
- license: MIT
|
||||
- bn.js
|
||||
- version: 4.12.2
|
||||
- license: MIT
|
||||
- asn1.js
|
||||
- version: 4.10.1
|
||||
- license: MIT
|
||||
- available-typed-arrays
|
||||
- version: 1.0.7
|
||||
- license: MIT
|
||||
|
|
@ -259,36 +149,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- base64-js
|
||||
- version: 1.5.1
|
||||
- license: MIT
|
||||
- blurhash
|
||||
- version: 2.0.5
|
||||
- license: MIT
|
||||
- bn.js
|
||||
- version: 5.2.2
|
||||
- license: MIT
|
||||
- brace-expansion
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- brorand
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- browserify-aes
|
||||
- version: 1.2.0
|
||||
- license: MIT
|
||||
- browserify-cipher
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- browserify-des
|
||||
- version: 1.0.2
|
||||
- license: MIT
|
||||
- browserify-rsa
|
||||
- version: 4.1.1
|
||||
- license: MIT
|
||||
- browserify-sign
|
||||
- version: 4.2.5
|
||||
- license: ISC
|
||||
- buffer-xor
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- buffer
|
||||
- version: 5.7.1
|
||||
- license: MIT
|
||||
|
|
@ -313,75 +176,24 @@ This file is generated from multiple sources. Included packages:
|
|||
- charenc
|
||||
- version: 0.0.2
|
||||
- license: BSD-3-Clause
|
||||
- cipher-base
|
||||
- version: 1.0.7
|
||||
- license: MIT
|
||||
- comma-separated-tokens
|
||||
- version: 2.0.3
|
||||
- license: MIT
|
||||
- core-util-is
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- bn.js
|
||||
- version: 4.12.2
|
||||
- license: MIT
|
||||
- create-ecdh
|
||||
- version: 4.0.4
|
||||
- license: MIT
|
||||
- create-hash
|
||||
- version: 1.2.0
|
||||
- license: MIT
|
||||
- create-hmac
|
||||
- version: 1.1.7
|
||||
- license: MIT
|
||||
- crypt
|
||||
- version: 0.0.2
|
||||
- license: BSD-3-Clause
|
||||
- crypto-browserify
|
||||
- version: 3.12.1
|
||||
- license: MIT
|
||||
- css-loader
|
||||
- version: 7.1.2
|
||||
- license: MIT
|
||||
- date-fns
|
||||
- version: 4.1.0
|
||||
- license: MIT
|
||||
- debounce
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- decode-named-character-reference
|
||||
- version: 1.2.0
|
||||
- license: MIT
|
||||
- define-data-property
|
||||
- version: 1.1.4
|
||||
- license: MIT
|
||||
- des.js
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- devlop
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- bn.js
|
||||
- version: 4.12.2
|
||||
- license: MIT
|
||||
- diffie-hellman
|
||||
- version: 5.0.3
|
||||
- license: MIT
|
||||
- dompurify
|
||||
- version: 3.3.1
|
||||
- license: (MPL-2.0 OR Apache-2.0)
|
||||
- dunder-proto
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- bn.js
|
||||
- version: 4.12.2
|
||||
- license: MIT
|
||||
- elliptic
|
||||
- version: 6.6.1
|
||||
- license: MIT
|
||||
- emoji-mart-vue-fast
|
||||
- version: 15.0.5
|
||||
- license: BSD-3-Clause
|
||||
- es-define-property
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
|
|
@ -394,18 +206,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- escape-html
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- estree-util-is-identifier-name
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- events
|
||||
- version: 3.3.0
|
||||
- license: MIT
|
||||
- evp_bytestokey
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- extend
|
||||
- version: 3.0.2
|
||||
- license: MIT
|
||||
- focus-trap
|
||||
- version: 7.6.6
|
||||
- license: MIT
|
||||
|
|
@ -436,30 +239,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- has-tostringtag
|
||||
- version: 1.0.2
|
||||
- license: MIT
|
||||
- hash-base
|
||||
- version: 3.0.5
|
||||
- license: MIT
|
||||
- hash.js
|
||||
- version: 1.1.7
|
||||
- license: MIT
|
||||
- hasown
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- hast-util-is-element
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- hast-util-whitespace
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- property-information
|
||||
- version: 7.1.0
|
||||
- license: MIT
|
||||
- hast-util-to-jsx-runtime
|
||||
- version: 2.3.6
|
||||
- license: MIT
|
||||
- hmac-drbg
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- hot-patcher
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
|
|
@ -472,9 +254,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- inherits
|
||||
- version: 2.0.4
|
||||
- license: ISC
|
||||
- is-absolute-url
|
||||
- version: 4.0.1
|
||||
- license: MIT
|
||||
- is-arguments
|
||||
- version: 1.2.0
|
||||
- license: MIT
|
||||
|
|
@ -496,120 +275,15 @@ This file is generated from multiple sources. Included packages:
|
|||
- is-typed-array
|
||||
- version: 1.1.15
|
||||
- license: MIT
|
||||
- isarray
|
||||
- version: 1.0.0
|
||||
- license: MIT
|
||||
- jquery
|
||||
- version: 3.7.1
|
||||
- license: MIT
|
||||
- layerr
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- linkifyjs
|
||||
- version: 4.3.2
|
||||
- license: MIT
|
||||
- material-colors
|
||||
- version: 1.2.6
|
||||
- license: ISC
|
||||
- math-intrinsics
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- md5.js
|
||||
- version: 1.3.5
|
||||
- license: MIT
|
||||
- md5
|
||||
- version: 2.3.0
|
||||
- license: BSD-3-Clause
|
||||
- mdast-squeeze-paragraphs
|
||||
- version: 6.0.0
|
||||
- license: MIT
|
||||
- escape-string-regexp
|
||||
- version: 5.0.0
|
||||
- license: MIT
|
||||
- mdast-util-find-and-replace
|
||||
- version: 3.0.2
|
||||
- license: MIT
|
||||
- mdast-util-from-markdown
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- mdast-util-newline-to-break
|
||||
- version: 2.0.0
|
||||
- license: MIT
|
||||
- mdast-util-to-hast
|
||||
- version: 13.2.1
|
||||
- license: MIT
|
||||
- mdast-util-to-string
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- micromark-core-commonmark
|
||||
- version: 2.0.3
|
||||
- license: MIT
|
||||
- micromark-factory-destination
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-factory-label
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-factory-space
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-factory-title
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-factory-whitespace
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-character
|
||||
- version: 2.1.1
|
||||
- license: MIT
|
||||
- micromark-util-chunked
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-classify-character
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-combine-extensions
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-decode-numeric-character-reference
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- micromark-util-decode-string
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-encode
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-html-tag-name
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-normalize-identifier
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-resolve-all
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-sanitize-uri
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- micromark-util-subtokenize
|
||||
- version: 2.1.0
|
||||
- license: MIT
|
||||
- micromark
|
||||
- version: 4.0.2
|
||||
- license: MIT
|
||||
- bn.js
|
||||
- version: 4.12.2
|
||||
- license: MIT
|
||||
- miller-rabin
|
||||
- version: 4.0.1
|
||||
- license: MIT
|
||||
- minimalistic-assert
|
||||
- version: 1.0.1
|
||||
- license: ISC
|
||||
- minimalistic-crypto-utils
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- nested-property
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
|
|
@ -619,42 +293,15 @@ This file is generated from multiple sources. Included packages:
|
|||
- object-inspect
|
||||
- version: 1.13.4
|
||||
- license: MIT
|
||||
- eventemitter3
|
||||
- version: 5.0.1
|
||||
- license: MIT
|
||||
- p-queue
|
||||
- version: 9.0.1
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- parse-asn1
|
||||
- version: 5.1.9
|
||||
- license: ISC
|
||||
- path-posix
|
||||
- version: 1.0.0
|
||||
- license: ISC
|
||||
- pbkdf2
|
||||
- version: 3.1.5
|
||||
- license: MIT
|
||||
- pinia
|
||||
- version: 2.3.1
|
||||
- license: MIT
|
||||
- possible-typed-array-names
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- process-nextick-args
|
||||
- version: 2.0.1
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
- bn.js
|
||||
- version: 4.12.2
|
||||
- license: MIT
|
||||
- public-encrypt
|
||||
- version: 4.0.3
|
||||
- license: MIT
|
||||
- punycode
|
||||
- version: 1.4.1
|
||||
- license: MIT
|
||||
|
|
@ -664,45 +311,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- querystringify
|
||||
- version: 2.2.0
|
||||
- license: MIT
|
||||
- randombytes
|
||||
- version: 2.1.0
|
||||
- license: MIT
|
||||
- randomfill
|
||||
- version: 1.0.4
|
||||
- license: MIT
|
||||
- safe-buffer
|
||||
- version: 5.1.2
|
||||
- license: MIT
|
||||
- string_decoder
|
||||
- version: 1.1.1
|
||||
- license: MIT
|
||||
- readable-stream
|
||||
- version: 2.3.8
|
||||
- license: MIT
|
||||
- rehype-external-links
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- remark-breaks
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- remark-parse
|
||||
- version: 11.0.0
|
||||
- license: MIT
|
||||
- remark-rehype
|
||||
- version: 11.1.2
|
||||
- license: MIT
|
||||
- remark-unlink-protocols
|
||||
- version: 1.0.0
|
||||
- license: MIT
|
||||
- requires-port
|
||||
- version: 1.0.0
|
||||
- license: MIT
|
||||
- hash-base
|
||||
- version: 3.1.2
|
||||
- license: MIT
|
||||
- ripemd160
|
||||
- version: 2.0.3
|
||||
- license: MIT
|
||||
- safe-buffer
|
||||
- version: 5.2.1
|
||||
- license: MIT
|
||||
|
|
@ -715,9 +326,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- set-function-length
|
||||
- version: 1.2.2
|
||||
- license: MIT
|
||||
- sha.js
|
||||
- version: 2.4.12
|
||||
- license: (MIT AND BSD-3-Clause)
|
||||
- side-channel-list
|
||||
- version: 1.0.0
|
||||
- license: MIT
|
||||
|
|
@ -730,9 +338,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- side-channel
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- space-separated-tokens
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- readable-stream
|
||||
- version: 3.6.2
|
||||
- license: MIT
|
||||
|
|
@ -748,69 +353,15 @@ This file is generated from multiple sources. Included packages:
|
|||
- string_decoder
|
||||
- version: 1.3.0
|
||||
- license: MIT
|
||||
- striptags
|
||||
- version: 3.2.0
|
||||
- license: MIT
|
||||
- style-loader
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- inline-style-parser
|
||||
- version: 0.2.4
|
||||
- license: MIT
|
||||
- style-to-object
|
||||
- version: 1.0.11
|
||||
- license: MIT
|
||||
- style-to-js
|
||||
- version: 1.1.18
|
||||
- license: MIT
|
||||
- tabbable
|
||||
- version: 6.3.0
|
||||
- license: MIT
|
||||
- isarray
|
||||
- version: 2.0.5
|
||||
- license: MIT
|
||||
- to-buffer
|
||||
- version: 1.2.2
|
||||
- license: MIT
|
||||
- toastify-js
|
||||
- version: 1.12.0
|
||||
- license: MIT
|
||||
- tributejs
|
||||
- version: 5.1.3
|
||||
- license: MIT
|
||||
- trim-lines
|
||||
- version: 3.0.1
|
||||
- license: MIT
|
||||
- trough
|
||||
- version: 2.2.0
|
||||
- license: MIT
|
||||
- typed-array-buffer
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- typescript-event-target
|
||||
- version: 1.1.2
|
||||
- license: MIT
|
||||
- unified
|
||||
- version: 11.0.5
|
||||
- license: MIT
|
||||
- unist-builder
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- unist-util-is
|
||||
- version: 6.0.0
|
||||
- license: MIT
|
||||
- unist-util-position
|
||||
- version: 5.0.0
|
||||
- license: MIT
|
||||
- unist-util-stringify-position
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- unist-util-visit-parents
|
||||
- version: 6.0.1
|
||||
- license: MIT
|
||||
- unist-util-visit
|
||||
- version: 5.0.0
|
||||
- license: MIT
|
||||
- url-join
|
||||
- version: 5.0.0
|
||||
- license: MIT
|
||||
|
|
@ -826,21 +377,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- util
|
||||
- version: 0.12.5
|
||||
- license: MIT
|
||||
- vfile-message
|
||||
- version: 4.0.3
|
||||
- license: MIT
|
||||
- vfile
|
||||
- version: 6.0.3
|
||||
- license: MIT
|
||||
- vm-browserify
|
||||
- version: 1.1.2
|
||||
- license: MIT
|
||||
- vue-demi
|
||||
- version: 0.14.10
|
||||
- license: MIT
|
||||
- vue-loader
|
||||
- version: 15.11.1
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 2.7.16
|
||||
- license: MIT
|
||||
|
|
|
|||
2
dist/systemtags-init.js.map
vendored
2
dist/systemtags-init.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/weather_status-weather-status.js
vendored
4
dist/weather_status-weather-status.js
vendored
File diff suppressed because one or more lines are too long
2
dist/weather_status-weather-status.js.map
vendored
2
dist/weather_status-weather-status.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue