diff --git a/components/content/ArticleDoiList.vue b/components/content/ArticleDoiList.vue index fe7727a672fbe67a3741e520b42d97b36550dc03..357e90ee40bc9dc5a3ac068918d372e8a3091926 100644 --- a/components/content/ArticleDoiList.vue +++ b/components/content/ArticleDoiList.vue @@ -1,11 +1,25 @@ <script setup lang="ts"> -const props = defineProps<{ - items: { doi: string, title?: string, divider: boolean, abstract?: string }[]; -}>(); +import ProseH2 from '~/components/content/ProseH2' +// const props = defineProps<{ +// items: { doi: string; title?: string; divider: boolean; abstract?: string }[]; +// }>(); + +const { page } = useContent(); +const computedDois = computed(() => { + if (page.value?.relevantAbstracts) { + return page.value.relevantAbstracts; + } else { + return []; + } +}); </script> <template> + <div v-if="computedDois?.length > 0"> + <ProseH2 id="relevant-abstracts">Relevant abstracts</ProseH2> + <v-list density="compact"> - <ArticleDoi v-for="item, index in props.items" :key="item.doi" :index="index + 1" :doi="item.doi" - :title="item?.title" :divider="item.divider" :abstract="item?.abstract" /> + <ArticleDoi v-for="(item, index) in computedDois" :key="item.doi" :index="index + 1" :doi="item.doi" + :title="item?.title" :divider="item.divider" :abstract="item?.abstract" /> </v-list> + </div> </template> \ No newline at end of file diff --git a/components/content/Contributors.vue b/components/content/Contributors.vue index 5c173d624212826b6e80db4755ee37639d1178ae..e79060863111661627017e26de255e35f3a2cc70 100644 --- a/components/content/Contributors.vue +++ b/components/content/Contributors.vue @@ -9,6 +9,6 @@ const contributorsString = computed(() => { </script> <template> - <div v-if="contributorsString" class="mt-n6 mb-6 text-subtitle-1 text-info">Contributors: {{ contributorsString }} + <div v-if="contributorsString" class="mt-n5 mb-6 text-subtitle-1 text-info">Contributors: {{ contributorsString }} </div> </template> \ No newline at end of file diff --git a/components/content/Ref.vue b/components/content/Ref.vue index 7031d3aefea6ec7d43376f37a1ddc9f92be269e3..006afc08445f05b49419d17bac3dc15f0df40cac 100644 --- a/components/content/Ref.vue +++ b/components/content/Ref.vue @@ -1,13 +1,17 @@ <script setup lang="ts"> - export interface Props { - doi: string; + doi: string; } const props = withDefaults(defineProps<Props>(), {}); const { article } = useFetchArticle(props.doi); </script> <template> - <v-chip variant="text" :href="`#${props.doi}`" class="pa-0 text-caption font-italic">({{ article?.author[0]?.family ?? 'test' }} et al, {{ - article.year - }})</v-chip> + <v-chip + v-if="article" + variant="text" + :href="`#${props.doi}`" + class="pa-0 text-caption font-italic" + >({{ article?.author[0]?.family ?? "test" }} et al, + {{ article?.year }})</v-chip + > </template> \ No newline at end of file diff --git a/content/3.defense-systems/abi2.md b/content/3.defense-systems/abi2.md index 808a7367c8c6f20bb252a410e57a5cec2b8d6a54..ee06af707f5751426dea7d9d69e2e96560ee7f21 100644 --- a/content/3.defense-systems/abi2.md +++ b/content/3.defense-systems/abi2.md @@ -9,6 +9,8 @@ tableColumns: Activator: '' Effector: '' PFAM: PF07751 +relevantAbstracts: + - doi: 10.1016/j.mib.2005.06.006 --- # Abi2 @@ -31,6 +33,3 @@ Among the 22k complete genomes of RefSeq, this system is present in 1210 genomes *Proportion of genome encoding the Abi2 system for the 14 phyla with more than 50 genomes in the RefSeq database.* -## Relevant abstracts - - diff --git a/content/3.defense-systems/abia.md b/content/3.defense-systems/abia.md index 912ea20db0b48724cc3d72306c6071bd0671ad41..3de86ab7e5ceebfb8521761e72cdbcdba832ccd7 100644 --- a/content/3.defense-systems/abia.md +++ b/content/3.defense-systems/abia.md @@ -9,9 +9,14 @@ tableColumns: Activator: Unknown Effector: Unknown PFAM: PF00078, PF18160, PF18732 +relevantAbstracts: + - doi: 10.1023/A:1002027321171 + - doi: 10.1016/j.mib.2005.06.006 + - doi: 10.1093/nar/gkac467 --- # AbiA + The AbiA system have been describe in a total of 2 subsystems. Here is some example found in the RefSeq database: @@ -69,14 +74,5 @@ AbiA systems were experimentally validated using: A system from *lactococcal plasmid* in *lactococci* has an anti-phage effect against 936, c2, P335 (Chopin et al., 2005) -## Relevant abstracts -::article-doi-list ---- -items: - - doi: 10.1023/A:1002027321171 - - doi: 10.1016/j.mib.2005.06.006 - - doi: 10.1093/nar/gkac467 ---- -:: diff --git a/content/3.defense-systems/detocs.md b/content/3.defense-systems/detocs.md index b715ca6408329a016b39d8cb29c7cd92d0152a84..40a0c168a451db0bf9fc1a75943956c544594c46 100644 --- a/content/3.defense-systems/detocs.md +++ b/content/3.defense-systems/detocs.md @@ -6,6 +6,8 @@ tableColumns: abstract: | During viral infection, cells can deploy immune strategies that deprive viruses of molecules essential for their replication. Here, we report a family of immune effectors in bacteria that, upon phage infection, degrade cellular adenosine triphosphate (ATP) and deoxyadenosine triphosphate (dATP) by cleaving the N-glycosidic bond between the adenine and sugar moieties. These ATP nucleosidase effectors are widely distributed within multiple bacterial defense systems, including cyclic oligonucleotide-based antiviral signaling systems (CBASS), prokaryotic argonautes, and nucleotide-binding leucine-rich repeat (NLR)-like proteins, and we show that ATP and dATP degradation during infection halts phage propagation. By analyzing homologs of the immune ATP nucleosidase domain, we discover and characterize Detocs, a family of bacterial defense systems with a two-component phosphotransfer-signaling architecture. The immune ATP nucleosidase domain is also encoded within diverse eukaryotic proteins with immune-like architectures, and we show biochemically that eukaryotic homologs preserve the ATP nucleosidase activity. Our findings suggest that ATP and dATP degradation is a cell-autonomous innate immune strategy conserved across the tree of life. PFAM: PF01048, PF18742 +relevantAbstracts: + - doi: 10.1016/j.cell.2023.07.020 contributors: - François Rousset --- @@ -14,6 +16,7 @@ contributors: # Detocs ## Description + Detocs (**De**fensive **T**w**o**-**C**omponent **S**ystem) is a family of 3-gene defense systems that mediate anti-phage activity by abortive infection. ## Molecular mechanism @@ -83,16 +86,3 @@ dataUrl: /detocs/Detocs_hydrolase__dtcC-plddts_89.47253.pdb --- :: -## Relevant abstract -::article-doi-list ---- -items: - - doi: 10.1016/j.cell.2023.07.020 - ---- -:: - - -## References - -Rousset et al., A conserved family of immune effectors cleaves cellular ATP upon viral infection. Cell 186, 1–13 (2023). https://doi.org/10.1016/j.cell.2023.07.020 diff --git a/server/plugins/content.ts b/server/plugins/content.ts index 0f843c65913eb850e528d7653738a8deb4ca9e55..19dad94f6b91ee1e41275d3b50c32c772861a4b7 100644 --- a/server/plugins/content.ts +++ b/server/plugins/content.ts @@ -4,34 +4,44 @@ export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('content:file:beforeParse', (file) => { if (file?._id?.startsWith('content:3.defense-systems:') && file?._id?.endsWith('.md')) { - const regexp = /(?<=---\n).*?(?=\n---)/sg; - const match = file.body.match(regexp); - const frontMatter = match[0] - const parsedFrontMatter = YAML.parse(frontMatter) - if (parsedFrontMatter?.contributors?.length > 0) { - file.body = file.body.replace(/(^#[\s+]\w*[\s\S])/gm, "$1:contributors\n\n") + const frontMatterRegex = /(?<=---\n).*?(?=\n---)/sg; + + const fontMatterMatch = file.body.match(frontMatterRegex); + if (fontMatterMatch?.length > 0) { + const frontMatter = fontMatterMatch[0] + const parsedFrontMatter = YAML.parse(frontMatter) + if (parsedFrontMatter?.contributors?.length > 0) { + file.body = file.body.replace(/(^#[\s+]\w*[\s\S])/gm, "$1\n:contributors\n\n") + } + // try to look at :ref{doi=xxxx} + const matchRef = file.body.match(/(?<=:ref{doi=).*(?=})/gm) + if (matchRef?.length > 0) { + if (parsedFrontMatter?.relevantAbstracts) { + const relevantAbstractsSet = new Set(parsedFrontMatter.relevantAbstracts.map(({ doi }: { doi: string }) => doi)) + const filteredMatchRef = matchRef.filter((doi: string) => !relevantAbstractsSet.has(doi)) + parsedFrontMatter.relevantAbstracts = [...parsedFrontMatter.relevantAbstracts, ...filteredMatchRef.map((doi: string) => ({ doi }))] + } else { + parsedFrontMatter.relevantAbstracts = matchRef.map((doi: string) => ({ doi })) + } + const newFrontMatterStr = YAML.stringify(parsedFrontMatter) + file.body = file.body.replace(/---\n(.*?)\n---/gs, `---\n${newFrontMatterStr}\n---`) + } } } }) - // nitroApp.hooks.hook( - // 'content:file:afterParse', - // (file) => { - // if (file._id.endsWith('.md')) { - - // file.body.children.push({ - // type: "element", - // tag: 'article-doi-list', - // props: { - // items: [ - // { doi: '10.1016/j.mib.2005.06.006' }, - // { doi: '10.1016/j.mib.2005.06.006' }] - // }, - // children: [] - // }) - - // } - // }) + nitroApp.hooks.hook( + 'content:file:afterParse', + (file) => { + if (file?._id?.startsWith('content:3.defense-systems:') && file._id.endsWith('.md')) { + file.body.children.push({ + type: "element", + tag: 'article-doi-list', + props: {}, + children: [] + }) + } + }) }) \ No newline at end of file