Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Api
148 changes: 148 additions & 0 deletions css/reset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
button {
border: none;
background-color: transparent;
padding: 0;
margin: 0;
}
input {
border: none;
outline: none;
}
textarea {
border: none;
resize: none;
outline: none;
}
input::placeholder,
textarea::placeholder {
color: #d7d7d7;
}
126 changes: 126 additions & 0 deletions css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
main {
display: flex;
width: 100%;
height: 100vh;
}

div.left {
width: 20%;
background-color: #f7f5f0;
color: #696969;
}

.left .header {
width: 100%;
height: 10%;
display: flex;
align-items: center;
}

.left .header h2 {
font-size: 20px;
font-weight: 500;
margin-left: 15px;
}

.left .postList {
width: 100%;
height: 90%;
overflow-y: auto;
}

.postList ul {
padding-left: 1.5vh;
cursor: pointer;
}

.document {
width: 100%;
height: fit-content;
padding: 1.5vh 0;
display: flex;
align-items: center;
justify-content: flex-end;
}

.document:hover {
background-color: #e8e6e0de;
}

.document span {
width: 75%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 15px;
margin-right: 5px;
}

.document button {
width: 30px;
height: 30px;
font-size: 20px;
border-radius: 5px;
margin-right: 5px;
color: #565656;
cursor: pointer;
}

.document button:hover {
background-color: #cac8c5cc;
}

.new-post {
width: 100%;
height: fit-content;
padding: 15px 0;
font-size: 20px;
text-align: left;
padding-left: 15px;
color: #565656;
cursor: pointer;
}

.new-post:hover {
background-color: #e8e6e0de;
}

div.right {
display: flex;
justify-content: center;
align-items: center;
width: 80%;
}

.editor {
width: 80%;
height: 80%;
display: flex;
flex-direction: column;
justify-content: space-between;
}

.editor input {
width: 100%;
padding: 10px 0;
font-size: 45px;
font-weight: 700;
}

.editor div:focus {
outline: none;
}

.content-container:empty:before {
content: attr(placeholder);
display: block;
color: rgb(174, 174, 174);
}

.content-container {
width: 100%;
height: 84%;
font-size: 25px;
padding: 10px 0;
overflow-y: auto;
}
15 changes: 15 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/reset.css" />
<link rel="stylesheet" href="./css/style.css" />
<title>Notion cloning</title>
</head>
<body>
<main id="app"></main>
<script src="./src/main.js" type="module"></script>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<script src="./src/main.js" type="module"></script>
<script src="/src/main.js" type="module"></script>

History API를 이용해 SPA형태로 만드려면 상대경로가 아닌 절대경로로 하셔야 한다고 들었습니다 !
URL이 바뀌는 걸 기준으로 src를 참조하기 때문에 문제가 생길 수도 있다네요 🧐

</body>
</html>
57 changes: 57 additions & 0 deletions src/Editor/editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { request } from "../../Api/api.js";

export default function Editor({ $target, initialState }) {
const $editor = document.createElement("div");
const $div = document.createElement("div");
$editor.setAttribute("class", "right");
$div.setAttribute("class", "editor");

$target.appendChild($editor);
$editor.appendChild($div);

this.state = initialState;

this.handleRevise = () => {
const plusEvent = new CustomEvent("@ReviseCompleted");
$editor.dispatchEvent(plusEvent);
};

this.render = () => {
$div.innerHTML = `
<input type="text" name="title" placeholder="제목 없음" />
<div class="content-container" name="content" contentEditable="true" placeholder="내용을 입력해주세요."></div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contentEditable을 사용하고 난 후의 rich Editor 처리 부분이 추가되면 좋을 것 같아요 ㅎㅎ textarea 대신 사용한 의미를 위해서요!

`;
};
this.render();

this.setState = (nextState) => {
this.state = nextState;
$div.querySelector("[name=title]").value = this.state.title;
$div.querySelector("[name=content]").innerHTML = this.state.content;
};

$div.querySelector("[name=title]").addEventListener("keyup", async (e) => {
e.preventDefault();
const $input = $div.querySelector("input");
await request(`/documents/${this.state.id}`, {
method: "PUT",
body: JSON.stringify({
title: $input.value,
}),
});
this.handleRevise();
});

$editor
.querySelector("[name=content]")
.addEventListener("input", async (e) => {
e.preventDefault();
await request(`/documents/${this.state.id}`, {
method: "PUT",
body: JSON.stringify({
content: e.target.innerHTML,
}),
});
this.handleRevise();
});
}
Loading