diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d88345c89f7a997feca27126dbad3d28c3bb3ad5..3bff11c094ec04bce7a87aed08e5e9b5e6e8a785 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -102,14 +102,14 @@ build:df-wiki-cli: --values deploy/meilisearch/values.yaml --values deploy/meilisearch/values.${ENV:-development}.yaml # wait for it to start - - MEILI_POD=$(kubectl -n=${KUBE_NAMESPACE} get po -l app.kubernetes.io\/instance=${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}-meilisearch,app.kubernetes.io\/name=meilisearch --output jsonpath='{.items[0].metadata.name}') - - | - until kubectl -n=${KUBE_NAMESPACE} wait --for=condition=ready pod ${MEILI_POD} --timeout=1s - do - date - sleep 1 - kubectl -n=${KUBE_NAMESPACE} get po - done + # - MEILI_POD=$(kubectl -n=${KUBE_NAMESPACE} get po -l app.kubernetes.io\/instance=${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}-meilisearch,app.kubernetes.io\/name=meilisearch --output jsonpath='{.items[0].metadata.name}') + # - | + # until kubectl -n=${KUBE_NAMESPACE} wait --for=condition=ready pod ${MEILI_POD} --timeout=1s + # do + # date + # sleep 1 + # kubectl -n=${KUBE_NAMESPACE} get po + # done deploy:meilisearch:dev: @@ -184,7 +184,7 @@ lint: stage: lint script: - cd content/3.defense-systems - - find . -name '*.md' ! -name '0.index.md' -print0 | xargs -0 -I {} df-wiki-cli content lint --file {} + - find . -name '*.md' ! -name '0.index.md' | sort | xargs -I {} df-wiki-cli content lint --file {} when: manual # Update Meili search indexes @@ -272,10 +272,10 @@ get-zotero: extends: .df-wiki-cli-run stage: get-data script: - - df-wiki-cli articles --key ${ZOTERO_API_KEY} --output public/articles.json + - df-wiki-cli articles --key ${ZOTERO_API_KEY} --output content/_data/_articles.json artifacts: paths: - - public/articles.json + - content/_data/_articles.json rules: - if: $CI_COMMIT_BRANCH == "main" @@ -322,6 +322,9 @@ build:dev:wiki: # - get-pfam variables: BASE_URL: /wiki/ + before_script: + - *docker-login + # - "sed -i 's/MEILISEARCH_API_KEY/${$MEILI_API_KEY}/g' nuxt.config.ts" rules: - if: $CI_COMMIT_BRANCH != "main" diff --git a/Dockerfile b/Dockerfile index 52f865fadee1d18436d81d8003e5831468a275c2..b3c9baec578099e63acfa53f4d2ecf6042283974 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,10 @@ ARG MEILI_HOST=http://localhost:7700 ARG MEILI_API_KEY=api_key ENV NUXT_APP_BASE_URL=${BASE_URL} +# nuxt module +ENV NUXT_PUBLIC_MEILISEARCH_CLIENT_HOST_URL=${MEILI_HOST} +ENV NUXT_PUBLIC_MEILISEARCH_CLIENT_SEARCH_API_KEY=${MEILI_API_KEY} + ENV NUXT_PUBLIC_MEILI_HOST=${MEILI_HOST} ENV NUXT_PUBLIC_MEILI_API_KEY=${MEILI_API_KEY} @@ -24,6 +28,7 @@ ENV NUXT_PUBLIC_MEILI_API_KEY=${MEILI_API_KEY} WORKDIR /usr/src/app COPY --from=install /usr/src/app ./ COPY . /usr/src/app + EXPOSE 3000 24678 4000 CMD ["npm", "run", "dev"] @@ -51,8 +56,13 @@ ARG BASE_URL=/ ARG MEILI_HOST=http://localhost:7700 ARG MEILI_API_KEY -ENV NODE_OPTIONS=--max_old_space_size=8192 +ENV NODE_OPTIONS=--max_old_space_size=12288 ENV NUXT_APP_BASE_URL=${BASE_URL} + +# nuxt module +ENV NUXT_PUBLIC_MEILISEARCH_CLIENT_HOST_URL=${MEILI_HOST} +ENV NUXT_PUBLIC_MEILISEARCH_CLIENT_SEARCH_API_KEY=${MEILI_API_KEY} + ENV NUXT_PUBLIC_MEILI_HOST=${MEILI_HOST} ENV NUXT_PUBLIC_MEILI_API_KEY=${MEILI_API_KEY} @@ -60,6 +70,7 @@ ENV NUXT_PUBLIC_MEILI_API_KEY=${MEILI_API_KEY} WORKDIR /usr/src/app COPY --from=install /usr/src/app ./ COPY . /usr/src/app + RUN npm run generate ### STAGE: NGINX ### diff --git a/components/AccessionChips.vue b/components/AccessionChips.vue deleted file mode 100644 index 76048b353b6b0e9a873e9de133c6dd3d1b8f4574..0000000000000000000000000000000000000000 --- a/components/AccessionChips.vue +++ /dev/null @@ -1,58 +0,0 @@ -<script setup lang="ts"> - -export interface Props { - accessions: string[]; - itemsToDisplay?: number; - baseUrl: string; -} - -const props = withDefaults(defineProps<Props>(), { - pfamString: null, - itemsToDisplay: 2, -}); -// const accessions = computed(() => { -// if (props.accessionString === null) { -// return []; -// } else { -// return props.accessionString.split(",").map((acc) => acc.trim()); -// } -// }); -const show = ref(false); - -function constructUrl(accession: string) { - return new URL(accession, props.baseUrl).toString(); -} -</script> -<template> - <!-- class="d-inline-flex justify-start align-center" --> - - <span v-if="show" class="d-flex flex-wrap align-center justify-start"> - <template v-if="accessions.length > itemsToDisplay"> - <template v-for="(acc) in accessions" :key="acc"> - <v-chip :href="constructUrl(acc)" target="_blank" color="info" class="mr-1 my-1 align-self-center" - size="small"> - {{ acc }} - </v-chip> - </template> - </template> - <v-btn v-if="itemsToDisplay < accessions.length" variant="text" :icon="'mdi-chevron-up'" - @click="show = !show"></v-btn> - </span> - <span v-else class="d-flex flex-wrap align-center justify-start"> - <template v-for="(acc, index) in accessions" :key="acc"> - <v-chip v-if="index < itemsToDisplay || itemsToDisplay < 0" :href="constructUrl(acc)" target="_blank" - color="info" class="mr-1 my-1 align-self-center" size="small"> - {{ acc }} - </v-chip> - <template v-if="index === itemsToDisplay"> - <v-chip v-if="!show" variant="text" class="text-grey text-caption align-self-center px-1" - @click="show = !show"> - (+{{ accessions.length - itemsToDisplay }} others) - </v-chip> - <v-btn v-if="itemsToDisplay < accessions.length && !show" variant="text" :icon="'mdi-chevron-down'" - @click="show = !show"></v-btn> - </template> - </template> - - </span> -</template> \ No newline at end of file diff --git a/components/CollapsibleChips.vue b/components/CollapsibleChips.vue new file mode 100644 index 0000000000000000000000000000000000000000..1ea5ef641757b2d5404d7524d5d4ade3acde6d89 --- /dev/null +++ b/components/CollapsibleChips.vue @@ -0,0 +1,56 @@ +<script setup lang="ts"> + + +interface item { + title: string; + href?: string | undefined +} + +export interface Props { + items: item[]; + itemsToDisplay?: number; +} + +const props = withDefaults(defineProps<Props>(), { + items: () => [], + itemsToDisplay: 1, + +}); + +const show = ref(false); + + +</script> +<template> + <!-- class="d-inline-flex justify-start align-center" --> + + <span v-if="show" class="d-flex flex-wrap align-center justify-start"> + <template v-if="items.length > itemsToDisplay"> + <template v-for="item in items" :key="item.title"> + <v-chip :href="item?.href" :target="item?.href === undefined ? item?.href : '_blank'" color="info" + class="mr-1 my-1 align-self-center" size="small"> + {{ item.title }} + </v-chip> + </template> + </template> + <v-btn v-if="itemsToDisplay < items.length" variant="text" :icon="'mdi-chevron-up'" @click="show = !show"></v-btn> + </span> + <span v-else class="d-flex flex-wrap align-center justify-start"> + <template v-for="(item, index) in items" :key="item.title"> + <v-chip v-if="index < itemsToDisplay || itemsToDisplay < 0" :href="item?.href" + :target="item?.href === undefined ? item?.href : '_blank'" color="info" class="mr-1 my-1 align-self-center" + size="small"> + {{ item.title }} + </v-chip> + <template v-if="index === itemsToDisplay"> + <v-chip v-if="!show" variant="text" class="text-grey text-caption align-self-center px-1" + @click="show = !show"> + (+{{ items.length - itemsToDisplay }} others) + </v-chip> + <v-btn v-if="itemsToDisplay < items.length && !show" variant="text" :icon="'mdi-chevron-down'" + @click="show = !show"></v-btn> + </template> + </template> + + </span> +</template> \ No newline at end of file diff --git a/components/LayoutWrapper.vue b/components/LayoutWrapper.vue index b322aa7c568d39fe9c29b6df062bfad4ac73c397..67192204f7cf580b8b1747202dd83b397749cbad 100644 --- a/components/LayoutWrapper.vue +++ b/components/LayoutWrapper.vue @@ -3,12 +3,14 @@ export interface Props { fluid?: boolean toc?: boolean edit?: boolean + navDrawer?: boolean } const props = withDefaults(defineProps<Props>(), { fluid: false, toc: true, - edit: true + edit: true, + navDrawer: true }); const drawer = ref(true); @@ -28,16 +30,23 @@ function onScroll() { <VApp> <v-main style="min-height: 300px"> <v-container v-scroll="onScroll" :fluid="fluid"> - <slot /> - <!-- </v-card-text> + <v-row justify="center"> + <v-col cols="auto"> + <v-card flat color="transparent" :max-width="fluid ? undefined : 1280"> + + <slot /> + <!-- </v-card-text> </v-card> --> - <EditGitlab v-if="edit" /> - <NavPrevNext v-if="edit" /> + <EditGitlab v-if="edit" /> + <NavPrevNext v-if="edit" /> + </v-card> + </v-col> + </v-row> </v-container> <!-- <Footer></Footer> --> </v-main> - <NavNavbar v-model:drawer="drawer" :density="density" /> - <slot name="drawer" :drawer="drawer"> + <NavNavbar v-model:drawer="drawer" :density="density" :drawer-enabled="navDrawer"/> + <slot v-if="navDrawer" name="drawer" :drawer="drawer"> <NavDrawer :drawer="drawer" /> </slot> <NavTableOfContent v-if="toc" :links="page.body.toc.links" /> diff --git a/components/Nav/Navbar.vue b/components/Nav/Navbar.vue index 87099cc8e9ad41befd3821754e8b121be23bf84a..0f19d827ce4ca870c56bc496d61559bdc11b4b2d 100644 --- a/components/Nav/Navbar.vue +++ b/components/Nav/Navbar.vue @@ -5,6 +5,7 @@ import { useDisplay, useTheme } from "vuetify"; export interface Props { density: 'prominent' | 'compact' drawer: boolean + drawerEnabled: boolean } const runtimeConfig = useRuntimeConfig(); @@ -15,7 +16,8 @@ const theme = useTheme(); const switchTheme = ref(false) const props = withDefaults(defineProps<Props>(), { density: "prominent", - drawer: true + drawer: true, + drawerEnabled: true }); const emit = defineEmits(['update:drawer']) function toggleTheme() { @@ -52,7 +54,7 @@ function toggleDrawer() { </script> <template> <v-app-bar :elevation="0" border name="app-bar" :density="density" color="background"> - <template #prepend> + <template v-if="drawerEnabled" #prepend> <v-app-bar-nav-icon @click.stop="toggleDrawer"></v-app-bar-nav-icon> <!-- <Logo height="45px" /> --> </template> diff --git a/components/ServerDbTable.vue b/components/ServerDbTable.vue new file mode 100644 index 0000000000000000000000000000000000000000..febe44253347aeca288f5b60d6070c8b526bf172 --- /dev/null +++ b/components/ServerDbTable.vue @@ -0,0 +1,396 @@ +<script setup lang="ts"> +// import type { FacetDistribution } from "meilisearch"; +import { useDisplay } from "vuetify"; +import { useFacetsStore, type Facets } from '~~/stores/facets' +import { useMeiliSearch } from "#imports" +interface SortItem { + key: string, + order: boolean | 'asc' | 'desc' +} + +export interface Props { + title?: string + db?: string + sortBy?: SortItem[] + facets: string[] + headers: { title: string, key: string }[] + itemValue: string +} + +export interface FilterItem { + type: 'facet' | 'operator' | 'value' | 'text' + value: string + title: string + count?: number + deletable: boolean + props: { + [key: string]: any + // title: string + // value: any + } + // raw?: any +} + +const props = withDefaults(defineProps<Props>(), { + title: '', + db: 'refseq', + sortBy: () => [{ key: "type", order: "asc" }], +}); + + +const sortByRef = ref(toValue(props.sortBy)) +const facetsRef = toRef(() => props.facets) + +const { search: msSearch, result: msResult } = useMeiliSearch(props.db) +const facetStore = useFacetsStore() +const search: Ref<string> = ref(""); +const filterOrSearch: Ref<FilterItem[] | null> = ref(null) +const hitsPerPage: Ref<number> = ref(25) +const limit = ref(1000) +const filterError: Ref<string | null> = ref(null) +const msFilter: Ref<string | undefined> = ref(undefined) +const page = ref(1) +let loading = ref(false) + +const { height } = useDisplay(); +const minTableHeight = ref(400) +const computedTableHeight = computed(() => { + const computedHeight = height.value - 350 + return computedHeight > minTableHeight.value ? computedHeight : minTableHeight.value +}) + + +const filterInputValues = computed(() => { + console.log("recompouted FILTER value") + if (filterOrSearch.value != null) { + return filterOrSearch.value.filter(({ props }) => props.type !== 'text') + } else { + return null + } +}) + +const queryInputValue = computed(() => { + console.log("recompouted TEXT value") + + if (filterOrSearch.value !== null) { + const phrase = filterOrSearch.value + .filter((f) => { + return f.props.type === 'text' + }) + .map((f) => { + return f.value + }) + if (phrase.length > 1) { + return `${phrase.join(" ")}` + } + else { return phrase[0] } + } else { + return null + } +}) + +const isFilter = computed(() => { + return Array.isArray(filterOrSearch.value) +}) + +const msSortBy = computed(() => { + if (sortByRef.value.length > 0) { + return sortByRef.value.map((curr) => { + if (curr?.key && curr?.order) { + return `${curr.key}:${curr.order}` + } + else { return "" } + }) + } else { return undefined } +}) + + +const reactiveParams = reactive({ + hitsPerPage: 25, + page: 1, + limit: 1000, + facets: ["*"], + filter: [], + sort: ["type:asc"], + // prefix_length: 3, + // attributesToHighlight: ["*"] +}) + + + +watch([reactiveParams, msSortBy, page], ([newParams, newSort, newPage]) => { + searchOrFilter() +}) + + +onMounted(async () => { + searchOrFilter() +}) +// Fetch results + +const msError = computed(() => { + if (filterError.value?.type && filterError.value?.message) { + return filterError.value?.message + } else { return false } +}) + +async function searchOrFilter() { + try { + loading.value = true + // const q = queryInputValue.value === null ? "" : queryInputValue.value + const q = search.value + await msSearch(q, { ...reactiveParams, filter: msFilter.value, sort: msSortBy.value }) + } catch (error: any) { + filterError.value = error + console.log(error) + } + finally { + loading.value = false + } +} + + +function clearFilterOrSearch() { + filterOrSearch.value = null + searchOrFilter() +} + +watch(msFilter, async (fos) => { + console.log("the filter change") + console.log(msFilter) + console.log(fos) + searchOrFilter() + search.value = '' + +}) + +watch(msResult, (newRes) => { + console.log(msResult) + console.log(newRes) + facetStore.setFacets({ facetDistribution: newRes.facetDistribution, facetStat: newRes.facetStat }) +}, { deep: true }) + + + +watch(filterInputValues, (newSoF) => { + if (isFilter.value && filterInputValues.value !== null && filterInputValues.value?.length % 3 === 0) { + msFilter.value = filterInputValues.value.map((it, index) => { + + const sanitizedValue = it.value.split("-")[0] + if (index >= 1 && (index + 1) % 3 === 1) { + return ` AND ${sanitizedValue}` + } else if ((index + 1) % 3 === 0) { + return `"${sanitizedValue}"` + } else { + return `${sanitizedValue}` + } + + }).join("") + } +}) + +watch(search, () => { searchOrFilter() }) +// watch(queryInputValue, (newQuery) => { +// searchOrFilter() + +// }) + +const filterStep = computed(() => { + return filterInputValues.value !== null && filterInputValues.value.length > 0 ? filterInputValues.value?.length % 3 : null +}) +const operatorItems = ref([ + { + type: "operator", value: '=', title: "is", deletable: false, props: { + type: "operator", deletable: false + } + }, { + type: "operator", value: '!=', title: "is not", deletable: false, props: { + type: "operator", + deletable: false + } + }, + +]) + +const autocompleteItems = computed(() => { + const index = filterOrSearch.value?.length ?? 0 + console.log(index) + if (filterStep.value === null || filterStep.value === 0) { + return props.facets.map(value => { + return { + type: "facet", + value: `${value}-${index}`, + title: value, + deletable: false, + props: { + deletable: false, + type: "facet" + } + } + }) + } + if (filterStep.value === 1) { + return operatorItems.value.map(it => { return { ...it, value: `${it.value}-${index}`, } }) + } + if (filterStep.value === 2) { + // get the facet value + if (Array.isArray(filterOrSearch.value)) { + const { type, value } = filterOrSearch.value?.slice(-2, -1)[0] + const sanitizedValue = value.split("-")[0] + console.log("compute new facets") + const facetDistri = facetStore.facets?.facetDistribution + console.log(facetDistri) + return facetDistri?.[sanitizedValue] ? Object.entries(facetDistri[sanitizedValue]).map(([key, val]) => { + return { + type: "value", value: `${key}-${index}`, title: key, count: val, deletable: true, props: { + type: "value", count: val, deletable: true + } + } + }) : [] + } + } +}) + +const canAddTextSearch = computed(() => { + if (filterOrSearch.value !== null && filterOrSearch.value.length > 0) { + const lastItem = filterOrSearch.value.slice(-1)[0] + return lastItem?.props.type === 'value' || lastItem?.props.type === "text" + } + return true +}) + +function selectItem(item) { + filterOrSearch.value = Array.isArray(filterOrSearch.value) ? [...filterOrSearch.value, item] : [item] +} + +function deleteOneFilter(index: number) { + console.log("deleteOnefilter") + console.log(index) + console.log(isFilter.value) + console.log(filterOrSearch) + if (isFilter.value) { + + filterOrSearch.value?.splice(index - 2, 2) + console.log(filterOrSearch.value) + + } + +} + +function deleteTextFilter(index: number) { + console.log("delete text filter") + console.log(index) + console.log(isFilter.value) + console.log(filterOrSearch) + console.log(filterOrSearch.value?.length) + if (isFilter.value) { + if (index === 0) { + filterOrSearch.value?.shift() + } else { + filterOrSearch.value?.splice(index, 1) + } + console.log(filterOrSearch.value?.length) + console.log(filterOrSearch.value) + + } + +} + + +function clearSearch() { + search.value = "" +} + + + +function runTextSearch() { + if (canAddTextSearch) { + const item: FilterItem = reactive({ + type: 'text', title: search.value, value: search.value, deletable: true, props: { type: "text", deletable: true, } + }) + if (Array.isArray(filterOrSearch.value)) { + filterOrSearch.value = [ + ...filterOrSearch.value, item + + ] + } else { + filterOrSearch.value = [item] + } + search.value = "" + searchOrFilter() + } +} + +function namesToCollapsibleChips(names: string[]) { + return names.filter((it) => it !== "").map(it => ({ title: it })) +} + +function namesToAccessionChips(names: string[]) { + return namesToCollapsibleChips(names).map(it => { + return { ...it, href: new URL(it.title, "http://toto.pasteur.cloud").toString() } + }) +} + + +</script> +<template> + <v-card flat> + <v-card-text> + <v-row> + <v-col cols="5"> + <v-text-field v-model="search" label="Search..." hide-details prepend-inner-icon="mdi-magnify" + single-line clearable></v-text-field> + </v-col> + <v-col> + <v-autocomplete ref="autocompleteInput" hide-details v-model:model-value="filterOrSearch" + auto-select-first chips clearable label="Filter results..." :items="autocompleteItems" single-line + item-value="value" item-title="title" multiple return-object prepend-inner-icon="md:search" + @click:appendInner="searchOrFilter" @click:clear="clearFilterOrSearch" + @update:modelValue="() => clearSearch()"> + <template #chip="{ props, item, index }"> + + + <v-chip v-bind="props" :text="item.raw.title" :closable="item.props.deletable" + @click:close="item.props.type === 'text' ? deleteTextFilter(index) : deleteOneFilter(index)"></v-chip> + <!-- <v-chip v-if="(index + 1) % 3 === 0" v-bind="props" :text="item.raw.title" closable + @click:close="deleteOneFilter(index)"></v-chip> + <v-chip v-else v-bind="props" :text="item.raw.title"></v-chip> --> + </template> + <template #item="{ props, item }"> + <v-list-item v-bind="{ ...props, active: false, onClick: () => selectItem(item) }" + :title="item.title" :subtitle="item.raw?.count ? item.raw.count : ''" :value="props.value"> + + </v-list-item> + </template> + <!-- <template #no-data></template> + <template #prepend-item> + <v-list-item v-if="canAddTextSearch" :title="`Text search: ${search}`" @click="runTextSearch"> </v-list-item> + </template> --> + </v-autocomplete> + </v-col> + </v-row> + </v-card-text> + <v-data-table-server v-if="!msError" v-model:page="reactiveParams.page" + v-model:items-per-page="reactiveParams.hitsPerPage" v-model:sortBy="sortByRef" fixed-header :loading="loading" + :headers="headers" :items="msResult?.hits ?? []" :items-length="msResult?.totalHits ?? 0" + :item-value="itemValue" multi-sort density="compact" :height="computedTableHeight" class="elevation-1 mt-2"> + <template #[`item.accession_in_sys`]="{ item }"> + <CollapsibleChips :items="namesToAccessionChips(item.accession_in_sys)"></CollapsibleChips> + </template> + <template #[`item.proteins_in_the_prediction`]="{ item }"> + <CollapsibleChips :items="namesToCollapsibleChips(item.proteins_in_the_prediction)"></CollapsibleChips> + </template> + <template #[`item.system_genes`]="{ item }"> + <CollapsibleChips :items="namesToCollapsibleChips(item.system_genes)"></CollapsibleChips> + </template> + + <template #[`item.completed`]="{ item }"> + <v-icon v-if="item.completed" color="success" icon="md:check"></v-icon> + <v-icon v-else color="warning" icon="md:dangerous"></v-icon> + </template> + </v-data-table-server> + <v-alert v-else type="error"> + {{ msError }} + </v-alert> + </v-card> +</template> \ No newline at end of file diff --git a/components/content/ArticleDoi.vue b/components/content/ArticleDoi.vue index c2bfa9e370386efb0cd1f88ee35fdd84de093169..f37e93fada781559f521e3795dd23a9301f1697d 100644 --- a/components/content/ArticleDoi.vue +++ b/components/content/ArticleDoi.vue @@ -1,5 +1,6 @@ <script setup lang="ts"> import { useDisplay } from "vuetify"; +import { useArticlesStore } from '@/stores/articles' export interface Props { index?: number; @@ -14,10 +15,27 @@ const props = withDefaults(defineProps<Props>(), { enumerate: true, divider: false, }); + + +// onBeforeMount(async () => { +// await useArticlesStore().initialize() +// }) + const { article } = useFetchArticle(props.doi); const { mobile } = useDisplay(); const show = ref(false); +// const computedArticle = computed(() => { return { ...article.value } }) + + +// watch(article, (newArticle) => { +// console.log("article updated") +// }, { deep: true }) + + +console.log("aritcle dans composant") +console.log(article) + const articleTitle = computed(() => { return props?.title ?? article?.value?.title ?? props.doi; }); @@ -26,8 +44,8 @@ const articleAbstract = computed(() => { }); </script> <template> - <v-list-item :href="article?.href" :id="props.doi" :target="article?.target" density="compact" color="transparent" - class="px-1"> + <v-list-item :href="article?.href" :id="props.doi" :target="article?.target" density="compact" + color="transparent" class="px-1"> <template #prepend v-if="!mobile && enumerate"> <v-avatar color="primary" size="small" density="compact" variant="tonal"> {{ props?.index ?? "#" }} diff --git a/components/content/RefseqDb.vue b/components/content/RefseqDb.vue new file mode 100644 index 0000000000000000000000000000000000000000..99aa1ebdeede76a3163ced2e9f673f414dbec3d9 --- /dev/null +++ b/components/content/RefseqDb.vue @@ -0,0 +1,189 @@ +<script setup lang="ts"> +import { useFacetsStore } from '~~/stores/facets' +import * as Plot from "@observablehq/plot"; +import PlotFigure from "~/components/PlotFigure"; +import { useDisplay } from "vuetify"; + + +const facetStore = useFacetsStore() + +const sortBy: Ref<{ key: string, order: string }[]> = ref([{ key: 'type', order: "asc" }]) +const itemValue = ref("id"); +const { width } = useDisplay(); +const distriTool: Ref<string[]> = ref([]) + +const facets = ref([ + "type", + "Superkingdom", + "phylum", + "order", + "family", + "genus", + "species", +]) +const availableTaxo: Ref<string[]> = ref([ + "species", + "genus", + "family", + "order", + "phylum", + "Superkingdom" +]); +const selectedTaxoRank = ref("phylum"); + +const headers = ref([ + { title: "Replicon", key: "replicon" }, + { + title: "Type", + key: "type", + }, + { + title: "Subtype", + key: "subtype", + }, + { + title: "Accessions", + key: "accession_in_sys" + } +]) +const logTransform = computed(() => { + return distriTool.value.includes('log') +}) +const fullWidth = computed(() => { + return distriTool.value.includes('fullwidth') +}) +const computedHeaders = computed(() => { + return [...headers.value, ...availableTaxo.value.map(taxo => { + return { + title: capitalize(taxo), + key: taxo + } + })] +}) + +const computedWidth = computed(() => { + return Math.max(width.value, 550); +}); + +const plotHeight = computed(() => { + return computedWidth.value / 3; + // return 500 +}); + + +const defaultBarPlotOptions = computed(() => { + const y = logTransform.value ? { nice: true, grid: true, type: 'symlog' } : { nice: true, grid: true, type: "linear" } + // const y = { nice: true, grid: true } + return { + x: { label: null, tickRotate: 70 }, + y, + color: { legend: true }, + width: computedWidth.value, + height: plotHeight.value, + } +}) + +const computedSystemDistribution = computed(() => { + if (facetStore.facets?.facetDistribution?.type) { + return Object.entries(facetStore.facets.facetDistribution.type).map(([key, value]) => { + return { + type: key, + // count: logTransform.value ? Math.log(value) : value + count: value + } + }).sort() + } else { return [] } + +}) +const computedDistriSystemOptions = computed(() => { + return { + ...defaultBarPlotOptions.value, + marginBottom: 120, + marks: [ + // Plot.frame(), + Plot.barY( + toValue(computedSystemDistribution), + { + y: "count", x: 'type', tip: true, + fill: "#6750a4", + sort: { x: "-y" }, + }, + + ), + ], + }; +}); +const computedTaxonomyDistribution = computed(() => { + if (facetStore.facets?.facetDistribution?.[selectedTaxoRank.value]) { + return Object.entries(facetStore.facets.facetDistribution[selectedTaxoRank.value]).map(([key, value]) => { + return { + [selectedTaxoRank.value]: key, + count: value + } + }).sort() + } else { return [] } + +}) + +const computedDistriTaxoOptions = computed(() => { + return { + ...defaultBarPlotOptions.value, + marginBottom: 200, + marks: [ + Plot.barY( + toValue(computedTaxonomyDistribution), + { + y: "count", + x: selectedTaxoRank.value, + tip: true, + fill: "#6750a4", + sort: { x: "-y" }, + } + ), + ], + }; +}); +function capitalize([first, ...rest]) { + return first.toUpperCase() + rest.join('').toLowerCase(); +} + + +</script> + +<template> + <v-card flat class="mb-2"> + <v-toolbar density="compact"> + <v-toolbar-title>Distributions</v-toolbar-title> + <v-btn-toggle v-model="distriTool" multiple density="compact" rounded="false" variant="text" color="primary" + class="mx-2"> + <v-btn icon="md:fullscreen" value="fullwidth"></v-btn> + <v-btn icon="mdi-math-log" value="log"></v-btn> + </v-btn-toggle> + </v-toolbar> + <v-row align="start" class="mb-2"> + <v-col :cols="fullWidth ? 12 : 6"> + <v-card flat class="my-3"> + <v-card-title>Systems </v-card-title> + + <v-card-text> + <PlotFigure :options="unref(computedDistriSystemOptions)" defer></PlotFigure> + </v-card-text> + </v-card> + </v-col> + <v-col :cols="fullWidth ? 12 : 6"> + <v-card flat> + <v-card-title>Taxonomic</v-card-title> + <v-card-text> + <v-select v-model="selectedTaxoRank" :items="availableTaxo" density="compact" + label="Select taxonomic rank"></v-select> + <PlotFigure defer :options="unref(computedDistriTaxoOptions)"></PlotFigure> + </v-card-text> + </v-card> + </v-col> + </v-row> + </v-card> + + <ServerDbTable title="RefSeq" db="refseq" :sortBy="sortBy" :headers="computedHeaders" :item-value="itemValue" + :facets="facets"> + </ServerDbTable> +</template> \ No newline at end of file diff --git a/components/content/StructureDb.vue b/components/content/StructureDb.vue new file mode 100644 index 0000000000000000000000000000000000000000..0233361b1af6c3a077ab0ffe754568d93b9d6c83 --- /dev/null +++ b/components/content/StructureDb.vue @@ -0,0 +1,26 @@ +<script setup lang="ts"> + +import { useFacetsStore } from '~~/stores/facets' +const sortBy: Ref<{ key: string, order: string }[]> = ref([{ key: 'system', order: "asc" }]) +const itemValue = ref("id"); +const facets = ref(["system", "completed", + "plddts",]) +const headers: Ref<Object[]> = ref([ + { title: "System", key: "system" }, + { title: "Proteins in structure", key: 'proteins_in_the_prediction', sortable: false }, + { title: "System genes", key: "system_genes", sortable: false }, + { title: "Completed", key: "completed" }, + { title: "Predition type", key: "prediction_type" }, + { title: "Num of genes", key: "system_number_of_genes" }, + { title: "pLDDT", key: "plddts" }, + { title: "iptm+ptm", key: "iptm+ptm" }, + { title: "pDockQ", key: "pDockQ" }, + { title: "Type", key: "type" } +]) + +</script> +<template> + <ServerDbTable title="Predicted Strucutres" db="structure" :sortBy="sortBy" :headers="headers" :item-value="itemValue" + :facets="facets"> + </ServerDbTable> +</template> \ No newline at end of file diff --git a/composables/useFetchArticle.ts b/composables/useFetchArticle.ts index a89adcac5d2ed8b0308989bb020bb0122d7f4ce1..59c1e51851cd53369ccd27d4db85c17b86508d28 100644 --- a/composables/useFetchArticle.ts +++ b/composables/useFetchArticle.ts @@ -2,17 +2,19 @@ import { useArticlesStore, type CslJson } from '../stores/articles' import { ref, computed, watchEffect, toValue } from "vue" // import { useFetch } from '#app'; // import { useFetch } from "nuxt" -import { useFetch } from '#imports' +import { type MaybeRef, useFetch } from '#imports' +import article from "@/public/articles.json" - -export interface ArticleMessage { +export interface CrossrefArticle { DOI: string; issue: number; - title: string | string[]; + type: string; + title: string[]; author: Array<{ family: string; given: string }>; - "container-title-short": string; + // "container-title-short": string; + "short-container-title": string; "container-title": string; - abstract: string; + abstract?: string; published: { "date-parts": string[]; }; @@ -23,7 +25,7 @@ export interface ArticleMessage { -export interface Article { +export interface WikiArticle { DOI: string title: string subtitle: string @@ -36,115 +38,125 @@ export interface Article { prependIcon: string } export interface RawArticle { - message: ArticleMessage + message: CrossrefArticle } -type SrcArticle = ArticleMessage | CslJson +type SrcArticle = CrossrefArticle | CslJson -export function useFetchArticle(doi: string) { +export function useFetchArticle(doi: MaybeRef<string> = ref("")) { // const article = ref<Article>() // const rawArticle = ref<RawArticle>() const srcArticle = ref<SrcArticle | null>(null) const store = useArticlesStore() const pending = ref(false) const doiBaseUrl = ref(new URL("https://doi.org/")); - const url = ref(new URL(`/works/${doi}`, " https://api.crossref.org/").href); - const article = computed(() => { - if (srcArticle.value != undefined) { + const url = ref(new URL(`/works/${toValue(doi)}`, " https://api.crossref.org/").href); + const article = ref() + const zoteroArticles = ref() + + function toAuthorsString(authors: Array<{ family: string; given: string }>) { + return authors + .map((curr) => { + return `${curr.family} ${curr.given}`; + }) + .join(", "); + } + + function getReferenceUrl(doi: string) { + return new URL(doi, doiBaseUrl.value).href; + } + + function zoteroArticleToArticle(zoteroArticle: CslJson) { + if (zoteroArticle != undefined) { const { DOI, title, - "container-title-short": cts, "container-title": ct, - journalAbbreviation, abstract, - published, issued, author, ...rest - } = srcArticle.value; - let sanitizedAbstract = abstract - if (sanitizedAbstract) { - - sanitizedAbstract = /(?:\<jats\:p\>)?(.*)(?:\<\/jats\:p\>)?/.exec(sanitizedAbstract)?.[1] ?? '' - } - - const sanitizedTitle = (Array.isArray(title)) ? title[0] : title - const sanitizedContainerTitle = (Array.isArray(ct)) ? cts?.length > 0 ? cts[0] : ct?.length > 0 ? ct[0] : "" : journalAbbreviation || ct + } = zoteroArticle; return { DOI, - title: sanitizedTitle, + title, subtitle: toAuthorsString(author || []), author, - containerTitle: sanitizedContainerTitle, - abstract: sanitizedAbstract, - year: published?.["date-parts"][0][0] ?? issued?.["date-parts"][0][0] ?? '', + containerTitle: ct, + abstract, + year: issued?.["date-parts"][0][0] ?? '', href: getReferenceUrl(DOI), target: "_blank", prependIcon: "mdi-newspaper-variant-outline", } - - } else { return srcArticle.value } - }) - const zoteroArticles = ref([]) - // const config = useRuntimeConfig() - // console.log(config.value) - - - const fetchLocalArticles = () => { - useFetch<RawArticle[]>( - "/articles.json", - { lazy: true, server: false } - ).then(({ data }) => { - zoteroArticles.value = data.value - }) // localPending.value = articlesPending.value - if (zoteroArticles.value?.length > 0) { - for (const article of zoteroArticles.value) { - // console.log("article files : ", article.DOI) - store.add(article) - } } - } - - const fetchCrossRef = () => { - useFetch<RawArticle>(toValue(url), { - lazy: true, server: false, - }).then(({ data, pending: pendingUseFetch }) => { - if (data.value?.message) { - srcArticle.value = data.value.message - } - pending.value = pendingUseFetch.value - }) } - - watchEffect(() => { - // no article in the store - if (store.articles.size === 0) { - fetchLocalArticles() + function crossrefToArticle(article: CrossrefArticle): WikiArticle { + const { title, DOI, type, "container-title": ct, "short-container-title": sct, abstract, author, issued } = article + // let sanitizedAbstract = abstract + const sanitizedAbstract = abstract ? /(?:\<jats\:p\>)?(.*)(?:\<\/jats\:p\>)?/.exec(abstract)?.[1] ?? '' : '' + const sanitizedContainerTitle = sct?.length > 0 ? sct[0] : ct?.length > 0 ? ct[0] : "" + return { + title: title?.length > 0 ? title[0] : "", + DOI, + abstract: sanitizedAbstract, + containerTitle: sanitizedContainerTitle, + subtitle: toAuthorsString(author || []), + author, + year: issued?.["date-parts"][0][0] ?? '', + href: getReferenceUrl(DOI), + target: "_blank", + prependIcon: "mdi-newspaper-variant-outline" } + } - if (store.articles.has(doi)) { - srcArticle.value = store.articles.get(doi) - return - } else { - fetchCrossRef() - } + function crossrefToCsl(article: CrossrefArticle): CslJson { + const { title, DOI, type, "container-title": ct, "short-container-title": sct, abstract, author, issued } = article + // let sanitizedAbstract = abstract + const sanitizedAbstract = abstract ? /(?:\<jats\:p\>)?(.*)(?:\<\/jats\:p\>)?/.exec(abstract)?.[1] ?? '' : '' + const sanitizedContainerTitle = sct?.length > 0 ? sct[0] : ct?.length > 0 ? ct[0] : "" + return { + title: title?.length > 0 ? title[0] : "", + type, + DOI, + abstract: sanitizedAbstract, + author, + "container-title": sanitizedContainerTitle, + issued - }) - function toAuthorsString(authors: Array<{ family: string; given: string }>) { - return authors - .map((curr) => { - return `${curr.family} ${curr.given}`; - }) - .join(", "); + } } - function getReferenceUrl(doi: string) { - return new URL(doi, doiBaseUrl.value).href; + if (store.articles.has(toValue(doi))) { + const cslArticle = store.articles.get(toValue(doi)) + article.value = cslArticle ? zoteroArticleToArticle(cslArticle) : undefined } + else { + useFetch<RawArticle>(toValue(url), { + lazy: true, server: false, + }).then(({ data, pending: pendingUseFetch }) => { + if (data.value?.message) { + article.value = crossrefToArticle(data.value.message) + store.add(crossrefToCsl(data.value.message)) + } + pending.value = pendingUseFetch.value + }) + } + // const fetchCrossRef = () => { + // useFetch<RawArticle>(toValue(url), { + // lazy: true, server: false, + // }).then(({ data, pending: pendingUseFetch }) => { + // if (data.value?.message) { + // srcArticle.value = data.value.message + // } + // pending.value = pendingUseFetch.value + // }) + + // } + return { article, pending } } diff --git a/composables/useFetchMsDocument.ts b/composables/useFetchMsDocument.ts index d5b981e18fb98a8422e93efcd89b25ad19ce0c72..21a4511365483a6cd97127177163633043ceada7 100644 --- a/composables/useFetchMsDocument.ts +++ b/composables/useFetchMsDocument.ts @@ -1,7 +1,10 @@ import { MeiliSearch } from 'meilisearch' import { useRuntimeConfig, watchEffect, type MaybeRef, ref, toValue } from '#imports' import type { FacetDistribution, Hits } from 'meilisearch'; -export function useFetchMsDocument( +import { useAsyncState } from '@vueuse/core' +import { errorMonitor } from 'events'; + +export async function useFetchMsDocument( index: MaybeRef<string> = ref(""), search: Ref<string> = ref(""), filter: Ref<string> = ref(''), @@ -18,12 +21,11 @@ export function useFetchMsDocument( apiKey: runtimeConfig.public.meiliApiKey }) const pending = ref(false) - const filterError = ref(null) + const filterError: Ref<string | null> = ref(null) const hits: Ref<Hits<Record<string, any>>> = ref([]) const totalHits = ref(0) const totalPages = ref(0) const facetDistribution: Ref<FacetDistribution | undefined> = ref({}) - // reset page when filter and search change watch(filter, () => { page.value = 1 @@ -32,34 +34,36 @@ export function useFetchMsDocument( page.value = 1 }) - watchEffect(async () => { - try { - pending.value = true - const res = await client - .index(toValue(index)) - .search(toValue(search), { - limit: toValue(limit), - filter: toValue(filter), - hitsPerPage: toValue(hitsPerPage), - page: toValue(page), - facets: toValue(facets), - sort: toValue(sort), - }) - filterError.value = null - const { hits: resHits, totalHits: resTotalHits, totalPages: resTotalPages, facetDistribution: facetD } = res - totalHits.value = resTotalHits - hits.value = resHits - totalPages.value = resTotalPages - facetDistribution.value = facetD - } catch ({ code, message }) { - if (code === 'invalid_search_filter') { - filterError.value = message - } - } finally { - pending.value = false - } - }) + try { + pending.value = true + console.log(pending.value) + const res = await client + .index(toValue(index)) + .search(toValue(search), { + limit: toValue(limit), + filter: toValue(filter), + hitsPerPage: toValue(hitsPerPage), + page: toValue(page), + facets: toValue(facets), + sort: toValue(sort), + }) + filterError.value = null + const { hits: resHits, totalHits: resTotalHits, totalPages: resTotalPages, facetDistribution: facetD } = res + + totalHits.value = resTotalHits + hits.value = resHits + totalPages.value = resTotalPages + facetDistribution.value = facetD + pending.value = false + } catch (e: any) { + filterError.value = e + } + finally { + pending.value = false + } + // }) + console.log(hits) return { hits, totalHits, pending, filterError, totalPages, facetDistribution } } diff --git a/content/4.refseq.md b/content/4.refseq.md index 16165e5f554c08a9afd5ae7aa9fccc995e4b4f86..f55ac77a3f87a98d2d22d0302d08f8f407898798 100644 --- a/content/4.refseq.md +++ b/content/4.refseq.md @@ -1,4 +1,12 @@ --- layout: db navigation: false ---- \ No newline at end of file +--- + + + + + +::refseq-db +:: + diff --git a/content/5.predicted-structure.md b/content/5.predicted-structure.md index 6fd0e7b6540f455abf3b8733b135e1b83ec5b868..859a7b74f16fa183f2e26839650e482ef3be0eec 100644 --- a/content/5.predicted-structure.md +++ b/content/5.predicted-structure.md @@ -3,3 +3,7 @@ layout: db navigation: false --- + + +::structure-db +:: \ No newline at end of file diff --git a/public/articles.json b/content/_data/_articles.json similarity index 92% rename from public/articles.json rename to content/_data/_articles.json index 1c2b5c9c8632cafef2b2ede35fcd65278c70633a..5605d2f4cb78c48150efa22a30418c53c8a269f2 100644 --- a/public/articles.json +++ b/content/_data/_articles.json @@ -425,6 +425,45 @@ ] } }, + { + "id": "15342854/42JKZL7K", + "type": "article-journal", + "title": "A NON HEREDITARY, HOST-INDUCED VARIATION OF BACTERIAL VIRUSES", + "container-title": "Journal of Bacteriology", + "page": "557-569", + "volume": "64", + "issue": "4", + "URL": "https://journals.asm.org/doi/10.1128/jb.64.4.557-569.1952", + "DOI": "10.1128/jb.64.4.557-569.1952", + "journalAbbreviation": "J Bacteriol", + "language": "en", + "author": [ + { + "family": "Luria", + "given": "S. E." + }, + { + "family": "Human", + "given": "Mary L." + } + ], + "issued": { + "date-parts": [ + [ + "1952" + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 21 + ] + ] + } + }, { "id": "15342854/NUNPK7GW", "type": "article-journal", @@ -825,18 +864,18 @@ } }, { - "id": "15342854/YQTB9FM9", + "id": "15342854/XWLAVRDY", "type": "article-journal", - "title": "A widespread bacteriophage abortive infection system functions through a Type IV toxin-antitoxin mechanism", + "title": "A widespread bacteriophage abortive infection system functions through a Type IV toxin\u2013antitoxin mechanism", "container-title": "Nucleic Acids Research", "page": "4590-4605", "volume": "42", "issue": "7", - "abstract": "Bacterial abortive infection (Abi) systems are 'altruistic' cell death systems that are activated by phage infection and limit viral replication, thereby providing protection to the bacterial population. Here, we have used a novel approach of screening Abi systems as a tool to identify and characterize toxin-antitoxin (TA)-acting Abi systems. We show that AbiE systems are encoded by bicistronic operons and function via a non-interacting (Type IV) bacteriostatic TA mechanism. The abiE operon was negatively autoregulated by the antitoxin, AbiEi, a member of a widespread family of putative transcriptional regulators. AbiEi has an N-terminal winged-helix-turn-helix domain that is required for repression of abiE transcription, and an uncharacterized bi-functional C-terminal domain, which is necessary for transcriptional repression and sufficient for toxin neutralization. The cognate toxin, AbiEii, is a predicted nucleotidyltransferase (NTase) and member of the DNA polymerase \u03b2 family. AbiEii specifically bound GTP, and mutations in conserved NTase motifs (I-III) and a newly identified motif (IV), abolished GTP binding and subsequent toxicity. The AbiE systems can provide phage resistance and enable stabilization of mobile genetic elements, such as plasmids. Our study reveals molecular insights into the regulation and function of the widespread bi-functional AbiE Abi-TA systems and the biochemical properties of both toxin and antitoxin proteins.", + "abstract": "Bacterial abortive infection (Abi) systems are \u2018altruistic\u2019 cell death systems that are activated by phage infection and limit viral replication, thereby providing protection to the bacterial population. Here, we have used a novel approach of screening Abi systems as a tool to identify and characterize toxin\u2013antitoxin (TA)-acting Abi systems. We show that AbiE systems are encoded by bicistronic operons and function via a non-interacting (Type IV) bacteriostatic TA mechanism. The abiE operon was negatively autoregulated by the antitoxin, AbiEi, a member of a widespread family of putative transcriptional regulators. AbiEi has an N-terminal winged-helix-turn-helix domain that is required for repression of abiE transcription, and an uncharacterized bi-functional C-terminal domain, which is necessary for transcriptional repression and sufficient for toxin neutralization. The cognate toxin, AbiEii, is a predicted nucleotidyltransferase (NTase) and member of the DNA polymerase b family. AbiEii specifically bound GTP, and mutations in conserved NTase motifs (I-III) and a newly identified motif (IV), abolished GTP binding and subsequent toxicity. The AbiE systems can provide phage resistance and enable stabilization of mobile genetic elements, such as plasmids. Our study reveals molecular insights into the regulation and function of the widespread bi-functional AbiE Abi-TA systems and the biochemical properties of both toxin and antitoxin proteins.", + "URL": "https://academic.oup.com/nar/article/42/7/4590/2436634", "DOI": "10.1093/nar/gkt1419", - "note": "PMID: 24465005\nPMCID: PMC3985639", - "journalAbbreviation": "Nucleic Acids Res", - "language": "eng", + "note": "tex.ids= Dy2014a\nPMCID: PMC3985639\nPMID: 24465005", + "language": "en", "author": [ { "family": "Dy", @@ -852,7 +891,7 @@ }, { "family": "Salmond", - "given": "George P. C." + "given": "George P.C." }, { "family": "Fineran", @@ -863,7 +902,17 @@ "date-parts": [ [ 2014, - 4 + 4, + 1 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 8, + 31 ] ] } @@ -2187,6 +2236,168 @@ ] } }, + { + "id": "15342854/KBU3L4WT", + "type": "article-journal", + "title": "Complete Sequence of the New Lactococcal Abortive Phage Resistance Gene abiO", + "container-title": "Journal of Dairy Science", + "page": "1483-1485", + "volume": "81", + "issue": "6", + "URL": "https://www.sciencedirect.com/science/article/pii/S0022030298757133", + "DOI": "10.3168/jds.S0022-0302(98)75713-3", + "journalAbbreviation": "Journal of Dairy Science", + "author": [ + { + "family": "Prevots", + "given": "Fabien" + }, + { + "family": "Ritzenthaler", + "given": "Paul" + } + ], + "issued": { + "date-parts": [ + [ + 1998, + 6, + 1 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 22 + ] + ] + } + }, + { + "id": "15342854/MX2D8C95", + "type": "article-journal", + "title": "Core defense hotspots within Pseudomonas aeruginosa are a consistent and rich source of anti-phage defense systems", + "container-title": "Nucleic Acids Research", + "page": "4995-5005", + "volume": "51", + "issue": "10", + "abstract": "Bacteria use a diverse arsenal of anti-phage immune systems, including CRISPR-Cas and restriction enzymes. Recent advances in anti-phage system discovery and annotation tools have unearthed many unique systems, often encoded in horizontally transferred defense islands, which can be horizontally transferred. Here, we developed Hidden Markov Models (HMMs) for defense systems and queried microbial genomes on the NCBI database. Out of the 30 species with >200 completely sequenced genomes, our analysis found Pseudomonas aeruginosa exhibits the greatest diversity of anti-phage systems, as measured by Shannon entropy. Using network analysis to identify the common neighbors of anti-phage systems, we identified two core defense hotspot loci (cDHS1 and cDHS2). cDHS1 is up to 224 kb (median: 26 kb) with varied arrangements of more than 30 distinct immune systems across isolates, while cDHS2 has 24 distinct systems (median: 6 kb). Both cDHS regions are occupied in a majority of P. aeruginosa isolates. Most cDHS genes are of unknown function potentially representing new anti-phage systems, which we validated by identifying a novel anti-phage system (Shango) commonly encoded in cDHS1. Identifying core genes flanking immune islands could simplify immune system discovery and may represent popular landing spots for diverse MGEs carrying anti-phage systems.", + "URL": "https://doi.org/10.1093/nar/gkad317", + "DOI": "10.1093/nar/gkad317", + "journalAbbreviation": "Nucleic Acids Research", + "author": [ + { + "family": "Johnson", + "given": "Matthew C" + }, + { + "family": "Laderman", + "given": "Eric" + }, + { + "family": "Huiting", + "given": "Erin" + }, + { + "family": "Zhang", + "given": "Chi" + }, + { + "family": "Davidson", + "given": "Alan" + }, + { + "family": "Bondy-Denomy", + "given": "Joseph" + } + ], + "issued": { + "date-parts": [ + [ + 2023, + 6, + 9 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 27 + ] + ] + } + }, + { + "id": "15342854/D4ZQGIA3", + "type": "article-journal", + "title": "CRISPR Provides Acquired Resistance Against Viruses in Prokaryotes", + "container-title": "Science", + "page": "1709-1712", + "volume": "315", + "issue": "5819", + "abstract": "Clustered regularly interspaced short palindromic repeats (CRISPR) are a distinctive feature of the genomes of most Bacteria and Archaea and are thought to be involved in resistance to bacteriophages. We found that, after viral challenge, bacteria integrated new spacers derived from phage genomic sequences. Removal or addition of particular spacers modified the phage-resistance phenotype of the cell. Thus, CRISPR, together with associated cas genes, provided resistance against phages, and resistance specificity is determined by spacer-phage sequence similarity.", + "URL": "https://www.science.org/doi/full/10.1126/science.1138140", + "DOI": "10.1126/science.1138140", + "note": "Publisher: American Association for the Advancement of Science", + "author": [ + { + "family": "Barrangou", + "given": "Rodolphe" + }, + { + "family": "Fremaux", + "given": "Christophe" + }, + { + "family": "Deveau", + "given": "H\u00e9l\u00e8ne" + }, + { + "family": "Richards", + "given": "Melissa" + }, + { + "family": "Boyaval", + "given": "Patrick" + }, + { + "family": "Moineau", + "given": "Sylvain" + }, + { + "family": "Romero", + "given": "Dennis A." + }, + { + "family": "Horvath", + "given": "Philippe" + } + ], + "issued": { + "date-parts": [ + [ + 2007, + 3, + 23 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 16 + ] + ] + } + }, { "id": "15342854/7ZMD86BY", "type": "article-journal", @@ -2430,6 +2641,54 @@ ] } }, + { + "id": "15342854/QT3LWYX4", + "type": "article-journal", + "title": "Defense Islands in Bacterial and Archaeal Genomes and Prediction of Novel Defense Systems", + "container-title": "Journal of Bacteriology", + "page": "6039-6056", + "volume": "193", + "issue": "21", + "abstract": "ABSTRACT\n The arms race between cellular life forms and viruses is a major driving force of evolution. A substantial fraction of bacterial and archaeal genomes is dedicated to antivirus defense. We analyzed the distribution of defense genes and typical mobilome components (such as viral and transposon genes) in bacterial and archaeal genomes and demonstrated statistically significant clustering of antivirus defense systems and mobile genes and elements in genomic islands. The defense islands are enriched in putative operons and contain numerous overrepresented gene families. A detailed sequence analysis of the proteins encoded by genes in these families shows that many of them are diverged variants of known defense system components, whereas others show features, such as characteristic operonic organization, that are suggestive of novel defense systems. Thus, genomic islands provide abundant material for the experimental study of bacterial and archaeal antivirus defense. Except for the CRISPR-Cas systems, different classes of defense systems, in particular toxin-antitoxin and restriction-modification systems, show nonrandom clustering in defense islands. It remains unclear to what extent these associations reflect functional cooperation between different defense systems and to what extent the islands are genomic \u201csinks\u201d that accumulate diverse nonessential genes, particularly those acquired via horizontal gene transfer. The characteristics of defense islands resemble those of mobilome islands. Defense and mobilome genes are nonrandomly associated in islands, suggesting nonadaptive evolution of the islands via a preferential attachment-like mechanism underpinned by the addictive properties of defense systems such as toxins-antitoxins and an important role of horizontal mobility in the evolution of these islands.", + "URL": "https://journals.asm.org/doi/10.1128/JB.05535-11", + "DOI": "10.1128/JB.05535-11", + "journalAbbreviation": "J Bacteriol", + "language": "en", + "author": [ + { + "family": "Makarova", + "given": "Kira S." + }, + { + "family": "Wolf", + "given": "Yuri I." + }, + { + "family": "Snir", + "given": "Sagi" + }, + { + "family": "Koonin", + "given": "Eugene V." + } + ], + "issued": { + "date-parts": [ + [ + "2011" + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 4, + 5 + ] + ] + } + }, { "id": "15342854/LWM56CT7", "type": "article-journal", @@ -3251,6 +3510,45 @@ ] } }, + { + "id": "15342854/YJPKUAZ2", + "type": "article-journal", + "title": "Host controlled variation in bacterial viruses", + "container-title": "Journal of Bacteriology", + "page": "113-121", + "volume": "65", + "issue": "2", + "URL": "https://journals.asm.org/doi/10.1128/jb.65.2.113-121.1953", + "DOI": "10.1128/jb.65.2.113-121.1953", + "note": "Publisher: American Society for Microbiology", + "author": [ + { + "family": "Bertani", + "given": "G." + }, + { + "family": "Weigle", + "given": "J. J." + } + ], + "issued": { + "date-parts": [ + [ + 1953, + 2 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 21 + ] + ] + } + }, { "id": "15342854/J75JJ8W8", "type": "article-journal", @@ -3363,6 +3661,55 @@ ] } }, + { + "id": "15342854/Y3G7W7UX", + "type": "article-journal", + "title": "Isolation, cloning and characterisation of the abiI gene from Lactococcus lactis subsp. lactis M138 encoding abortive phage infection", + "container-title": "Journal of Biotechnology", + "page": "95-104", + "volume": "54", + "issue": "2", + "abstract": "Plasmid pND852 (56 kb) encodes nisin resistance and was isolated from Lactococcus lactis ssp lactis (L. lactis) M138 by conjugation to L. lactis LM0230. It conferred strong resistance to the isometric-headed phage \u03c6712 and partial resistance to the prolate-headed phage \u03c6c2. A 2.6 kb HpaII fragment encoding phage resistance was cloned into the streptococcal/Bacillus hybrid vector pGB301 to generate pND817. The mechanism of phage resistance encoded by pND817 involved abortive infection and this was illustrated by a reduction in burst size from 166 to 6 at 30\u00b0C and from 160 to 90 at 37\u00b0C. Partial resistance was therefore retained at 37\u00b0C. DNA sequencing revealed that the abortive infection was encoded by a single open reading frame (ORF), designated abiI, encoding a 332 amino acid protein. Neither abiI nor the predicted product showed significant homology to any existing sequence in the GenBank database. Frame shift mutation at the unique EcoRI site within the ORF resulted in loss of the Abi+ phenotype, confirming that the ORF is responsible for the encoded phage resistance.", + "URL": "https://www.sciencedirect.com/science/article/pii/S0168165697016921", + "DOI": "10.1016/S0168-1656(97)01692-1", + "journalAbbreviation": "Journal of Biotechnology", + "author": [ + { + "family": "Su", + "given": "Ping" + }, + { + "family": "Harvey", + "given": "Melissa" + }, + { + "family": "Im", + "given": "Hee J" + }, + { + "family": "Dunn", + "given": "Noel W" + } + ], + "issued": { + "date-parts": [ + [ + 1997, + 4, + 25 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 22 + ] + ] + } + }, { "id": "15342854/2ENY7AF5", "type": "article-journal", @@ -3711,7 +4058,7 @@ "issue": "4", "abstract": "Abortive infection (Abi) systems, also called phage exclusion, block phage multiplication and cause premature bacterial cell death upon phage infection. This decreases the number of progeny particles and limits their spread to other cells allowing the bacterial population to survive. Twenty Abi systems have been isolated in Lactococcus lactis, a bacterium used in cheese-making fermentation processes, where phage attacks are of economical importance. Recent insights in their expression and mode of action indicate that, behind diverse phenotypic and molecular effects, lactococcal Abis share common traits with the well-studied Escherichia coli systems Lit and Prr. Abis are widespread in bacteria, and recent analysis indicates that Abis might have additional roles other than conferring phage resistance.", "DOI": "10.1016/j.mib.2005.06.006", - "note": "PMID: 15979388", + "note": "tex.ids= Chopin2005\nPMID: 15979388", "shortTitle": "Phage abortive infection in lactococci", "journalAbbreviation": "Curr Opin Microbiol", "language": "eng", @@ -4045,6 +4392,66 @@ ] } }, + { + "id": "15342854/IHZP7M6I", + "type": "article-journal", + "title": "Phenotypic and genetic characterization of the bacteriophage abortive infection mechanism AbiK from Lactococcus lactis", + "container-title": "Applied and Environmental Microbiology", + "page": "1274-1283", + "volume": "63", + "issue": "4", + "abstract": "The natural plasmid pSRQ800 isolated from Lactococcus lactis subsp. lactis W1 conferred strong phage resistance against small isometric phages of the 936 and P335 species when introduced into phage-sensitive L. lactis strains. It had very limited effect on prolate phages of the c2 species. The phage resistance mechanism encoded on pSRQ800 is a temperature-sensitive abortive infection system (Abi). Plasmid pSRQ800 was mapped, and the Abi genetic determinant was localized on a 4.5-kb EcoRI fragment. Cloning and sequencing of the 4.5-kb fragment allowed the identification of two large open reading frames. Deletion mutants showed that only orf1 was needed to produce the Abi phenotype. orf1 (renamed abiK) coded for a predicted protein of 599 amino acids (AbiK) with an estimated molecular size of 71.4 kDa and a pI of 7.98. DNA and protein sequence alignment programs found no significant homology with databases. However, a database query based on amino acid composition suggested that AbiK might be in the same protein family as AbiA. No phage DNA replication nor phage structural protein production was detected in infected AbiK+ L. lactis cells. This system is believed to act at or prior to phage DNA replication. WHen cloned into a high-copy vector, AbiK efficiency increased 100-fold. AbiK provides another powerful tool that can be useful in controlling phages during lactococcal fermentations.", + "URL": "https://journals.asm.org/doi/10.1128/aem.63.4.1274-1283.1997", + "DOI": "10.1128/aem.63.4.1274-1283.1997", + "note": "Publisher: American Society for Microbiology", + "author": [ + { + "family": "Emond", + "given": "E" + }, + { + "family": "Holler", + "given": "B J" + }, + { + "family": "Boucher", + "given": "I" + }, + { + "family": "Vandenbergh", + "given": "P A" + }, + { + "family": "Vedamuthu", + "given": "E R" + }, + { + "family": "Kondo", + "given": "J K" + }, + { + "family": "Moineau", + "given": "S" + } + ], + "issued": { + "date-parts": [ + [ + 1997, + 4 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 22 + ] + ] + } + }, { "id": "15342854/UXQPXABE", "type": "article-journal", @@ -4340,7 +4747,7 @@ "abstract": "Viperin is an interferon-induced cellular protein that is conserved in animals1. It has\u00a0previously been shown to inhibit the replication of multiple viruses by producing the ribonucleotide 3\u2032-deoxy-3\u2032,4\u2032-didehydro (ddh)-cytidine triphosphate (ddhCTP), which acts as a chain terminator for viral RNA polymerase2. Here we show that eukaryotic viperin originated from a clade of bacterial and archaeal proteins that protect against phage infection. Prokaryotic viperins produce a set of modified ribonucleotides that include ddhCTP, ddh-guanosine triphosphate (ddhGTP) and ddh-uridine triphosphate (ddhUTP). We further show that prokaryotic viperins protect against T7 phage infection by inhibiting viral polymerase-dependent transcription, suggesting that it has an antiviral mechanism of action similar to that of animal viperin. Our results reveal a class of potential natural antiviral compounds produced by bacterial immune systems.", "URL": "https://www.nature.com/articles/s41586-020-2762-2", "DOI": "10.1038/s41586-020-2762-2", - "note": "Number: 7840\nPublisher: Nature Publishing Group", + "note": "tex.ids= Bernheim2021, Bernheim2021a\nnumber: 7840\npublisher: Nature Publishing Group", "language": "en", "author": [ { @@ -4455,7 +4862,7 @@ } }, { - "id": "15342854/SGKZUETF", + "id": "15342854/KYSKHP5G", "type": "article-journal", "title": "Prophage-mediated defence against viral attack and viral counter-defence", "container-title": "Nature Microbiology", @@ -4465,7 +4872,7 @@ "abstract": "Temperate phages are common, and prophages are abundant residents of sequenced bacterial genomes. Mycobacteriophages are viruses that infect mycobacterial hosts including Mycobacterium tuberculosis and Mycobacterium smegmatis, encompass substantial genetic diversity and are commonly temperate. Characterization of ten Cluster N temperate mycobacteriophages revealed at least five distinct prophage-expressed viral defence systems that interfere with the infection of lytic and temperate phages that are either closely related (homotypic defence) or unrelated (heterotypic defence) to the prophage. Target specificity is unpredictable, ranging from a single target phage to one-third of those tested. The defence systems include a single-subunit restriction system, a heterotypic exclusion system and a predicted (p)ppGpp synthetase, which blocks lytic phage growth, promotes bacterial survival and enables efficient lysogeny. The predicted (p)ppGpp synthetase coded by the Phrann prophage defends against phage Tweety infection, but Tweety codes for a tetrapeptide repeat protein, gp54, which acts as a highly effective counter-defence system. Prophage-mediated viral defence offers an efficient mechanism for bacterial success in host\u2013virus dynamics, and counter-defence promotes phage co-evolution.", "URL": "https://www.nature.com/articles/nmicrobiol2016251", "DOI": "10.1038/nmicrobiol.2016.251", - "note": "Number: 3\nPublisher: Nature Publishing Group", + "note": "tex.ids= Dedrick2017\nnumber: 3\npublisher: Nature Publishing Group", "journalAbbreviation": "Nat Microbiol", "language": "en", "author": [ @@ -4659,8 +5066,8 @@ "date-parts": [ [ 2023, - 1, - 18 + 9, + 27 ] ] } @@ -5374,6 +5781,50 @@ ] } }, + { + "id": "15342854/2WVG5C98", + "type": "article-journal", + "title": "Study of membrane attachment and in vivo co-localization of TerB protein from uropathogenic Escherichia coli KL53", + "container-title": "General Physiology and Biophysics", + "page": "286-292", + "volume": "30", + "issue": "3", + "abstract": "The tellurite resistance operon has been found in a wide range of bacteria. We have previously identi\ufb01ed the ter operon (terXYW and terZABCDEF) of the uropathogenic strain Escherichia coli KL53. In this study, we use an innovative approach to identify putative protein-protein interaction partners for one of the essential tellurite resistance proteins \u2013 TerB. We observe that N-terminus of TerB attaches to the periplasmic membrane, while the C-terminus is partly localized in the cytoplasm. Subsequently, by methods of in vivo cross-linking and mass-spectroscopic analysis, we have determined the proteins from both the membrane and cytoplasmic fractions, which can potentially interact with TerB.", + "URL": "http://www.elis.sk/index.php?page=shop.product_details&flypage=flypage.tpl&product_id=2468&category_id=78&option=com_virtuemart&Itemid=11", + "DOI": "10.4149/gpb_2011_03_286", + "journalAbbreviation": "gpb", + "language": "en", + "author": [ + { + "family": "Alekhina", + "given": "O." + }, + { + "family": "Valkovicova", + "given": "L." + }, + { + "family": "Turna", + "given": "J." + } + ], + "issued": { + "date-parts": [ + [ + 2011 + ] + ] + }, + "accessed": { + "date-parts": [ + [ + 2023, + 11, + 30 + ] + ] + } + }, { "id": "15342854/LDQLNJ9U", "type": "article-journal", @@ -5384,7 +5835,7 @@ "issue": "6379", "abstract": "The arms race between bacteria and phages led to the development of sophisticated antiphage defense systems, including CRISPR-Cas and restriction-modification systems. Evidence suggests that known and unknown defense systems are located in \"defense islands\" in microbial genomes. Here, we comprehensively characterized the bacterial defensive arsenal by examining gene families that are clustered next to known defense genes in prokaryotic genomes. Candidate defense systems were systematically engineered and validated in model bacteria for their antiphage activities. We report nine previously unknown antiphage systems and one antiplasmid system that are widespread in microbes and strongly protect against foreign invaders. These include systems that adopted components of the bacterial flagella and condensin complexes. Our data also suggest a common, ancient ancestry of innate immunity components shared between animals, plants, and bacteria.", "DOI": "10.1126/science.aar4120", - "note": "PMID: 29371424\nPMCID: PMC6387622", + "note": "tex.ids= Doron2018, Doron2018a, Doron2018b\nPMCID: PMC6387622\nPMID: 29371424", "journalAbbreviation": "Science", "language": "eng", "author": [ diff --git a/deploy/meilisearch/Chart.yaml b/deploy/meilisearch/Chart.yaml index e9d0dea98545c77d5a09c91555236318281e8aa8..35cb6b57488aa0b4e75c7df8be8477071e0eb2dd 100644 --- a/deploy/meilisearch/Chart.yaml +++ b/deploy/meilisearch/Chart.yaml @@ -25,6 +25,6 @@ appVersion: "1.16.0" dependencies: - name: meilisearch - version: 0.2.8 + version: 0.3.0 repository: "https://meilisearch.github.io/meilisearch-kubernetes" diff --git a/docker-compose.yml b/docker-compose.yml index 21157aa4987e2a13fb10323e019230184bd447e6..251560e0dfa9efa3ce9f42c3f0bbbd5ba0ad052a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: args: BASE_URL: /wiki/ MEILI_HOST: http://localhost:7700 - MEILI_API_KEY: 269d546c85959e3d125cf7b34975a91503e0a63f0547c395c06ddf696a7cf12d + MEILI_API_KEY: f9cc073016cbb392365aae86517878cb3f3408bb85c1fafd06e27f73ccb35e3d container_name: nuxt environment: HOST: 0.0.0.0 @@ -30,7 +30,7 @@ services: - main meilisearch: - image: getmeili/meilisearch:v1.4 + image: getmeili/meilisearch:v1.5 # command: # - meilisearch # - --http-addr diff --git a/layouts/article.vue b/layouts/article.vue index 415a26a707657557b6325fab8a603761e1dbc491..0837b5fa59db8c2970b03ec22749c8af105dde16 100644 --- a/layouts/article.vue +++ b/layouts/article.vue @@ -1,4 +1,18 @@ -<script setup lang="ts"></script> +<script setup lang="ts"> +import { useArticlesStore } from '@/stores/articles' +const store = useArticlesStore() + +const { data } = await useAsyncData('zotero-articles', async () => queryContent('_data/_articles').where({ _partial: true }).findOne()) +if (data.value) { + const dataValue = toValue(data)?.body + for (const cslArticle of dataValue) { + if (cslArticle?.DOI) { + store.add(cslArticle) + } + } +} + +</script> <template> <LayoutWrapper> <slot /> diff --git a/layouts/db.vue b/layouts/db.vue index 911df8380744c976d6fe9085eb075e2edd3e7714..55982ec2cfe62124b994b2c97d1cd948803bebab 100644 --- a/layouts/db.vue +++ b/layouts/db.vue @@ -5,15 +5,8 @@ import { useFacetsStore, type Facets } from '~~/stores/facets' const facetStore = useFacetsStore() </script> <template> - <LayoutWrapper :fluid="true" :toc="false" :edit="false"> - <template #drawer="{ drawer }"> - <v-navigation-drawer :model-value="drawer" :border="1" color="background"> - <v-list> - <v-list-item v-for="(value, key) in facetStore.facets.facetDistribution" :key="key" - :title="key"></v-list-item> - </v-list> - </v-navigation-drawer> - </template> + <LayoutWrapper :fluid="true" :toc="false" :edit="false" :nav-drawer="false"> + <slot /> </LayoutWrapper> diff --git a/nuxt.config.ts b/nuxt.config.ts index 93880873f8f9742a9c8f810e418f1f329d52399a..57f09717aec376064e97b96ca38d5bb0a82777d5 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -6,6 +6,7 @@ export default defineNuxtConfig({ 'vuetify-nuxt-module', '@vueuse/nuxt', '@pinia/nuxt', + 'nuxt-meilisearch', // '@unocss/nuxt', ], content: { @@ -32,6 +33,11 @@ export default defineNuxtConfig({ } }, + meilisearch: { + hostUrl: 'https://my-meilisearch-server.example.com', + searchApiKey: 'api_key', + serverSideUsage: false // default false + }, devtools: { enabled: false }, @@ -39,6 +45,10 @@ export default defineNuxtConfig({ public: { defenseFinderWebservice: '/', + meilisearchClient: { + hostUrl: 'http://localhost:7700', + searchApiKey: 'api_key', + }, meiliHost: 'http://localhost:7700', meiliApiKey: 'api_key' } diff --git a/package-lock.json b/package-lock.json index 764ea4a8d4bfe1cef05aa6de9922d892e105ed45..0ce532335de56cd6452a821572b1f91bfc5a9e72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,9 +20,185 @@ "@vueuse/core": "^10.6.1", "@vueuse/nuxt": "^10.6.1", "nuxt": "^3.8.1", + "nuxt-meilisearch": "^1.1.0", "vuetify-nuxt-module": "^0.6.7" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.20.0.tgz", + "integrity": "sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-common": "4.20.0" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.20.0.tgz", + "integrity": "sha512-vCfxauaZutL3NImzB2G9LjLt36vKAckc6DhMp05An14kVo8F1Yofb6SIl6U3SaEz8pG2QOB9ptwM5c+zGevwIQ==", + "dev": true, + "peer": true + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.20.0.tgz", + "integrity": "sha512-Wm9ak/IaacAZXS4mB3+qF/KCoVSBV6aLgIGFEtQtJwjv64g4ePMapORGmCyulCFwfePaRAtcaTbMcJF+voc/bg==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-common": "4.20.0" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.20.0.tgz", + "integrity": "sha512-GGToLQvrwo7am4zVkZTnKa72pheQeez/16sURDWm7Seyz+HUxKi3BM6fthVVPUEBhtJ0reyVtuK9ArmnaKl10Q==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.20.0", + "@algolia/client-search": "4.20.0", + "@algolia/transporter": "4.20.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.20.0.tgz", + "integrity": "sha512-EIr+PdFMOallRdBTHHdKI3CstslgLORQG7844Mq84ib5oVFRVASuuPmG4bXBgiDbcsMLUeOC6zRVJhv1KWI0ug==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.20.0", + "@algolia/client-search": "4.20.0", + "@algolia/requester-common": "4.20.0", + "@algolia/transporter": "4.20.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.20.0.tgz", + "integrity": "sha512-P3WgMdEss915p+knMMSd/fwiHRHKvDu4DYRrCRaBrsfFw7EQHon+EbRSm4QisS9NYdxbS04kcvNoavVGthyfqQ==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/requester-common": "4.20.0", + "@algolia/transporter": "4.20.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.20.0.tgz", + "integrity": "sha512-N9+zx0tWOQsLc3K4PVRDV8GUeOLAY0i445En79Pr3zWB+m67V+n/8w4Kw1C5LlbHDDJcyhMMIlqezh6BEk7xAQ==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.20.0", + "@algolia/requester-common": "4.20.0", + "@algolia/transporter": "4.20.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.20.0.tgz", + "integrity": "sha512-zgwqnMvhWLdpzKTpd3sGmMlr4c+iS7eyyLGiaO51zDZWGMkpgoNVmltkzdBwxOVXz0RsFMznIxB9zuarUv4TZg==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.20.0", + "@algolia/requester-common": "4.20.0", + "@algolia/transporter": "4.20.0" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==", + "dev": true + }, + "node_modules/@algolia/logger-common": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.20.0.tgz", + "integrity": "sha512-xouigCMB5WJYEwvoWW5XDv7Z9f0A8VoXJc3VKwlHJw/je+3p2RcDXfksLI4G4lIVncFUYMZx30tP/rsdlvvzHQ==", + "dev": true, + "peer": true + }, + "node_modules/@algolia/logger-console": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.20.0.tgz", + "integrity": "sha512-THlIGG1g/FS63z0StQqDhT6bprUczBI8wnLT3JWvfAQDZX5P6fCg7dG+pIrUBpDIHGszgkqYEqECaKKsdNKOUA==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/logger-common": "4.20.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.20.0.tgz", + "integrity": "sha512-HbzoSjcjuUmYOkcHECkVTwAelmvTlgs48N6Owt4FnTOQdwn0b8pdht9eMgishvk8+F8bal354nhx/xOoTfwiAw==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/requester-common": "4.20.0" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.20.0.tgz", + "integrity": "sha512-9h6ye6RY/BkfmeJp7Z8gyyeMrmmWsMOCRBXQDs4mZKKsyVlfIVICpcSibbeYcuUdurLhIlrOUkH3rQEgZzonng==", + "dev": true, + "peer": true + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.20.0.tgz", + "integrity": "sha512-ocJ66L60ABSSTRFnCHIEZpNHv6qTxsBwJEPfYaSBsLQodm0F9ptvalFkHMpvj5DfE22oZrcrLbOYM2bdPJRHng==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/requester-common": "4.20.0" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.20.0.tgz", + "integrity": "sha512-Lsii1pGWOAISbzeyuf+r/GPhvHMPHSPrTDWNcIzOE1SG1inlJHICaVe2ikuoRjcpgxZNU54Jl+if15SUCsaTUg==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-common": "4.20.0", + "@algolia/logger-common": "4.20.0", + "@algolia/requester-common": "4.20.0" + } + }, + "node_modules/@algolia/ui-components-highlight-vdom": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@algolia/ui-components-highlight-vdom/-/ui-components-highlight-vdom-1.2.2.tgz", + "integrity": "sha512-/+7jh7cd5rR2yQC7ME4SDcnAMiD1Ofn5Qq+E7afTJx9XSMOHkLR77/o6YcuJ60TfD1S+9lr7yjBLACon8gOuzQ==", + "dev": true, + "dependencies": { + "@algolia/ui-components-shared": "1.2.2", + "@babel/runtime": "^7.0.0" + } + }, + "node_modules/@algolia/ui-components-shared": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@algolia/ui-components-shared/-/ui-components-shared-1.2.2.tgz", + "integrity": "sha512-FYwEG5sbr8p4V8mqP0iUaKgmWfcrMXRXwp7e6iBuB65P/7QyL8pT4I6/iGb85Q5mNH+UtYYSmLZhKjEblllKEQ==", + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "license": "Apache-2.0", @@ -459,6 +635,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", + "integrity": "sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/standalone": { "version": "7.23.4", "license": "MIT", @@ -536,6 +724,117 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "peer": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@fastify/busboy": { "version": "2.1.0", "dev": true, @@ -544,6 +843,66 @@ "node": ">=14" } }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "peer": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true, + "peer": true + }, "node_modules/@ioredis/commands": { "version": "1.2.0", "dev": true, @@ -748,6 +1107,15 @@ "node": ">= 6" } }, + "node_modules/@meilisearch/instant-meilisearch": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/@meilisearch/instant-meilisearch/-/instant-meilisearch-0.13.6.tgz", + "integrity": "sha512-olVCeOXmignmfY+ML8ExgyPCLGkr/XPXcz0n8tajRFr4afDKzomxySGMfQXVok9SoyhB+xeNH/mEMhguxCwklg==", + "dev": true, + "dependencies": { + "meilisearch": "^0.35.0" + } + }, "node_modules/@netlify/functions": { "version": "2.4.0", "dev": true, @@ -1428,6 +1796,22 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@nuxt/eslint-config": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.2.0.tgz", + "integrity": "sha512-NeJX8TLcnNAjQFiDs3XhP+9CHKK8jaKsP7eUyCSrQdgY7nqWe7VJx64lwzx5FTT4cW3RHMEyH+Y0qzLGYYoa/A==", + "dev": true, + "dependencies": { + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/eslint-plugin": "^6.5.0", + "@typescript-eslint/parser": "^6.5.0", + "eslint-plugin-vue": "^9.17.0", + "typescript": "^5.2.2" + }, + "peerDependencies": { + "eslint": "^8.48.0" + } + }, "node_modules/@nuxt/kit": { "version": "3.8.2", "license": "MIT", @@ -1966,6 +2350,12 @@ "linux" ] }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz", + "integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==", + "dev": true + }, "node_modules/@sigstore/bundle": { "version": "2.1.0", "dev": true, @@ -2100,10 +2490,22 @@ "@types/ms": "*" } }, + "node_modules/@types/dom-speech-recognition": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz", + "integrity": "sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw==", + "dev": true + }, "node_modules/@types/estree": { "version": "1.0.5", "license": "MIT" }, + "node_modules/@types/google.maps": { + "version": "3.54.9", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.54.9.tgz", + "integrity": "sha512-kovzglL9eC/zsMnhIpBsiuUDPwhNsRDQzjtKDHZ3D4lYHi7l7IgZPE8/yz+I4Wb96cQXkz2W0DcOiF5RaNPovA==", + "dev": true + }, "node_modules/@types/hast": { "version": "3.0.3", "dev": true, @@ -2112,6 +2514,12 @@ "@types/unist": "*" } }, + "node_modules/@types/hogan.js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hogan.js/-/hogan.js-3.0.5.tgz", + "integrity": "sha512-/uRaY3HGPWyLqOyhgvW9Aa43BNnLZrNeQxl2p8wqId4UHMfPKolSB+U7BlZyO1ng7MkLnyEAItsBzCG0SDhqrA==", + "dev": true + }, "node_modules/@types/http-proxy": { "version": "1.17.14", "dev": true, @@ -2120,6 +2528,12 @@ "@types/node": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/mdast": { "version": "4.0.3", "dev": true, @@ -2145,11 +2559,23 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/qs": { + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", + "dev": true + }, "node_modules/@types/resolve": { "version": "1.20.2", "dev": true, "license": "MIT" }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, "node_modules/@types/unist": { "version": "3.0.2", "dev": true, @@ -2160,59 +2586,277 @@ "dev": true, "license": "MIT" }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/@unhead/dom": { - "version": "1.8.5", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "dev": true, - "license": "MIT", "dependencies": { - "@unhead/schema": "1.8.5", - "@unhead/shared": "1.8.5" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/harlan-zw" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@unhead/schema": { - "version": "1.8.5", + "node_modules/@typescript-eslint/parser": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "dev": true, - "license": "MIT", "dependencies": { - "hookable": "^5.5.3", - "zhead": "^2.2.4" + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/harlan-zw" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@unhead/shared": { - "version": "1.8.5", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, - "license": "MIT", "dependencies": { - "@unhead/schema": "1.8.5" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/harlan-zw" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@unhead/ssr": { - "version": "1.8.5", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, - "license": "MIT", "dependencies": { - "@unhead/schema": "1.8.5", - "@unhead/shared": "1.8.5" + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/harlan-zw" - } - }, - "node_modules/@unhead/vue": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@unhead/dom": { + "version": "1.8.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@unhead/schema": "1.8.5", + "@unhead/shared": "1.8.5" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/schema": { + "version": "1.8.5", + "dev": true, + "license": "MIT", + "dependencies": { + "hookable": "^5.5.3", + "zhead": "^2.2.4" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/shared": { + "version": "1.8.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@unhead/schema": "1.8.5" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/ssr": { + "version": "1.8.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@unhead/schema": "1.8.5", + "@unhead/shared": "1.8.5" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/vue": { "version": "1.8.5", "dev": true, "license": "MIT", @@ -2571,6 +3215,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.0", "license": "MIT", @@ -2593,6 +3246,58 @@ "node": ">=8" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/algoliasearch": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.20.0.tgz", + "integrity": "sha512-y+UHEjnOItoNy0bYO+WWmLWBlPwDjKHW6mNHrPi0NkuhpQOOEbrkwQH/wgKFDLh7qlKjzoKeiRtlpewDPDG23g==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.20.0", + "@algolia/cache-common": "4.20.0", + "@algolia/cache-in-memory": "4.20.0", + "@algolia/client-account": "4.20.0", + "@algolia/client-analytics": "4.20.0", + "@algolia/client-common": "4.20.0", + "@algolia/client-personalization": "4.20.0", + "@algolia/client-search": "4.20.0", + "@algolia/logger-common": "4.20.0", + "@algolia/logger-console": "4.20.0", + "@algolia/requester-browser-xhr": "4.20.0", + "@algolia/requester-common": "4.20.0", + "@algolia/requester-node-http": "4.20.0", + "@algolia/transporter": "4.20.0" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.15.0.tgz", + "integrity": "sha512-DGUnK3TGtDQsaUE4ayF/LjSN0DGsuYThB8WBgnnDY0Wq04K6lNVruO3LfqJOgSfDiezp+Iyt8Tj4YKHi+/ivSA==", + "dev": true, + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, "node_modules/ansi-colors": { "version": "4.1.3", "dev": true, @@ -2729,6 +3434,15 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/ast-kit": { "version": "0.11.2", "dev": true, @@ -3067,6 +3781,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "dev": true, @@ -4048,6 +4772,13 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "peer": true + }, "node_modules/deepmerge": { "version": "4.3.1", "dev": true, @@ -4294,6 +5025,40 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "peer": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "dev": true, @@ -4555,28 +5320,423 @@ "version": "3.1.1", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.18.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.18.1.tgz", + "integrity": "sha512-7hZFlrEgg9NIzuVik2I9xSnJA5RsmOfueYgsUGUokEDLJ1LHtxO0Pl4duje1BriZ/jDWb+44tcIlC3yi0tdlZg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.13", + "semver": "^7.5.4", + "vue-eslint-parser": "^9.3.1", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "peer": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "peer": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "node_modules/escape-html": { - "version": "1.0.3", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.0" } }, "node_modules/estree-walker": { "version": "2.0.2", "license": "MIT" }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "dev": true, @@ -4628,6 +5788,13 @@ "ufo": "^1.1.2" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "peer": true + }, "node_modules/fast-fifo": { "version": "1.3.2", "dev": true, @@ -4647,6 +5814,20 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "peer": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "peer": true + }, "node_modules/fastq": { "version": "1.15.0", "license": "ISC", @@ -4654,6 +5835,19 @@ "reusify": "^1.0.4" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "peer": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-saver": { "version": "2.0.5", "license": "MIT" @@ -4708,6 +5902,21 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "peer": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/flatted": { "version": "3.2.9", "dev": true, @@ -4964,6 +6173,12 @@ "dev": true, "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/gzip-size": { "version": "7.0.0", "dev": true, @@ -5445,6 +6660,44 @@ "version": "0.2.7", "license": "MIT" }, + "node_modules/hogan.js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", + "dev": true, + "dependencies": { + "mkdirp": "0.3.0", + "nopt": "1.0.10" + }, + "bin": { + "hulk": "bin/hulk" + } + }, + "node_modules/hogan.js/node_modules/mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hogan.js/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/hookable": { "version": "5.5.3", "license": "MIT" @@ -5468,6 +6721,12 @@ "node": "14 || >=16.14" } }, + "node_modules/htm": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", + "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==", + "dev": true + }, "node_modules/html-tags": { "version": "3.3.1", "dev": true, @@ -5600,6 +6859,33 @@ "dev": true, "license": "MIT" }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "peer": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "dev": true, @@ -5638,6 +6924,36 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/instantsearch.css": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/instantsearch.css/-/instantsearch.css-8.1.0.tgz", + "integrity": "sha512-rPhcAZ02bLwUn3iOXbldZW/yl+17guWoH3qWYZ8nQEwNBx5+wZ6Bv8mFqqK448+R2aU4nbFKIhmoTIPXI5Zobg==", + "dev": true + }, + "node_modules/instantsearch.js": { + "version": "4.60.0", + "resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.60.0.tgz", + "integrity": "sha512-u/xeCT1DaxPioJnSm3hV4lNAojlhbjGrpX5fHO6+RJjpDFv/MgYxiIOdaIRowmt5F0v/3QCm+Un5f4jy1/+emA==", + "dev": true, + "dependencies": { + "@algolia/events": "^4.0.1", + "@algolia/ui-components-highlight-vdom": "^1.2.2", + "@algolia/ui-components-shared": "^1.2.2", + "@types/dom-speech-recognition": "^0.0.1", + "@types/google.maps": "^3.45.3", + "@types/hogan.js": "^3.0.0", + "@types/qs": "^6.5.3", + "algoliasearch-helper": "3.15.0", + "hogan.js": "^3.0.2", + "htm": "^3.0.0", + "preact": "^10.10.0", + "qs": "^6.5.1 < 6.10", + "search-insights": "^2.6.0" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, "node_modules/internmap": { "version": "2.0.3", "license": "ISC", @@ -6034,6 +7350,13 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "peer": true + }, "node_modules/json-parse-even-better-errors": { "version": "3.0.0", "dev": true, @@ -6042,6 +7365,20 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "peer": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "peer": true + }, "node_modules/json5": { "version": "2.2.3", "license": "MIT", @@ -6075,6 +7412,16 @@ ], "license": "MIT" }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "peer": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/khroma": { "version": "2.1.0" }, @@ -6154,6 +7501,20 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lilconfig": { "version": "2.1.0", "dev": true, @@ -6247,6 +7608,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "peer": true + }, "node_modules/lodash.pick": { "version": "4.4.0", "license": "MIT" @@ -8899,6 +10267,12 @@ "version": "4.0.0", "license": "ISC" }, + "node_modules/mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==", + "dev": true + }, "node_modules/mkdirp": { "version": "1.0.4", "license": "MIT", @@ -8955,6 +10329,12 @@ "node": "^14 || ^16 || >=18" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.3", "dev": true, @@ -9515,6 +10895,30 @@ } } }, + "node_modules/nuxt-meilisearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nuxt-meilisearch/-/nuxt-meilisearch-1.1.0.tgz", + "integrity": "sha512-lVY++RoLOa2Egy7NXml72QPs28Kn480gY7qtqCcg9zNQ0UAXArWo/IGJgty5JFy3BECfs/23idLEqTTnjrQ2zQ==", + "dev": true, + "dependencies": { + "@meilisearch/instant-meilisearch": "0.13.6", + "@nuxt/eslint-config": "0.2.0", + "@nuxt/kit": "3.8.2", + "defu": "6.1.3", + "instantsearch.css": "8.1.0", + "meilisearch": "0.36.0", + "vue-instantsearch": "4.12.1" + } + }, + "node_modules/nuxt-meilisearch/node_modules/meilisearch": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.36.0.tgz", + "integrity": "sha512-swcvEYrct0/zsGj3jlbPm1OYxbH14IURnlysKlXywNicIQ5EMkSYLYCLCwOuBKAaGcdISWdgdylH9TXVLegmOQ==", + "dev": true, + "dependencies": { + "cross-fetch": "^3.1.6" + } + }, "node_modules/nuxt/node_modules/estree-walker": { "version": "3.0.3", "dev": true, @@ -9762,6 +11166,24 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "peer": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "dev": true, @@ -9844,6 +11266,19 @@ "version": "5.4.1", "license": "MIT" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "peer": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-entities": { "version": "4.0.1", "dev": true, @@ -10481,6 +11916,26 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/preact": { + "version": "10.19.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.2.tgz", + "integrity": "sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/pretty-bytes": { "version": "6.1.1", "dev": true, @@ -10548,6 +12003,28 @@ "dev": true, "license": "MIT" }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "funding": [ @@ -10712,6 +12189,12 @@ "node": ">=4" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "dev": true + }, "node_modules/rehype-external-links": { "version": "3.0.0", "dev": true, @@ -11489,6 +12972,12 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/search-insights": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.11.0.tgz", + "integrity": "sha512-Uin2J8Bpm3xaZi9Y8QibSys6uJOFZ+REMrf42v20AA3FUDUrshKkMEP6liJbMAHCm71wO6ls4mwAf7a3gFVxLw==", + "dev": true + }, "node_modules/semver": { "version": "7.5.4", "license": "ISC", @@ -11979,6 +13468,19 @@ "node": ">=6" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-literal": { "version": "1.3.0", "license": "MIT", @@ -12143,6 +13645,13 @@ "dev": true, "license": "MIT" }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "peer": true + }, "node_modules/tiny-invariant": { "version": "1.3.1", "dev": true, @@ -12214,6 +13723,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-dedent": { "version": "2.2.0", "license": "MIT", @@ -12234,6 +13755,19 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "3.13.1", "dev": true, @@ -12245,6 +13779,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typescript": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/ufo": { "version": "1.3.2", "license": "MIT" @@ -12732,6 +14279,16 @@ "dev": true, "license": "MIT" }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/urlpattern-polyfill": { "version": "8.0.2", "dev": true, @@ -13365,6 +14922,54 @@ "dev": true, "license": "MIT" }, + "node_modules/vue-eslint-parser": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.2.tgz", + "integrity": "sha512-q7tWyCVaV9f8iQyIA5Mkj/S6AoJ9KBN8IeUSf3XEmBrOtxOZnfTg5s4KClbZBCK3GtnT/+RyCLZyDHuZwTuBjg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-instantsearch": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/vue-instantsearch/-/vue-instantsearch-4.12.1.tgz", + "integrity": "sha512-Of3LSiY26mUYKx6d+l/GEPe2MtQ3yhlxI0V71dhMFRTU35c2XZQFS+RfJf2WWRdPSjMyGYlaQnpRdfaHDdLI2w==", + "dev": true, + "dependencies": { + "instantsearch.js": "4.60.0", + "mitt": "^2.1.0" + }, + "peerDependencies": { + "@vue/server-renderer": "^3.1.2", + "algoliasearch": ">= 3.32.0 < 5", + "vue": "^2.6.0 || >=3.0.0-rc.0", + "vue-server-renderer": "^2.6.11" + }, + "peerDependenciesMeta": { + "@vue/server-renderer": { + "optional": true + }, + "vue-server-renderer": { + "optional": true + } + } + }, "node_modules/vue-json-csv": { "version": "2.1.0", "dependencies": { @@ -13616,6 +15221,15 @@ } } }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", "dev": true, @@ -13667,6 +15281,19 @@ "node": ">=12" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zhead": { "version": "2.2.4", "dev": true, diff --git a/package.json b/package.json index 5e3a703f001761252317bd63f85dc8f67865fbef..6d6bb0ac5eab2f4cdf66dd6f10acf423981eb195 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@vueuse/core": "^10.6.1", "@vueuse/nuxt": "^10.6.1", "nuxt": "^3.8.1", + "nuxt-meilisearch": "^1.1.0", "vuetify-nuxt-module": "^0.6.7" }, "overrides": { diff --git a/packages/df-wiki-cli/df_wiki_cli/meilisearch/__init__.py b/packages/df-wiki-cli/df_wiki_cli/meilisearch/__init__.py index c979cf9afd0c3b0ed2d7e55a144854809200fc1d..563be0c4fa41e07635d04c2f9ce6787b75d57dd0 100644 --- a/packages/df-wiki-cli/df_wiki_cli/meilisearch/__init__.py +++ b/packages/df-wiki-cli/df_wiki_cli/meilisearch/__init__.py @@ -108,6 +108,18 @@ def update_refseq( "species", ] ) + params = { + "maxValuesPerFacet": 1000000, + "sortFacetValuesBy": {"*": "count"}, + } + index.update_faceting_settings(params) + print("typo toler") + index.update_typo_tolerance( + { + "enabled": False + # "minWordSizeForTypos": {"oneTypo": 50, "twoTypos": 100} + } + ) def update_structure( @@ -150,6 +162,7 @@ def update_structure( "plddts", ] ) + index.update_typo_tolerance({"enabled": False}) def split_on_comma(str_val: str) -> List[str]: diff --git a/pages/[...slug].vue b/pages/[...slug].vue index 9c9bf619593d96b76a11deffcd089d6df558fdf6..7fa8469ba5e0b03e3c1f21cd3218aac9afeffd25 100644 --- a/pages/[...slug].vue +++ b/pages/[...slug].vue @@ -1,11 +1,8 @@ <template> - <v-row justify="center"> - <v-col cols="auto"> - <v-card flat color="transparent" max-width="1280"> + <v-card-text> <ContentDoc /> </v-card-text> - </v-card></v-col> - </v-row> + </template> diff --git a/pages/predicted-structure.vue b/pages/predicted-structure.vue deleted file mode 100644 index b783a347255709e715bf9bb0fa23d63bef50c25b..0000000000000000000000000000000000000000 --- a/pages/predicted-structure.vue +++ /dev/null @@ -1,105 +0,0 @@ -<script setup lang="ts"> -import { useRuntimeConfig, useFetch, type MaybeRefOrGetter, ref, computed, toValue, type Ref } from '#imports' - -import JsonCSV from 'vue-json-csv' -import { useDisplay } from "vuetify"; -import { useFacetsStore, type Facets } from '~~/stores/facets' - - -const facetStore = useFacetsStore() - -const { height } = useDisplay(); -const minTableHeight = ref(400) -const computedTableHeight = computed(() => { - const computedHeight = height.value - 500 - return computedHeight > minTableHeight.value ? computedHeight : minTableHeight.value -}) - - -// SORTING -const sortBy: Ref<{ key: string, order: string }[]> = ref([{ key: 'system', order: "asc" }]) -const msSortBy = computed(() => { - if (sortBy.value.length > 0) { - return sortBy.value.map((curr) => { - if (curr?.key && curr?.order) { - return `${curr.key}:${curr.order}` - } - else { return "" } - }) - } else { return [""] } -}) - - - -const itemValue = ref("id"); -const search: Ref<string> = ref(""); -const filter: Ref<string> = ref('') -const hitsPerPage: Ref<number> = ref(25) -const limit: Ref<number> = ref(500000) -const facets = ref(["system"]) -const page = ref(1) -const headers: Ref<Object[]> = ref([ - { title: "System", key: "system" }, - { title: "Completed", key: "completed" }, - { title: "Predition type", key: "prediction_type" }, - { title: "Num of genes", key: "system_number_of_genes" }, - { title: "pLDDT", key: "plddts" }, - { title: "Type", key: "type" } -]) -const { - hits: items, - pending, - totalHits: itemsLength, - filterError, - facetDistribution -} = useFetchMsDocument( - "structure", search, filter, limit, hitsPerPage, page, facets, msSortBy) - -watch(facetDistribution, (facetDistri) => { - - facetStore.setFacets({ facetDistribution: facetDistri, facetStat: undefined }) -}) - -</script> - -<template> - <v-card flat> - <v-card-text> - text here - </v-card-text> - <v-toolbar color="primary" density="compact"> - <v-app-bar-nav-icon></v-app-bar-nav-icon> - <v-toolbar-title>Predicted Structures summary ({{ itemsLength }}) - </v-toolbar-title> - <JsonCSV :data="items" name="predicted-structures-summary-defense-system.csv"> - <v-btn disabled icon> - <v-icon icon="md:download"></v-icon> - <v-tooltip activator="parent" location="bottom">Download {{ itemsLength }} entries</v-tooltip> - </v-btn> - </JsonCSV> - </v-toolbar> - <v-card-text> - text here - </v-card-text> - <v-col> - <v-text-field v-model="search" prepend-inner-icon="mdi-magnify" - label="Search for defense systems predicted structures" hide-details class="mx-2" - clearable></v-text-field></v-col> - <v-col cols="auto"> - <v-text-field v-model="filter" prepend-inner-icon="mdi-magnify" label="Filter" hide-details="auto" class="mx-2" - clearable :error-messages="filterError"></v-text-field></v-col> - <v-data-table-server v-model:page="page" v-model:items-per-page="hitsPerPage" v-model:sortBy="sortBy" - ref="datatable" fixed-header :loading="pending" :headers="headers" :items="items" :item-value="itemValue" - :items-length="itemsLength" multi-sort density="compact" :height="computedTableHeight" class="elevation-1 mt-2"> - <!-- <template v-if="refseqData?.length >= 10000" #top> - <v-alert type="warning" variant="tonal" title="Results table" - text="Results won't be displayed since there is over 10000 hits"></v-alert> - </template> --> - - <template #[`item.completed`]="{ item }"> - <v-icon v-if="item.completed" color="success" icon="md:check"></v-icon> - <v-icon v-else color="warning" icon="md:dangerous"></v-icon> - </template> - </v-data-table-server> - </v-card> -</template> \ No newline at end of file diff --git a/pages/refseq.vue b/pages/refseq.vue deleted file mode 100644 index ffb9fc6ae599faba5d097043c75de2b8c590c741..0000000000000000000000000000000000000000 --- a/pages/refseq.vue +++ /dev/null @@ -1,266 +0,0 @@ -<script setup lang="ts"> -import * as Plot from "@observablehq/plot"; -import PlotFigure from "~/components/PlotFigure"; -import { useDisplay } from "vuetify"; -import JsonCSV from 'vue-json-csv'; -import { useFacetsStore, type Facets } from '~~/stores/facets' - -const runtimeConfig = useRuntimeConfig(); -const facetStore = useFacetsStore() -const { width, height } = useDisplay(); -const minTableHeight = ref(400) -const computedTableHeight = computed(() => { - const computedHeight = height.value - 500 - return computedHeight > minTableHeight.value ? computedHeight : minTableHeight.value -}) - - - -// SORTING -const sortBy: Ref<{ key: string, order: string }[]> = ref([{ key: 'type', order: "asc" }]) -const msSortBy = computed(() => { - if (sortBy.value.length > 0) { - return sortBy.value.map((curr) => { - if (curr?.key && curr?.order) { - return `${curr.key}:${curr.order}` - } - else { return "" } - }) - } else { return [""] } -}) - - - - - -const availableTaxo: Ref<string[]> = ref(["species", "genus", "family", "order", "phylum", "Superkingdom"]); -const selectedTaxoRank = ref("phylum"); - - -const computedWidth = computed(() => { - return Math.max(width.value, 550); -}); - -const plotHeight = computed(() => { - return computedWidth.value / 4; -}); -// const filterError = ref(null) -const search: Ref<string> = ref(""); -const filter: Ref<string> = ref('') -const hitsPerPage: Ref<number> = ref(25) -const limit = ref(1000) -const itemValue = ref("id"); -const facets = ref([ - "type", - "Superkingdom", - "phylum", - "order", - "family", - "genus", - "species", -]) -const page = ref(1) -const prependHeaders = ref([ - { title: "Replicon", key: "replicon" }, - { - title: "System", - key: "type", - }, - { - title: "Subtype", - key: "subtype", - }, - - -]); -const appendHeaders = ref([ - { - title: "Accessions", - key: "accession_in_sys" - } -]) - - - -function capitalize([first, ...rest]) { - return first.toUpperCase() + rest.join('').toLowerCase(); -} - - -const { - hits: items, - pending, - totalHits: itemsLength, - filterError, - facetDistribution } - = useFetchMsDocument( - "refseq", - search, - filter, - limit, - hitsPerPage, - page, - facets, - msSortBy - ) - -watch(facetDistribution, (facetDistri) => { - facetStore.setFacets({ facetDistribution: facetDistri, facetStat: undefined }) -}) -const computedSystemDistribution = computed(() => { - if (facetDistribution.value?.type) { - return Object.entries(facetDistribution.value.type).map(([key, value]) => { - return { type: key, count: value } - }).sort() - } else { return [] } - -}) - -const computedTaxonomyDistribution = computed(() => { - if (facetDistribution.value?.[selectedTaxoRank.value]) { - return Object.entries(facetDistribution.value[selectedTaxoRank.value]).map(([key, value]) => { - return { [selectedTaxoRank.value]: key, count: value } - }).sort() - } else { return [] } - -}) - - -const computedHeaders = computed(() => { - return [...prependHeaders.value, ...availableTaxo.value.map(taxo => { - return { - title: capitalize(taxo), - key: taxo - } - }), ...appendHeaders.value] -}) - - -function itemToFilter(item, key) { - const value = item[key] - const filterToAdd = /\s/g.test(value) ? `${key}="${value}"` : `${key}=${value}` - return filter.value === '' ? filterToAdd : `${filter.value} AND ${filterToAdd}` -} - - -const itemFilterKeys = computed(() => { - return [...availableTaxo.value, 'type', 'subtype'] -}) -const defaultBarPlotOptions = computed(() => { - return { - x: { label: null, tickRotate: 70 }, - y: { nice: true, grid: true }, - color: { legend: true }, - width: computedWidth.value, - height: plotHeight.value, - } -}) -const computedDistriSystemOptions = computed(() => { - return { - ...defaultBarPlotOptions.value, - marginBottom: 120, - marks: [ - // Plot.frame(), - Plot.barY( - toValue(computedSystemDistribution), - { - y: "count", x: 'type', tip: true, - fill: "#6750a4", - sort: { x: "-y" }, - }, - - ), - ], - }; -}); - -const computedDistriTaxoOptions = computed(() => { - return { - ...defaultBarPlotOptions.value, - marginBottom: 200, - marks: [ - Plot.barY( - toValue(computedTaxonomyDistribution), - { - y: "count", - x: selectedTaxoRank.value, - tip: true, - fill: "#6750a4", - sort: { x: "-y" }, - } - ), - ], - }; -}); -// const datatable = ref(null) -const hasToGenerateDownload = ref(false) -let itemsToDownload = ref([]) - -watch(hasToGenerateDownload, (val) => { - console.log(val) - if (val === true) { - const { hits: items, pending, totalHits: itemsLength, filterError, facetDistribution } = useFetchMsDocument("refseq", search, filter, limit, hitsPerPage, page, facets) - itemsToDownload.value = items.value - } -}) -</script> - -<template> - <v-card flat> - <v-toolbar color="primary" density="compact"> - <v-app-bar-nav-icon></v-app-bar-nav-icon> - <v-toolbar-title>RefSeq Entries ({{ itemsLength }}) - </v-toolbar-title> - <JsonCSV :data="itemsToDownload" name="refseq-defenes-system.csv"> - <v-btn disabled icon @click="hasToGenerateDownload = true"> - <v-icon icon="md:download"></v-icon> - <v-tooltip activator="parent" location="bottom">Download {{ itemsLength }} entries</v-tooltip> - </v-btn> - </JsonCSV> - </v-toolbar> - <!-- </template> --> - <v-card-text> - - Tu peux mettre du texte ici - - </v-card-text> - <v-col> - <v-text-field v-model="search" prepend-inner-icon="mdi-magnify" label="Search for defense systems" hide-details - class="mx-2 mb-1" clearable></v-text-field> - - </v-col> - <v-col class="pt-1"> - Examples: <v-chip color="primary" @click="search = 'RADAR'">RADAR</v-chip> <v-chip color="primary" - @click="search = 'BREX'">BREX</v-chip> - </v-col> - <v-col cols="auto"> - <v-text-field v-model="filter" prepend-inner-icon="mdi-magnify" label="Filter" hide-details="auto" class="mx-2" - clearable :error-messages="filterError"></v-text-field></v-col> - <v-data-table-server v-model:page="page" v-model:items-per-page="hitsPerPage" v-model:sortBy="sortBy" fixed-header - :loading="pending" :headers="computedHeaders" :items="items" :items-length="itemsLength" :item-value="itemValue" - multi-sort density="compact" :height="computedTableHeight" class="elevation-1 mt-2"> - <template #[`item.${key}`]="{ item }" v-for="key in itemFilterKeys" :key="key"> - <v-chip @click="filter = itemToFilter(item, key)">{{ item[key] }}</v-chip> - </template> - <template #[`item.accession_in_sys`]="{ item }"> - <accession-chips :accessions="item.accession_in_sys" baseUrl="http://toto.pasteur.cloud"></accession-chips> - </template> - </v-data-table-server> - - </v-card> - <v-card flat class="my-3" :loading="pending"> - <v-card-title> Systems Distribution</v-card-title> - - <v-card-text> - <PlotFigure :options="unref(computedDistriSystemOptions)" defer></PlotFigure> - </v-card-text> - </v-card> - <v-card flat :loading="pending"> - <v-card-title> Taxonomic Distribution</v-card-title> - <v-card-text> - <v-select v-model="selectedTaxoRank" :items="availableTaxo" density="compact" - label="Select taxonomic rank"></v-select> - <PlotFigure defer :options="unref(computedDistriTaxoOptions)"></PlotFigure> - </v-card-text> - </v-card> -</template> \ No newline at end of file diff --git a/stores/articles.ts b/stores/articles.ts index b737ad7dd6af04377eeb6d1bd0ffbe8d6cb78c30..1ba95fd2d0584f76814bd6818b4ab794bf0f534a 100644 --- a/stores/articles.ts +++ b/stores/articles.ts @@ -1,19 +1,19 @@ import { defineStore } from 'pinia' import { ref } from 'vue' - +// import jsonArticles from '@/assets/articles.json' export interface CslJson { - id: string + // id: string type: string title: string "container-title": string - page: string, - volume: string, + // page: string, + // volume: string, abstract: string - URL: string + // URL: string DOI: string - journalAbbreviation: string - language: string + // journalAbbreviation: string + // language: string author: Array<{ family: string, given: string }> issued: { "date-parts": Array<string> @@ -21,12 +21,15 @@ export interface CslJson { } export const useArticlesStore = defineStore('articles', () => { - const articles = ref(new Map<string, CslJson>()) + const articleMap = new Map([]) + const articles = ref(articleMap) function add(article: CslJson) { const doi = article.DOI if (articles.value.has(doi)) return articles.value.set(article.DOI, article) } + + return { articles, add } }) \ No newline at end of file diff --git a/stores/facets.ts b/stores/facets.ts index 4efeb6bfb1f557b25d13f2ded3582bc4f76f3c3c..40a320d2e9b6d2905843e44b3c8c59c28fbd9404 100644 --- a/stores/facets.ts +++ b/stores/facets.ts @@ -14,7 +14,10 @@ export const useFacetsStore = defineStore('facets', () => { function setFacets(newFacets: Facets) { + console.log("start set facets") + console.log(newFacets) facets.value = newFacets + console.log("end set facets") }