Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface Command {
name?: string
type?: 'text' | 'regex' | 'over' | 'img' | 'files' | 'window' | string
match?: {
match?: string
match?: string | Record<string, any>
minLength?: number
maxLength?: number
extensions?: string[]
Expand All @@ -32,6 +32,22 @@ const tagClass = computed(() => {
// 否则使用 props.type
return props.type ? `tag-${props.type}` : ''
})

function getMinLength(command?: Command): number {
return command?.match?.minLength ?? 1
}

function getMaxLength(command?: Command): number {
return command?.match?.maxLength ?? 10000
}

function getExtensions(command?: Command): string[] {
return command?.match?.extensions ?? []
}

function getFileType(command?: Command): string | undefined {
return command?.match?.fileType
}
</script>
<template>
<span :class="['command-tag', tagClass, { disabled: disabled }]">
Expand All @@ -51,9 +67,7 @@ const tagClass = computed(() => {
<!-- 任意文本 -->
<template v-else-if="command.type === 'over'">
<span class="tag-badge">{{ command.name }}</span>
<span v-if="command.match" class="tag-badge">
{{ command.match.minLength || 1 }}-{{ command.match.maxLength || 10000 }}
</span>
<span class="tag-badge"> {{ getMinLength(command) }}-{{ getMaxLength(command) }} </span>
<div class="i-z-text tag-icon font-size-12px" />
</template>

Expand All @@ -66,13 +80,13 @@ const tagClass = computed(() => {
<!-- 文件/文件夹 -->
<template v-else-if="command.type === 'files'">
<span class="tag-badge">{{ command.name }}</span>
<span v-if="command.match?.extensions" class="tag-badge">
{{ command.match.extensions.slice(0, 3).join(', ') }}
{{ command.match.extensions.length > 3 ? '...' : '' }}
<span v-if="getExtensions(command).length > 0" class="tag-badge">
{{ getExtensions(command).slice(0, 3).join(', ') }}
{{ getExtensions(command).length > 3 ? '...' : '' }}
</span>
<div
:class="[
command.match?.fileType === 'directory' ? 'i-z-folder' : 'i-z-file',
getFileType(command) === 'directory' ? 'i-z-folder' : 'i-z-file',
'tag-icon',
'font-size-12px'
]"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { computed, ref, type ComputedRef, type Ref } from 'vue'

export interface MatchCommandFeature {
code?: string
name?: string
explain?: string
[key: string]: any
}

export interface MatchCommandDetailCommand {
text?: string
label?: string
name?: string
type?: string
match?: string | Record<string, any>
regex?: string
[key: string]: any
}

export interface SelectedMatchCommand {
command: MatchCommandDetailCommand
feature: MatchCommandFeature
pluginName?: string
}

export interface UseMatchCommandDetailOptions {
getPluginName?: () => string | undefined
isDisabled?: (detail: SelectedMatchCommand) => boolean
toggleDisabled?: (detail: SelectedMatchCommand) => void | Promise<void>
}

export interface UseMatchCommandDetailResult {
selectedMatchCommand: Ref<SelectedMatchCommand | null>
selectedMatchCommandDisabled: ComputedRef<boolean>
openMatchCommandDetail: (feature: MatchCommandFeature, cmd: MatchCommandDetailCommand) => void
closeMatchCommandDetail: () => void
toggleSelectedMatchCommandDisabled: () => Promise<void>
cmdKey: (cmd: MatchCommandDetailCommand | string) => string
normalizeCommand: (cmd: MatchCommandDetailCommand | string) => MatchCommandDetailCommand
isMatchCommand: (cmd: unknown) => boolean
}

export function useMatchCommandDetail(
options: UseMatchCommandDetailOptions = {}
): UseMatchCommandDetailResult {
const selectedMatchCommand = ref<SelectedMatchCommand | null>(null)

const selectedMatchCommandDisabled = computed(() => {
const detail = selectedMatchCommand.value
if (!detail || !options.isDisabled) return false
return options.isDisabled(detail)
})

function cmdKey(cmd: MatchCommandDetailCommand | string): string {
if (cmd && typeof cmd === 'object') {
return cmd.label || cmd.text || cmd.name || ''
}
return String(cmd)
}

function normalizeCommand(cmd: MatchCommandDetailCommand | string): MatchCommandDetailCommand {
if (cmd && typeof cmd === 'object') {
return {
name: cmd.label || cmd.name,
text: cmd.label,
type: cmd.type,
match: cmd.match
}
}
return {
text: String(cmd),
type: 'text'
}
}

function isMatchCommand(cmd: unknown): boolean {
return Boolean(
cmd &&
typeof cmd === 'object' &&
'type' in cmd &&
(cmd as MatchCommandDetailCommand).type &&
(cmd as MatchCommandDetailCommand).type !== 'text'
)
}

function openMatchCommandDetail(
feature: MatchCommandFeature,
cmd: MatchCommandDetailCommand
): void {
const rawMatch =
cmd.match && typeof cmd.match === 'object'
? cmd.match
: { match: cmd.match || cmd.regex || '' }

selectedMatchCommand.value = {
command: {
...cmd,
...rawMatch,
type: cmd.type,
label: cmd.label || cmd.name
},
feature: {
code: feature.code,
name: feature.name,
explain: feature.explain
},
pluginName: options.getPluginName?.() || ''
}
}

function closeMatchCommandDetail(): void {
selectedMatchCommand.value = null
}

async function toggleSelectedMatchCommandDisabled(): Promise<void> {
const detail = selectedMatchCommand.value
if (!detail || !options.toggleDisabled) return
await options.toggleDisabled(detail)
}

return {
selectedMatchCommand,
selectedMatchCommandDisabled,
openMatchCommandDetail,
closeMatchCommandDetail,
toggleSelectedMatchCommandDisabled,
cmdKey,
normalizeCommand,
isMatchCommand
}
}
Loading