feat: added dynamin article page

This commit is contained in:
Sergey Yarkov 2022-08-01 01:30:50 +03:00
parent 73ee879952
commit d935483507
13 changed files with 74 additions and 111 deletions

View File

@ -1,5 +1,4 @@
import { defineConfig } from 'astro/config';
import solid from '@astrojs/solid-js';
// https://astro.build/config

View File

@ -6,7 +6,7 @@
if (window.theme) {
/* the {theme} in the path will be dynamically changed */
const PATH = `assets/css/code-highlight-{theme}.min.css`;
const PATH = `/assets/css/code-highlight-{theme}.min.css`;
const $head = document.getElementsByTagName('head')[0];
const getPath = (theme) => PATH.replace(`{theme}`, theme);
const createLink = (theme, media) => {

View File

@ -9,7 +9,7 @@ export type ArticleItemProps = {
export const ArticleItem: Component<ArticleItemProps> = (props) => {
return (
<article class="article-item">
<a href="#">
<a href={`/${new Date(props.data.published_at).toLocaleDateString('en-CA')}/${props.data.slug}`}>
<h3>{props.data.title}</h3>
<p>
<time datetime={props.data.published_at.toString()}>{DateFormatter.format(new Date(props.data.published_at))}</time>

View File

@ -16,7 +16,7 @@ const { title, tags, author, published_at } = data;
<ul class='list-links'>
{tags.map((tag) => (
<li>
<a class="btn-link" href={`/articles?tags=${tag}`}>
<a class="btn-link" href={`/articles?tags=${tag.toLocaleLowerCase()}`}>
{tag}
</a>
</li>
@ -32,10 +32,7 @@ const { title, tags, author, published_at } = data;
</div>
<div>
<figure>
<img
src='https://img.freepik.com/premium-photo/beautiful-emerald-lake-yoho-national-park-british-columbia-canada_131985-177.jpg?w=1920'
alt='Article Image'
/>
<img src='https://picsum.photos/1920/1080' alt='Article Image' />
</figure>
</div>
</header>

View File

@ -1,18 +1,17 @@
---
import { SITE_METADATA } from '@root/config';
import { SITE_METADATA } from '@root/config';
export interface Props {
export interface Props {
title?: string | undefined;
description?: string | undefined;
}
}
const { title = SITE_METADATA.title, description } = Astro.props as Props;
const { title = SITE_METADATA.title, description } = Astro.props as Props;
---
<link rel='preconnect' href='https://fonts.googleapis.com' />
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin />
<link href='https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap'
rel='stylesheet' />
<link href='https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap' rel='stylesheet' />
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1' />
@ -21,5 +20,5 @@
</title>
<meta name='title' content={title} />
<meta name='description' content={description || SITE_METADATA.description} />
<script is:inline src='assets/js/detect-theme.min.js' />
<script is:inline src='/assets/js/detect-theme.min.js' />
<slot></slot>

View File

@ -0,0 +1,17 @@
import type { Component } from 'solid-js';
import { createSignal, createEffect } from 'solid-js';
const Counter: Component = () => {
const [count, setCount] = createSignal<number>(0);
createEffect(() => {
setInterval(() => {
setCount(count() + 1);
}, 500);
});
return <div>{count()}</div>;
};
export default Counter;

View File

@ -0,0 +1 @@
export { default } from './Counter';

View File

@ -18,9 +18,7 @@ const { lang = 'ru', content } = Astro.props as Props;
<html lang={lang}>
<head>
<BaseHead title={content.title} description={content.description}>
<script is:inline defer src='assets/js/load-code-highlight.js'>
</script>
<script is:inline defer src='/assets/js/load-code-highlight.js' />
</BaseHead>
</head>

22
src/pages/[...slug].astro Normal file
View File

@ -0,0 +1,22 @@
---
import type { MarkdownInstance } from 'astro';
import ArticleLayout from '@root/layouts/article.astro';
// TODO: generate pages based on user language
export async function getStaticPaths() {
const data = await Astro.glob<ArticleType>('../../content/articles/**/*.md');
return data.map((article) => {
const published_at = new Date(article.frontmatter.published_at).toLocaleDateString('en-CA');
const slug = `${published_at}/${article.frontmatter.slug}`;
const props = { Content: article.Content, frontmatter: article.frontmatter };
return { params: { slug }, props };
});
}
const { Content, frontmatter: data } = Astro.props as MarkdownInstance<ArticleType>;
---
<ArticleLayout content={data}>
<Content />
</ArticleLayout>

View File

@ -1,80 +0,0 @@
---
import ArticleLayout from '@root/layouts/article.astro';
import { Markdown } from 'astro/components';
export function getStaticPaths() {
return [{ params: { article: 'article' } }];
}
---
<ArticleLayout
content={{
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
description: 'description1',
author: 'Sergey Yarkov',
tags: ['AVR', 'JavaScript', 'NodeJS'],
published_at: new Date().toISOString(),
}}
>
<Markdown>
## Introduction
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus.
Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus.
Maecenas eget condimentum velit, sit amet feugiat lectus. Class aptent taciti sociosqu ad litora torquent per
conubia nostra, per inceptos himenaeos. [Praesent auctor](#) purus luctus enim egestas, ac scelerisque ante
pulvinar.
Donec ut rhoncus ex. Suspendisse ac rhoncus nisl, eu tempor urna. Curabitur vel bibendum lorem. Morbi convallis
convallis diam sit amet [lacinia](#). Aliquam in elementum
Curabitur tempor quis eros tempus lacinia. Nam bibendum pellentesque quam a convallis. Sed ut vulputate nisi.
Integer in felis sed leo vestibulum venenatis. Suspendisse quis arcu sem. Aenean feugiat ex eu vestibulum
vestibulum. Morbi a eleifend magna. Nam metus lacus, porttitor eu mauris a, blandit ultrices nibh. Mauris sit
amet magna non ligula vestibulum eleifend. Nulla varius volutpat turpis sed lacinia. Nam eget mi in purus
lobortis eleifend. Sed nec ante dictum sem condimentum ullamcorper quis venenatis nisi. Proin vitae facilisis
nisi, ac posuere leo.
### Another Heading
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus.
Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus.
- `Nam metus lacus`: porttitor eu mauris a, [blandit ultrices](#) nibh.
- `Class aptent`: taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
- `Sed nec ante`: dictum sem condimentum [ullamcorper quis](#) venenatis nisi.
```typescript
import type { APIContext } from 'astro';
export async function get({ params, request }: APIContext) {
return {
body: JSON.stringify({
path: new URL(request.url).pathname,
}),
};
}
```
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus.
Sed dignissim.
<figure>
<img src="https://wallpaperaccess.com/full/138733.jpg" alt="test" />
<figcaption>This is a test image!</figcaption>
</figure>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis
tellus.
Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed
risus.
</p>
<p>— <a href="#">Metus Nec</a></p>
</blockquote>
## Conclusion
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus.
Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus.
</Markdown>
</ArticleLayout>

View File

@ -1,16 +1,24 @@
---
import PageLayout from '@layouts/default.astro';
import ArticlesList from '@components/ArticlesList';
import { transformArticles, formatToArticleBlocks } from '@utils/articles';
import PageLayout from '@layouts/default.astro';
import ArticlesList from '@components/ArticlesList';
import { transformArticles, formatToArticleBlocks } from '@utils/articles';
const articles = await Astro.glob<ArticleType>('../../content/articles/**/*.md');
const tags = new Set(articles.map((article) => article.frontmatter.tags).flat());
const articles = await Astro.glob<ArticleType>('../../content/articles/**/*.md');
const tags = new Set(articles.map((article) => article.frontmatter.tags).flat());
---
<PageLayout title='Статьи'
description='Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.'>
<PageLayout
title='Статьи'
description='Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.'
>
<section>
<ArticlesList client:load data={{ articles: formatToArticleBlocks(transformArticles(articles)), tags: [...tags], }}
emptyPlaceholder='Не найдено ни одной статьи...' />
<ArticlesList
client:load
data={{
articles: formatToArticleBlocks(transformArticles(articles)),
tags: [...tags],
}}
emptyPlaceholder='Не найдено ни одной статьи...'
/>
</section>
</PageLayout>

1
src/types/main.d.ts vendored
View File

@ -11,6 +11,7 @@ declare global {
}
type ArticleType = {
slug: string;
title: string;
description: string;
author: string;

View File

@ -2,6 +2,7 @@ import { MarkdownInstance } from 'astro';
export const transformArticles = (articles: MarkdownInstance<ArticleType>[]): ArticleType[] =>
articles.map((article) => ({
slug: article.frontmatter.slug,
title: article.frontmatter.title,
description: article.frontmatter.description,
author: article.frontmatter.author,