【Godot4.3】MarkDown编辑和控件事实渲染

概述

这是本人2024年5月份左右编写的一个简易的MarkDown编辑和渲染测试项目,基于自己编写的MarkDown解析和生成类MDdoc编写。之前是作为一个试验性的内容混乱的放置在另一个测试项目中,现在独立为一个单独项目。因为测验成功后就一直没改动,所以这仍然是一个很初期的版本。

项目核心

在这里插入图片描述

它的核心是有两部分:

  • MDdoc类:一个MarkDown纯文本解析类,可以将MarkDown文档元素按其顺序解析为对象,从存入内部的数组。每个MarkDown文档元素对应MDdoc的一个内部类:
    • CodebBlock:代码块
    • Headding:标题,H1-H6
    • Paragraph:普通段落
    • Img:图片
    • UL:无序列表
    • OL:有序列表
    • Table:表格
  • 主编辑器:采用传统的左侧编写,右侧渲染的形式。其主要是在左侧编辑器编辑时,利用MDdoc类实时的生成MarkDown元素列表,再借由右侧的一个VBoxContainer顺序渲染相应的控件显示内容。

在这里插入图片描述

编辑器语法高亮

为了让MarkDown代码显得不那么无聊,在对应的CodeEdit上手动用代码添加了一些语法高亮规则。

extends CodeEdit

@export var Hedding_color:= Color.GOLD
@export var codeblock_color:= Color.AQUAMARINE

func _ready() -> void:
	var highlighter = CodeHighlighter.new()
	# H1 - H6
	for i in range(6):
		highlighter.add_color_region("%s " % "#".repeat(i+1)," ",Hedding_color,true)
	
	highlighter.add_color_region("```","```",codeblock_color,false)
	highlighter.add_color_region("- "," ",codeblock_color,true)
	for i in range(100):
		var start = "1. " % (i+1)
		highlighter.add_color_region(start," ",codeblock_color,true)
	#highlighter.add_color_region("- "," ",codeblock_color,true)
	syntax_highlighter = highlighter

实时渲染

mdTest(VBoxContainer)节点上,我们通过遍历MDdoc解析后生成的MarkDown元素数组,并根据对应的元素类型添加不同的控件为mdTest的子节点,从而实现MarkDown内容渲染和显示。

  • 每次调用render,都会先清空mdTest(VBoxContainer)上的所有子节点,然后重新渲染MDdoc解析后生成的MarkDown元素
# ==================== 核心渲染方法 ====================
# 渲染为控件
func render(md):
	# 清空原来的
	for child in get_children():
		remove_child(child)
	# 渲染
	var doc := MDdoc.parse(md)
	for ele in doc._doc:
		if ele is MDdoc.Headding:
			add_child(H(ele.level,ele.text))
		if ele is MDdoc.CodebBlock:
			add_child(CodeBlock(ele.language,ele.code))
		if ele is MDdoc.Paragraph:
			add_child(p(ele.text))
		if ele is MDdoc.UL:
			add_child(ul(ele))
		if ele is MDdoc.OL:
			add_child(ol(ele))
		if ele is MDdoc.Img:
			add_child(img(ele.src,ele.desc))

其中render()_ready()CodeEdit发生文本改变时调用,从而实现运行后的解析和编辑时的实时渲染。

func _ready() -> void:
	render(code_edit.text)

# 文本发生改变时
func _on_code_edit_text_changed() -> void:
	render(code_edit.text)
	pass

为了让代码清晰,为控件生成编写了对应的函数。

# ==================== 获取对应的控件 ====================
# H1- H6
func H(level:int,text:String) -> Label:
	var lab := Label.new()
	lab.text = text
	lab.set("theme_override_font_sizes/font_size",H_size[level-1])
	lab.set("theme_override_colors/font_color",font_color)
	return lab
	
# 段落
func p(text:String) -> Label:
	var lab := Label.new()
	lab.text = text
	lab.set("theme_override_font_sizes/font_size",p_size)
	lab.set("theme_override_colors/font_color",font_color)
	return lab

# 代码块
func CodeBlock(language:String,code:String) -> CodeEdit:
	var txt := CodeEdit.new()
	txt.text = code
	txt.custom_minimum_size.y = 200
	txt.gutters_draw_line_numbers = true
	return txt

# 无序列表
func ul(ele) -> Label:
	var lab := Label.new()
	lab.text = ele.to_string()
	lab.set("theme_override_font_sizes/font_size",p_size)
	lab.set("theme_override_colors/font_color",font_color)
	return lab

# 无序列表
func ol(ele) -> Label:
	var lab := Label.new()
	lab.text = ele.to_string()
	lab.set("theme_override_font_sizes/font_size",p_size)
	lab.set("theme_override_colors/font_color",font_color)
	return lab
# 图片
func img(src:String,desc:String):
	var pic := TextureRect.new()
	pic.expand_mode = TextureRect.EXPAND_FIT_WIDTH
	pic.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
	pic.custom_minimum_size.y = 100
	if load(src):
		pic.texture = load(src)
	else:
		pic.texture = load("res://1.jpeg")
	
	return pic

剩余的就是基础的应用和参数设定了。

extends VBoxContainer

@onready var code_edit: CodeEdit = %CodeEdit

# 文本颜色
@export var font_color:Color = Color.BLACK

# 字号
var H_size = [48,40,36,32,28,26]  # H1-H6字号
var p_size = 20  # 正文字号

其他渲染选择

其实利用VBoxContainer按顺序动态加载控件的形式只是一个很简易甚至粗鄙的形式,完全没有考虑长篇幅文档的性能问题。
在Godot内部,可以选择其他的形式来作为MarkDown内容渲染和显示的选择:

  • RichTextLabel+BBCode:富文本标签,天然支持BBCode语法,也是Godot内置文档的渲染和显示控件,很容易实现,而且可以选择和复制内容
  • 基于绘图函数的渲染:基于CanvasItem的绘图函数,我们可以将MarkDown内容渲染到一个Control

其中RichTextLabel是比较有前途的选项。

代码实时渲染类工具的魅力

其实采用VBoxContainer动态渲染是为了检验一种工具软件类型的可行性,就是代码实时渲染类工具。
它的特点就是一边编写,一边运行代码进行测试。在5月份编写这个工具的同时,我还测试编写了一个用代码测试绘图函数和动画的小工具。

界面和功能分离

MDdoc其实是MarkDown解析和生成的核心,借由这个类,我可以选择不同的MarkDown渲染路线,创建不同的界面,甚至完全不同的程序。甚至也可以将其用于创建游戏项目的内置百科。

  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巽星石

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值