Gatsby: ์งˆ๋ฌธ-Frontmatter์—์„œ Markdown์„ ์ฝ๋Š” ๋ฐฉ๋ฒ•

์— ๋งŒ๋“  2018๋…„ 04์›” 17์ผ  ยท  41์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: gatsbyjs/gatsby

๊ธฐ์ˆ 

frontmatter์—์„œ ๋งˆํฌ ๋‹ค์šด ์ฝ˜ํ…์ธ ๋ฅผ ์ฝ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด :

 halfBlocks :
 -์ œ๋ชฉ : ์ฒซ ๋ฒˆ์งธ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค.
 ๋‚ด์šฉ :>-
 ### ** MarkDown ** ํ˜•์‹์˜ ์‹ค์ œ ์ฝ˜ํ…์ธ ์ž…๋‹ˆ๋‹ค.

 -์ด๊ฒƒ์€ ์ฒซ ๋ฒˆ์งธ ํ–‰์ž…๋‹ˆ๋‹ค
 -๋‘ ๋ฒˆ์งธ ์ค„์ž…๋‹ˆ๋‹ค
 -์ด๊ฒƒ์€ ์„ธ ๋ฒˆ์งธ ์ค„์ž…๋‹ˆ๋‹ค
 -์ œ๋ชฉ : ๋‘ ๋ฒˆ์งธ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค.
 ๋‚ด์šฉ :>-
 ### ** MarkDown ** ํ˜•์‹์˜ ์‹ค์ œ ์ฝ˜ํ…์ธ ์ž…๋‹ˆ๋‹ค.

 -์ด๊ฒƒ์€ ์ฒซ ๋ฒˆ์งธ ํ–‰์ž…๋‹ˆ๋‹ค
 -๋‘ ๋ฒˆ์งธ ์ค„์ž…๋‹ˆ๋‹ค
 -์ด๊ฒƒ์€ ์„ธ ๋ฒˆ์งธ ์ค„์ž…๋‹ˆ๋‹ค

๋‹ค์Œ graphql์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 halfBlocks {
 ํ‘œ์ œ
 ์˜์ƒ
 ํ•จ์œ ๋Ÿ‰
 }

HTML๋กœ ๋ณ€ํ™˜ ๋œ ์ปจํ…์ธ ๋ฅผ ์ฝ๊ฑฐ๋‚˜ HTML๋กœ ํ‘œ์‹œํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒํ•ฉ๋‹ˆ๊นŒ?

์˜ˆ์ƒ ๊ฒฐ๊ณผ

๋‚˜๋Š” ์ด๊ฒƒ์„ 'index.md'๋ผ๊ณ ํ•˜๋Š” ๋งˆํฌ ๋‹ค์šด ํŒŒ์ผ์—์„œ ์ฝ์„ ์ˆ˜ ์žˆ๊ณ  ์ด๊ฒƒ์„ HTML๋กœ ๋ Œ๋”๋ง ํ•  ์ˆ˜์žˆ์„ ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ๊ฒฐ๊ณผ

Markdown์€ ํ•ด์„์—†์ด ๊ทธ๋Œ€๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ

  • ๊ฐœ์ธ ๋น„ ๋ฒ„์ „ ( npm list gatsby ) : gatsby@^1.9.247
  • gatsby-cli ๋ฒ„์ „ ( gatsby --version ) : 1.1.50
question or discussion

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด๊ฒƒ์€ ์™„์ „ํžˆ ๊บผ์ ธ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ HTML๋กœ ๋ณ€ํ™˜ํ•ด์•ผํ•˜๋Š” ๋งˆํฌ ๋‹ค์šด์ด ํ•„์š”ํ•œ ๋ชจ๋“  ๊ณณ์—์„œ ํ…œํ”Œ๋ฆฟ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋งˆํฌ ๋‹ค์šด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

import React from 'react'
import PropTypes from 'prop-types'
import showdown from 'showdown'

const converter = new showdown.Converter()

const MarkdownContent = ({ content, className }) => (
  <div className={className} dangerouslySetInnerHTML={{ __html: converter.makeHtml(content) }} />
)

MarkdownContent.propTypes = {
  content: PropTypes.string,
  className: PropTypes.string,
}


export default MarkdownContent

๋ชจ๋“  41 ๋Œ“๊ธ€

์ด ํŠœํ† ๋ฆฌ์–ผ์€ ์ด์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ 5-7 ๋ถ€ https://www.gatsbyjs.org/tutorial/

๋˜ํ•œ ์‹œ์ž‘ ๋„๊ตฌ ์ค‘ ํ•˜๋‚˜๋กœ ์‹œ์ž‘ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์€ ์ด๋ฏธ ๋งˆํฌ ๋‹ค์šด ์ง€์›์ด ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. https://www.gatsbyjs.org/docs/gatsby-starters/

์งˆ๋ฌธ์€ ๋” ๋ฏธ๋ฌ˜ํ•˜๊ณ  ํŠœํ† ๋ฆฌ์–ผ์—์„œ ๋‹ค๋ฃจ์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‹ค์‹œ ์—ด์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ œ ์ƒ๊ฐ์—๋Š” ๋‘ ๊ฐ€์ง€ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋งˆํฌ ๋‹ค์šด ์ฝ˜ํ…์ธ ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ํŒŒ์ผ์„ ๋ถ„๋ฆฌํ•˜๊ณ  ๊ฒฝ๋กœ ๋งํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
Separate file - let's call it `someContent.md`
```md
### This is the actual content in **MarkDown** format.

- This is the first row
- This is second row
- This is third row
```
and reference that file in your main file (by relative path):
```md
halfBlocks:
  - title: This is first title
    content: "./someContent.md"
```
then in query you could
```
halfBlocks {
  content {
    childMarkdownRemark {
      html
    }
}
```
  1. ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์€์ด๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. frontmatter ํ•„๋“œ์— ๋Œ€ํ•œ ๋งˆํฌ ๋‹ค์šด ๋…ธ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  createNodeField ๋ฅผ ํ†ตํ•ด ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. MarkdownRemark ๋…ธ๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด๋ ค๋ฉด Contentful ์†Œ์Šค ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ฐพ์•„์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @KyleAMathews ๊ท€ํ•˜์˜ ์ œ์•ˆ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ๋“ค์„ ์ฝ์—ˆ์ง€๋งŒ ์ด๊ฒƒ์— ๋Œ€ํ•ด ์™„์ „ํžˆ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์› ๋‹ค. ๋‚˜๋Š” ์Šคํƒ€ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ด๊ฒƒ์€ ๋” ๋ณต์žกํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๋œ ์Šคํƒ€ํ„ฐ : https://github.com/v4iv/gatsby-starter-business

@pieh ๋‚˜๋ฅผ ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ์˜ณ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋„ˆ๋ฌด ๋งŽ์€ ์ž‘์€ ํŒŒ์ผ์„ ๊ฐ€์งˆ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜ ์ฝ”๋“œ๋กœ ์ž‘์—…ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„์ด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๊ธฐ์— ์ด๊ฒƒ์„ ๋ฌธ์„œํ™”ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

1 ๋‹จ๊ณ„ : ์ฝ˜ํ…์ธ  ์ฝ๊ธฐ

Graphql์„ ํ†ตํ•ด ์ •์ƒ์ ์œผ๋กœ ๋‚ด์šฉ์„ ์ฝ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋งˆํฌ ๋‹ค์šด์„ ๋ฌธ์ž์—ด๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ๋ณ€ํ™˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

2 ๋‹จ๊ณ„ : HTML๋กœ ๋ณ€ํ™˜

์ด๋ฅผ ์œ„ํ•ด ๋‚˜๋Š” ์ด๊ฒƒ์„ ํ‘œ์‹œ ํ•  ์‹ค์ œ ๊ตฌ์„ฑ ์š”์†Œ์— ๋„๋‹ฌ ํ•  ๋•Œ๊นŒ์ง€ ๋‚ด์šฉ์„ ๋ฌธ์ž์—ด๋กœํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฑฐ๊ธฐ์—์„œ ๋งˆํฌ ๋‹ค์šด์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค. remark-preset-lint-recommended๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค์น˜ ๋น„๊ณ 

yarn add remark remark-preset-lint-recommended remark-html

์ˆ˜์ž…

import remark from 'remark';
import recommended from 'remark-preset-lint-recommended';
import remarkHtml from 'remark-html';

์„ธ์šฐ๋‹ค
๋‚˜์ค‘์— ๋ Œ๋”๋ง ๋ถ€๋ถ„์—์„œ content ๊ฐ€ ๋ฌธ์ž์—ด๋กœ ์ฝํžŒ ๋งˆํฌ ๋‹ค์šด์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

content = remark()
      .use(recommended)
      .use(remarkHtml)
      .processSync(content).toString();

์ด์ œ ์ฝ˜ํ…์ธ ๋ฅผ HTML๋กœ ์žฌ ํ•ด์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3 ๋‹จ๊ณ„ : ๋งˆํฌ ๋‹ค์šด์— ์ฝ˜ํ…์ธ  ์ถ”๊ฐ€

๋‚ด๊ฐ€ ๋งŒ๋‚œ ํ•œ ๊ฐ€์ง€ ๋” ์žˆ์Šต๋‹ˆ๋‹ค. >- ์— ์—ฌ๋Ÿฌ ์ค„์„ ์‚ฌ์šฉํ•  ๋•Œ ํ˜•์‹์ด ์ ์ ˆํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

content: >-
    ### This is the actual content in **MarkDown** format.
    - This is the first row
    - This is second row

๊ทธ๋Ÿฌ๋‚˜ ํŒŒ์ดํ”„ ๊ธฐํ˜ธ | ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

content: |
    ### This is the actual content in **MarkDown** format.
    - This is the first row
    - This is second row

์ง€๊ธˆ์€ ์ด๊ฒƒ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค. ์›ํ•˜์‹œ๋ฉด ์–ธ์ œ๋“ ์ง€ ์žฌ๊ฐœ ์žฅํ•˜์‹ญ์‹œ์˜ค.

๊ฐ์‚ฌ!!

๋‚˜๋Š” ํ‘œ์ œ (์ œ๋ชฉ, ์ •ํ™•ํ•œ ๋ฐœ์ทŒ)์—๋„ ๋งˆํฌ ๋‹ค์šด์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›๋˜์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

gatsby-transformer-remark ๊ฐ€ ์˜ˆ๋ฅผ ๋“ค์–ด title.md ๊ฐ€ ๋งˆํฌ ๋‹ค์šด ํ•„๋“œ๋ผ๋Š” ๊ฒƒ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ช…๋ช… ๊ทœ์น™์„ ๊ฐ–๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

@omeid @ thorn0 ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ gatsby-transformer-remark์—์„œ ์ง์ ‘ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ ๋™์•ˆ https://github.com/gatsbyjs/gatsby/issues/5729#issuecomment ์™€ ๊ฐ™์ด์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -395701042 ๋ฐ createNodeField

์ด๋ฏธ ์ข…๋ฃŒ ๋œ ๋ฌธ์ œ์— ๋Œ€ํ•ด ๋Œ“๊ธ€์„ ๋‚จ๊ฒจ ์ฃผ์…”์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.ํ•˜์ง€๋งŒ ์ œ๊ฐ€ ์‚ฌ์šฉํ–ˆ๋˜ gatsby-node.js ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ์Šค ๋‹ˆํŽซ์„ ๊ณต์œ ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

// Need to `yarn add remark remark-html`, then include the following code in
// gatsby-node.js.
const remark = require('remark');
const remarkHTML = require('remark-html');

exports.onCreateNode = ({ node }) => {
  // Conditionals, etc. can be used here, but I omitted those just for example's sake.
  const markdown = node.frontmatter.my_field;
  node.frontmatter.my_field = remark()
    .use(remarkHTML)
    .processSync(markdown)
    .toString();
  return node;
};

createNodeField ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊ทธ๋ ‡๊ฒŒํ•ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๊นŒ? ํ˜ผ๋ž€ ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

@ thorn0 ์€ node.frontmatter.my_field = createNodeField ๋Œ€์‹  node ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฒ„๊ทธ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

@amitjindal @nshki ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ "react-flickity-component"๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„์ „ํžˆ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค.

success delete html and css files from previous builds โ€” 0.626 s
success open and validate gatsby-config โ€” 0.018 s
success copy gatsby files โ€” 0.075 s
success onPreBootstrap โ€” 2.782 s
error UNHANDLED EXCEPTION


  TypeError: Cannot set property 'Compiler' of null

  - index.js:16 plugin
    [blog]/[remark-html]/index.js:16:17

  - index.js:271 Function.use
    [blog]/[unified]/index.js:271:25

  - gatsby-node.js:63 exports.onCreateNode.postscriptumsMarkdown.forEach.postscr    iptum
    /home/projects/blog/gatsby-node.js:63:12

  - Array.forEach

  - gatsby-node.js:61 Object.exports.onCreateNode
    /home/projects/blog/gatsby-node.js:61:29

  - api-runner-node.js:110 runAPI
    [blog]/[gatsby]/dist/utils/api-runner-node.js:110:36

  - api-runner-node.js:187 
    [blog]/[gatsby]/dist/utils/api-runner-node.js:187:33

  - map.js:27 
    [blog]/[async]/internal/map.js:27:9

  - eachOfLimit.js:66 replenish
    [blog]/[async]/internal/eachOfLimit.js:66:17

  - eachOfLimit.js:50 iterateeCallback
    [blog]/[async]/internal/eachOfLimit.js:50:17

  - onlyOnce.js:12 module.exports
    [blog]/[async]/internal/onlyOnce.js:12:16

  - map.js:29 
    [blog]/[async]/internal/map.js:29:13

  - util.js:16 tryCatcher
    [blog]/[bluebird]/js/release/util.js:16:23

  - nodeify.js:23 Promise.successAdapter
    [blog]/[bluebird]/js/release/nodeify.js:23:30

  - promise.js:566 Promise.module.exports.Promise._settlePromise
    [blog]/[bluebird]/js/release/promise.js:566:21

  - promise.js:606 Promise.module.exports.Promise._settlePromiseCtx
    [blog]/[bluebird]/js/release/promise.js:606:10


Waiting for the debugger to disconnect...

Process finished with exit code 130 (interrupted by signal 2: SIGINT)

Webpack์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ์™ธํ•˜๋ ค๊ณ ํ•˜๋ฉด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ( @see https://github.com/gatsbyjs/gatsby/issues/7599).

์•ˆ๋…•ํ•˜์„ธ์š” David (@comxd), ์—ฌํ–‰ ์ค‘์ด ์–ด์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.
๋ถˆํ–‰ํžˆ๋„ ๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ํ†ต์ฐฐ๋ ฅ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜๋ ค๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค. null์˜ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋น„๊ณ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์˜ค๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

gatsby-node.js ํŒŒ์ผ์—์„œ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋งˆํฌ ๋‹ค์šด์ด ์•„๋‹ˆ๊ฑฐ๋‚˜ ๋น„์–ด์žˆ๋Š” ์ผ๋ถ€ ์ฝ˜ํ…์ธ ์™€ ๊ด€๋ จ์ด์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ฒ˜๋ฆฌํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ๊ฑฐ๊ธฐ์— console.log ๋ฌธ์„ ๋„ฃ๊ณ  ๋น„์–ด์žˆ๋Š” ๊ฒƒ์ด ์›์ธ์ด๋˜๋Š” ํŒจํ„ด์„ ์ฐพ๋Š” ์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

์ด๊ฒƒ์€ ์™„์ „ํžˆ ๊บผ์ ธ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ HTML๋กœ ๋ณ€ํ™˜ํ•ด์•ผํ•˜๋Š” ๋งˆํฌ ๋‹ค์šด์ด ํ•„์š”ํ•œ ๋ชจ๋“  ๊ณณ์—์„œ ํ…œํ”Œ๋ฆฟ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋งˆํฌ ๋‹ค์šด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

import React from 'react'
import PropTypes from 'prop-types'
import showdown from 'showdown'

const converter = new showdown.Converter()

const MarkdownContent = ({ content, className }) => (
  <div className={className} dangerouslySetInnerHTML={{ __html: converter.makeHtml(content) }} />
)

MarkdownContent.propTypes = {
  content: PropTypes.string,
  className: PropTypes.string,
}


export default MarkdownContent

@blakenoll ํ™•์‹คํžˆ ์™„์ „ํžˆ ๊บผ์ง„ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค! ํ•ฉ๋ฆฌ์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์ฆ‰, Gatsby์˜ ํฐ ์ด์  ์ค‘ ํ•˜๋‚˜๋Š” ๋นŒ๋“œ ํƒ€์ž„์— ์ด๋Ÿฌํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ Markdown ํŒŒ์„œ๋ฅผ ๊ตฌ์ž…ํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ข‹์Šต๋‹ˆ๋‹ค!

@DSchau ์•ฑ์ด ์žฌ์ˆ˜ ํ™” ๋  ๋•Œ Markdown ํŒŒ์„œ๊ฐ€ ์‹ค์ œ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐฐ์†ก๋˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

@blakenoll ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ƒ๊ฐ์„ ์‚ฌ๋ž‘ํ•˜์‹ญ์‹œ์˜ค!

gatsby-config.js ๋‚ด์— ํฌํ•จ ๋œ ๋ชจ๋“  remark ํ”Œ๋Ÿฌ๊ทธ์ธ / ๊ตฌ์„ฑ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜์žˆ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ž˜์„œ Gatsby์˜ remark ๊ตฌํ˜„์ด ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๋ณต์ œ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ? ๊ทธ๋Ÿฌ๋ฉด ๋…ธ๋“œ ํ•„๋“œ๋ฅผ ์ข€ ๋” ์‰ฝ๊ฒŒ ์ƒ์„ฑ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ค‘์ฒฉ๋˜๊ณ  ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ํ•„๋“œ์™€ ํŽ˜์ด์ง€ ๋‹น ์ฝ˜ํ…์ธ ์˜ ๋ณ€ํ˜•์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ๋•Œ ์—„์ฒญ๋‚˜๊ฒŒ ๋ฒˆ๊ฑฐ ๋กญ์Šต๋‹ˆ๋‹ค.

@blakenoll ๋Œ€๊ฒฐ ํŒ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋งค์šฐ ๋„์›€์ด๋˜์—ˆ๊ณ  ํ”„๋ก ํŠธ ๋งคํ„ฐ์—์„œ HTML์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, Markdown์„ ์‚ฌ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์— ๋‹ค๋ฅธ ์ฝ˜ํ…์ธ  ์กฐ๊ฐ์„ ์ „๋‹ฌํ•ด์•ผํ•˜๋Š” ์›น ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์–ด์ƒ‰ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

graphQL ์ฟผ๋ฆฌ์˜ frontmatter ์„น์…˜ ๋‚ด์— ์ผ์ข…์˜ markdownParser ํ•จ์ˆ˜๋ฅผ ์ ์šฉ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? (์ด๋ฏธ์ง€๋ฅผ ์กฐ์ž‘ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•๊ณผ ์œ ์‚ฌ) frontmatter์—์„œ ๋“ค์–ด์˜ค๋Š” markdown ๋ฌธ์ž์—ด์„ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ณ ์ด๋ฅผ HTML๋กœ ๋ณ€ํ™˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? graphQL ์ „๋ฌธ๊ฐ€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค ... ๊ทธ๋ƒฅ ์ƒ๊ฐํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค.

Netifly CMS์™€ ํ•จ๊ป˜ Gatsby๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ IMO b / c๋Š” ์ค‘์š”ํ•œ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. Netifly๋Š” ๋‹ค์–‘ํ•œ frontmatter ํ•„๋“œ๊ฐ€ Markdown์„ ๊ฐ’์œผ๋กœ ๋ฐ›์•„๋“ค์ด๋„๋กํ•˜๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ํ•„๋“œ๋ฅผ ์ฟผ๋ฆฌ ํ•  ๋•Œ HTML๋กœ ๊ตฌ๋ฌธ ๋ถ„์„๋˜๋Š” ๋Œ€์‹  ๋ฌธ์ž์—ด์˜ ๋งˆํฌ ๋‹ค์šด์œผ๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. @amitjindal ๋ฐ @blakenoll ์˜ ์†”๋ฃจ์…˜์€ ์ž‘๋™ํ•˜์ง€๋งŒ @DSchau๊ฐ€ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋งˆํฌ ๋‹ค์šด ๊ตฌ๋ฌธ ๋ถ„์„์„ ํ”ผํ•  ์ˆ˜์žˆ๋Š” ๊ฒฝ์šฐ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜๋ณด๋‹ค Gatbsy๋ฅผ ๋” ์ž˜ ์•„๋Š” ์‚ฌ๋žŒ์˜ ์ƒ๊ฐ์€?

@skylarweaver ๋‚˜๋Š” ํ™•์‹คํžˆ ๋‹น์‹ ๊ณผ ๊ฐ™์€ ํŽ˜์ด์ง€์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ ํ•  ์ˆ˜์žˆ๋Š” ๋…ธ๋“œ ํ•„๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ํŠน์„ฑ์„ ์ดํ•ดํ•˜๊ณ  ์žˆ์ง€๋งŒ ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ํ•„๋“œ์™€ ์—„์ฒญ๋‚˜๊ฒŒ ๋งŽ์€ ํ•„๋“œ ์ด๋ฆ„ ๋ณ€ํ˜•์ด์žˆ์„ ์ˆ˜์žˆ๋Š” CMS ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์†Œ ๋‹ค๋ฃจ๊ธฐ ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค. ๊ทธ ๋‹น์‹œ ๋ชจ๋“  Gatsby Remark ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ช…ํ™•ํ•œ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@skylarweaver๊ฐ€ ๋งํ•œ ๋‚ด์šฉ +1!

@amitjindal ์–ด์ฉŒ๋ฉด ์–ด๋ฆฌ์„์€ ์งˆ๋ฌธ์ผ์ง€๋„ ๋ชจ๋ฅด์ง€๋งŒ ">-"๋Š” ๋ฌด์—‡์„ ํ•˜๋Š”๊ฐ€? netlify cms ์Šคํƒ€ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ์„ฑ ๋œ ์ถœ๋ ฅ์—>,>-, |๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์ „ํ˜€์—†๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

@ nol13 ๋ธ”๋ก ์Šค์นผ๋ผ ์ฐธ์กฐ, ๊ฐœํ–‰์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ‘œ๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฝ์ž… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด๊ฒƒ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

content: |
        |   |   |   |   |   |
        |---|---|---|---|---|
        |   |   |   |   |   |
        |   |   |   |   |   |
        |   |   |   |   |   |

@ qnguyen12 https://jmalarcon.github.io/markdowntables/ ์™€ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€ํ™˜์„ ๋„์™€ ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์˜ˆ, ํ…Œ์ด๋ธ”์ด ์•„๋‹Œ ์†Œ์Šค๋กœ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค๋ฉด :

text: |
        test   
        ### This is the actual content in **MarkDown** format.  
        |Month|Savings|Spending|
        |--- |--- |--- |
        |January|$100|$900|
        |July|$750|$1000|
        |December|$250|$300|
        |April|$400|$700|

๋‹ค์Œ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
ํ…Œ์ŠคํŠธ

์ด๊ฒƒ์€ MarkDown ํ˜•์‹์˜ ์‹ค์ œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

| ์›” | ์ €์ถ• | ์ง€์ถœ | | --- | --- | --- | | 1 ์›” | $ 100 | $ 900 | | 7 ์›” | $ 750 | $ 1000 | | 12 ์›” | $ 250 | $ 300 | | 4 ์›” | $ 400 | $ 700 |

@KyleAMathews ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์ข…๋ฅ˜์˜ ์ž‘์—…์ด์ง€๋งŒ ๋ถ„๋ช…ํžˆ ์„ค๋ช… ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ตฌ์„ฑ ๋ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์‘๋‹ตํ•ด์•ผํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. ๋งˆํฌ ๋‹ค์šด ํ”„๋ก ํŠธ ๋งคํ„ฐ๋ฅผ ์ง€์›ํ•  ๊ณ„ํš์ด ์žˆ์Šต๋‹ˆ๊นŒ? frontmattermd ํ•„๋“œ์™€ ์›์‹œ frontmatter ?

@omeid ์ €๋Š” ๊ณ„ํš์ด ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋งŒ๋“ค๊ณ  ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๊ณต์œ  ํ•  ์ˆ˜์žˆ๋Š” ํ›Œ๋ฅญํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค!

์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค : gatsby-transformer-remark-frontmatter . ๋‚ด ํ…Œ์ŠคํŠธ์—์„œ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™๊ณ  ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•ด ์ˆ˜ํ–‰ํ•˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•  ๊ณ„ํš์ด์ง€๋งŒ ์—ฌ๋Ÿฌ๋ถ„์ด ์‚ดํŽด๋ณด๊ณ  ์ž˜๋ชป๋œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์•Œ๋ ค ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. , ์ฒ˜์Œ์œผ๋กœ gatsby ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. @omeid๊ฐ€ ์ œ์•ˆํ•œ ๊ฒฝ๋กœ๋ฅผ ์ทจํ•˜๊ณ  MarkdownRemark ๋…ธ๋“œ์— frontmattermd ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” gatsby-transformer-remark๊ฐ€ ์‚ฌ์šฉํ•  ์ƒˆ ๋งˆํฌ ๋‹ค์šด ํŒŒ์ผ ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊นจ๋‹ซ๊ธฐ ์ „์— gatsby-transformer-remark์˜ setFieldsOnGraphQLNodeType ํ•จ์ˆ˜์—์„œ ๋‚ด ๋ณด๋‚ธ ๋ฆฌ์กธ๋ฒ„๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์ƒˆ๋กœ์šด ๋‹ค๋ฅธ ๋ฆฌ์กธ๋ฒ„ ๋‚ด์—์„œ ์ƒ์„ฑ ๋œ ๋งˆํฌ ๋‹ค์šด ๋…ธ๋“œ. ์ด๋ ‡๊ฒŒํ•˜๋ฉด ํ•„๋“œ ์—ด๊ฑฐ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ MarkdownRemark ๋…ธ๋“œ์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ฟผ๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฃน ํ•จ์ˆ˜์— ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ํ•„๋“œ๊ฐ€ ์ •๋ง ๋งˆ์Œ์— ๋“ค์—ˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋ฌด์—‡์ด๋“  ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ํ•ดํ‚น์ฒ˜๋Ÿผ ๋Š๊ปด์กŒ์Šต๋‹ˆ๋‹ค. ํ›„์†์„ ์œ„ํ•ด ์—ฌ๊ธฐ ์— ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @WhiteAbeLincoln ์„ค์น˜ ๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.
npm i gatsby-transformer-remark-frontmatter npm ERR! code ENOVERSIONS npm ERR! No valid versions available for gatsby-transformer-remark-frontmatter

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์•„์ง npm์— ๊ฒŒ์‹œํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค. ํ‡ด๊ทผ ํ›„ ์•Œ๋ ค ๋“œ๋ฆด๊ฒŒ์š”.

โ€” ์•„๋ฒ  ํ™”์ดํŠธ

2019 ๋…„ 6 ์›” 17 ์ผ 22:53์— broeker [email protected] ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @WhiteAbeLincoln ์„ค์น˜ ๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.
npm i gatsby-transformer-remark-frontmatter npm ERR! ์ฝ”๋“œ ENOVERSIONS npm ERR! gatsby-transformer-remark-frontmatter์— ์œ ํšจํ•œ ๋ฒ„์ „์ด ์—†์Šต๋‹ˆ๋‹ค.

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ๋ณด๊ฑฐ๋‚˜ ๋Œ€ํ™” ๋ชฉ๋ก์„ ์Œ์†Œ๊ฑฐํ•˜์„ธ์š”.

@WhiteAbeLincoln ๋‚˜๋Š” gatsby-transformer-remark-frontmatter๋ฅผ ์‹œ๋„ ํ–ˆ์ง€๋งŒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์˜ค๋ฅ˜ # 11325

์‚ฌ์ดํŠธ์˜ "gatsby-node.js"๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€์žˆ๋Š” ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ?

์›๋ž˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์˜ ๋ฌธ์ œ ๋กœ๊ทธ์—

์•„๋งˆ๋„ ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋„์›€์„ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@nshki ๋‹ต๋ณ€ ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ๋…ธ๋“œ ๋ณ€ํ˜•์— ๋Œ€ํ•œ

const remark = require("remark");
const remarkHTML = require("remark-html");

exports.onCreateNode = ({ node, actions: { createNodeField } }) => {
  const my_field = node.frontmatter.my_field;

  if (my_field) {
    const value = remark()
      .use(remarkHTML)
      .processSync(my_field)
      .toString();

    // new node at:
    // fields {
    //   my_field_html
    // }
    createNodeField({
      name: `my_field_html`,
      node,
      value
    });
  }
};

์ˆ˜์ • : my_field => my_field_html

@aziaziazi ๋ฐฐ์—ด์— ์ค‘์ฒฉ ๋œ ํ•„๋“œ์— ๋Œ€ํ•ด ๋™์ผํ•œ ์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

pressEventsList:
  - body: >-
      *My md content...*
    image: 'https://res.cloudinary.com/press/01.jpg'
  - body: >-
      *My md content...*
    image: 'https://res.cloudinary.com/press/02.jpg'
---

๊ฐ pressEventsList[i].body ๋ฅผ ๋ณ€ํ™˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

@alexeychikk ์ €๋Š” pressEventList ๋ฅผ ์ฐพ์€ ๋‹ค์Œ ์ฝ˜ํ…์ธ ๋ฅผ ๋งคํ•‘ํ•˜์—ฌ ๊ฒฐ๊ณผ ๋ฐฐ์—ด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const remark = require("remark");
const remarkHTML = require("remark-html");

exports.onCreateNode = ({ node, actions: { createNodeField } }) => {
const pressEventList = node.frontmatter.pressEventList;

if (pressEventList) {
  const value = pressEventList.map(event =>
     remark()
    .use(remarkHTML)
    .processSync(event.body)
    .toString()
  )

  createNodeField({
    name: `pressEventList`,
    node,
    value
  });
}
};

createNodeField ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์œ„์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ์ž ์ง€์ • YAML ํƒœ๊ทธ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“œ๋Š” ๋ฐ ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค (์ƒคํ”„ ์ด๋ฏธ์ง€ URL ๊ตฌ๋ฌธ ๋ถ„์„๊ณผ ๊ฐ™์€ ๋ฐฉ์‹).
๋ˆ„๊ตฌ๋“ ์ง€ ์ด๋ฏธ์ง€ URL์ด ํŒŒ์‹ฑ๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๐Ÿ‘‹ MDX๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด frontmatter ์ง€์›์„ ์ถ”๊ฐ€ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค https://www.gatsbyjs.org/packages/gatsby-plugin-mdx-frontmatter/

@zslabs , "9 ์‹œ๊ฐ„ ์ „์—"๊ฒŒ์‹œ ๋œ ์†”๋ฃจ์…˜์„ ์ž์ฃผ ๋ณด์ง€ ์•Š์Šต๋‹ˆ๋‹ค! ๋‚ด๊ฐ€ ๋Œ๋ ค ์ค„๊ฒŒ! ์ž˜ ํ–ˆ์–ด.

๋‚ด ํŽ˜์ด์ง€ ์ค‘ ํ•˜๋‚˜์— ๋” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์—ˆ ๊ธฐ ๋•Œ๋ฌธ์—์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ์‹ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
Frontmatter์—๋Š” ์ œ๋ชฉ ๋ฐ ์ถ”์ฒœ ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ๋ช‡ ๊ฐœ์˜ ํ•„๋“œ๊ฐ€์žˆ๋Š” ์„น์…˜ ๋ฐฐ์—ด์ด ์žˆ์—ˆ๊ณ  ๊ฐ ์„น์…˜์—๋Š” ๋งˆํฌ ๋‹ค์šด์œผ๋กœ ๋งŒ๋“  ๋ณธ๋ฌธ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
createNodeField๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ธฐ์กด์˜ frontmatter ๊ตฌ์กฐ์— ์ถ”๊ฐ€๋˜์ง€ ์•Š๊ณ  ์ž์ฒด ํ•„๋“œ์—์„œ ์ƒ์„ฑ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋…ผ๋ฆฌ์ ์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ €์—๊ฒŒ ์ ํ•ฉํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
๋‚ด section.body๊ฐ€ ์ฟผ๋ฆฌ๋˜๋ฉด HTML๋กœ ๋ฐ˜ํ™˜๋˜๋„๋ก createFieldExtension์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์ด ์•„๋‹ˆ๋ผ๋ฉด ๋ˆ„๊ตฐ๊ฐ€ ๋‚˜๋ฅผ ๋ฐ”๋กœ ์žก์œผ์‹ญ์‹œ์˜ค. ๋‚˜์—๊ฒŒ ํšจ๊ณผ๊ฐ€์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ์ด๊ฒƒ์ด ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ๋Š๋‚Œ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚ด frontmatter ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

templateKey: project-entry
date: 2020-06-22T13:16:57.702Z
featuredproject: true
title: Project title
description: Description for listing the project on other pages
featuredimage: Image for listing the project on other pages
featuredpost: false
sections:
  - heading: Section heading
    standout: false
    intro: >-
      Introduction to be displayed separately to body
    body: >-
       ## section title
       * bullet point
       * bullet point
       Some other text here

๊ทธ๋ฆฌ๊ณ  gatsby-node.js์—์„œ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ

exports.createSchemaCustomization = ({actions}) => {
  const { createTypes, createFieldExtension} = actions

  createFieldExtension({
    name: 'toHTML',
    extend:() => ({
        resolve(source) {
          return remark().use(remarkHTML).processSync(source.body).toString()
        }
      })
  })
  const typeDefs = `
  type MarkdownRemark implements Node {
    frontmatter: Frontmatter
  }
  type Frontmatter <strong i="14">@infer</strong> {
    sections: [section]
  }
  type section <strong i="15">@infer</strong> {
    body: String <strong i="16">@toHTML</strong>
  }
  `
  createTypes(typeDefs)
}

๊ด€์‹ฌ์ด์žˆ๋Š” ๋‹ค๋ฅธ ์‚ฌ๋žŒ์„ ์œ„ํ•ด ์‚ฌ์šฉ์ž ์ง€์ • YAML ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž„์˜์˜ ํ•„๋“œ๋ฅผ ๋งˆํฌ ๋‹ค์šด์œผ๋กœ ๊ตฌ๋ฌธ ๋ถ„์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

---
title: My Page
inline: !md Some **bold** and _italic_ text
block: !md |
  ## I'm a H2 title
  [I'm an inline-style link](https://www.google.com)
---

์ด๋ ‡๊ฒŒํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž ์ง€์ • ์œ ํ˜•์„ ๋งŒ๋“  ๋‹ค์Œ grey-matter์˜ YAML ํŒŒ์„œ๋ฅผ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

// custom-yaml.js
const yaml = require('js-yaml')
const remark = require('remark')
const remarkHTML = require('remark-html')

const MarkdownYamlType = new yaml.Type('!md', {
  kind: 'scalar',
  construct: data => remark().use(remarkHTML).processSync(data).toString(),
})

const MARKDOWN_SCHEMA = yaml.Schema.create(MarkdownYamlType)

module.exports = doc => yaml.safeLoad(doc, { schema: MARKDOWN_SCHEMA })
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        engines: { yaml: require("path/to/custom-yaml.js") },
      },
    }
  ]
}

๋‚˜๋Š” ์ด๊ฒƒ์„ ์กฐ๊ธˆ ๋‹ค๋ฅด๊ฒŒ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. @md ๋ผ๋Š” ํ•„๋“œ ํ™•์žฅ์„ ๋งŒ๋“ค๊ณ  ์›ํ•˜๋Š” ์ถ”์ƒํ™”๋ฅผ ์–ป์„ ์ˆ˜์žˆ๋Š” ํ•„๋“œ ์ด๋ฆ„ ๋ณ€๊ฒฝ๊ณผ ๊ฒฐํ•ฉ ๋œ frontmatter ์œ ํ˜• ์ •์˜์—์„œ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

exports.createSchemaCustomization = ({ actions }) => {
  actions.createFieldExtension({
    name: "md",
    args: {
      from: {
        type: "String!",
        defaultValue: true,
      },
    },

    extend() {
      return {
        args: {
          from: "String!",
        },
        resolve(source, args) {
          const fieldValue = source[args.from]
          return convertToHTML(fieldValue)
        },
      }
    },
  })
  const typeDefs = `
    type MarkdownRemark implements Node <strong i="7">@infer</strong> {
      frontmatter: Frontmatter
    }
    type Frontmatter {
      markdownField: String! <strong i="8">@md</strong>
    }
  `
  actions.createTypes(typeDefs)
}

๋‹ค์Œ์€ ์‚ฌ์šฉ ์˜ˆ์ž…๋‹ˆ๋‹ค.

...
frontmatter {
        title: markdownField(from: "title")
        subtitle: markdownField(from: "subtitle")
}

๋‚˜๋Š” ์ด๊ฒƒ์„ ์กฐ๊ธˆ ๋‹ค๋ฅด๊ฒŒ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž˜ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋จผ์ € from ์ธ์ˆ˜์— ๋Œ€ํ•ด defaultValue: true ์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด์ด์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. defaultValue: '' ๋ณ€๊ฒฝํ•˜๋ฉด ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Encountered an error parsing the provided GraphQL type definitions:
Argument "from" of required type "String!" was not provided.

  1 |
  2 |     type MarkdownRemark implements Node <strong i="11">@infer</strong> {
  3 |       frontmatter: Frontmatter
  4 |     }
  5 |     type Frontmatter {
> 6 |       markdownField: String! <strong i="12">@md</strong>
    |                              ^
  7 |     }

์ด๊ฒƒ์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.

๊ด€์‹ฌ์ด์žˆ๋Š” ๋‹ค๋ฅธ ์‚ฌ๋žŒ์„ ์œ„ํ•ด ์‚ฌ์šฉ์ž ์ง€์ • YAML ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž„์˜์˜ ํ•„๋“œ๋ฅผ ๋งˆํฌ ๋‹ค์šด์œผ๋กœ ๊ตฌ๋ฌธ ๋ถ„์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

---
title: My Page
inline: !md Some **bold** and _italic_ text
block: !md |
  ## I'm a H2 title
  [I'm an inline-style link](https://www.google.com)
---

์ด๋ ‡๊ฒŒํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž ์ง€์ • ์œ ํ˜•์„ ๋งŒ๋“  ๋‹ค์Œ grey-matter์˜ YAML ํŒŒ์„œ๋ฅผ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

// custom-yaml.js
const yaml = require('js-yaml')
const remark = require('remark')
const remarkHTML = require('remark-html')

const MarkdownYamlType = new yaml.Type('!md', {
  kind: 'scalar',
  construct: data => remark().use(remarkHTML).processSync(data).toString(),
})

const MARKDOWN_SCHEMA = yaml.Schema.create(MarkdownYamlType)

module.exports = doc => yaml.safeLoad(doc, { schema: MARKDOWN_SCHEMA })
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        engines: { yaml: require("path/to/custom-yaml.js") },
      },
    }
  ]
}

"gatsby-transformer-remark"์— ๋Œ€ํ•œ ์ž˜๋ชป๋œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์˜ต์…˜์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.์ด ๋ฐฉ๋ฒ•์„ ์‹œ๋„ํ•˜๋ฉด?

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰