Compare commits
No commits in common. "f6cc226e0386d77c7f2ffcb8222d3933f75cc4ef" and "73f8046888f94c024fe95a6ca5da79c77e2f9dee" have entirely different histories.
f6cc226e03
...
73f8046888
11 changed files with 81 additions and 186 deletions
|
@ -1,11 +1,8 @@
|
||||||
---
|
---
|
||||||
import ArticleMenu from './ArticleMenu.astro';
|
|
||||||
|
|
||||||
import { AstroComponentFactory } from 'astro/dist/runtime/server';
|
import { AstroComponentFactory } from 'astro/dist/runtime/server';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
PostContent: AstroComponentFactory;
|
PostContent: AstroComponentFactory;
|
||||||
slug: string;
|
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
readingTime: number;
|
readingTime: number;
|
||||||
|
@ -15,9 +12,8 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
PostContent, slug,
|
PostContent, title, description,
|
||||||
title, description,
|
readingTime, date, image,
|
||||||
readingTime, date,
|
|
||||||
preview = false,
|
preview = false,
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
|
@ -36,28 +32,13 @@ const locale = 'ru';
|
||||||
{readingTime.toFixed(1)} min read
|
{readingTime.toFixed(1)} min read
|
||||||
</span>
|
</span>
|
||||||
</address>
|
</address>
|
||||||
{
|
|
||||||
!preview ?
|
|
||||||
<ArticleMenu slug={slug} title={title} /> :
|
|
||||||
""
|
|
||||||
}
|
|
||||||
</header>
|
</header>
|
||||||
{
|
{
|
||||||
!preview ?
|
!preview ?
|
||||||
<article>
|
<article>
|
||||||
<PostContent />
|
<PostContent />
|
||||||
</article> :
|
</article> :
|
||||||
<div class="description">
|
<div>
|
||||||
{description}
|
{description}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<style lang="less">
|
|
||||||
address {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
---
|
---
|
||||||
import Article from './Article.astro';
|
import Article from './Article.astro';
|
||||||
import ArticleMenu from './ArticleMenu.astro';
|
import SimpleMenu from '../layouts/SimpleMenu.astro';
|
||||||
|
import MenuItem from './MenuItem.astro';
|
||||||
|
|
||||||
import postRenderer from '../post-renderer.mjs';
|
import postRenderer from '../post-renderer.mjs';
|
||||||
import { postType } from '../post-renderer.mjs';
|
import { postType } from '../post-renderer.mjs';
|
||||||
|
@ -14,6 +15,7 @@ const {
|
||||||
PostContent, title, description,
|
PostContent, title, description,
|
||||||
readingTime, date, image,
|
readingTime, date, image,
|
||||||
} = await postRenderer(post);
|
} = await postRenderer(post);
|
||||||
|
const link = `/blog/${post.slug}`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="card card-elevated" id={post.slug}>
|
<div class="card card-elevated" id={post.slug}>
|
||||||
|
@ -26,7 +28,41 @@ const {
|
||||||
image={image}
|
image={image}
|
||||||
preview={true}
|
preview={true}
|
||||||
/>
|
/>
|
||||||
<ArticleMenu slug={post.slug} title={title} isCard />
|
<SimpleMenu jcc="end">
|
||||||
|
<MenuItem
|
||||||
|
name={/*Comments*/""}
|
||||||
|
link={`/blog/comments#${post.slug}`}
|
||||||
|
icon=""
|
||||||
|
atLeft={false}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
name={/*Copy Link*/""}
|
||||||
|
link="javascript:void(0)"
|
||||||
|
icon=""
|
||||||
|
atLeft={false}>
|
||||||
|
<span slot="js-dataset"
|
||||||
|
data-btn="copylink"
|
||||||
|
data-url={link}>
|
||||||
|
</span>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
name={/*Share*/""}
|
||||||
|
link="javascript:void(0)"
|
||||||
|
icon=""
|
||||||
|
atLeft={false}>
|
||||||
|
<span slot="js-dataset"
|
||||||
|
data-btn="share"
|
||||||
|
data-title={title}
|
||||||
|
data-url={link}>
|
||||||
|
</span>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
name="Read"
|
||||||
|
link={link}
|
||||||
|
icon=""
|
||||||
|
atLeft={false}
|
||||||
|
/>
|
||||||
|
</SimpleMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
---
|
|
||||||
import SimpleMenu from '../layouts/SimpleMenu.astro';
|
|
||||||
import MenuItem from './MenuItem.astro';
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
slug: string;
|
|
||||||
title: string;
|
|
||||||
isCard?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { slug, title, isCard = false } = Astro.props;
|
|
||||||
const link = `/blog/${slug}`;
|
|
||||||
---
|
|
||||||
|
|
||||||
<SimpleMenu jc={isCard ? "end" : "start"} largeGap={!isCard}>
|
|
||||||
<MenuItem
|
|
||||||
name="Comments"
|
|
||||||
link={`${link}#comments`}
|
|
||||||
icon=""
|
|
||||||
iconAfter={isCard}
|
|
||||||
hideLabel={isCard}
|
|
||||||
/>
|
|
||||||
<MenuItem
|
|
||||||
name="Copy link"
|
|
||||||
link="javascript:void(0)"
|
|
||||||
icon=""
|
|
||||||
classes={["btn-copy"]}
|
|
||||||
dataset={{"data-url": link}}
|
|
||||||
iconAfter={isCard}
|
|
||||||
hideLabel={isCard}
|
|
||||||
/>
|
|
||||||
<MenuItem
|
|
||||||
name="Share"
|
|
||||||
link="javascript:void(0)"
|
|
||||||
icon=""
|
|
||||||
classes={["btn-share"]}
|
|
||||||
dataset={{"data-url": link, "data-title": title}}
|
|
||||||
iconAfter={isCard}
|
|
||||||
hideLabel={isCard}
|
|
||||||
/>
|
|
||||||
{
|
|
||||||
isCard ?
|
|
||||||
<MenuItem
|
|
||||||
name="Read"
|
|
||||||
link={link}
|
|
||||||
icon=""
|
|
||||||
iconAfter={true}
|
|
||||||
/> :
|
|
||||||
""
|
|
||||||
}
|
|
||||||
</SimpleMenu>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const handlerCopy = (ev: Event) => {
|
|
||||||
const elem = ev.currentTarget as HTMLAnchorElement
|
|
||||||
navigator.clipboard.writeText(
|
|
||||||
location.origin + elem.dataset.url
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlerShare = (ev: Event) => {
|
|
||||||
const elem = ev.currentTarget as HTMLAnchorElement
|
|
||||||
navigator.share({
|
|
||||||
title: elem.dataset.title,
|
|
||||||
url: elem.dataset.url,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const btnsCopy = document.querySelectorAll('.btn-copy')
|
|
||||||
for (let btn of btnsCopy) {
|
|
||||||
btn.addEventListener('click', handlerCopy)
|
|
||||||
}
|
|
||||||
|
|
||||||
const btnsShare = document.querySelectorAll('.btn-share')
|
|
||||||
for (let btn of btnsShare) {
|
|
||||||
btn.addEventListener('click', handlerShare)
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
import SimpleMenu from '../layouts/SimpleMenu.astro';
|
||||||
import Icon from './Icon.astro';
|
import Icon from './Icon.astro';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|
|
@ -6,89 +6,51 @@ export interface Props {
|
||||||
link: string;
|
link: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
tblank?: boolean;
|
tblank?: boolean;
|
||||||
iconAfter?: boolean;
|
atLeft?: boolean;
|
||||||
hideLabel?: boolean;
|
|
||||||
classes?: Array<string>;
|
classes?: Array<string>;
|
||||||
dataset?: Object;
|
datajs?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
name, link, icon,
|
name, link, icon,
|
||||||
tblank = false,
|
tblank = false,
|
||||||
iconAfter = false,
|
atLeft = true,
|
||||||
hideLabel = false,
|
|
||||||
classes = [],
|
classes = [],
|
||||||
dataset = {},
|
datajs = "",
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<li class:list={{"icon-after": iconAfter, "hide-label": hideLabel}}>
|
<li>
|
||||||
<a href={link} target={tblank ? "_blank" : "_self"} class:list={classes} {...dataset}>
|
<slot name="js-dataset"></slot>
|
||||||
|
<a href={link} target={tblank ? "_blank" : "_self"} class:list={classes} data-js={datajs}>
|
||||||
<span class="icon-wrapper">
|
<span class="icon-wrapper">
|
||||||
<Icon code={icon} />
|
<Icon code={icon} />
|
||||||
</span>
|
</span>
|
||||||
<span class="name">{name}</span>
|
{name}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less" define:vars={{fxd: atLeft ? "row" : "row-reverse"}}>
|
||||||
@icon-size: 1.5rem;
|
|
||||||
|
|
||||||
li {
|
|
||||||
a {
|
a {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: var(--fxd);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
column-gap: 0.125rem;
|
|
||||||
|
|
||||||
font-size: 1.15rem;
|
font-size: 1.15rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
.icon-wrapper {
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--fg-sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover {
|
||||||
.icon-wrapper {
|
.icon-wrapper {
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
li.icon-after {
|
|
||||||
a {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
li.hide-label {
|
|
||||||
a {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
&:hover {
|
|
||||||
.name {
|
|
||||||
display: block;
|
|
||||||
width: max-content;
|
|
||||||
padding: 0.2rem;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
bottom: @icon-size + 0.25rem;
|
|
||||||
z-index: 10;
|
|
||||||
|
|
||||||
font-size: 0.9rem;
|
|
||||||
color: #eee;
|
|
||||||
background: rgba(0, 0, 0, .7);
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-wrapper {
|
|
||||||
width: @icon-size;
|
|
||||||
font-size: @icon-size;
|
|
||||||
color: var(--fg-sec);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -6,18 +6,19 @@ import MenuItem from "../components/MenuItem.astro";
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
mainpage?: boolean;
|
article?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title, description, mainpage = false } = Astro.props;
|
const { title, description, article = false } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={"Blog | " + title} description={description}>
|
<Layout title={"Blog | " + title} description={description}>
|
||||||
<slot name="metadata" slot="metadata" />
|
<slot name="metadata" slot="metadata" />
|
||||||
<NavMenu>
|
<NavMenu>
|
||||||
{
|
{
|
||||||
mainpage ?
|
!article ?
|
||||||
<MenuItem name="Home" icon="" link="/" /> :
|
<MenuItem name="Home" icon="" link="/" />
|
||||||
|
<MenuItem name="Articles" icon="" link="/blog" /> :
|
||||||
<MenuItem name="Articles" icon="" link="/blog" />
|
<MenuItem name="Articles" icon="" link="/blog" />
|
||||||
}
|
}
|
||||||
<MenuItem name="Shorts" icon="" link="/blog/shorts" />
|
<MenuItem name="Shorts" icon="" link="/blog/shorts" />
|
||||||
|
|
|
@ -52,6 +52,7 @@ const { title, description } = Astro.props;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: @main-padding;
|
padding: @main-padding;
|
||||||
max-width: @max-width;
|
max-width: @max-width;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
article {
|
article {
|
||||||
|
|
|
@ -59,7 +59,6 @@ const { id } = Astro.props;
|
||||||
|
|
||||||
border-radius: var(--bdrs);
|
border-radius: var(--bdrs);
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
box-shadow: 0 0 1rem #161616;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
---
|
---
|
||||||
export interface Props {
|
export interface Props {
|
||||||
jc: "start" | "center" | "end" | "space-around" | "space-between";
|
jcc: "start" | "center" | "end" | "space-around" | "space-between";
|
||||||
largeGap?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { jc, largeGap = false } = Astro.props;
|
const { jcc } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<ul style={{columnGap: largeGap ? "0.5rem" : "0.125rem"}}>
|
<ul>
|
||||||
<slot />
|
<slot />
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<style lang="less" define:vars={{jc: jc}}>
|
<style lang="less" define:vars={{jcc: jcc}}>
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -19,6 +18,6 @@ const { jc, largeGap = false } = Astro.props;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: var(--jc);
|
justify-content: var(--jcc);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,9 +3,7 @@ import BlogLayout from "../../layouts/BlogLayout.astro";
|
||||||
import Article from "../../components/Article.astro";
|
import Article from "../../components/Article.astro";
|
||||||
|
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
import postRenderer from "../../post-renderer.mjs";
|
import postRenderer from "../../post-renderer.mjs";
|
||||||
import { postType } from "../../post-renderer.mjs";
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await getCollection("blog");
|
const posts = await getCollection("blog");
|
||||||
|
@ -17,14 +15,14 @@ export async function getStaticPaths() {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
const post: postType = Astro.props.post;
|
const { post } = Astro.props;
|
||||||
const {
|
const {
|
||||||
PostContent, title, description,
|
PostContent, title, description,
|
||||||
readingTime, date, image,
|
readingTime, date, image,
|
||||||
} = await postRenderer(post);
|
} = await postRenderer(post);
|
||||||
---
|
---
|
||||||
|
|
||||||
<BlogLayout title={title} description={description}>
|
<BlogLayout title={title} description={description} article={true}>
|
||||||
<Fragment slot="metadata">
|
<Fragment slot="metadata">
|
||||||
<meta property="og:type" content="article" />
|
<meta property="og:type" content="article" />
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
|
@ -39,7 +37,6 @@ const {
|
||||||
</Fragment>
|
</Fragment>
|
||||||
<Article
|
<Article
|
||||||
PostContent={PostContent}
|
PostContent={PostContent}
|
||||||
slug={post.slug}
|
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
readingTime={readingTime}
|
readingTime={readingTime}
|
||||||
|
@ -51,10 +48,6 @@ const {
|
||||||
<style lang="less" is:global>
|
<style lang="less" is:global>
|
||||||
@import "/src/styles/max_width.less";
|
@import "/src/styles/max_width.less";
|
||||||
|
|
||||||
main {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
article {
|
article {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ const description =
|
||||||
"The simpliest things!";
|
"The simpliest things!";
|
||||||
---
|
---
|
||||||
|
|
||||||
<BlogLayout title="Homepage" description={description} mainpage>
|
<BlogLayout title="Homepage" description={description}>
|
||||||
<Fragment slot="metadata">
|
<Fragment slot="metadata">
|
||||||
<meta name="robots" content="noindex, follow" />
|
<meta name="robots" content="noindex, follow" />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
Loading…
Add table
Reference in a new issue