EJS를 사용한 마크다운 블로그

20300 단어 expresswebdevnodeejs
이 게시물은 EJS로 Markdown 블로그를 만드는 방법에 관한 것입니다.

소개



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에서 영감을 받아 일부 개선 사항과 모든 세부 정보를 제공합니다.

요구 사항



마법 주문을 실행하려면 다음 패키지가 필요합니다.
  • 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,
    레브시트

    좋은 웹페이지 즐겨찾기