Skip to content
Snippets Groups Projects
useFetchArticle.ts 3.79 KiB
import { useArticlesStore } from '@/stores/articles'
import { ref, computed, watchEffect, queryContent } from '#imports'

import { CslJson } from '@/stores/articles'

export interface ArticleMessage {
    DOI: string;
    issue: number;
    title: string | string[];
    author: Array<{ family: string; given: string }>;
    "container-title-short": string;
    "container-title": string;
    abstract: string;
    published: {
        "date-parts": string[];
    };
    issued: {
        "date-parts": string[];
    };
}



export interface Article {
    DOI: string
    title: string
    subtitle: string
    containerTitle: string
    abstract: string
    year: string
    href: string
    target: string
    prependIcon: string
}
export interface RawArticle {
    message: ArticleMessage

}

type SrcArticle = ArticleMessage | CslJson

export function useFetchArticle(doi: string) {
    // 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 {
                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
            return {
                DOI,
                title: sanitizedTitle,
                subtitle: toAuthorsString(author || []),
                containerTitle: sanitizedContainerTitle,
                abstract: sanitizedAbstract,
                year: published?.["date-parts"][0][0] ?? issued?.["date-parts"][0][0] ?? '',
                href: getReferenceUrl(DOI),
                target: "_blank",
                prependIcon: "mdi-newspaper-variant-outline",
            }

        } else { return srcArticle.value }
    })

    watchEffect(async () => {

        if (store.articles.size === 0) {
            const localArticles = await queryContent('/_partials/_articles').where({ _partial: true }).findOne()
            if (localArticles?.articles && store.articles.size <= 0) {
                for (const article of localArticles.articles) {
                    store.add(article)
                }
            }
        }

        if (store.articles.has(doi)) {
            srcArticle.value = store.articles.get(doi)
            return
        } else {
            const { data, pending: pendingUseFetch, error, refresh } = await useFetch<RawArticle>(toValue(url), {
                lazy: true, server: false,
            })
            if (data.value?.message) {
                srcArticle.value = data.value.message
            }
            pending.value = pendingUseFetch.value
        }

    })
    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;
    }
    return { article, pending }
}