mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-29 07:53:27 -04:00
174 lines
4.8 KiB
Vue
174 lines
4.8 KiB
Vue
<script setup lang="ts">
|
|
import Columnist from 'avris-columnist';
|
|
import { useNuxtApp, useRoute } from 'nuxt/app';
|
|
import { computed, ref } from 'vue';
|
|
|
|
import useConfig from '~/composables/useConfig.ts';
|
|
import useSimpleHead from '~/composables/useSimpleHead.ts';
|
|
import parseMarkdown from '~/src/parseMarkdown.ts';
|
|
import type { MarkdownInfo } from '~/src/parseMarkdown.ts';
|
|
|
|
definePageMeta({
|
|
translatedPaths: (config) => {
|
|
if (!config.links.enabled || !config.links.blog) {
|
|
return [];
|
|
}
|
|
const shortcuts = Object.entries(config.blog?.shortcuts ?? {})
|
|
.filter(([_shortcut, slug]) => !(config.blog?.keepFullPath ?? []).includes(slug))
|
|
.map(([shortcut, slug]) => {
|
|
const shortcutRoute = { paths: [`/${encodeURIComponent(shortcut)}`], meta: { slug } };
|
|
return [`blogEntryShortcut:${shortcut}`, shortcutRoute] as const;
|
|
});
|
|
return {
|
|
blogEntry: { paths: [`/${encodeURIComponent(config.links.blogRoute)}/:slug`] },
|
|
...Object.fromEntries(shortcuts),
|
|
};
|
|
},
|
|
});
|
|
|
|
const { $translator: translator, $loadScript: loadScript } = useNuxtApp();
|
|
const route = useRoute();
|
|
const slug = (route.params.slug ?? route.meta.slug) as string;
|
|
|
|
const blogEntry = ref<MarkdownInfo>({ title: null, img: null, intro: null, content: null });
|
|
|
|
const title = computed(() => blogEntry.value.title);
|
|
|
|
const banner = computed(() => blogEntry.value.img);
|
|
const description = computed(() => blogEntry.value.intro);
|
|
const content = computed(() => blogEntry.value.content);
|
|
|
|
useSimpleHead({
|
|
title,
|
|
description,
|
|
banner,
|
|
}, translator);
|
|
|
|
const post = useTemplateRef<HTMLDivElement>('post');
|
|
|
|
try {
|
|
const markdown = (await import(`~/data/blog/${slug}.md`)).default;
|
|
blogEntry.value = await parseMarkdown(markdown, translator);
|
|
} catch (error) {
|
|
// import failed
|
|
}
|
|
|
|
const config = useConfig();
|
|
|
|
onMounted(async () => {
|
|
if (!content.value) {
|
|
return;
|
|
}
|
|
if (content.value.includes('twitter-tweet')) {
|
|
await loadScript('twitter', 'https://platform.twitter.com/widgets.js');
|
|
}
|
|
|
|
if (content.value.includes('fb-post')) {
|
|
const divElement = document.createElement('div');
|
|
divElement.id = 'fb-root';
|
|
document.body.appendChild(divElement);
|
|
|
|
await loadScript('facebook', 'https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v19.0', 'xwbrn1J4');
|
|
}
|
|
|
|
for (const wall of post.value?.querySelectorAll('.columnist-wall') ?? []) {
|
|
const columnist = new Columnist(wall);
|
|
columnist.start();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Page>
|
|
<NotFound v-if="!content" />
|
|
<div v-else ref="post" class="blog-post">
|
|
<p v-if="!config.links.split">
|
|
<nuxt-link v-if="config.links.blog" :to="{ name: 'blog' }">
|
|
<Icon v="pen-nib" />
|
|
<T>links.blog</T>
|
|
</nuxt-link>
|
|
</p>
|
|
|
|
<AdPlaceholder :phkey="['content-0', 'content-mobile-0']" />
|
|
|
|
<Spelling :text="content" />
|
|
|
|
<AdPlaceholder :phkey="['content-1', 'content-mobile-1']" />
|
|
|
|
<div class="d-print-none">
|
|
<Separator icon="heart" />
|
|
<BlogReactionSection :slug="slug" />
|
|
<section>
|
|
<Share :title="title ?? undefined" />
|
|
</section>
|
|
<Support />
|
|
</div>
|
|
</div>
|
|
</Page>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
@import "assets/variables";
|
|
|
|
.blog-post {
|
|
hyphens: auto;
|
|
text-align: justify;
|
|
|
|
h1 {
|
|
text-align: left;
|
|
}
|
|
|
|
img {
|
|
max-width: 100%;
|
|
}
|
|
|
|
figure {
|
|
width: 100%;
|
|
max-width: 24rem;
|
|
padding: $spacer;
|
|
img {
|
|
width: 100%;
|
|
}
|
|
figcaption {
|
|
margin-top: $spacer / 2;
|
|
font-size: $small-font-size;
|
|
}
|
|
}
|
|
|
|
.forms-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(18rem, 3fr));
|
|
grid-gap: $spacer;
|
|
justify-items: center;
|
|
figure {
|
|
padding: 0;
|
|
figcaption {
|
|
font-size: 90%;
|
|
}
|
|
}
|
|
}
|
|
|
|
hr {
|
|
border: none;
|
|
border-top: 3px solid $primary;
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.columnist-wall > .columnist-column {
|
|
transition: margin-top .2s ease-in-out;
|
|
}
|
|
|
|
.spoiler {
|
|
background-color: $dark;
|
|
color: $dark;
|
|
padding: map-get($spacers, 1);
|
|
border-radius: $border-radius;
|
|
cursor: pointer;
|
|
transition: background-color .2s ease-in-out;
|
|
&:hover {
|
|
background-color: $light;
|
|
}
|
|
}
|
|
</style>
|