article page

This commit is contained in:
Sergey Yarkov 2020-07-03 14:38:27 +03:00
parent b2c90f83e1
commit dae20275be
14 changed files with 467 additions and 11 deletions

View File

@ -1,5 +1,7 @@
import React from "react"
import './src/styles/global.scss'
import 'prismjs/themes/prism-tomorrow.css'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'
import { ThemeProvider } from "./src/context/ThemeContext"
export const wrapRootElement = ({ element }) => (

View File

@ -31,10 +31,43 @@ module.exports = {
]
},
plugins: [
'gatsby-plugin-netlify-cms',
'gatsby-plugin-react-helmet',
'gatsby-plugin-sass',
'gatsby-transformer-remark',
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-remark-prismjs`,
options: {
classPrefix: "language-",
inlineCodeMarker: null,
aliases: {},
showLineNumbers: false,
noInlineHighlight: false,
languageExtensions: [
{
language: "superscript",
extend: "javascript",
definition: {
superscript_types: /(SuperType)/,
},
insertBefore: {
function: {
superscript_keywords: /(superif|superelse)/,
},
},
},
],
prompt: {
user: "root",
host: "localhost",
global: false,
},
escapeEntities: {},
},
},
],
},
},
{
resolve: 'gatsby-plugin-react-svg',
options: {
@ -42,6 +75,16 @@ module.exports = {
include: /images/
}
}
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'content',
path: `${__dirname}/content`
}
},
'gatsby-plugin-netlify-cms',
'gatsby-plugin-react-helmet',
'gatsby-plugin-sass'
],
}

34
gatsby-node.js Normal file
View File

@ -0,0 +1,34 @@
const path = require('path')
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions
const articleTemplate = path.resolve('src/templates/articleTemplate.js')
return graphql(`
{
allMarkdownRemark(filter: {frontmatter: {templateKey: {eq: "article"}}}) {
edges {
node {
frontmatter {
slug
}
}
}
}
}
`).then(result => {
if (result.errors) {
return Promise.reject(result.errors);
}
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: `article/${node.frontmatter.slug}`,
component: articleTemplate,
context: {
slug: node.frontmatter.slug
},
});
});
})
}

107
package-lock.json generated
View File

@ -3877,6 +3877,17 @@
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
},
"clipboard": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
"integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
"optional": true,
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"clipboardy": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
@ -5026,6 +5037,12 @@
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
"optional": true
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@ -7598,10 +7615,38 @@
}
}
},
"gatsby-remark-prismjs": {
"version": "3.5.9",
"resolved": "https://registry.npmjs.org/gatsby-remark-prismjs/-/gatsby-remark-prismjs-3.5.9.tgz",
"integrity": "sha512-Nmc5DayvCJQZ+z8Z44fH3aEvDXsb7daY/cEDW02uecwl0xz4g3B7KGEPfI+EDXWCOoB3X5BzYAk/nMKI0UUt1A==",
"requires": {
"@babel/runtime": "^7.10.3",
"parse-numeric-range": "^0.0.2",
"unist-util-visit": "^1.4.1"
},
"dependencies": {
"unist-util-visit": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz",
"integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==",
"requires": {
"unist-util-visit-parents": "^2.0.0"
}
},
"unist-util-visit-parents": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz",
"integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==",
"requires": {
"unist-util-is": "^3.0.0"
}
}
}
},
"gatsby-source-filesystem": {
"version": "2.3.14",
"resolved": "https://registry.npmjs.org/gatsby-source-filesystem/-/gatsby-source-filesystem-2.3.14.tgz",
"integrity": "sha512-AUnSikwa8+bW0DFWOV1Dq8ZUNxCnEGmx7uxxutLTolHSMhFct2cpxwaXX5ITtjqb9KgfcQ+y0EbKhzXLWpmOzg==",
"version": "2.3.18",
"resolved": "https://registry.npmjs.org/gatsby-source-filesystem/-/gatsby-source-filesystem-2.3.18.tgz",
"integrity": "sha512-HcPhm8yIYrpSVCVOiCzE8dGOKfv78Dvw8p86COE/EbvqRyXQ7x2N+v5dZSluSejtoXck0vISa2kJCGPTGzcsbw==",
"requires": {
"@babel/runtime": "^7.10.3",
"better-queue": "^3.8.10",
@ -7609,7 +7654,7 @@
"chokidar": "3.4.0",
"file-type": "^12.4.2",
"fs-extra": "^8.1.0",
"gatsby-core-utils": "^1.3.8",
"gatsby-core-utils": "^1.3.11",
"got": "^9.6.0",
"md5-file": "^3.2.3",
"mime": "^2.4.6",
@ -7617,9 +7662,22 @@
"progress": "^2.0.3",
"read-chunk": "^3.2.0",
"valid-url": "^1.0.9",
"xstate": "^4.10.0"
"xstate": "^4.11.0"
},
"dependencies": {
"gatsby-core-utils": {
"version": "1.3.11",
"resolved": "https://registry.npmjs.org/gatsby-core-utils/-/gatsby-core-utils-1.3.11.tgz",
"integrity": "sha512-eaplfOveXLl1RCWja7QIke560jUKLprvCXZ446YgQ8vAYB0fXVz3u6AOf7XUmEV9F9PIkNjmfevd1oUPy9qISw==",
"requires": {
"ci-info": "2.0.0",
"configstore": "^5.0.1",
"fs-extra": "^8.1.0",
"node-object-hash": "^2.0.0",
"proper-lockfile": "^4.1.1",
"xdg-basedir": "^4.0.0"
}
},
"got": {
"version": "9.6.0",
"resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
@ -7637,6 +7695,11 @@
"to-readable-stream": "^1.0.0",
"url-parse-lax": "^3.0.0"
}
},
"xstate": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/xstate/-/xstate-4.11.0.tgz",
"integrity": "sha512-v+S3jF2YrM2tFOit8o7+4N3FuFd9IIGcIKHyfHeeNjMlmNmwuiv/IbY9uw7ECifx7H/A9aGLcxPSr0jdjTGDww=="
}
}
},
@ -8220,6 +8283,15 @@
"minimatch": "~3.0.2"
}
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"optional": true,
"requires": {
"delegate": "^3.1.2"
}
},
"got": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz",
@ -12818,6 +12890,11 @@
"unist-util-visit-children": "^1.0.0"
}
},
"parse-numeric-range": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-0.0.2.tgz",
"integrity": "sha1-tPCdQTx6282Yf26SM8e0shDJOOQ="
},
"parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
@ -13747,6 +13824,14 @@
}
}
},
"prismjs": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.20.0.tgz",
"integrity": "sha512-AEDjSrVNkynnw6A+B1DsFkd6AVdTnp+/WoUixFRULlCLZVRZlVQMVWio/16jv7G1FscUxQxOQhWwApgbnxr6kQ==",
"requires": {
"clipboard": "^2.0.0"
}
},
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@ -15943,6 +16028,12 @@
}
}
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
"optional": true
},
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@ -17519,6 +17610,12 @@
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
"optional": true
},
"tiny-invariant": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",

View File

@ -21,10 +21,12 @@
"gatsby-plugin-react-helmet": "^3.3.8",
"gatsby-plugin-react-svg": "^3.0.0",
"gatsby-plugin-sass": "^2.3.7",
"gatsby-source-filesystem": "^2.3.14",
"gatsby-remark-prismjs": "^3.5.9",
"gatsby-source-filesystem": "^2.3.18",
"gatsby-transformer-remark": "^2.8.23",
"netlify-cms-app": "^2.12.16",
"node-sass": "^4.14.1",
"prismjs": "^1.20.0",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",

View File

@ -0,0 +1,74 @@
import React from 'react';
import { Link } from 'gatsby'
import './Article.scss'
import ViewsIcon from '../../images/views-icon.svg'
import VkIcon from '../../images/vk-icon.svg'
import TwitterIcon from '../../images/twitter-icon__large.svg'
import FacebookIcon from '../../images/facebook-icon__large.svg'
const Article = ({ data: { title, description, category, tags, time }, html }) => {
return (
<div className="article">
<article>
<div className="article-info">
<div className="article-info__time">
<span>~ {time} мин</span>
</div>
<div className="article-info__views">
<ViewsIcon />
<span>4252</span>
</div>
</div>
<div className="article-heading">
<h1>{title}</h1>
</div>
<div className="article-category">
<Link to={`/category/${category}`}>{category}</Link>
</div>
<div className="article-share">
<span>Поделиться:</span>
<div className="article-share__social">
<a href="/">
<VkIcon />
</a>
<a href="/">
<TwitterIcon />
</a>
<a href="/">
<FacebookIcon />
</a>
</div>
</div>
<div className="article-description">
<p>
{description}
</p>
</div>
<div className="article-tags">
{tags.map((tag, i) => <div key={i} className="tag-item">
<Link to={`category/${tag}`}>{tag}</Link>
</div>)}
</div>
<div className="article-image">
<img src="https://c.wallhere.com/photos/fb/a1/JavaScript_minimalism-1227036.jpg!d" alt="article" />
</div>
<div className="article-inner inner">
<div dangerouslySetInnerHTML={{__html: html}}></div>
</div>
<div className="article-more">
<span>Смотреть еще в категории <Link to={`/category/${category}`}>{category}</Link></span>
</div>
<div className="article-comments">
<div className="article-comments__heading">
<h2>Комментарии</h2>
</div>
<div className="article-comments__content">
</div>
</div>
</article>
</div>
)
}
export default Article

View File

@ -0,0 +1,114 @@
@import '../../styles/variables.scss';
.article {
& article {
& .article-info {
display: flex;
margin-bottom: 10px;
font-size: 14px;
&__views {
display: flex;
align-items: center;
margin-left: 15px;
& svg {
margin-right: 7px;
}
}
}
& .article-heading {
margin-bottom: 5px;
& h1 {
font-size: 40px;
font-weight: 700;
line-height: 48px;
color: $black-clr;
}
}
& .article-category {
margin-bottom: 10px;
& a {
font-size: 16px;
}
}
& .article-share {
display: flex;
margin-bottom: 15px;
&__social{
margin-left: 15px;
& a {
text-decoration: none;
margin-right: 5px;
}
& a:nth-child(3) {
margin-right: 0;
}
}
}
& .article-description {
margin-bottom: 20px;
& p {
font-size: 17px;
color: $black-clr;
}
}
& .article-tags {
display: flex;
margin-bottom: 20px;
}
& .article-image {
& img {
height: auto;
max-width: 100%;
border-radius: 7px;
}
margin-bottom: 25px;
}
& .article-more {
margin: 15px 0;
}
& .article-comments {
margin: 25px 0;
}
}
}
.dark {
& .article {
& article {
& .article-share {
&__social {
& a {
& svg {
& .vk-icon, .twitter-icon, .facebook-icon {
fill: $white-clr;
}
}
}
}
}
& .article-info, & .article-share {
color: $white-clr;
}
& .article-more {
color: $white-clr;
}
& p, h1, h2, h3, h4, h5, h6, ul, ol {
color: $white-clr;
}
& blockquote {
background: #2A2A2A;
color: $white-clr;
}
}
}
}
@media (min-width: 768px) and (max-width: 1023px) {
.article {
article {
& .article-image {
padding: 0 5rem;
}
}
}
}

View File

@ -0,0 +1,18 @@
import React from 'react';
import ArticleCard from '../ArticleCard/ArticleCard'
import './MoreArticles.scss'
const MoreArticles = () => {
return (
<div className="more-articles">
<div className="more-articles__heading">
<h2>Вам также может понравится...</h2>
</div>
<div className="more-articles__content">
{[1,2,3,4].map(e => <ArticleCard key={e} />)}
</div>
</div>
)
}
export default MoreArticles

View File

@ -0,0 +1,19 @@
@import '../../../styles/variables.scss';
.more-articles {
margin-top: 40px;
& .more-articles__heading {
margin-bottom: 35px;
}
& .more-articles__content {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
}
.dark {
& .more-articles__heading {
color: $white-clr;
}
}

View File

@ -0,0 +1 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path class="facebook-icon" d="M20 10C20 4.47656 15.5234 0 10 0C4.47656 0 0 4.47656 0 10C0 15.5234 4.47656 20 10 20C10.0586 20 10.1172 20 10.1758 19.9961V12.2148H8.02734V9.71094H10.1758V7.86719C10.1758 5.73047 11.4805 4.56641 13.3867 4.56641C14.3008 4.56641 15.0859 4.63281 15.3125 4.66406V6.89844H14C12.9648 6.89844 12.7617 7.39062 12.7617 8.11328V9.70703H15.2422L14.918 12.2109H12.7617V19.6133C16.9414 18.4141 20 14.5664 20 10Z" fill="black"></path></svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -0,0 +1 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path class="twitter-icon" d="M6.51564 17.5086C13.5915 17.5086 17.461 11.6465 17.461 6.56331C17.461 6.39682 17.4575 6.23102 17.4501 6.06613C18.2011 5.52308 18.8539 4.84541 19.369 4.07406C18.6797 4.38056 17.9379 4.58661 17.1599 4.67983C17.954 4.2034 18.5638 3.45006 18.8514 2.552C18.1081 2.99266 17.285 3.3128 16.4087 3.48572C15.7067 2.73799 14.7072 2.27039 13.6005 2.27039C11.4763 2.27039 9.75343 3.99311 9.75343 6.1167C9.75343 6.41872 9.78726 6.71226 9.85319 6.99388C6.65599 6.83301 3.82079 5.30235 1.92367 2.97466C1.59343 3.54305 1.40286 4.20352 1.40286 4.90825C1.40286 6.24271 2.08202 7.42112 3.11469 8.11025C2.48357 8.09088 1.89076 7.91762 1.37247 7.62924C1.3719 7.6454 1.3719 7.66111 1.3719 7.67831C1.3719 9.54138 2.69788 11.0969 4.45833 11.4494C4.13497 11.5374 3.79476 11.5847 3.44389 11.5847C3.19644 11.5847 2.95519 11.5604 2.72081 11.5153C3.21055 13.0438 4.63078 14.1561 6.31452 14.1873C4.99783 15.2192 3.3392 15.8339 1.53656 15.8339C1.2265 15.8339 0.920006 15.8162 0.618896 15.7806C2.32144 16.8719 4.34309 17.5087 6.51576 17.5087" fill="black"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
src/images/vk-icon.svg Normal file
View File

@ -0,0 +1 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#vk-icon)"><path class="vk-icon" d="M16.5958 10.8566C16.2725 10.4483 16.365 10.2666 16.5958 9.90163C16.6 9.89746 19.2692 6.20913 19.5442 4.95829L19.5458 4.95746C19.6825 4.50163 19.5458 4.16663 18.885 4.16663H16.6983C16.1417 4.16663 15.885 4.45413 15.7475 4.77579C15.7475 4.77579 14.6342 7.44079 13.0592 9.16829C12.5508 9.66746 12.3158 9.82746 12.0383 9.82746C11.9017 9.82746 11.6892 9.66746 11.6892 9.21163V4.95746C11.6892 4.41079 11.5333 4.16663 11.0725 4.16663H7.63417C7.285 4.16663 7.0775 4.42163 7.0775 4.65913C7.0775 5.17746 7.865 5.29663 7.94667 6.75496V9.91913C7.94667 10.6125 7.82083 10.74 7.54167 10.74C6.79833 10.74 4.99417 8.06413 3.925 5.00163C3.70917 4.40746 3.49833 4.16746 2.9375 4.16746H0.75C0.125833 4.16746 0 4.45496 0 4.77663C0 5.34496 0.743333 8.17079 3.45667 11.9041C5.265 14.4525 7.81167 15.8333 10.1283 15.8333C11.5208 15.8333 11.6908 15.5266 11.6908 14.9991C11.6908 12.5641 11.565 12.3341 12.2625 12.3341C12.5858 12.3341 13.1425 12.4941 14.4425 13.7233C15.9283 15.1808 16.1725 15.8333 17.0042 15.8333H19.1908C19.8142 15.8333 20.13 15.5266 19.9483 14.9216C19.5325 13.6491 16.7225 11.0316 16.5958 10.8566Z" fill="black"></path></g><defs><clipPath id="vk-icon"><rect width="20" height="20" fill="white"></rect></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,48 @@
import React from 'react'
import Layout from '../components/Layout/Layout'
import Article from '../components/Article/Article'
import Offers from '../components/Offers/Offers'
import MoreArticles from '../components/Articles/MoreArticles/MoreArticles'
import Newsletter from '../components/Newsletter/Newsletter'
import { graphql } from "gatsby"
export default function Template ({ data }) {
const { markdownRemark } = data
const { frontmatter, html } = markdownRemark
console.log(markdownRemark.frontmatter)
return (
<Layout>
<main>
<div className="container-fluid">
<div className="row">
<div className="col-md-9 col-xs-12">
<Article data={frontmatter} html={html} />
<Newsletter />
<MoreArticles />
</div>
<div className="col-md-3 col-xs-12">
<Offers />
</div>
</div>
</div>
</main>
</Layout>
)
}
export const pageQuery = graphql`
query Article($slug: String!) {
markdownRemark(frontmatter: {slug: {eq: $slug}}) {
html
frontmatter {
slug
title
time
tags
description
date
category
}
}
}
`

View File

@ -11,6 +11,8 @@ collections:
slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
fields:
- {label: "Template Key", name: "templateKey", widget: "hidden", default: "article"}
- {label: "Slug", name: "slug", widget: "string"}
- {label: "Время чтения", name: "time", widget: "string"}
- {label: "Заголовок", name: "title", widget: "string"}
- {label: "Категория", name: "category", widget: "relation", collection: "categories", valueField: "title", searchFields: ["title"]}
- {label: "Дата публикации", name: "date", widget: "datetime"}