-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
412 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
<script setup lang="ts"> | ||
import { defineModel, ref, watchEffect } from 'vue' | ||
import { payload } from '../composables/payload' | ||
import { useRouter } from '#app/composables/router' | ||
import type { FilesGroup } from '~~/types' | ||
defineProps<{ | ||
index: number | ||
group: FilesGroup | ||
}>() | ||
const open = defineModel('open', { | ||
default: true, | ||
}) | ||
const hasShown = ref(open.value) | ||
if (!hasShown.value) { | ||
const stop = watchEffect(() => { | ||
if (open.value) { | ||
hasShown.value = true | ||
stop() | ||
} | ||
}) | ||
} | ||
const router = useRouter() | ||
function goToConfig(idx: number) { | ||
router.push(`/configs?index=${idx + 1}`) | ||
} | ||
</script> | ||
|
||
<template> | ||
<details | ||
class="flat-config-item" | ||
:open="open" | ||
border="~ base rounded-lg" relative | ||
@toggle="open = $event.target.open" | ||
> | ||
<summary block> | ||
<div class="absolute right-[calc(100%+10px)] top-1.5" text-right font-mono op35 lt-lg:hidden> | ||
#{{ index + 1 }} | ||
</div> | ||
<div flex="~ gap-2 items-start wrap items-center" cursor-pointer select-none bg-hover px2 py2 text-sm font-mono> | ||
<div i-ph-caret-right class="[details[open]_&]:rotate-90" transition op50 /> | ||
<div flex flex-col gap-3 md:flex-row flex-auto> | ||
<span op50 flex-auto> | ||
<span>Files group #{{ index + 1 }}</span> | ||
</span> | ||
|
||
<div flex="~ gap-2 items-start wrap"> | ||
<SummarizeItem | ||
icon="i-ph-files-duotone" | ||
:number="group.files?.length || 0" | ||
color="text-yellow5" | ||
title="Files" | ||
/> | ||
<SummarizeItem | ||
icon="i-ph-stack-duotone" | ||
:number="group.configs.length" | ||
color="text-blue5 dark:text-blue4" | ||
title="Rules" | ||
mr-2 | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</summary> | ||
|
||
<div absolute right-2 top-2 text-right text-5em font-mono op5 pointer-events-none> | ||
#{{ index + 1 }} | ||
</div> | ||
|
||
<div v-if="hasShown" px4 py4 flex="~ col gap-4" of-auto> | ||
<div flex="~ gap-2 items-center"> | ||
<div i-ph-files-duotone flex-none /> | ||
<div>Matched Local Files ({{ group.files.length }})</div> | ||
</div> | ||
|
||
<div flex="~ col gap-1" ml7 mt--2> | ||
<FileItem v-for="file of group.files" :key="file" font-mono :filepath="file" /> | ||
</div> | ||
|
||
<div flex="~ gap-2 items-center"> | ||
<div i-ph-stack-duotone flex-none /> | ||
<div>Configs specific to files ({{ group.configs.length }})</div> | ||
</div> | ||
<div flex="~ col gap-1" ml6 mt--2> | ||
<div v-for="configIdx of group.configs" :key="configIdx" font-mono flex="~ gap-2"> | ||
<VDropdown> | ||
<button border="~ base rounded px2" flex="~ gap-2 items-center" hover="bg-active" px2 py0.5> | ||
<ColorizedConfigName v-if="payload.configs[configIdx].name" :name="payload.configs[configIdx].name!" /> | ||
<div v-else op50 italic> | ||
anonymous | ||
</div> | ||
<div op50 text-sm> | ||
#{{ configIdx + 1 }} | ||
</div> | ||
</button> | ||
<template #popper="{ shown }"> | ||
<div v-if="shown" max-h="50vh" min-w-100> | ||
<div flex="~ items-center gap-2" p3> | ||
<button | ||
action-button | ||
title="Copy" | ||
@click="goToConfig(configIdx)" | ||
> | ||
<div i-ph-stack-duotone /> | ||
Go to this config | ||
</button> | ||
<slot name="popup-actions" /> | ||
</div> | ||
<div p3 border="t base"> | ||
<div flex="~ gap-2 items-start"> | ||
<div i-ph-file-magnifying-glass-duotone my1 flex-none op75 /> | ||
<div flex="~ col gap-2"> | ||
<div op50> | ||
Applies to files matching | ||
</div> | ||
<div flex="~ gap-2 items-center wrap"> | ||
<GlobItem v-for="glob, idx of payload.configs[configIdx].files" :key="idx" :glob="glob" /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
</VDropdown> | ||
</div> | ||
</div> | ||
</div> | ||
</details> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<script setup lang="ts"> | ||
import { computed } from 'vue' | ||
import { filepathIconsMap } from '../composables/icons' | ||
import { filtersConfigs } from '../composables/state' | ||
import { useRouter } from '#app/composables/router' | ||
const props = defineProps<{ | ||
filepath: string | ||
}>() | ||
const icon = computed(() => { | ||
for (const rule of filepathIconsMap) { | ||
if (rule.match.test(props.filepath)) | ||
return rule.icon | ||
} | ||
return 'i-ph-file-duotone' | ||
}) | ||
const router = useRouter() | ||
function searchFile() { | ||
filtersConfigs.filepath = props.filepath | ||
filtersConfigs.rule = undefined | ||
router.push(`/configs`) | ||
} | ||
</script> | ||
|
||
<template> | ||
<div flex="~ gap-2 items-center"> | ||
<div :class="icon" flex-none h="1em" translate-y-1px /> | ||
<button text-gray hover="underline" @click="searchFile"> | ||
{{ filepath }} | ||
</button> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import type { Linter } from 'eslint' | ||
import { minimatch } from 'minimatch' | ||
import type { FlatESLintConfigItem } from '~~/types' | ||
|
||
function matchGlob(file: string, glob: (Linter.FlatConfigFileSpec | Linter.FlatConfigFileSpec[])[]) { | ||
const globs = (Array.isArray(glob) ? glob : [glob]).flat() | ||
return globs.some(glob => typeof glob === 'function' ? glob(file) : minimatch(file, glob)) | ||
} | ||
|
||
export function isIgnoreOnlyConfig(config: FlatESLintConfigItem) { | ||
const keys = Object.keys(config).filter(i => !['name'].includes(i)) | ||
return keys.length === 1 && keys[0] === 'ignores' | ||
} | ||
|
||
export function getMatchedConfigs(filepath: string, configs: FlatESLintConfigItem[]): number[] { | ||
const ignoreOnlyConfigs = configs.filter(isIgnoreOnlyConfig) | ||
const isIgnored = ignoreOnlyConfigs.some(config => matchGlob(filepath, config.ignores!)) | ||
if (isIgnored) | ||
return [] | ||
const isAnyIncluded = configs.some(config => matchGlob(filepath, config.files || [])) | ||
if (!isAnyIncluded) | ||
return [] | ||
|
||
return configs | ||
.map((config, index) => { | ||
const isIncluded = config.files ? matchGlob(filepath, config.files) : true | ||
const isExcluded = config.ignores ? matchGlob(filepath, config.ignores) : false | ||
if (isIncluded && !isExcluded) | ||
return index | ||
return undefined | ||
}) | ||
.filter(index => index !== undefined) as number[] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// @unocss-include | ||
export const filepathIconsMap = [ | ||
{ | ||
match: /package\.json$/, | ||
icon: 'i-file-icons-npm text-red scale-110', | ||
}, | ||
{ | ||
match: /eslint\.config\.\w+$/, | ||
icon: 'i-file-icons-eslint text-primary', | ||
}, | ||
{ | ||
match: /\.[mc]?jsx?$/, | ||
icon: 'i-vscode-icons-file-type-js-official', | ||
}, | ||
{ | ||
match: /\.[mc]?tsx?$/, | ||
icon: 'i-file-icons-typescript-alt text-blue3', | ||
}, | ||
{ | ||
match: /\.vue$/, | ||
icon: 'i-logos-vue', | ||
}, | ||
{ | ||
match: /\.svelte$/, | ||
icon: 'i-logos-svelte-icon', | ||
}, | ||
{ | ||
match: /\.html?$/, | ||
icon: 'i-devicon-html5', | ||
}, | ||
{ | ||
match: /\.md$/, | ||
icon: 'i-simple-icons-markdown text-gray', | ||
}, | ||
{ | ||
match: /\.json[c5]?$/, | ||
icon: 'i-simple-icons-json text-gray', | ||
}, | ||
{ | ||
match: /\.css$/, | ||
icon: 'i-vscode-icons-file-type-css', | ||
}, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.