Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e1271b1a8 | |||
| 5daee3ab47 | |||
| 636a02cdcf | |||
| df1461e85d | |||
| 95ba8fcf15 | |||
| dda5ab7bb3 | |||
| a796807be0 | |||
| fce52767f1 | |||
| ffa941b39c | |||
| c50c1aa675 | |||
| c987e1bd77 | |||
| 9389490177 | |||
| a3b124a2a3 | |||
| ea50584e15 | |||
| 132c0e37e8 | |||
| b02ba3d41d | |||
| b31ba8a6d3 | |||
| e2e6680a54 | |||
| a1ce057391 | |||
| 87bdf58bc2 | |||
| 229c374d1b | |||
| 3aea695634 | |||
| 43af318592 | |||
| f642a0145c | |||
| 3c19dfad04 | |||
| aeb0712725 | |||
| 975d1cf8bb | |||
| 46cb2a4d25 | |||
| 818f292831 |
@ -83,23 +83,21 @@ npx tsc --init
|
|||||||
Теперь после того как все пакеты установлены, определимся со структурой проекта:
|
Теперь после того как все пакеты установлены, определимся со структурой проекта:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.
|
typescript-apollo-server
|
||||||
└── typescript-apollo-server
|
├── graphql
|
||||||
├── graphql
|
│ ├── resolvers - обработчики запросов
|
||||||
│ ├── resolvers - обработчики запросов
|
│ │ ├── Books
|
||||||
│ │ ├── Books
|
│ │ │ └── Books.ts
|
||||||
│ │ │ └── Books.ts
|
│ │ └── Users
|
||||||
│ │ ├── Users
|
│ │ └── Users.ts
|
||||||
│ │ │ └── Users.ts
|
│ ├── typeDefs - типы
|
||||||
│ │ └── index.ts
|
│ │ ├── Book.graphql
|
||||||
│ ├── typeDefs - типы
|
│ │ ├── User.graphql
|
||||||
│ │ ├── Book.graphql
|
│ │ └── schema.graphql
|
||||||
│ │ ├── User.graphql
|
│ └── schema.ts
|
||||||
│ │ └── schema.graphql
|
├── index.ts - сервер
|
||||||
│ └── schema.ts
|
├── package.json
|
||||||
├── index.ts - сервер
|
└── tsconfig.json
|
||||||
├── package.json
|
|
||||||
└── tsconfig.json
|
|
||||||
```
|
```
|
||||||
|
|
||||||
В качестве простого примера GraphQL сервера, будем создавать несколько resolvers - это **Books** и **Users**.
|
В качестве простого примера GraphQL сервера, будем создавать несколько resolvers - это **Books** и **Users**.
|
||||||
@ -202,7 +200,7 @@ cd ..
|
|||||||
|
|
||||||
Файл **Books.ts**:
|
Файл **Books.ts**:
|
||||||
|
|
||||||
```js
|
```ts
|
||||||
// ./graphql/resolvers/Books/Books.ts
|
// ./graphql/resolvers/Books/Books.ts
|
||||||
|
|
||||||
import { IResolvers } from "graphql-tools"
|
import { IResolvers } from "graphql-tools"
|
||||||
@ -228,7 +226,7 @@ export default booksResolver
|
|||||||
|
|
||||||
Файл **Users.ts**:
|
Файл **Users.ts**:
|
||||||
|
|
||||||
```js
|
```ts
|
||||||
// ./graphql/resolvers/Users/Users.ts
|
// ./graphql/resolvers/Users/Users.ts
|
||||||
|
|
||||||
import { IResolvers } from "graphql-tools"
|
import { IResolvers } from "graphql-tools"
|
||||||
@ -254,7 +252,7 @@ export default usersResolver
|
|||||||
|
|
||||||
Резолверы получились довольно простые и понятные, теперь нужно собрать их в один массив для дальнейшего экспорта. В файле **index.ts** прописываем следующее:
|
Резолверы получились довольно простые и понятные, теперь нужно собрать их в один массив для дальнейшего экспорта. В файле **index.ts** прописываем следующее:
|
||||||
|
|
||||||
```js
|
```ts
|
||||||
// ./graphql/resolvers/index.ts
|
// ./graphql/resolvers/index.ts
|
||||||
|
|
||||||
import { IResolvers } from "graphql-tools"
|
import { IResolvers } from "graphql-tools"
|
||||||
@ -274,7 +272,7 @@ export default resolvers
|
|||||||
Раньше для того чтобы работали наши graphql импорты мы применяли пакет **graphql-import**, но теперь его не нужно устанавливать так как он уже входит в состав **graphql-tools**. Подробнее об этом можно прочитать [здесь](https://www.graphql-tools.com/docs/migration-from-import).
|
Раньше для того чтобы работали наши graphql импорты мы применяли пакет **graphql-import**, но теперь его не нужно устанавливать так как он уже входит в состав **graphql-tools**. Подробнее об этом можно прочитать [здесь](https://www.graphql-tools.com/docs/migration-from-import).
|
||||||
С помощью функций **loadSchemaSync**, **loadFilesSync**, и **addResolversToSchema** мы собираем нашу схему. Функция **mergeResolvers** предназначена для объединения наших резолверов. Подробнее о "**Resolvers merging**" [здесь](https://www.graphql-tools.com/docs/merge-resolvers/). Далее всё что нам остается сделать - это экспортировать нашу схему и написать сервер.
|
С помощью функций **loadSchemaSync**, **loadFilesSync**, и **addResolversToSchema** мы собираем нашу схему. Функция **mergeResolvers** предназначена для объединения наших резолверов. Подробнее о "**Resolvers merging**" [здесь](https://www.graphql-tools.com/docs/merge-resolvers/). Далее всё что нам остается сделать - это экспортировать нашу схему и написать сервер.
|
||||||
|
|
||||||
```js
|
```ts
|
||||||
// ./graphql/schema.ts
|
// ./graphql/schema.ts
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -309,7 +307,7 @@ touch index.ts
|
|||||||
|
|
||||||
Импортируем все необходимые пакеты и напишем функцию **startServer**, которая будет запускать наш сервер. Сделаем это согласно документации к пакету [apollo-server-express](https://www.npmjs.com/package/apollo-server-express).
|
Импортируем все необходимые пакеты и напишем функцию **startServer**, которая будет запускать наш сервер. Сделаем это согласно документации к пакету [apollo-server-express](https://www.npmjs.com/package/apollo-server-express).
|
||||||
|
|
||||||
```js
|
```ts
|
||||||
// ./index.ts
|
// ./index.ts
|
||||||
|
|
||||||
import express, { Application, Request, Response } from "express"
|
import express, { Application, Request, Response } from "express"
|
||||||
@ -346,7 +344,7 @@ const startServer = (): void => {
|
|||||||
startServer()
|
startServer()
|
||||||
```
|
```
|
||||||
|
|
||||||
Как видим, ничего сложного нет, просто применяем функцию [applyMiddleware](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#applymiddleware) для того чтобы соедениеть Apollo Server с фрэймворком Express.js. Далее можно протестировать наш сервер, запускаем команду **npm run start** и переходим по адресу **/graphql**. Для тестирования можно выполнить вот такой запрос:
|
Как видим, ничего сложного нет, просто применяем функцию [applyMiddleware](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#applymiddleware) для того чтобы соединить Apollo Server с фрэймворком Express.js. Далее можно протестировать наш сервер, запускаем команду **npm run start** и переходим по адресу **/graphql**. Для тестирования можно выполнить вот такой запрос:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
{
|
{
|
||||||
|
|||||||
4
content/categories/cms.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
templateKey: category
|
||||||
|
title: CMS
|
||||||
|
---
|
||||||
4
content/tags/gatsbyjs.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
templateKey: tag
|
||||||
|
title: gatsbyjs
|
||||||
|
---
|
||||||
4
content/tags/jamstack.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
templateKey: tag
|
||||||
|
title: jamstack
|
||||||
|
---
|
||||||
4
content/tags/javascript.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
templateKey: tag
|
||||||
|
title: javascript
|
||||||
|
---
|
||||||
4
content/tags/netlify.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
templateKey: tag
|
||||||
|
title: netlify
|
||||||
|
---
|
||||||
@ -4,21 +4,7 @@ import Layout from "./src/components/Layout/Layout"
|
|||||||
|
|
||||||
import "prismjs/themes/prism-tomorrow.css"
|
import "prismjs/themes/prism-tomorrow.css"
|
||||||
import "prismjs/plugins/line-numbers/prism-line-numbers.css"
|
import "prismjs/plugins/line-numbers/prism-line-numbers.css"
|
||||||
|
|
||||||
import "./src/styles/global.scss"
|
import "./src/styles/global.scss"
|
||||||
import "./src/components/Header/Header.scss"
|
|
||||||
import "./src/components/About/About.scss"
|
|
||||||
import "./src/components/Offers/Offers.scss"
|
|
||||||
import "./src/components/Articles/Articles.scss"
|
|
||||||
import "./src/components/Articles/ArticleCard/ArticleCard.scss"
|
|
||||||
import "./src/components/Newsletter/Newsletter.scss"
|
|
||||||
import "./src/components/Article/Article.scss"
|
|
||||||
import "./src/components/Snippet/Snippet.scss"
|
|
||||||
import "./src/components/Snippets/Snippets.scss"
|
|
||||||
import "./src/components/Articles/MoreArticles/MoreArticles.scss"
|
|
||||||
import "./src/components/Books/Books.scss"
|
|
||||||
import "./src/components/Contacts/Contacts.scss"
|
|
||||||
import "./src/components/Footer/Footer.scss"
|
|
||||||
|
|
||||||
export const shouldUpdateScroll = ({ routerProps: { location } }) => {
|
export const shouldUpdateScroll = ({ routerProps: { location } }) => {
|
||||||
const { pathname } = location
|
const { pathname } = location
|
||||||
|
|||||||
@ -56,6 +56,12 @@ module.exports = {
|
|||||||
defer: false,
|
defer: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
resolve: "gatsby-plugin-mailchimp",
|
||||||
|
options: {
|
||||||
|
endpoint: process.env.MAILCHIMP_ENDPOINT,
|
||||||
|
},
|
||||||
|
},
|
||||||
"gatsby-plugin-sitemap",
|
"gatsby-plugin-sitemap",
|
||||||
{
|
{
|
||||||
resolve: "gatsby-plugin-robots-txt",
|
resolve: "gatsby-plugin-robots-txt",
|
||||||
@ -206,7 +212,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
resolve: `gatsby-remark-images`,
|
resolve: `gatsby-remark-images`,
|
||||||
options: {
|
options: {
|
||||||
maxWidth: 900,
|
maxWidth: 970,
|
||||||
quality: 100,
|
quality: 100,
|
||||||
withWebp: true,
|
withWebp: true,
|
||||||
loading: "lazy",
|
loading: "lazy",
|
||||||
|
|||||||
@ -53,13 +53,13 @@ exports.createPages = async ({ actions, graphql }) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
createPage({
|
// createPage({
|
||||||
path: `amp/article/${node.frontmatter.slug}/`,
|
// path: `amp/article/${node.frontmatter.slug}/`,
|
||||||
component: articleTemplateAMP,
|
// component: articleTemplateAMP,
|
||||||
context: {
|
// context: {
|
||||||
slug: node.frontmatter.slug,
|
// slug: node.frontmatter.slug,
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
})
|
})
|
||||||
|
|
||||||
snippets.forEach(({ node }) => {
|
snippets.forEach(({ node }) => {
|
||||||
|
|||||||
39
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "devthread.ru",
|
"name": "devthread.ru",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -7055,6 +7055,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"email-validator": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ=="
|
||||||
|
},
|
||||||
"emoji-regex": {
|
"emoji-regex": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
@ -9148,6 +9153,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/gatsby-plugin-firebase/-/gatsby-plugin-firebase-0.2.0-beta.4.tgz",
|
"resolved": "https://registry.npmjs.org/gatsby-plugin-firebase/-/gatsby-plugin-firebase-0.2.0-beta.4.tgz",
|
||||||
"integrity": "sha512-F1uh9T5dY38aeNvKzqj+3K655dce1QS70wuG4bhV9L3cnTJR2vitTWyIoCvRJJfPs7Xq7LgjUDmHDrEos4S3gQ=="
|
"integrity": "sha512-F1uh9T5dY38aeNvKzqj+3K655dce1QS70wuG4bhV9L3cnTJR2vitTWyIoCvRJJfPs7Xq7LgjUDmHDrEos4S3gQ=="
|
||||||
},
|
},
|
||||||
|
"gatsby-plugin-mailchimp": {
|
||||||
|
"version": "5.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/gatsby-plugin-mailchimp/-/gatsby-plugin-mailchimp-5.2.2.tgz",
|
||||||
|
"integrity": "sha512-O9JizVPJAe5YT1QAHZNRh1xUVdPnfayfIRhsBULiK2629TQRvEzzQxTDbt/WZU02cVm8415Fx2CneaxYKLt0ag==",
|
||||||
|
"requires": {
|
||||||
|
"email-validator": "^2.0.4",
|
||||||
|
"jsonp": "^0.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"gatsby-plugin-manifest": {
|
"gatsby-plugin-manifest": {
|
||||||
"version": "2.4.17",
|
"version": "2.4.17",
|
||||||
"resolved": "https://registry.npmjs.org/gatsby-plugin-manifest/-/gatsby-plugin-manifest-2.4.17.tgz",
|
"resolved": "https://registry.npmjs.org/gatsby-plugin-manifest/-/gatsby-plugin-manifest-2.4.17.tgz",
|
||||||
@ -13254,6 +13268,29 @@
|
|||||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
|
||||||
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
|
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
|
||||||
},
|
},
|
||||||
|
"jsonp": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz",
|
||||||
|
"integrity": "sha1-pltPoPEL2nGaBUQep7lMVfPhW64=",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^2.1.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"jsprim": {
|
"jsprim": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
"gatsby-plugin-amp": "^0.2.2",
|
"gatsby-plugin-amp": "^0.2.2",
|
||||||
"gatsby-plugin-feed": "^2.5.11",
|
"gatsby-plugin-feed": "^2.5.11",
|
||||||
"gatsby-plugin-firebase": "^0.2.0-beta.4",
|
"gatsby-plugin-firebase": "^0.2.0-beta.4",
|
||||||
|
"gatsby-plugin-mailchimp": "^5.2.2",
|
||||||
"gatsby-plugin-manifest": "^2.4.17",
|
"gatsby-plugin-manifest": "^2.4.17",
|
||||||
"gatsby-plugin-netlify-cms": "^4.3.9",
|
"gatsby-plugin-netlify-cms": "^4.3.9",
|
||||||
"gatsby-plugin-netlify-cms-paths": "^1.3.0",
|
"gatsby-plugin-netlify-cms-paths": "^1.3.0",
|
||||||
|
|||||||
@ -130,7 +130,7 @@ const Article = ({
|
|||||||
owner,
|
owner,
|
||||||
admin: admin.split(","),
|
admin: admin.split(","),
|
||||||
language: "ru",
|
language: "ru",
|
||||||
id: slug,
|
id: slug.substr(0, 48),
|
||||||
title: title,
|
title: title,
|
||||||
labels: ["Статья", "Обсуждение"],
|
labels: ["Статья", "Обсуждение"],
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,8 +1,59 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
import addToMailchimp from "gatsby-plugin-mailchimp"
|
||||||
|
|
||||||
const Newsletter = () => {
|
const Newsletter = () => {
|
||||||
const submitHandler = e => {
|
const [email, setEmail] = React.useState("")
|
||||||
|
const [success, setSuccess] = React.useState(false)
|
||||||
|
const [error, setError] = React.useState({ isError: false, message: "" })
|
||||||
|
const $subscribeButton = React.useRef()
|
||||||
|
|
||||||
|
const submitHandler = async e => {
|
||||||
|
try {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
document.body.style.cursor = "wait"
|
||||||
|
$subscribeButton.current.style.cursor = "wait"
|
||||||
|
|
||||||
|
if (
|
||||||
|
!email.match(
|
||||||
|
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
setError({ isError: true, message: "Заполните поле в формате E-mail!" })
|
||||||
|
setSuccess(false)
|
||||||
|
window.setTimeout(() => setError({ isError: false, message: "" }), 5000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setError({ isError: false, message: "" })
|
||||||
|
|
||||||
|
const data = await addToMailchimp(email)
|
||||||
|
|
||||||
|
if (data.result !== "success") {
|
||||||
|
setError({
|
||||||
|
isError: true,
|
||||||
|
message: `Произошла ошибка, возможно "${email}" уже подписан на рассылку. Попробуйте запрос позже.`,
|
||||||
|
})
|
||||||
|
window.setTimeout(() => setError({ isError: false, message: "" }), 5000)
|
||||||
|
console.log(data.msg)
|
||||||
|
document.body.style.cursor = "auto"
|
||||||
|
$subscribeButton.current.style.cursor = "pointer"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setSuccess(true)
|
||||||
|
window.setTimeout(() => setSuccess(false), 5000)
|
||||||
|
document.body.style.cursor = "auto"
|
||||||
|
$subscribeButton.current.style.cursor = "pointer"
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
setSuccess(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeEmail = e => {
|
||||||
|
const email = e.target.value.trim().toLowerCase()
|
||||||
|
|
||||||
|
setEmail(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -19,10 +70,27 @@ const Newsletter = () => {
|
|||||||
</p>
|
</p>
|
||||||
<form onSubmit={submitHandler} action="#" target="_blank">
|
<form onSubmit={submitHandler} action="#" target="_blank">
|
||||||
<div className="email-field">
|
<div className="email-field">
|
||||||
<input placeholder="ваш e-mail" type="email" name="email" />
|
<input
|
||||||
<button>Подписаться</button>
|
value={email}
|
||||||
|
onChange={handleChangeEmail}
|
||||||
|
placeholder="ваш e-mail"
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
/>
|
||||||
|
<button ref={$subscribeButton}>Подписаться</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{success ? (
|
||||||
|
<p className="newsletter-content__success">
|
||||||
|
<span role="img" aria-label="checkMark">
|
||||||
|
✔️
|
||||||
|
</span>{" "}
|
||||||
|
Вы успешно подписались на рыссылку!
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
|
{error.isError ? (
|
||||||
|
<p className="newsletter-content__error">{error.message}</p>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -51,6 +51,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&__error {
|
||||||
|
color: tomato;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
&__success {
|
||||||
|
color: rgb(101, 190, 101);
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const Snippet = ({ data: { slug, description, title, date }, html }) => {
|
|||||||
owner,
|
owner,
|
||||||
admin: admin.split(","),
|
admin: admin.split(","),
|
||||||
language: "ru",
|
language: "ru",
|
||||||
id: slug,
|
id: slug.substr(0, 48),
|
||||||
title: title,
|
title: title,
|
||||||
labels: ["Сниппет", "Обсуждение"],
|
labels: ["Сниппет", "Обсуждение"],
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,6 +1,22 @@
|
|||||||
@import './variables.scss';
|
@import './variables.scss';
|
||||||
@import './fonts.scss';
|
@import './fonts.scss';
|
||||||
|
|
||||||
|
/* Components */
|
||||||
|
|
||||||
|
@import '../components/Header/Header.scss';
|
||||||
|
@import '../components/About/About.scss';
|
||||||
|
@import '../components/Offers/Offers.scss';
|
||||||
|
@import '../components/Articles/Articles.scss';
|
||||||
|
@import '../components/Articles/ArticleCard/ArticleCard.scss';
|
||||||
|
@import '../components/Newsletter/Newsletter.scss';
|
||||||
|
@import '../components/Article/Article.scss';
|
||||||
|
@import '../components/Snippet/Snippet.scss';
|
||||||
|
@import '../components/Snippets/Snippets.scss';
|
||||||
|
@import '../components/Articles/MoreArticles/MoreArticles.scss';
|
||||||
|
@import '../components/Books/Books.scss';
|
||||||
|
@import '../components/Contacts/Contacts.scss';
|
||||||
|
@import '../components/Footer/Footer.scss';
|
||||||
|
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@ -91,15 +107,21 @@ article .gt-container {
|
|||||||
& p img {
|
& p img {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
& ul {
|
& ul {
|
||||||
margin-left: 34px;
|
margin-left: 34px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 5px;
|
||||||
|
|
||||||
& li {
|
& li {
|
||||||
padding: 7px 0;
|
padding: 7px 0;
|
||||||
|
& p {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
position: relative;
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
&::before {
|
&::before {
|
||||||
content: "\2022";
|
content: "\2022";
|
||||||
color: #6394F7;
|
color: #6394F7;
|
||||||
@ -179,11 +201,67 @@ article .gt-container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-scss"]:before {
|
||||||
|
content: "scss";
|
||||||
|
background: #e73eaf;
|
||||||
|
color: $white-clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-scss"] {
|
||||||
|
& code {
|
||||||
|
& span.token.property {
|
||||||
|
color: #dea53d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-ts"] {
|
||||||
|
& code {
|
||||||
|
& span.token.class-name {
|
||||||
|
color: #f08787;
|
||||||
|
}
|
||||||
|
& span.token.constant {
|
||||||
|
color: #9a6c07;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-js"] {
|
||||||
|
& code {
|
||||||
|
& span.token.class-name {
|
||||||
|
color: #f08787;
|
||||||
|
}
|
||||||
|
& span.token.constant {
|
||||||
|
color: #9a6c07;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-jsx"] {
|
||||||
|
& code {
|
||||||
|
& span.token.class-name {
|
||||||
|
color: #f08787;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.gatsby-highlight pre[class*="language-js"]:before {
|
.gatsby-highlight pre[class*="language-js"]:before {
|
||||||
content: "js";
|
content: "js";
|
||||||
background: rgb(247, 223, 30);
|
background: rgb(247, 223, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-jsx"]:before {
|
||||||
|
content: "jsx";
|
||||||
|
background: #0a91eb;
|
||||||
|
color: $white-clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-ts"]:before {
|
||||||
|
content: "ts";
|
||||||
|
background: #007acc;
|
||||||
|
color: $white-clr;
|
||||||
|
}
|
||||||
|
|
||||||
.gatsby-highlight pre[class*="language-text"]:before {
|
.gatsby-highlight pre[class*="language-text"]:before {
|
||||||
content: "text";
|
content: "text";
|
||||||
background: #efefef;
|
background: #efefef;
|
||||||
@ -293,6 +371,26 @@ article .gt-container {
|
|||||||
}
|
}
|
||||||
& .inner {
|
& .inner {
|
||||||
border-bottom: 1px solid rgba(153, 153, 153, 0.2);
|
border-bottom: 1px solid rgba(153, 153, 153, 0.2);
|
||||||
|
& p img {
|
||||||
|
border: 1px solid #505050;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-ts"] {
|
||||||
|
& code {
|
||||||
|
& span.token.constant {
|
||||||
|
color: #f8c555;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gatsby-highlight pre[class*="language-js"] {
|
||||||
|
& code {
|
||||||
|
& span.token.constant {
|
||||||
|
color: #f8c555;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.gatsby-highlight pre[class*="language-"] {
|
.gatsby-highlight pre[class*="language-"] {
|
||||||
background: #282c34;
|
background: #282c34;
|
||||||
& code {
|
& code {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ collections:
|
|||||||
create: true
|
create: true
|
||||||
slug: "{{year}}-{{month}}-{{day}}_{{slug}}"
|
slug: "{{year}}-{{month}}-{{day}}_{{slug}}"
|
||||||
fields:
|
fields:
|
||||||
- {label: "Template Key", name: "templateKey", wisdget: "hidden", default: "article"}
|
- {label: "Template Key", name: "templateKey", widget: "hidden", default: "article"}
|
||||||
- {label: "Slug", name: "slug", widget: "string"}
|
- {label: "Slug", name: "slug", widget: "string"}
|
||||||
- {label: "Keywords", name: "keywords", widget: "list"}
|
- {label: "Keywords", name: "keywords", widget: "list"}
|
||||||
- {label: "Время чтения", name: "time", widget: "string"}
|
- {label: "Время чтения", name: "time", widget: "string"}
|
||||||
|
|||||||
BIN
static/assets/ekwhwhj.png
Normal file
|
After Width: | Height: | Size: 280 KiB |
BIN
static/assets/gatsby-netlifycms.jpg
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
static/assets/n4kwm2v.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
static/assets/p5meca8.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
static/assets/td2wlx2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/assets/ueqolge.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
static/assets/wyoedkj.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
static/assets/yvvs281.png
Normal file
|
After Width: | Height: | Size: 95 KiB |