Skip to content

Commit 5eb38ce

Browse files
committed
feat(blog-post): 블로그 포스트 화면 대응
- mdx 포맷 지원을 위한 gatsby 플러그인 추 - 'gatsby-browser.js'와 'gatsby-ssr.js'에서 사용되는 동일한 로직을 'gatsby' 디렉토리 하위로 분리 - 이미지 포맷 확장자에 대한 타입 지원 추가 - mdx 내에서 사용되는 컴포넌트 스타일을 커스터마이징하기 위한 'mdx-components' 추가 - 블로그 포스트 화면 UI 스타일링 Signed-off-by: chayeoi <[email protected]>
1 parent 06054cb commit 5eb38ce

19 files changed

+479
-66
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ gatsby-browser.js
33
gatsby-config.js
44
gatsby-node.js
55
gatsby-ssr.js
6+
gatsby/

gatsby-browser.js

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
11
import 'gatsby-image/withIEPolyfill'
22

3-
import React from 'react'
4-
import { Global } from '@emotion/core'
5-
import { ThemeProvider } from 'emotion-theming'
3+
export { wrapRootElement } from './gatsby'
64

7-
import global from './src/styles/global'
8-
import theme from './src/styles/theme'
9-
10-
export const wrapRootElement = ({ element }) => (
11-
<ThemeProvider theme={theme}>
12-
<Global styles={global} />
13-
{element}
14-
</ThemeProvider>
15-
)

gatsby-config.js

+41-35
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module.exports = {
2323
about: {
2424
title: '개발자 김찬연',
2525
content: [
26-
{ key: 0, value: `수학교육을 전공한 후 좋은 기회가 생겨 개발을 시작했고, 현재는 에듀테크 스타트업 클래스팅에서 ${currentYear - FIRST_YEAR + 1}년째 교육 서비스를 만들고 있습니다. 웹 표준과 새로운 기술 동향에 관심이 많습니다.` },
26+
{ key: 0, value: `수학교육을 전공한 후 창업 공부를 하다가 개발을 시작했고, 현재는 에듀테크 스타트업 클래스팅에서 ${currentYear - FIRST_YEAR + 1}년째 교육 서비스를 만들고 있습니다. 웹 표준과 새로운 기술 동향에 관심이 많습니다.` },
2727
{ key: 1, value: '\n' },
2828
{ key: 2, value: '음, 그런데 무슨 내용을 더 써야할 지 아직 모르겠.. 나중에 천천히 채워넣도록 하겠습니다. 그럼 이만! 😆' },
2929
],
@@ -33,35 +33,11 @@ module.exports = {
3333
plugins: [
3434
'gatsby-plugin-emotion',
3535
'gatsby-plugin-lodash',
36-
'gatsby-plugin-mdx',
37-
'gatsby-plugin-react-helmet',
38-
'gatsby-plugin-sharp',
39-
'gatsby-plugin-sitemap',
40-
'gatsby-plugin-typescript',
41-
{
42-
resolve: 'gatsby-plugin-google-analytics',
43-
options: {
44-
trackingId: 'YOUR_GOOGLE_ANALYTICS_TRACKING_ID',
45-
},
46-
},
47-
{
48-
resolve: 'gatsby-source-filesystem',
49-
options: {
50-
name: 'assets',
51-
path: `${__dirname}/src/assets/`,
52-
},
53-
},
5436
{
55-
resolve: 'gatsby-source-filesystem',
37+
resolve: 'gatsby-plugin-mdx',
5638
options: {
57-
name: 'posts',
58-
path: `${__dirname}/src/posts/`,
59-
},
60-
},
61-
{
62-
resolve: 'gatsby-transformer-remark',
63-
options: {
64-
plugins: [
39+
extensions: ['.mdx', '.md'],
40+
gatsbyRemarkPlugins: [
6541
{
6642
resolve: 'gatsby-remark-images',
6743
options: {
@@ -70,30 +46,60 @@ module.exports = {
7046
},
7147
},
7248
{
73-
resolve: 'gatsby-remark-images-medium-zoom',
49+
resolve: 'gatsby-remark-responsive-iframe',
7450
options: {
75-
margin: 36,
76-
scrollOffset: 0,
51+
wrapperStyle: 'margin-bottom: 1.0725rem',
7752
},
7853
},
7954
{
80-
resolve: 'gatsby-remark-responsive-iframe',
55+
resolve: 'gatsby-remark-autolink-headers',
8156
options: {
82-
wrapperStyle: 'margin-bottom: 1.0725rem',
57+
enableCustomId: true,
58+
icon: '<svg aria-hidden="true" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="icon-7f6730be--text-3f89f380"><g><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></g></svg>',
59+
isIconAfterHeader: true,
60+
maintainCase: false,
8361
},
8462
},
8563
{
8664
resolve: 'gatsby-remark-prismjs',
8765
options: {
88-
inlineCodeMarker: '%',
66+
classPrefix: 'language-',
67+
inlineCodeMarker: {
68+
tsx: 'tsx',
69+
},
70+
showLineNumbers: true,
71+
noInlineHighlight: false,
8972
},
9073
},
91-
'gatsby-remark-autolink-headers',
9274
'gatsby-remark-copy-linked-files',
9375
'gatsby-remark-smartypants',
9476
],
9577
},
9678
},
79+
'gatsby-plugin-react-helmet',
80+
'gatsby-plugin-sharp',
81+
'gatsby-plugin-sitemap',
82+
'gatsby-plugin-typescript',
83+
{
84+
resolve: 'gatsby-plugin-google-analytics',
85+
options: {
86+
trackingId: 'YOUR_GOOGLE_ANALYTICS_TRACKING_ID',
87+
},
88+
},
89+
{
90+
resolve: 'gatsby-source-filesystem',
91+
options: {
92+
name: 'assets',
93+
path: `${__dirname}/src/assets/`,
94+
},
95+
},
96+
{
97+
resolve: 'gatsby-source-filesystem',
98+
options: {
99+
name: 'posts',
100+
path: `${__dirname}/src/posts/`,
101+
},
102+
},
97103
'gatsby-remark-autolink-headers',
98104
'gatsby-remark-copy-linked-files',
99105
'gatsby-remark-smartypants',

gatsby-ssr.js

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
11
import 'gatsby-image/withIEPolyfill'
22

3-
import React from 'react'
4-
import { Global } from '@emotion/core'
5-
import { ThemeProvider } from 'emotion-theming'
3+
export { wrapRootElement } from './gatsby'
64

7-
import global from './src/styles/global'
8-
import theme from './src/styles/theme'
9-
10-
export const wrapRootElement = ({ element }) => (
11-
<ThemeProvider theme={theme}>
12-
<Global styles={global} />
13-
{element}
14-
</ThemeProvider>
15-
)

gatsby/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as wrapRootElement } from './wrap-root-element'

gatsby/wrap-root-element.tsx

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Global } from '@emotion/core'
2+
import { MDXProvider } from '@mdx-js/react'
3+
import { ThemeProvider } from 'emotion-theming'
4+
import React from 'react'
5+
6+
import * as MDXComponents from '../src/components/mdx-components'
7+
import global from '../src/styles/global'
8+
import theme from '../src/styles/theme'
9+
10+
interface Components {
11+
[key: string]: React.FC;
12+
}
13+
14+
const components: Components = {
15+
a: MDXComponents.Anchor,
16+
h1: MDXComponents.H1,
17+
h2: MDXComponents.H2,
18+
h3: MDXComponents.H3,
19+
h4: MDXComponents.H4,
20+
h5: MDXComponents.H5,
21+
h6: MDXComponents.H6,
22+
ul: MDXComponents.UnorderedList,
23+
ol: MDXComponents.OrderedList,
24+
li: MDXComponents.ListItem,
25+
p: MDXComponents.Paragraph,
26+
}
27+
28+
const wrapRootElement = ({ element }: { element: React.ReactNode }): React.ReactNode => (
29+
<ThemeProvider theme={theme}>
30+
<MDXProvider components={components}>
31+
<Global styles={global} />
32+
{element}
33+
</MDXProvider>
34+
</ThemeProvider>
35+
)
36+
37+
export default wrapRootElement;

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"@emotion/core": "^10.0.27",
99
"@mdx-js/mdx": "^1.5.5",
1010
"@mdx-js/react": "^1.5.5",
11+
"@types/mdx-js__react": "^1.5.0",
1112
"emotion-theming": "^10.0.27",
1213
"gatsby": "^2.19.7",
1314
"gatsby-image": "^2.2.40",
@@ -33,6 +34,8 @@
3334
"gatsby-transformer-remark": "^2.6.50",
3435
"gatsby-transformer-sharp": "^2.3.14",
3536
"lodash": "^4.17.15",
37+
"mdx-utils": "^0.2.0",
38+
"prism-react-renderer": "^1.0.2",
3639
"prismjs": "^1.19.0",
3740
"prop-types": "^15.7.2",
3841
"react": "^16.12.0",
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/** @jsx jsx */
2+
import { css, jsx, SerializedStyles } from '@emotion/core'
3+
4+
import { Theme } from '../../styles/theme'
5+
6+
export const Anchor: React.FC = props => <a css={s.a} {...props} />
7+
8+
const s = {
9+
a: (theme: Theme): SerializedStyles => css`
10+
color: ${theme.palette.primary.main};
11+
:hover {
12+
text-decoration: underline;
13+
}
14+
`,
15+
}
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/** @jsx jsx */
2+
import { css, jsx } from '@emotion/core'
3+
4+
export const H1: React.FC = props => <h1 css={s.h1} {...props} />
5+
6+
export const H2: React.FC = props => <h1 css={s.h2} {...props} />
7+
8+
export const H3: React.FC = props => <h1 css={s.h3} {...props} />
9+
10+
export const H4: React.FC = props => <h1 css={s.h4} {...props} />
11+
12+
export const H5: React.FC = props => <h1 css={s.h5} {...props} />
13+
14+
export const H6: React.FC = props => <h1 css={s.h6} {...props} />
15+
16+
const s = {
17+
h1: css`
18+
margin: 3rem 0 1.5rem;
19+
font-size: 1.625rem;
20+
font-weight: 700;
21+
`,
22+
h2: css`
23+
margin: 3rem 0 1.5rem;
24+
font-size: 1.5rem;
25+
font-weight: 700;
26+
`,
27+
h3: css`
28+
margin: 2rem 0 1rem;
29+
font-size: 1.375rem;
30+
font-weight: 700;
31+
`,
32+
h4: css`
33+
margin: 2rem 0 1rem;
34+
font-size: 1.25rem;
35+
font-weight: 700;
36+
`,
37+
h5: css`
38+
margin: 1.5rem 0 0.75rem;
39+
font-size: 1.125rem;
40+
font-weight: 700;
41+
`,
42+
h6: css`
43+
margin: 1.5rem 0 0.75rem;
44+
font-size: 1rem;
45+
font-weight: 700;
46+
`,
47+
}
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './anchor'
2+
export * from './headings'
3+
export * from './list'
4+
export * from './paragraph'
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/** @jsx jsx */
2+
import { css, jsx } from '@emotion/core'
3+
4+
export const UnorderedList: React.FC = props => <ul css={s.ul} {...props} />
5+
6+
export const OrderedList: React.FC = props => <ol css={s.ol} {...props} />
7+
8+
export const ListItem: React.FC = props => <li css={s.li} {...props} />
9+
10+
const s = {
11+
ul: css`
12+
margin-bottom: 1.5rem;
13+
padding-left: 32px;
14+
list-style-type: disc;
15+
`,
16+
ol: css`
17+
margin-bottom: 1.5rem;
18+
padding-left: 32px;
19+
list-style-type: decimal;
20+
`,
21+
li: css`
22+
margin-bottom: 0.75rem;
23+
`,
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/** @jsx jsx */
2+
import { css, jsx } from '@emotion/core'
3+
4+
export const Paragraph: React.FC = props => <p css={s.p} {...props} />
5+
6+
const s = {
7+
p: css`
8+
margin-bottom: 1.5rem;
9+
`,
10+
}

src/styles/global.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { css, SerializedStyles } from '@emotion/core'
22

3+
import mdx from './mdx'
34
import { Theme } from './theme'
45

56
const global = (theme: Theme): SerializedStyles => css`
@@ -89,6 +90,10 @@ const global = (theme: Theme): SerializedStyles => css`
8990
font-weight: bolder;
9091
}
9192
93+
em {
94+
font-style: italic;
95+
}
96+
9297
dfn {
9398
font-style: italic;
9499
}
@@ -217,7 +222,9 @@ const global = (theme: Theme): SerializedStyles => css`
217222
word-break: keep-all;
218223
font-family:
219224
'Avenir Next',
225+
'Futura PT',
220226
'Spoqa Han Sans',
227+
'spoqahansans',
221228
'Apple SD Gothic Neo',
222229
'Nanum Barun Gothic',
223230
'Nanum Gothic',
@@ -231,6 +238,7 @@ const global = (theme: Theme): SerializedStyles => css`
231238
-webkit-font-smoothing: antialiased;
232239
-moz-osx-font-smoothing: grayscale;
233240
}
241+
${mdx}
234242
`
235243

236244
export default global

0 commit comments

Comments
 (0)