gpt4 book ai didi

node.js - 在 Jade/Node.js 中过滤 Markdown 内容

转载 作者:搜寻专家 更新时间:2023-11-01 00:19:06 31 4
gpt4 key购买 nike

尊敬的黑客,

我希望在 Jade 模板中过滤一个充满 Markdown 的字符串。我在变量中有 Markdown。

Jade 在 Markdown 中插入一个变量就好了:

这个:

var jade = require('jade');

var jade_string = [
':markdown',
' ## This is markdown!',
' * First',
' * #{var2}',
' * Third'
].join('\n');

var fn = jade.compile( jade_string, { pretty: true } );

console.log( fn( { var1: "First!", var2: "Second!" } ) );

产生这个:

<h2>This is markdown!</h2>

<ul>
<li>First</li>
<li>Second!</li>
<li>Third</li>
</ul>

但是,我所拥有的是变量内部的实际完整 Markdown。还有这个:

var jade = require('jade');

var jade_string = [
'div.markedup',
' :markdown',
' \\#{var2}'
].join('\n');

var fn = jade.compile( jade_string, { pretty: true } );

var markdown = [
'## I am marked!',
'* One',
'* Two'
].join('\n');

console.log( fn( { var1: "First!", var2: markdown } ) );

只提供这个:

<div class="markedup"><p>## I am marked!
* One
* Two</p>
</div>

因此在我看来,Jade 会在 执行任何变量之前过滤 block 插值,然后在生成的 HTML 中插入变量。这是如果你想用 Markdown 编写你的模板,那很好,但这并不多如果您想在 Markdown 中编写您的内容,请提供帮助。

我知道我可以通过更多编程来解决这个问题,但我觉得我一定是少了什么。毕竟,将 Markdown 内容的片段保存在一个数据库并将生成的 HTML 片段填充到模板中似乎:markdown 过滤器最明显的用例。

在 Jade 中是否有一种“正常”的方式来做到这一点?

非常感谢您的启发。

最佳答案

我认为答案是更多的编程,但我会向您展示我所做的。我使用自定义中间件,让我在获得最终 HTML 文档输出之前组合任意转换过程。因此,例如,我的 middleware.js 模块中有以下过滤器,我将依次解释。

如此简单的 View 只使用普通的 jade 及其用于 markdown、javascript、coffeescript 的各种过滤器。某些 View (例如博客文章)需要更复杂的中间件链,如下所示。

首先,根据请求,我建立了包含此响应核心内容的文件,并将其设置为 res.viewPath 上的属性。 .这可以是原始 HTML 片段文件或 Markdown 文件。然后我通过一系列中间件转换发送响应。我用 res.htmlres.dom在建立响应时存储响应的中间表示。

这个只存储原始 HTML(只是一个没有头部或布局的文档主体片段)。

html = function(req, res, next) {
if (!/\.html$/.test(res.viewPath)) return next();
return fs.readFile(res.viewPath, "utf8", function(error, htmlText) {
res.html = htmlText;
return next(error);
});
};

这会将 markdown 文件转换为 HTML(使用 markdown-js 模块)。

markdownToHTML = function(req, res, next) {
if (!/\.md$/.test(res.viewPath)) return next();
return fs.readFile(res.viewPath, "utf8", function(error, markdownText) {
res.html = markdown(markdownText);
return next(error);
});
};

我有一个子布局,它位于我的主布局内,但围绕着每篇博文。所以我将博客文章包装在此处的子布局中。 (未显示的单独代码从 json 元数据文件生成 res.post 对象)。

blogArticle = function(req, res, next) {
var footerPath, post;
post = res.post;
footerPath = path.join(__dirname, "..", "templates", "blog_layout.jade");
return fs.readFile(footerPath, "utf8", function(error, jadeText) {
var footerFunc;
if (error) return next(error);
footerFunc = jade.compile(jadeText);
res.html = footerFunc({
post: post,
body: res.html
});
return next();
});
};

现在我将布局围绕主要内容 HTML 进行包装。请注意,我可以在此处设置诸如页面标题之类的内容,或者等到稍后,因为我可以在此之后通过 jsdom 操作响应。我做body: res.html || ""所以我可以渲染一个空布局,如果方便的话,稍后再插入正文。

exports.layout = function(req, res, next) {
var layoutPath;
layoutPath = path.join(__dirname, "..", "templates", "layout.jade");
return fs.readFile(layoutPath, "utf8", function(error, jadeText) {
var layoutFunc, locals;
layoutFunc = jade.compile(jadeText, {
filename: layoutPath
});
locals = {
config: config,
title: "",
body: res.html || ""
};
res.html = layoutFunc(locals);
return next(error);
});
};

真正强大的东西就在这里。我将 HTML 字符串转换为 jsdom 文档对象模型,该模型允许在服务器端进行基于 jQuery 的转换。 toMarkup下面的函数只允许我在没有额外的 <script> 的情况下取回 HTML jsdom 添加的内存中 jquery 的标记。

exports.domify = function(req, res, next) {
return jsdom.env(res.html, [jqueryPath], function(error, dom) {
if (error) return next(error);
res.dom = dom;
dom.toMarkup = function() {
this.window.$("script").last().remove();
return this.window.document.doctype + this.window.document.innerHTML;
};
return next(error);
});
};

这是我进行的自定义转换。这可以替换像 <flickrshow href="http://flickr.com/example"/> 这样的虚构 DSL 标签使用真正有效的 HTML,否则会很讨厌 <object>我将不得不在每篇博客文章中复制样板文件,如果 flickr 曾经更改过他们使用的样板文件标记,那么在许多单独的博客文章 Markdown 文件中修复它将会是一种维护上的痛苦。他们目前使用的样板文件在 flickrshowTemplate 中。变量并包含一个 mustache 占位符 {URLs} .

exports.flickr = function(req, res, next) {
var $ = res.dom.window.$;
$("flickrshow").each(function(index, elem) {
var $elem, URLs;
$elem = $(elem);
URLs = $elem.attr("href");
return $elem.replaceWith(flickrshowTemplate.replace(/\{URLs\}/g, URLs));
});
return next();
};

嵌入 YouTube 视频也是如此。 <youtube href="http://youtube.com/example"/> .

exports.youtube = function(req, res, next) {
var $ = res.dom.window.$;
$("youtube").each(function(index, elem) {
var $elem, URL;
$elem = $(elem);
URL = $elem.attr("href");
return $elem.replaceWith(youtubeTemplate.replace(/\{URL\}/, URL));
});
return next();
};

现在我可以根据需要更改标题,添加/删除 javascript 或样式表等。这里我在布局已经呈现后设置标题。

postTitle = function(req, res, next) {
var $;
$ = res.dom.window.$;
$("title").text(res.post.title + " | Peter Lyons");
return next();
};

好的,是时候回到最终的 HTML 了。

exports.undomify = function(req, res, next) {
res.html = res.dom.toMarkup();
return next();
};

现在我们发货了!

exports.send = function(req, res) {
return res.send(res.html);
};

为了按顺序将它们捆绑在一起并快速使用它,我们这样做

postMiddleware = [
loadPost,
html,
markdownToHTML,
blogArticle,
layout,
domify,
postTitle,
flickr,
youtube,
undomify,
send
]

app.get("/your/uri", postMiddleware);

简洁?不,干净吗?我想是这样。灵活的?极其。快如闪电?可能不会很快,因为我相信 jsdom 是您可以做的更重量级的事情之一,但我将其用作静态站点生成器,因此速度无关紧要。当然,在中间件链的开头和结尾再添加一个函数,将最终的 HTML 写入一个静态文件,如果它比对应的 markdown 页面主体内容文件更新,则直接提供服务。 Stackoverflowers,我很想听听关于这种方法的想法和建议!

关于node.js - 在 Jade/Node.js 中过滤 Markdown 内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9159826/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com