mirror of
https://github.com/sergeyyarkov/yarkov.tech.git
synced 2026-10-11 10:29:21 +03:00
fixes
This commit is contained in:
parent
d40d8bb730
commit
35806aa60d
43
directus.ts
43
directus.ts
@ -1,9 +1,50 @@
|
||||
import { createDirectus, graphql, staticToken } from "@directus/sdk";
|
||||
import { DIRECTUS_TOKEN, DIRECTUS_URL } from "astro:env/server";
|
||||
import type { Schema } from "./directus-schema";
|
||||
import type { ArticleTranslation, Schema } from "./directus-schema";
|
||||
|
||||
const directus = createDirectus<Schema>(DIRECTUS_URL)
|
||||
.with(staticToken(DIRECTUS_TOKEN))
|
||||
.with(graphql());
|
||||
|
||||
export async function fetchArticleBySlug(slug: string): Promise<ArticleTranslation | null> {
|
||||
const data = await directus.query<{ article_translations: ArticleTranslation[] }>(`
|
||||
query Article_translations {
|
||||
article_translations(
|
||||
filter: {
|
||||
slug: {
|
||||
_eq: "${slug}"
|
||||
}
|
||||
}
|
||||
) {
|
||||
title
|
||||
tags {
|
||||
tag_id {
|
||||
title
|
||||
}
|
||||
}
|
||||
description
|
||||
slug
|
||||
content
|
||||
author {
|
||||
first_name
|
||||
last_name
|
||||
}
|
||||
pub_date
|
||||
views
|
||||
languages_code {
|
||||
code
|
||||
}
|
||||
cover_image {
|
||||
title
|
||||
filename_disk
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
if (data.article_translations.length === 0) return null;
|
||||
|
||||
return data.article_translations[0];
|
||||
}
|
||||
|
||||
export default directus;
|
||||
|
||||
2226
package-lock.json
generated
2226
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -19,49 +19,51 @@ export type Props = {
|
||||
const { article, availableOnLangs } = Astro.props as Props;
|
||||
const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
|
||||
const { id, cover_image, title, author, description, tags, pub_date, slug } = article;
|
||||
|
||||
const { cover_image, title, author, description, tags, pub_date, slug, views } = article;
|
||||
const t = useTranslation(Astro);
|
||||
---
|
||||
|
||||
<article itemscope itemtype="http://schema.org/BlogPosting" class="article">
|
||||
<article itemscope itemtype='http://schema.org/BlogPosting' class='article'>
|
||||
<header>
|
||||
<div>
|
||||
{
|
||||
tags && (
|
||||
<div class="tags">
|
||||
<ul itemprop="keywords">
|
||||
{tags.map((tag) => (
|
||||
<li>
|
||||
<TranslatedLink rel="tag" to={`/articles/?tags=${tag}`}>
|
||||
{tag}
|
||||
</TranslatedLink>
|
||||
</li>
|
||||
))}
|
||||
<div class='tags'>
|
||||
<ul itemprop='keywords'>
|
||||
{tags.map(
|
||||
(tag) =>
|
||||
typeof tag === "object" && (
|
||||
<li>
|
||||
<TranslatedLink rel='tag' to={`/articles/?tags=${tag.tag_id.title}`}>
|
||||
{tag.tag_id.title}
|
||||
</TranslatedLink>
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class="views">
|
||||
<Icon name="eye" width="21" height="21" />
|
||||
<span><span id="views">---</span> {t("article.views")}</span>
|
||||
<div class='views'>
|
||||
<Icon name='eye' width='21' height='21' />
|
||||
<span><span>{views}</span> {t("article.views")}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="heading">
|
||||
<h1 itemprop="headline">{title}</h1>
|
||||
<div class='heading'>
|
||||
<h1 itemprop='headline'>{title}</h1>
|
||||
</div>
|
||||
<div class="published">
|
||||
<time itemprop="datePublished" datetime={pub_date}>
|
||||
<div class='published'>
|
||||
<time itemprop='datePublished' datetime={pub_date}>
|
||||
{createDateFormatter(pageLang).format(new Date(pub_date))}
|
||||
</time>
|
||||
<span itemprop="author">{author}</span>
|
||||
<span itemprop='author'>{`${author.first_name} ${author.last_name}`}</span>
|
||||
</div>
|
||||
{
|
||||
cover_image && (
|
||||
<ArticleCover src={`${DIRECTUS_URL}/assets/${cover_image.filename_disk}`} alt={title} />
|
||||
)
|
||||
}
|
||||
<div class="description">
|
||||
<div class='description'>
|
||||
<p>
|
||||
{description}
|
||||
</p>
|
||||
@ -72,19 +74,7 @@ const t = useTranslation(Astro);
|
||||
<ArticleComments url={canonicalUrl.href} id={slug} />
|
||||
</article>
|
||||
|
||||
<script define:vars={{ slug, IS_DEV: import.meta.env.DEV }}>
|
||||
(async () => {
|
||||
if (IS_DEV) return;
|
||||
const response = await fetch(`/api/views?slug=${slug}`, { method: "POST" });
|
||||
if (!response.ok) return;
|
||||
const views = await response.text();
|
||||
const $views = document.getElementById("views");
|
||||
if (isNaN(parseInt(views, 10))) return;
|
||||
if ($views) $views.textContent = views;
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style lang="scss" is:global>
|
||||
<style lang='scss' is:global>
|
||||
.article {
|
||||
& header {
|
||||
& div:nth-child(1) {
|
||||
|
||||
@ -19,7 +19,7 @@ export interface Props {
|
||||
}
|
||||
|
||||
const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
|
||||
const { lang = DEFAULT_LANGUAGE, article, headings, availableOnLangs } = Astro.props as Props;
|
||||
const { lang = DEFAULT_LANGUAGE, article, availableOnLangs } = Astro.props as Props;
|
||||
const { title, description, cover_image, content } = article;
|
||||
const htmlContent = await utils.markdownToHTML(content);
|
||||
---
|
||||
@ -30,19 +30,18 @@ const htmlContent = await utils.markdownToHTML(content);
|
||||
title={title}
|
||||
siteName={SITE_METADATA.name}
|
||||
description={description}
|
||||
type="article"
|
||||
type='article'
|
||||
url={canonicalUrl.href}
|
||||
image={cover_image
|
||||
? { path: cover_image.filename_disk, width: "700", height: "400", type: cover_image.type }
|
||||
: undefined}
|
||||
/>
|
||||
<script is:inline defer src="/assets/js/load-code-highlight.js"></script>
|
||||
<script is:inline defer src='/assets/js/load-code-highlight.js'></script>
|
||||
</BaseHead>
|
||||
|
||||
<BaseLayout>
|
||||
<div class="container">
|
||||
<div class='container'>
|
||||
<ArticlePost lang={lang} article={article} availableOnLangs={availableOnLangs}>
|
||||
<!-- <TableOfContents headings={headings} /> -->
|
||||
<ArticleContent set:html={htmlContent} />
|
||||
</ArticlePost>
|
||||
</div>
|
||||
|
||||
15
src/pages/[blog]/[...path].astro
Normal file
15
src/pages/[blog]/[...path].astro
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
import ArticleLayout from "@root/layouts/article.astro";
|
||||
import { fetchArticleBySlug } from "@/directus";
|
||||
|
||||
const { path } = Astro.params as { blog: string; path: string };
|
||||
const slug = path.split("/").at(-1);
|
||||
|
||||
if (!slug) return Astro.redirect("/404");
|
||||
|
||||
const article = await fetchArticleBySlug(slug);
|
||||
|
||||
if (!article) return Astro.redirect("/404");
|
||||
---
|
||||
|
||||
<ArticleLayout lang={article.languages_code.code} article={article} />
|
||||
@ -1,91 +0,0 @@
|
||||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { getCollection, getEntry, render } from "astro:content";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import ArticleLayout from "@root/layouts/article.astro";
|
||||
import { createRelativeArticleUrl, removeLanguageCodeFromPath } from "@root/utils";
|
||||
import directus from "@/directus";
|
||||
import type { ArticleTranslation } from "@/directus-schema";
|
||||
|
||||
/**
|
||||
* Generate articles pages from `blog` collection.
|
||||
* The final url will be `http://website.com/blog/2023-01-01/my-article` with default language
|
||||
* and `http://website.com/{language-code}/blog/2023-01-01/my-article` with other languages.
|
||||
*/
|
||||
// export async function getStaticPaths() {
|
||||
// const collection = await getCollection("blog", (e) => !e.data.draft);
|
||||
// return collection.map((article) => {
|
||||
// const {
|
||||
// id,
|
||||
// data: { title, pubDate },
|
||||
// } = article;
|
||||
// const url = createRelativeArticleUrl({ id, title, pubDate });
|
||||
// return {
|
||||
// params: { blog: url.slice(1) },
|
||||
// props: {
|
||||
// article,
|
||||
// availableOnLangs: collection.filter((e) =>
|
||||
// e.id.includes(removeLanguageCodeFromPath(article.id))
|
||||
// ),
|
||||
// },
|
||||
// };
|
||||
// });
|
||||
// }
|
||||
|
||||
type Props = { article: CollectionEntry<"blog">; availableOnLangs: CollectionEntry<"blog">[] };
|
||||
|
||||
const { slug } = Astro.params as { blog: string; date: string; slug: string };
|
||||
|
||||
const { article_translations: data } = await directus.query<{
|
||||
article_translations: ArticleTranslation[];
|
||||
}>(`
|
||||
query Article_translations {
|
||||
article_translations(
|
||||
filter: {
|
||||
slug: {
|
||||
_eq: "${slug}"
|
||||
}
|
||||
}
|
||||
) {
|
||||
title
|
||||
tags {
|
||||
tag_id {
|
||||
title
|
||||
}
|
||||
}
|
||||
description
|
||||
slug
|
||||
content
|
||||
author {
|
||||
first_name
|
||||
last_name
|
||||
}
|
||||
pub_date
|
||||
views
|
||||
languages_code {
|
||||
code
|
||||
}
|
||||
cover_image {
|
||||
title
|
||||
filename_disk
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
// const { blog } = Astro.params as { blog: string };
|
||||
// const collection = await getCollection("blog", (e) => !e.data.draft);
|
||||
// const slug = blog.split("/").at(-1);
|
||||
// const article = collection.find(
|
||||
// (a) => slugify(a.slug.split("/").at(-1) || "", { lowercase: true }) === slug
|
||||
// );
|
||||
|
||||
if (data.length === 0) return Astro.redirect("/404");
|
||||
|
||||
const article = data[0];
|
||||
|
||||
// const { Content, headings } = await render(article);
|
||||
// const { article, availableOnLangs } = Astro.props;
|
||||
---
|
||||
|
||||
<ArticleLayout lang={article.languages_code.code} article={article} />
|
||||
@ -65,10 +65,6 @@ export function formatToArticleBlocks(articles: CollectionEntry<"blog">[]) {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
export function getUniqueTags(articles: CollectionEntry<"blog">[]): string[] {
|
||||
return Array.from(new Set(articles.map((a) => a.data.tags).flat()));
|
||||
}
|
||||
|
||||
export type MarkdownHeadingToc = MarkdownHeading & { subheadings?: MarkdownHeading[] };
|
||||
|
||||
export function buildToc(headings: MarkdownHeading[], maxDepth: number = 2) {
|
||||
@ -96,8 +92,8 @@ export async function markdownToHTML(content: string): Promise<string> {
|
||||
|
||||
const file = await unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkPrism)
|
||||
.use(remarkToc)
|
||||
.use(remarkToc, { heading: "(table[ -]of[ -])?contents?|toc|содержание", maxDepth: 2 })
|
||||
.use(remarkPrism as any)
|
||||
.use(remarkRehype)
|
||||
.use(rehypeSlug)
|
||||
.use(rehypeAutolinkHeadings, {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user