EJS를 사용한 마크다운 블로그
소개
HTML을 사용하여 게시물 내용을 작성하는 것은 Markdown을 사용하는 것만큼 쉽지 않습니다.
back to the roots whit a static site 오고 나서 Markdown으로 게시물 콘텐츠를 작성합니다.
그 후 얼마 지나지 않아 Deta Cloud을 발견했고 Node.js에 대해 배운 모든 것을 라이브 서버에서 사용해 볼 수 있었습니다.
내가 가장 좋아하는 템플릿 언어는 EJS 이며 Markdown 파일의 콘텐츠를 EJS 템플릿과 결합하여 아주 간단한 블로그를 만들고 싶었습니다.
많은 연구와 시도와 실패 끝에 목표를 달성하는 데 필요한 메커니즘을 이해했습니다.
이 주제에 대한 몇 가지 자습서를 찾았고 이 자습서는 내가 우연히 발견한 마지막 항목인 Building A Markdown Blog App with Express and EJS에서 영감을 받아 일부 개선 사항과 모든 세부 정보를 제공합니다.
요구 사항
마법 주문을 실행하려면 다음 패키지가 필요합니다.
Express , Node.js용 웹 프레임워크
gray-matter , Markdown 파일에서 머리말을 구문 분석하기 위해
markdown-it , Markdown 파일 내용을 구문 분석하기 위해
하나의 명령으로 설치하려면 다음을 수행하십시오.
npm i ejs express gray-matter markdown-it
서버 설정
메인 서버 파일에서 내 것은
index.js
입니다. 다음을 입력하십시오.// /index.js
const express = require("express")
const app = express()
// Built-in module to access and interact with the file system
const fs = require("fs")
// To parse front matter from Markdown files
const matter = require("gray-matter")
app.set("view engine", "ejs")
app.use(express.static("public"))
const getPosts = () => {
// Get the posts from their directory
const posts = fs.readdirSync(__dirname + "/views/posts").filter((post) => post.endsWith(".md"))
// Set the post content as an empty array
const postContent = []
// Inject into the post content array the front matter
posts.forEach((post) => {
postContent.push(matter.read(__dirname + "/views/posts/" + post))
})
/**
* 1- Return a list of posts as a two dimensional array containing for each one :
* . the post filename with it's extension (e.g : postFilename.md)
* . the post content as an object {content:"Markdown content as a string", data:{front matter}, excerpt:""}
* 2- Return each array as an object and create a Date instance from it's date front matter
* 3- Sort posts by publication's date in descending order (newest to oldest)
*/
const postsList = posts
.map(function (post, i) {
return [post, postContent[i]]
})
.map((obj) => {
return { ...obj, date: new Date(obj[1].data.date) }
})
.sort((objA, objB) => Number(objB.date) - Number(objA.date))
return postsList
}
// Render the list of posts on the main route
app.get("/", (req, res) => {
res.render("postsList", {
posts: getPosts(),
})
})
// Using a route parameter to render each post on a route matching it's filename
app.get("/posts/:post", (req, res) => {
const postTitle = req.params.post // Get the Markdown filename
// Read the Markdown file and parse it's front matter
const post = matter.read(__dirname + "/views/posts/" + postTitle + ".md")
// Convert the Markdown file content to HTML with markdown-it
const md = require("markdown-it")({ html: true }) // Allows HTML tags inside the Markdown file
const content = post.content // Read the Markdown file content
const html = md.render(content) // Convert the Markdown file content to HTML
// Render the postsTemplate for each post and pass it's front matter as a data object into postsTemplate
res.render("postsTemplate", {
title: post.data.title,
date: post.data.date,
postContent: html,
})
})
// Launching the application on port 3000
app.listen(3000, () => {
console.log(`App 🚀 @ http://localhost:3000`)
})
보시다시피 모든 것이 자세히 설명되어 있습니다.
참고: 저는 views 폴더를 템플릿 파일 위치로 직접 사용하고 있습니다. 선언할 필요가 없습니다. Express는 기본적으로 이를 감지하고 Markdown 파일은 posts라는 다른 폴더 내의 views 폴더 아래에 있습니다.
한 가지 특정한 점에 주의를 기울이고 싶습니다.
postTemplate
를 렌더링하고 Markdown 머리말과 콘텐츠를 데이터 객체로 전달할 때 원하는 만큼 key: value
쌍을 추가하고 전달할 수 있지만 key
내부에서 정의되지 않은postTemplate
을 호출할 수는 없습니다. ) !그래서 마크다운 파일의 머리말에
description: my post description
를 추가하면 데이터 객체에 추가하지 않고는 postTemplate
내부에서 직접 호출할 수 없다.참고: 템플릿 파일의 확장자
.ejs
를 선언할 필요가 없습니다. Express는 기본적으로 이를 감지합니다.프런트엔드 렌더링
index.js
에서 본 것처럼 postsList.ejs
라는 템플릿에서 기본 경로의 게시물 목록을 렌더링하고 있습니다. 이 파일에 다음을 추가합니다.<!-- /views/postsList.ejs -->
<!DOCTYPE html>
<html lang="en">
<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" />
<title>Home | My blog</title>
</head>
<body>
<h1>
Welcome to my blog
<br />
List of recent posts
</h1>
<% posts.forEach(post => { %>
<!-- Get the Markdown filename without it's extension -->
<% const postFilename = post[0].replace(/\.[^/.]+$/, "") %>
<!-- Get the Markdown post title from it's front matter -->
<% const postTitle = post[1].data.title %>
<!-- Render the title as a link to the post -->
<h2><a href="/posts/<%= postFilename %>"><%= postTitle%></a></h2>
<% }) %>
</body>
</html>
이제 각 게시물은
postsTemplate.ejs
라는 하나의 템플릿 파일이라는 동일한 구조를 가집니다. 여기에 다음을 추가합니다.<!-- /views/postsTemplate.ejs -->
<!DOCTYPE html>
<html lang="en">
<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" />
<title><%= title %> | My blog</title>
</head>
<body>
<h1><%= title %></h1>
<p><%= date %></p>
<div><%- postContent %></div>
</body>
</html>
모든 것이 제자리에 있으므로 이제
views
폴더 아래의 posts
폴더에 Markdown을 사용하여 게시물을 작성할 수 있습니다 🥳시도하면 출력을 볼 수 있도록 두 개의 파일을 만들었습니다.
---
title: "My first article"
date: 2022/07/23
---
This is the content of my first article
<!--- /views/posts/my-first-article.md -->
---
title: "A second post"
date: 2022/07/25
---
Here goes the content of my second post
<!--- /views/posts/a-second-post.md -->
앱 구조는 다음 트리와 같습니다.
// App's structure without the node_modules folder
├── index.js
├── package-lock.json
├── package.json
└── views
├── posts
│ ├── a-second-post.md
│ └── my-first-article.md
├── postsList.ejs
└── postsTemplate.ejs
이 튜토리얼이 EJS로 Markdown 블로그를 만들려는 모든 사람에게 도움이 되기를 바랍니다.
질문이 있으시면 주저하지 마십시오.
지금까지 읽어주셔서 감사합니다 💗
SYA,
레브시트
Reference
이 문제에 관하여(EJS를 사용한 마크다운 블로그), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/lebcit/markdown-blog-with-ejs-ogl텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)