DZone>Web Dev Zone> 我们是如何将数百个帖子从Hugo迁移到Webflow的?
我们是如何将数百个帖子从Hugo迁移到Webflow的?
在这篇文章中,我将介绍我们是如何将所有的内容从旧的Hugo网站成功迁移到Webflow的。我还会告诉你我是如何解决迁移过程中的这些棘手问题的,并提供一些有用的脚本。
通过
-
May.22, 22 - Web Dev Zone -教程
喜欢 (1)
评论
保存
鸣叫
2.65K浏览次数
加入DZone社区,获得完整的会员体验。
我们最近完成了 Nebula Graph的网站 从Hugo到Webflow的迁移,从一个静态的网站转移到一个更加互动的网站。作出这一决定的原因有很多,但最明显的是性能和做表格提交和无代码设计等事情的能力。
虽然在Webflow上重新设计网站很容易,因为我们有一个了不起的内部设计团队,而且Webflow对设计师也非常友好,但困难的部分是将我们已经从Hugo发布的100多篇博文迁移到Webflow的内容管理系统(CMS)。
基本上,这100篇文章是以Markdown文件的形式存储在GitHub上的--不像WordPress这样的CMS,将文章作为结构化数据存储在数据库中。在Webflow中,CMS需要结构化的CSV数据来进行批量导入。
好吧,在我们真正动手做这个项目之前,每个人都认为这是件容易的事--只要把那些Markdown文件转换成HTML格式,然后把它们塞进CSV文件,然后,砰!就可以了。
事实证明,事情要复杂得多,最明显的原因是Webflow的CMS的限制。它只支持有限数量的HTML标签,如 <h1> 到<h6> 和 <img> 。 如果你不使用它的自定义代码功能,则不支持 像 <table> 和<code> 这样的HTML标签 --在批量导入时不能使用。
在这篇文章中,我将介绍我们如何成功地将所有内容从我们的旧雨果网站迁移到Webflow中。我还会告诉你我是如何在迁移过程中解决这些棘手的问题,并提供一些有用的脚本。如果你正在使用像Hugo这样的静态网站生成器,并想将你的博客网站迁移到Webflow中,你可能会发现这篇文章对你有帮助。
一些背景
首先,介绍一下Webflow的背景。Webflow是一个可视化的拖放式网站建设工具,可以让你在没有任何代码的情况下创建漂亮的、可移动的网站。我从使用它中注意到的主要好处是,我能够以很少的努力来创建视觉上有吸引力的、响应式的网站。
在我们网站的第一个版本中,我们选择了雨果,它是一个静态网站生成器。它的速度和做定制的灵活性给我们留下了深刻印象。但是,由于它是一个静态网站,我们无法为那些想对我们的文章发表评论或订阅我们的通讯的用户添加动态内容。此外,营销团队使用git等工具向网站上传文章也不容易。
这就是为什么我们决定将我们的网站迁移到一个CMS平台。然而,由于没有关于如何从Hugo迁移到Webflow的现有资源,我们不得不自己编写脚本,手动将数百个帖子和页面转换成Webflow中的集合。
为文章数据绘制蓝图
正如我在上面提到的,我们的文章是以单独的 Markdown文件形式存储 在GitHub上。如果我们想把它们转换成结构化的CSV文件,首先要做的就是为CSV文件创建蓝图。
下面是我们的帖子文件夹的结构。
普通文本
----posts
--------random-article-one
------------thumbnail-image-article-one.png
------------index.md
--------random-article-two
------------thumbnail-image-article-one.png
------------index.md
--------random-article-three
------------thumbnail-image-article-one.png
------------index.md
...
我们使用存放文章的文件夹的名称作为文章在Hugo网站上的URL slug。例如,文章一的路径将是/posts/random-article-one。在Webflow CSM中有一个slug属性,它决定了动态资源的路径。因此,我们可以使用这里提到的文件夹名称作为Webflow CMS中的slug字段。
现在让我们来看看每个Markdown文件是如何结构化的。在上面的文件树中, 每个文件夹下的[index.md](http://index.md) 文件存储了关于一篇文章的所有信息。
纯文本
---
title: "How I cracked Chinese Wordle using knowledge graph"
date: 2022-04-15
description: "Wordle is going viral these days. So is Handle, the Chinese Wordle. This post explains how to crack Chinese Wordle using knowledge graph."
tags: ["use-cases"]
author: "Wey"
---

Wordle is going viral these days on social media. The [game](https://www.nytimes.com/games/wordle/index.html) made by *Josh Wardle* allows players to try six times to guess a five-letter word, with feedback given for each guess in the form of colored tiles indicating when letters match or occupy the correct position.
We have seen many Wordle variants for languages that use the Latin script, such as the [Spanish Wordle](https://wordle.danielfrg.com/), [French Wordle](https://wordle.louan.me/), and [German Wordle](https://wordle.at/). However, for non-alphabetic languages like Chinese, a simple adaptation of the English Wordle’s rules just won’t work.
...
这个文件的前几行包涵了这篇文章的所有信息。在第一个表格中,你可以得到 这篇文章的title ,date, description, tags, 和 author 。表格下面的其他内容都是文章的主体。
请注意,当我们以Markdown格式存储文章正文时,Webflow的CMS以HTML格式存储正文。因此,在我们生成CSV文件之前,必须在Markdown和HTML之间进行转换。
BTW,实际上,我们在这里需要两个CSV文件,因为标签 在Webflow中是作为 一个多参考字段存储 的 。它们是post.csv和tags.csv。
现在我们有了post CSV的蓝图。
| 字段 | 标题 | 标签 | 发表在 | 帖子正文 | 描述 | 缩略图 | 作者 | 标签 |
|---|---|---|---|---|---|---|---|---|
| 描述 | Markdown文件中的标题字段。 | 储存Markdown文件的文件夹的名称。 | Markdown文件中的日期字段。 | Markdown文件中的帖子主体被转换为HTML。 | Markdown文件中的描述字段。 | 缩略图的URL在同一个文件夹中。 | 作者字段在Markdown文件中。 | 从Markdown文件中的标签字段中提取的逗号分隔的标签列表。 |
注意:你必须在Webflow的CMS中创建一个Post集合,并按照上面列出的CSV标题使用准确的字段名来创建字段。我的意思是,你不必使用准确的名称,但如果你这样做,你就不必在导入时手动匹配字段。
然后是tags.csv。
| FIELD | 标签 | 术语 |
|---|---|---|
| 描述 | 标签的名称 | 在我们的例子中,这很简单。它只是标签的名字,因为所有的标签都使用蛇形大小写显示。 |
将Markdown文件转换为CSV
蓝图完成后,我们可以开始将post文件夹中的帖子转换为一个CSV文件。下面是我们使用的工作流程。
- 遍历post文件夹下的每个post文件夹。
- 使用软件包 gray-matter 从每个markdown帖子文件中提取信息。
- 在帖子正文字段中,使用 showdown 将Markdown转换为HTML。
- 使用包 CSV-writer 将信息写进CSV文件。
下面是整个过程 的代码。你也可以访问 它的GitHub Gist 来做贡献。
Python
const fs = require('fs');
const showdown = require('showdown');
const matter = require('gray-matter');
const createCsvWriter = require('csv-writer').createArrayCsvWriter;
const csvWriter = createCsvWriter({
header: ['Title','Slug','Published on','Post Body','Description','Thumbnail image','Author','tags'],
path: './post.csv'
});
var getAHref = function(htmlstr){
var reg = /<img [^>]*src=['"]([^'"]+)[^>]*>/gi
var arr = [];
while(tem=reg.exec(htmlstr)){
arr.push(tem[1]);
}
return arr;
}
const rtfToMarkdown =(txt)=> {
// txt = txt.replace(/<p>/g, '');
// txt = txt.replace(/<\/p>/g, '\n\n');
txt = txt.replace(/\n/g, '<br/>');
txt = txt.replace(/ /g, ' ');
// console.log(txt);
return txt;
}
const download=()=>{
const files = fs.readdirSync('./posts');
const csvItems = []
const tags = new Set([])
files.forEach(filename =>{
if(filename !=='.DS_Store'){
let readMe = fs.readFileSync(`./posts/${filename}/index.md`, 'utf8');
//Extract header information from the Markdown file
const _data = matter(readMe);
const { data, content} = _data
// console.log("_data", rtfToMarkdown(content))
//Extract post body from the Markdown file
const converter = new showdown.Converter({
noHeaderId: true,
headerLevelStart: 2,
literalMidWordUnderscores: true
})
let html = converter.makeHtml(content);
// html = html.replace(/<pre><code>/g, '<h6>');
html = html.replace(/ /g, ' ');
html = html.replace(/<pre(([\s\S])*?)<\/pre>/g, item=>{
item= item.replace(/\s+(?:class|className)=(?:["']\W+\s*(?:\w+)\()?["']([^'"]+)['"]+>/g, calss=>{
const _calss = calss.substring(1,calss.length-1)
return `>${_calss}`
})
item = item.replace(/<pre><code>/g, '<pre><code><h6>');
item = item.replace(/<\/code><\/pre>/g, '</h6></code></pre>');
return item
});
data.tags.map(_tag => tags.add(_tag))
let csvItem = [
data.title,
filename,
data.date,
html,
data.description,
getAHref(html)[0],
data.author,
data.tags.join(';')
]
csvItems.push(csvItem)
}
})
console.log("tags",tags)
csvWriter.writeRecords(csvItems).then(() => console.log('Done~'));
}
download();
将CSV文件导入到Webflow中
现在我们已经有了一个包含110个帖子的CSV文件,我们认为把它放入Webflow CMS会很容易。
但这正是所有麻烦的开始。
挑战一:Webflow不支持所有的HTML标签
是的,我们成功地将所有的帖子导入了Webflow CMS,而且这个过程还算顺利。但事实证明,这些帖子并没有像我们预期的那样被呈现出来。
问题在于,Webflow只支持有限数量的原生HTML标签。作为一家科技创业公司,我们的博客包含了很多包含代码块的文章。但Webflow不支持 <code> 和<pre> 标签,这些标签通常与标签代码块结合使用。
根据 Webflow 的文档,它只支持 <H1> 到<H6>, <p>,<a>, <img>, <ul>, <ol>, <li>, <label>, <strong>, <em>,<blockquote>, 和 <figure> 。我强调 "原生",因为你实际上可以在 CMS的自定义代码块中编写其他的HTML标签 。但在批量导入时,你没有办法在自定义代码块中上传或包装你不支持的HTML标签。
由于对 HTML标签的限制 ,Webflow会自动修剪正文中所有不支持的标签。所以说,我们有一个代码块,最初看起来像这样。
HTML
<pre class="language-python"><code class="language-python">
from nebula3.gclient.net import ConnectionPool
from nebula3.Config import Config
# define a config
config = Config()
config.max_connection_pool_size = 10
# init connection pool
connection_pool = ConnectionPool()
# if the given servers are ok, return true, else return false
ok = connection_pool.init([('127.0.0.1', 9669)], config)
</code></pre>
帖子正文将只显示纯文本的代码块,没有任何 <pre> 和<code> 标签。
然后我们想到了一个解决方案,我们可以选择一个在普通博客文章中不经常使用的标签,比如说 <h6> ,然后 在源文件中用 <h6> 标签 替换所有 的<pre> 和<code> 标签 ,这样在导入时,代码块就被包裹起来了。而在前台页面,我们可以使用JavaScript将 <h6> 标签改回<pre> 和<code> 。
顺便说一下,我们使用 Prism.js 来为代码块做语法高亮。我们需要在 <pre> 和<code> 标签 中使用一个 类来告诉Prism每个代码块是用哪种语言写的。对于上面的例子,这个类是 "language-python"。
你猜对了,Webflow在导入时也会修剪HTML标签中的所有类。为 了解决这个问题,我们提取了每个 <pre> 和<code> 标签的类 ,并把它们放在 了<h6>标签 的开头 。
因此,对于上面的代码块例子,转换后的代码将是。
Python
<h6>class="language-python"
from nebula3.gclient.net import ConnectionPool
from nebula3.Config import Config
# define a config
config = Config()
config.max_connection_pool_size = 10
# init connection pool
connection_pool = ConnectionPool()
# if the given servers are ok, return true, else return false
ok = connection_pool.init([('127.0.0.1', 9669)], config)
</h6>
而在前端页面中,我们使用下面的JavaScript将 <h6> 标签改回<pre> 和<code> ,并将它们的类加回去。(这个脚本需要JQuery。)
JavaScript
$(document).ready(function() {
$('h6').each(function(_,item){
let newEl = document.createElement("pre");
let codeEl =document.createElement('code')
newEl.appendChild(codeEl);
codeEl.innerHTML = item.innerHTML.replace(/<br>/g, '\n');
item.parentNode.replaceChild(newEl, item);
});
//Add 'language-base' if the class is not specified.
$('pre').addClass('language-base');
$('code').addClass('language-base');
let _snips = $('code:contains("class=")');
_snips.toArray().forEach(el =>{
const txt =el.innerHTML;
const classStr =txt.match(/(?:class|className)=(?:["']\W+\s*(?:\w+)\()?["']([^'"]+)['"]/)
el.setAttribute("class",classStr[1]);
el.parentNode.setAttribute("class",classStr[1]);
el.innerHTML =el.innerHTML.replace(/(?:class|className)=(?:["']\W+\s*(?:\w+)\()?["']([^'"]+)['"]/g, '');
el.innerHTML =el.innerHTML.replace(/<br>/g, '\n');
});
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://web-cdn.nebula-graph.io/nebula-website/js/prism.js";
document.body.appendChild(script);
})
挑战之二。在导入过程中去掉换行符和空格
这应该是可行的......除了一件事:因为我们使用了 <h6> ,Webflow会删除所有的换行符和包裹在<h6> 内的代码的多余空格 。因此,我们最终得到的结果是这样的。
HTML
<pre class="language-python"><code class="language-python">
from nebula3.gclient.net import ConnectionPoolfrom nebula3.Config import Config# define a configconfig = Config() config.max_connection_pool_size = 10# init connection poolconnection_pool = ConnectionPool()# if the given servers are ok, return true, else return falseok = connection_pool.init([('127.0.0.1', 9669)], config)
</code></pre>
是的,这只是一行代码,所有的换行符和多余的空格都在导入过程中被提交。
这个问题花了我们好几天的时间来解决。而这是徒劳的。
首先,我们认为我们可以使用先将所有的换行符和空格转换成一些占位符,如[lineebreak]和[space],然后在前端将它们转换回真正的换行符和空格。
我们很快就放弃了这个想法,因为这对SEO来说是一场灾难--虽然在第二次转换后,代码块在人眼里可能看起来是正常的,但Google的爬虫从页面上获取的将是一堆[换行]和[空格]。
从这个想法出发,我们不得不向Webflow的技术支持寻求帮助。而他们给了我们一个解决方案,终于成功了。
以下是Webflow的解决方案。在原始文件中,我们可以 在 <h6> 周围 再添加两个 <pre> 和<code> 标签 ,这样,在导入过程中,即使Webflow会修剪 <pre> 和<code> 标签,它也会保留 <h6> 里面的所有换行符和空格 。我猜那些 <pre> 和<code> 标签被当作某种牺牲品。
因此,我们需要为帖子主体准备的原始HTML代码将是这样的。
HTML
<pre><code><h6>class="language-python"
from nebula3.gclient.net import ConnectionPool
from nebula3.Config import Config
# define a config
config = Config()
config.max_connection_pool_size = 10
# init connection pool
connection_pool = ConnectionPool()
# if the given servers are ok, return true, else return false
ok = connection_pool.init([('127.0.0.1', 9669)], config)
</h6></code></pre>
最后,这就完美地工作了。我们拥有所有代码块的语法高亮--你可以从这个页面上看到!
还有一件事
请记住, Webflow也不支持<table> ,以及<tr> 、<th> 、<td> 等标签。对于我们来说,我们并没有试图为表格找到一个通用的解决方案,因为我们并不经常使用它们。我们的解决方案是在CMS中手动找到所有导入的帖子中的表格,并用包含表格元素的自定义代码来替代它们。
总结
对于设计师和营销人员来说,Webflow是一个伟大的平台。如果你不需要担心从其他平台上迁移帖子,你通常会很顺利。但如果你像我们一样,需要迁移数百个包含Webflow不支持的HTML标签的帖子,你可能需要一些额外的工作。但好在Webflow允许你使用很多变通方法来解决这些问题。你总是可以黑掉你的出路。
内容管理系统 Webflow POST(HTTP)
发布在DZone上,得到了Wei Sheng的许可。点击这里查看原文。
DZone贡献者所表达的观点属于他们自己。
DZone上的热门文章
评论