Skip to content

Commit 3bb4dd9

Browse files
committed
Shows title in the preview pane
1 parent d433563 commit 3bb4dd9

13 files changed

+188
-26
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"@types/react-dom": "16.8.0",
2828
"@types/react-icons": "^2.2.6",
2929
"@types/react-outside-click-handler": "^1.2.0",
30-
"@types/react-redux": "^7.0.1",
30+
"@types/react-redux": "^7.0.6",
3131
"@types/react-router-dom": "^4.3.1",
3232
"@types/react-textarea-autosize": "^4.3.3",
3333
"@types/redux-devtools-extension": "^2.13.2",
@@ -93,7 +93,7 @@
9393
"react-dom": "^16.8.1",
9494
"react-icons": "^3.3.0",
9595
"react-outside-click-handler": "^1.2.3",
96-
"react-redux": "^6.0.1",
96+
"react-redux": "^7.0.1",
9797
"react-router-dom": "^4.3.1",
9898
"react-testing-library": "^5.9.0",
9999
"react-textarea-autosize": "^7.1.0",

src/components/write/MarkdownEditor.tsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import AddLink from './AddLink';
1414

1515
export interface MarkdownEditorProps {
1616
onChangeMarkdown: (markdown: string) => void;
17+
onChangeTitle: (title: string) => void;
18+
title: string;
1719
}
1820
type MarkdownEditorState = {
1921
shadow: boolean;
@@ -514,13 +516,22 @@ ${selected}
514516
codemirror.focus();
515517
};
516518

519+
handleTitleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
520+
this.props.onChangeTitle(e.target.value);
521+
};
522+
517523
public render() {
518524
const { shadow, addLink } = this.state;
525+
const { title } = this.props;
519526
return (
520527
<MarkdownEditorBlock ref={this.block} onScroll={this.handleScroll}>
521528
<div className="wrapper">
522529
<PaddingWrapper>
523-
<TitleTextarea placeholder="제목을 입력하세요" />
530+
<TitleTextarea
531+
placeholder="제목을 입력하세요"
532+
onChange={this.handleTitleChange}
533+
value={title}
534+
/>
524535
</PaddingWrapper>
525536
<Toolbar
526537
visible

src/components/write/MarkdownPreview.tsx

+16-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import MarkdownRender from '../common/MarkdownRender';
44
import palette from '../../lib/styles/palette';
55

66
const MarkdownPreviewBlock = styled.div`
7+
word-break: break-word;
8+
font-size: 1.3125rem;
79
&::-webkit-scrollbar {
810
border-radius: 3px;
911
width: 6px;
@@ -21,15 +23,27 @@ const MarkdownPreviewBlock = styled.div`
2123
padding: 3rem;
2224
flex: 1;
2325
overflow-y: auto;
26+
color: ${palette.gray9};
2427
`;
2528

26-
interface MarkdownPreviewProps {
29+
const Title = styled.h1`
30+
font-size: 2.5em;
31+
margin-bottom: 4rem;
32+
font-weight: 800;
33+
`;
34+
35+
export interface MarkdownPreviewProps {
2736
markdown: string;
37+
title: string;
2838
}
2939

30-
const MarkdownPreview: React.SFC<MarkdownPreviewProps> = ({ markdown }) => {
40+
const MarkdownPreview: React.SFC<MarkdownPreviewProps> = ({
41+
markdown,
42+
title,
43+
}) => {
3144
return (
3245
<MarkdownPreviewBlock>
46+
<Title>{title}</Title>
3347
<MarkdownRender markdown={markdown} />
3448
</MarkdownPreviewBlock>
3549
);

src/components/write/__tests__/MarkdownEditor.test.tsx

+32-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import * as React from 'react';
2-
import { render } from 'react-testing-library';
2+
import { render, fireEvent } from 'react-testing-library';
33
import MarkdownEditor, { MarkdownEditorProps } from '../MarkdownEditor';
44

55
describe('MarkdownEditor', () => {
66
const setup = (props: Partial<MarkdownEditorProps> = {}) => {
7-
const initialProps: MarkdownEditorProps = {};
7+
const initialProps: MarkdownEditorProps = {
8+
onChangeMarkdown: () => {},
9+
onChangeTitle: () => {},
10+
title: '',
11+
};
812
const utils = render(<MarkdownEditor {...initialProps} {...props} />);
9-
const titleTextarea = utils.getByPlaceholderText('제목을 입력하세요');
13+
const titleTextarea = utils.getByPlaceholderText(
14+
'제목을 입력하세요',
15+
) as HTMLTextAreaElement;
1016
return {
1117
titleTextarea,
1218
...utils,
@@ -19,4 +25,27 @@ describe('MarkdownEditor', () => {
1925
const { container } = setup();
2026
expect(container).toMatchSnapshot();
2127
});
28+
it('has codemirror editor', () => {
29+
const utils = setup();
30+
utils.getByText('당신의 이야기를 적어보세요...');
31+
});
32+
it('changes title properly', () => {
33+
const onChangeTitle = jest.fn();
34+
const utils = setup({
35+
onChangeTitle,
36+
});
37+
fireEvent.change(utils.titleTextarea, {
38+
target: {
39+
value: 'changed',
40+
},
41+
});
42+
expect(onChangeTitle).toBeCalledWith('changed');
43+
// expect(utils.titleTextarea.value).toBe('changed!');
44+
});
45+
it('uses title prop', () => {
46+
const utils = setup({
47+
title: 'hello world',
48+
});
49+
expect(utils.titleTextarea.value).toBe('hello world');
50+
});
2251
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as React from 'react';
2+
import { render } from 'react-testing-library';
3+
import MarkdownPreview, { MarkdownPreviewProps } from '../MarkdownPreview';
4+
5+
describe('MarkdownPreview', () => {
6+
const setup = (props: Partial<MarkdownPreviewProps> = {}) => {
7+
const initialProps: MarkdownPreviewProps = {
8+
markdown: '',
9+
title: '',
10+
};
11+
const utils = render(<MarkdownPreview {...initialProps} {...props} />);
12+
return {
13+
...utils,
14+
};
15+
};
16+
it('renders properly', () => {
17+
setup();
18+
});
19+
it('matches snapshot', () => {
20+
const { container } = setup();
21+
expect(container).toMatchSnapshot();
22+
});
23+
it('renders markdown', () => {
24+
const utils = setup({
25+
markdown: '## hello world',
26+
});
27+
const element = utils.getByText('hello world');
28+
expect(element.tagName).toBe('H2');
29+
});
30+
it('renders title', () => {
31+
const utils = setup({
32+
title: 'this is the title',
33+
});
34+
utils.getByText('this is the title');
35+
});
36+
});

src/components/write/__tests__/__snapshots__/MarkdownEditor.test.tsx.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
exports[`MarkdownEditor matches snapshot 1`] = `
44
<div>
55
<div
6-
class="sc-htoDjs fvjPke"
6+
class="sc-htoDjs jVrSIz"
77
>
88
<div
99
class="wrapper"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`MarkdownPreview matches snapshot 1`] = `
4+
<div>
5+
<div
6+
class="sc-bwzfXH iQyFQe"
7+
>
8+
<h1
9+
class="sc-htpNat gQoHLP"
10+
/>
11+
<div
12+
class="atom-one-light sc-bdVaJa eVCcCu"
13+
>
14+
15+
16+
</div>
17+
</div>
18+
</div>
19+
`;

src/components/write/__tests__/__snapshots__/Toolbar.test.tsx.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
exports[`Toolbar matches snapshot 1`] = `
44
<div>
55
<div
6-
class="sc-bdVaJa cnmSue"
6+
class="sc-bdVaJa dpLdTa"
77
id="toolbar"
88
>
99
<div

src/containers/write/MarkdownEditorContainer.tsx

+18-4
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,38 @@ import * as React from 'react';
22
import MarkdownEditor from '../../components/write/MarkdownEditor';
33
import { connect } from 'react-redux';
44
import { RootState } from '../../modules';
5-
import { changeMarkdown } from '../../modules/write';
5+
import { changeMarkdown, changeTitle } from '../../modules/write';
66

77
interface OwnProps {}
8-
interface StateProps {}
8+
interface StateProps {
9+
title: string;
10+
}
911
interface DispatchProps {
1012
changeMarkdown: typeof changeMarkdown;
13+
changeTitle: typeof changeTitle;
1114
}
1215
type MarkdownEditorContainerProps = OwnProps & StateProps & DispatchProps;
1316

1417
const MarkdownEditorContainer: React.SFC<MarkdownEditorContainerProps> = ({
1518
changeMarkdown,
19+
changeTitle,
20+
title,
1621
}) => {
17-
return <MarkdownEditor onChangeMarkdown={changeMarkdown} />;
22+
return (
23+
<MarkdownEditor
24+
title={title}
25+
onChangeMarkdown={changeMarkdown}
26+
onChangeTitle={changeTitle}
27+
/>
28+
);
1829
};
1930

2031
export default connect<StateProps, DispatchProps, OwnProps, RootState>(
21-
state => ({}),
32+
state => ({
33+
title: state.write.title,
34+
}),
2235
{
2336
changeMarkdown,
37+
changeTitle,
2438
},
2539
)(MarkdownEditorContainer);

src/containers/write/MarkdownPreviewContainer.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,22 @@ import { RootState } from '../../modules';
66
interface OwnProps {}
77
interface StateProps {
88
markdown: string;
9+
title: string;
910
}
1011
interface DispatchProps {}
1112
type MarkdownPreviewContainerProps = OwnProps & StateProps & DispatchProps;
1213

1314
const MarkdownPreviewContainer: React.SFC<MarkdownPreviewContainerProps> = ({
1415
markdown,
16+
title,
1517
}) => {
16-
return <MarkdownPreview markdown={markdown} />;
18+
return <MarkdownPreview markdown={markdown} title={title} />;
1719
};
1820

1921
export default connect<StateProps, DispatchProps, OwnProps, RootState>(
2022
({ write }) => ({
2123
markdown: write.markdown,
24+
title: write.title,
2225
}),
2326
dispatch => ({}),
2427
)(MarkdownPreviewContainer);

src/modules/__tests__/write.test.ts

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ describe('write redux module', () => {
88
const state = getInitialState();
99
expect(state).toEqual({
1010
markdown: '',
11+
title: '',
1112
});
1213
});
1314
describe('action handlers', () => {
@@ -16,5 +17,10 @@ describe('write redux module', () => {
1617
state = reducer(state, write.changeMarkdown('Hello'));
1718
expect(state.markdown).toBe('Hello');
1819
});
20+
it('CHANGE_TITLE', () => {
21+
let state = getInitialState();
22+
state = reducer(state, write.changeTitle('World'));
23+
expect(state.title).toBe('World');
24+
});
1925
});
2026
});

src/modules/write.ts

+9
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@ import { createStandardAction } from 'typesafe-actions';
22
import { createReducer } from '../lib/utils';
33

44
const CHANGE_MARKDOWN = 'write/CHANGE_MARKDOWN';
5+
const CHANGE_TITLE = 'write/CHANGE_TITLE';
56

67
export const changeMarkdown = createStandardAction(CHANGE_MARKDOWN)<string>();
8+
export const changeTitle = createStandardAction(CHANGE_TITLE)<string>();
79

810
type ChangeMarkdown = ReturnType<typeof changeMarkdown>;
11+
type ChangeTitle = ReturnType<typeof changeTitle>;
912

1013
export type WriteState = {
1114
markdown: string;
15+
title: string;
1216
};
1317

1418
const initialState: WriteState = {
1519
markdown: '',
20+
title: '',
1621
};
1722

1823
const write = createReducer(
@@ -21,6 +26,10 @@ const write = createReducer(
2126
...state,
2227
markdown: action.payload,
2328
}),
29+
[CHANGE_TITLE]: (state, action: ChangeTitle) => ({
30+
...state,
31+
title: action.payload,
32+
}),
2433
},
2534
initialState,
2635
);

0 commit comments

Comments
 (0)