-
-
Notifications
You must be signed in to change notification settings - Fork 893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
yaml-front-matter 提供自定义渲染功能 #1751
Comments
今天又研究了一下,发现直接在渲染的时候这么搞还是有点难度的,我参考了CodeBlock的实现过程,也动手在浏览器中手动动态更改代码尝试了一下,发现了一些问题。 首先就是现在CodeBlock的模式是点击就会把原始代码显示出来,这种放到复杂情况又是文本输入框、标签选择框又是开关,时间拾取器这些,就有些不合适 此外就算暴露接口,我也已经意识到了渲染器也会很难写。(直接用Vue在编辑器外面会简单很多) 所以最后我还是先采用笨办法实现了,经过阅读源码我已经知道不能随意改动Vditor内部的元素,所以这次就直接放在外面,至于编辑器是内部自滚动,现在我加上yaml-front-matter这个块后就得重新设置滚动区域。我直接暴力使用important覆盖掉了样式(虽然不雅观吧,但是非常有效,我自己随手写的也不要求太严格了) 可以看出最终效果还是不错的,能够可视化几种常见的基本类型数据,然后编辑器也能够正常滚动,工具栏吸顶也没问题。最重要的是其实也看不出是拼接的感觉,可以说完美符合我的预期 下面放我主要的代码,希望能帮助到和我有一样需求的人。 .vditor {
border: none !important;
height: 100% !important;
}
.vditor-toolbar {
padding: 0 !important;
}
.vditor-reset {
overflow: visible !important;
padding: 0 40px !important;
}
.vditor-outline {
display: none !important;
} 打开文件以及获取文件内容的时候分别要进行front matter与主内容的分离和合并操作 const getContent = () => {
/**
* 获取编辑器内容
* 会将 frontMatter 和 content 合并
*/
let yamlFrontMatter = stringifyFrontMatter(frontMatterObject);
let content = (vditorInstance as any).getValue();
return yamlFrontMatter + content;
};
const openFile = async (path: string) => {
/**
* 读取文件内容并设置到编辑器中
* 会将 frontMatter 的内容分离出来,并设置到 frontMatter 中
* 由 createVditorInstance 创建完Vditor实例后调用
* */
console.log("openFile", path);
fs.get(path).then((content) => {
console.log("openFile content", content);
// 分离 frontMatter 和 content
let result: { frontMatter: Record<string, any>; content: string } =
splitFrontMatter(content);
frontMatterObject = result.frontMatter;
for (const key in frontMatterObject) {
let value = frontMatterObject[key];
let type = typeof value;
let item_type: fronMatterValueType = fronMatterValueType.string;
if (type === "string") {
item_type = fronMatterValueType.string;
} else if (type === "number") {
item_type = fronMatterValueType.number;
} else if (type === "boolean") {
item_type = fronMatterValueType.boolean;
} else if (type === "object") {
if (Array.isArray(value)) {
item_type = fronMatterValueType.array;
} else if (value instanceof Date) {
item_type = fronMatterValueType.date;
}
} else {
continue; // 其他类型不处理, 暂时不支持
}
frontMatter.value.push({
name: key,
type: item_type,
value: value,
});
}
frontMatterBack = frontMatter.value.map((item) => item.name);
// 设置清理后的内容到编辑器中
if (vditorInstance) {
vditorInstance.setValue(result.content, true);
}
});
};
// yaml的处理工具函数
export const splitFrontMatter = (content: string) => {
const yalmPattern = /^---[\s\S]*?---/;
const yamlMatch = content.match(yalmPattern);
const yamlContent = yamlMatch ? yamlMatch[0] : "";
const cleanedContent = content.replace(yamlContent, "");
let frontMatter = {};
if (yamlContent) {
frontMatter = parseFrontMatter(yamlContent);
}
return {
frontMatter,
content: cleanedContent,
};
};
export const parseFrontMatter = (content: string) => {
let parsedYaml = <Record<string, any>>{};
if (content) {
try {
parsedYaml = yaml.load(content.replace(/^---|---$/g, "")) as Record<
string,
any
>;
} catch (e) {
console.error("Error parsing YAML:", e);
}
}
return parsedYaml;
};
export const formatDate = (date: Date, formatString: string, offset:string) => {
return format(date, formatString) + offset;
};
export const stringifyFrontMatter = (frontMatter: Record<string, any>) => {
console.log("frontMatterObject", frontMatter);
for (const key in frontMatter) {
console.log("key", key);
let value = frontMatter[key];
if (value instanceof Date) {
console.log("formatDate", formatDate(value, "yyyy-MM-dd'T'HH:mm:ss", "+08:00"));
frontMatter[key] = formatDate(value, "yyyy-MM-dd'T'HH:mm:ss", "+08:00");
}
}
return `---\n${yaml.dump(frontMatter)}---\n`;
}; |
你在什么场景下需要该功能?
我在做 Hugo 的博客文章编辑器,这个场景下大部分需要的 Front Matter 都是可以预测,且需要
Date
这样的数据手动输入太麻烦。我的目的是能够给编辑器提供更友好且智能的FrontMatter编辑方案。描述最优的解决方案
最好是能够暴露一个像已有的自定义渲染器那样的接口(已有的测试貌似只能对代码块起作用)。
描述候选解决方案
如果您实在是没有时间支持这种小众功能,我希望能够从您那儿了解到
codeRender
这类模块是如何工作的。我在源码中已经翻找到了相关的代码(
src\ts\wysiwyg\input.ts
),但是我不明白即时渲染模式下用户看到的和实际内在输入是怎么区分的,我分析了yaml-front-matter块和代码块的区别,如下图,怀疑是vditor-wysiwyg__block
与vditor-wysiwyg__preview
。yaml-front-matter
块没有vditor-wysiwyg__preview
。但在这又是lute
模块的问题了,继续深入后我发现只提供了lute.min.js
没有相关的未压缩版本。其他信息
下面给出一张最终希望功能的大致动态图(简单更改了
src\ts\wysiwyg\input.ts
,具体代码在文末)我预计特殊处理的 Hugo Front Matter 字段有
以上是我的所有想法,感谢帮助!
The text was updated successfully, but these errors were encountered: