如何将Markdown转换成HTML

作者 : IT 大叔 本文共5103个字,预计阅读时间需要13分钟 发布时间: 2020-11-19

谈到MarkdownHTML是一个非常有用的任务。Markdown可以简化语法,减少嵌套,也可以简化文档的阅读和阅读。本教程将介绍读取Markdown文件并将其转换为HTML可以在博客上使用的步骤,就像我在我的网站上所做的那样,或将其用于您希望更容易编辑潜力的任何其他目的。本教程将在Next.js博客上使用这些概念,但是无需了解这些部分即可了解其工作原理。

尽管此帖子是系列文章的一部分,但其目的是使该文章能够相对独立地站立,即使您不关注该系列教程,您也应该可以带走一些知识。如果您有兴趣,教程系列将从这里开始:第1部分


先决条件

本教程的先决条件在第1部分中进行了说明,本教程中将使用的组件来自本系列的先前部分:

从零开始编写博客网站:初始化Next.js项目

从零开始编写博客网站:在Next.js中路由

从零开始编写博客网站:Next.js中的样式化组件


利用前题

能够将元数据连接到Markdown您编写的文档非常有用,这通常是通过所谓的“前沿问题”(有时是“ YAML前沿问题”)完成的。一个示例如下所示:

复制
---
date: "2020-11-15 09:31"
title: "My first blog post!"
slug: "my-first-blog-post"
---

首先,我们需要一些库来帮助我们简化此任务,安装两个新的依赖项:

复制
yarn add -D marked front-matter
  • marked将被用来Markdown变成HTML
  • front-matter将从Front Matter我们的Markdown文档中提取元数据

我们的首要任务是Front MatterMarkdown文档中启用。

首先在项目的根目录中创建一个文件夹,然后调用它,posts然后在该目录中创建一个文件posts/my_first_post.md

复制
---
date: "2020-11-15 09:31"
title: "My first blog post!"
slug: "my-first-blog-post"
---

Welcome to my first blog post :)

```javascript
// Look, we have highlighting!

const a = 5;
const b = "Testing";

function yay() {
    console.log("Yay!");
}
```

现在Markdown已经创建了第一个文件的基础,让我们编写一些代码来读取此文件夹中的帖子,并使用此元数据生成对象,HTML以便我们可以在页面上使用它:

如果一直遵循,请转到pages/_posts.js,否则创建一个新文件,其中将包含用于读取posts目录的代码:

复制
// pages/_posts.js

const fs = require("fs");
const marked = require("marked");
const fm = require("front-matter");

const postFiles = fs.readdirSync("posts");
const posts = [];
for (let i = 0; i < postFiles.length; i++) {
    const postContent = fs.readFileSync(`posts/${postFiles[i]}`, {
        encoding: "utf-8",
    });
    const { body, ...frontMatter } = fm(postContent);
    posts.push({
        html: marked(body),
        ...frontMatter,
    });
}

// posts will now be an array of objects with the following structure:
/*
posts = [
    {
        attributes: { date, title, slug } <- from our front matter,
        html: "A string with our HTML content"
    }
]
*/

export default posts;

由于我们要从中公开一个新结构,因此pages/_posts.js我们还需要更改BlogPagepages/blog/index.js这些文件中定义的组件的呈现方式,因此只有Component部分已更改,其余部分保持不变。这是现在的样子:

复制
// part of `pages/blog/index.js`
const BlogPage = ({ posts }) => {
  return (
    <Main>
      <Ul>
        {posts.map((post) => (
          <Li key={post.attributes.slug}>
            <Link href={`blog/${post.attributes.slug}`}>
              <a>
                <BlogLink>
                  <h3>{post.attributes.title}</h3>
                  <h5>{post.attributes.date}</h5>
                </BlogLink>
              </a>
            </Link>
          </Li>
        ))}
      </Ul>
    </Main>
  )
}

注意,我们在Front Matter这里访问.attributes对象的属性。

我们pages/blog/[slug].js还需要更新,因为它也以旧的方式阅读帖子。所有的引用titleslug以及date现在从嵌套对象。这是更新的文件:

复制
// `pages/blog/[slug].js`
import styled from "styled-components"
import posts from "../_posts"

const Article = styled.article`
  max-width: 56em;
  padding: 0.8em;
  margin: 0 auto;
`

const BlogPost = ({ post }) => (
  <Article>
    <h1>{post.attributes.title}</h1>
    <p>{post.attributes.date}</p>
  </Article>
)
export default BlogPost

export async function getStaticPaths() {
  return {
    paths: posts.map((post) => ({ params: { slug: post.attributes.slug } })),
    fallback: false,
  }
}

export async function getStaticProps({ params }) {
  return {
    props: {
      post: posts.find((post) => post.attributes.slug === params.slug),
    },
  }
}

您现在应该可以像在上一步中一样使用页面,但是该信息现在是动态的,并且来自目录Markdown中的posts文件!例如,尝试添加另一条帖子,它应该显示在我们的第一篇博客文章的旁边。但是请注意,在posts目录中更改文件时yarn dev,必须重新启动dev服务器(),因为这些文件仅被读取和解析一次(由生成页面时Next.js)。


显示HTML内容

到目前为止,我们的职位只显示从该数据Front Matter中的Markdown文件,我们也让他们显示HTML的内容。这样做React很容易,但是听起来很危险:

复制
// part of pages/blog/[slug].js
const BlogPost = ({ post }) => (
  <Article>
    <h1>{post.attributes.title}</h1>
    <p>{post.attributes.date}</p>
    <div className="blog-post-content" dangerouslySetInnerHTML={{ __html: post.html }}></div>
  </Article>
)
export default BlogPost

dangerouslySetInnerHTML准确地命名。通常这不是一件好事,但是当您有一个要呈现为实际HTML的HTML字符串时,这就是方法。除非您完全控制在这里传递的字符串,否则永远不要这样做!

className这里指定为简单string。这样一来,我们就可以在全局样式表中设置所有与博客文章相关的内容的样式,因为这些元素是在dangerouslySetInnerHTML零件中创建的,目前无法访问。

现在刷新博客文章页面之一,您应该看到该文章内容显示出来。

现在,即使帖子的内容是动态的,也可以从文件中读取,然后继续更改文件中最重要的内容,posts/my_first_post.md然后重新启动服务器,您应该看到页面上的内容也已更改。

您可能已经尝试了代码块,Markdown并意识到它没有任何语法高亮显示,如果您想知道如何使它工作,请阅读下一节。


添加语法突出显示

代码块很好。但是,如果它们实际上包含语法突出显示,它们甚至会更好。为此,我们将使用一个名为的库highlight.js

复制
yarn add -D highlight.js

要使用此库,我们必须采取两个步骤,一个步骤是包括一个主题样式表,另一个是marked使用我们早先安装的库来使用highlight.jslib。

让我们开始marked使用文件中的highlight.jspages/_posts.js

复制
// Add this below the require statements at the top of `pages/_posts.js` 
const hljs = require("highlight.js")

marked.setOptions({
    highlight: function (code, lang) {
        if (lang) return hljs.highlight(lang, code).value;
        return code
    }
});

这样一来,当marked跨代码块运行时,它将运行该hljs.highlight函数并将相应元素的类放入HTML由生成的字符串中marked

然后,确保BlogPostpages/blog/[slug].js文件的组件中导入主题:

复制
const BlogPost = ({ post }) => (
  <Article>
    <Head><link
      rel="stylesheet"
      href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/styles/atom-one-dark-reasonable.min.css"
    /></Head>
    <h1>{post.attributes.title}</h1>
    <p>{post.attributes.date}</p>
    <div className="blog-post-content" dangerouslySetInnerHTML={{ __html: post.html }}></div>
  </Article>
)
export default BlogPost

确保也将import Head from "next/head"文件放在顶部,以从中导入Head组件Next.js

此处提供更多主题:https://highlightjs.org/static/demo/。替换hreflink与您所选择的主题元素,它应该工作。


样式化我们生成的HTML

在上一篇文章中,我们只是对自己创建的组件进行样式设置。现在,marked将为我们创建一堆组件。让我们尝试在中进行一些样式设置styles/globals.css

如果此时您完全了解了本系列教程,那么您的页面将如下所示:

如何将Markdown转换成HTML插图

这并不可怕,但是很明显,代码块确实可以使用背景,在我看来,它与其他文本的区别还不够。现在开始吧。

在本文的前面,我们在content元素上定义了一个名为的类blog-post-content。此类是我们用于定位博客文章元素的类。检查该元素,您会发现代码块只是一个<pre>带有<code>标签的标签。

让我们的代码块更漂亮styles/globals.css

复制
/* at the bottom add */
pre {
  color: white;
  background: #282c34;
  padding: 10px;
  border-radius: 6px;
}

刷新页面应该会给您一个更好看的代码块。当然,您也可以重复创建的其他组件marked。只需检查DOM并查看呈现了哪些标签并设置样式即可styles/globals.css


现在,我们有一个样式化的Next.js应用程序,它支持基于markdown文件中指定的动态数据进行动态路由,这些文件已准备好用于本系列教程的下一部分。

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 如何将Markdown转换成HTML

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论