【Godot4.2】MLTag类:HTML、XML通用标签类
概述
HTML和XML采用类似的标签形式。
之前在Godot中以函数库形式实现了网页标签和内容生成。能用,但是缺点也很明显。函数之间没有从属关系,但是多有依赖,而且没有划分出各种对象和类型。
如果以完全的面向对象形式来设计标签类或者元素类,将可以更贴近HTML或XML的本来面目。也更容易生成。
整体思路是设计如下的类继承结构:
实现之后,将可以充分的定义和生成HTML、XML和SVG标签,并用于内容生成或文档解析。
通用标签类
因为HTML和XML标签的语法格式和要素是类似的,因此可以通过创建一个通用的标签类,来生成HTML或XML标签。
MLtag
就是这个通用的标签类,它定义了几个核心的属性:
tag_name
:标签名称attrs
:包含标签所有属性的字典is_single
:是否为单标签,默认为false
content
:标签的子内容,可以直接赋值,也可以使用append()
方法追加。单标签(is_single
为true
)时被忽略get_end_tag()
:获取结束标签,单标签时返回空字符串append()
:追加当前标签的子内容,可以是字符串形式,也可以是SVG标签实例(会自动调用to_string()
方法转化为字符串)
# =============================================
# 名称:MLtag
# 类型:类
# 描述:HTML、XML通用标签类,用于定义和生成HTML、XML标签字符串
# 作者:巽星石
# 创建时间:2024年7月16日17:48:01
# 最后修改时间:2024年7月16日22:27:53
# =============================================
class_name MLTag# ====================== 属性 ======================
var tag_name = "" # 标签名称
var attrs:Dictionary = {} # 属性字典
var is_single = false # 是否单标签
var content = "" # 子内容 # ====================== 方法 ======================
# 获取结束标签
func get_end_tag() -> String:return "" if is_single else "</%s>" % tag_name# 追加子内容
func append(new_content) -> void:if new_content is String:content += "\n" + new_contentelse:content += "\n" + new_content.to_string()# ====================== 虚函数 ======================
# 转化为字符串
func _to_string() -> String:var tag_str:String# 获取属性字典的字符串var attr = ""for key in attrs.keys():if attrs[key] != "":attr += "%s=\"%s\" " % [key,attrs[key]]tag_str = "<%s%s/>" % [tag_name," " + attr] if is_single else "<%s%s>%s</%s>" % [tag_name," " + attr,content,tag_name]return tag_str
测试:
@tool
extends EditorScriptfunc _run() -> void:var tag = MLTag.new() # 创建一个标签tag.name = "a" # 名称tag.attrs["id"] = "a1" # 设定属性tag.attrs["href"] = "https://www.runoob.com/"tag.content = "菜鸟教程"print(tag)
默认是双标签,也就是带有起始标签和结束标签的标签对。
<a id="a1" href="https://www.runoob.com/" >菜鸟教程</a>
is_single
设为true
后,就被认为是单标签:
@tool
extends EditorScriptfunc _run() -> void:var tag = MLTag.new() # 创建一个标签tag.name = "a" # 名称tag.attrs["id"] = "a1" # 设定属性tag.attrs["href"] = "1.com"tag.innerHTML = "hahah"tag.is_single = true # 设为标签print(tag)
打印输出的结果也就变了:
<a id="a1" href="https://www.runoob.com/" />
可以看到没有了结束标签,子内容部分也自动省略。
HTML标签基类
# =============================================
# 名称:HTMLtag
# 类型:类
# 描述:HTML标签基类
# 作者:巽星石
# 创建时间:2024年7月16日19:05:46
# 最后修改时间:2024年7月16日19:29:34
# =============================================
class_name HTMLTag extends MLTag# ====================== 属性 ======================
# ID
var id:String:set(val):attrs["id"] = valget:return attrs["id"]
# name
var name:String:set(val):attrs["name"] = valget:return attrs["name"]
# css类名
var className:String:set(val):attrs["class"] = valget:return attrs["class"]
# 行内CSS样式
var style:String:set(val):attrs["style"] = valget:return attrs["style"]
# ====================== 初始化 ======================
func _init() -> void:# HTML标签通用属性attrs = {"id" = "", # ID"name" = "", # name属性"class" = "", # css类名"style" = "", # 行内样式}
测试代码:
@tool
extends EditorScriptfunc _run() -> void:var tag = HTMLTag.new() # 创建一个标签tag.tag_name = "a" # 名称# 设定HTML标签通用属性tag.id = "a2"tag.name = "a2"tag.className = "url"tag.style = "font-size:16px;"tag.innerHTML = "一个超链接"print(tag)
输出:
<a id="a2" name="a2" class="url" style="font-size:16px;" >一个超链接</a>
HTML<a>标签
# =============================================
# 名称:HTMLtagA
# 类型:类
# 描述:HTML的<a>标签类
# 作者:巽星石
# 创建时间:2024年7月16日19:32:47
# 最后修改时间:2024年7月16日22:30:57
# =============================================
class_name HTMLTagA extends HTMLTag# ====================== 属性 ======================
# 链接地址
var href:String:set(val):attrs["href"] = valget:return attrs["href"]
# 指定链接如何在浏览器中打开
var target:String:set(val):attrs["target"] = valget:return attrs["target"]
# 鼠标提示文本
var title:String:set(val):attrs["title"] = valget:return attrs["title"]
# 指定与链接目标的关系,如 nofollow、noopener 等
var rel:String:set(val):attrs["rel"] = valget:return attrs["rel"]# ====================== 初始化 ======================
func _init() -> void:super() # 初始化父类,否则无法继承相关的默认属性# 确定标签名称以及是否单标签tag_name = "a"is_single = false# <a>标签可用属性attrs["href"] = "" # 链接地址attrs["target"] = "" # 指定链接如何在浏览器中打开attrs["title"] = "" # 鼠标提示文本attrs["rel"] = "" # 指定与链接目标的关系,如 nofollow、noopener 等
测试代码:
@tool
extends EditorScriptfunc _run() -> void:var link = HTMLTagA.new() # 创建一个标签# 设定<a>标签属性link.href = "https://www.runoob.com/"link.innerHTML = "菜鸟教程"print(link)
输出:
<a href="https://www.runoob.com/" >菜鸟教程</a>
SVG标签类
我发现专门做一个XML标签基类是没有必要的,XML本身就没有固定的标签,所以由MLTag定义完全可以解决XML标签定义和生成的功能。
而<svg>
本身既可以算HTML标签,也可以看做是XML标签。这里为了简化,我创建SVG类,代表<svg>
标签,并直接继承自MLTag
类型。
# =============================================
# 名称:SVG
# 类型:类
# 描述:SVG的<svg>标签类
# 作者:巽星石
# 创建时间:2024年7月16日21:37:24
# 最后修改时间:2024年7月16日21:44:04
# =============================================
class_name SVG extends MLTag# ====================== 属性 ======================
# SVG画布宽度
var width:String:set(val):attrs["width"] = valget:return attrs["width"]
# SVG画布高度
var height:String:set(val):attrs["height"] = valget:return attrs["height"]# ====================== 初始化 ======================
func _init() -> void:tag_name = "svg"# HTML标签通用属性attrs = {"version"="1.1","baseProfile"="full","width"="200","height"="200","xmlns"="http://www.w3.org/2000/svg",}
SVGShape
SVG的形状和路径有许多共同的属性,所以抽象出一个SVGShape
类型,用来承载共同属性。
# =============================================
# 名称:SVGShape
# 类型:类
# 描述:SVG所有形状和路径标签类的基类,承载共同属性
# 作者:巽星石
# 创建时间:2024年7月16日21:51:00
# 最后修改时间:2024年7月16日23:07:46
# =============================================
class_name SVGShape extends MLTag# ====================== 属性 ======================
# 填充颜色
var fill:String:set(val):attrs["fill"] = valget:return attrs["fill"]# 描边颜色
var stroke:String:set(val):attrs["stroke"] = valget:return attrs["stroke"]# 描边宽度
var stroke_width:int:set(val):attrs["stroke-width"] = str(val)get:return int(attrs["stroke-width"])# ====================== 初始化 ======================
func _init() -> void:tag_name = "svg"# svg形状和路径标签通用属性attrs["fill"] = "#fff"attrs["stroke"] = "#000"attrs["stroke-width"] = "1"
矩形
基于SVGShape
类型,我们可以创建SVG具体的形状和路径类型。SVGRect
就是SVG矩形
# =============================================
# 名称:SVGRect
# 类型:类
# 描述:SVG的<rect>标签类
# 作者:巽星石
# 创建时间:2024年7月16日21:47:43
# 最后修改时间:2024年7月16日22:16:54
# =============================================
class_name SVGRect extends SVGShape# ====================== 属性 ======================# ---------------------- 位置 ----------------------
# 矩形左上角x坐标
var x:String:set(val):attrs["x"] = valget:return attrs["x"]# 矩形左上角y坐标
var y:String:set(val):attrs["y"] = valget:return attrs["y"]
# ---------------------- 尺寸 ----------------------
# 矩形宽度
var width:String:set(val):attrs["width"] = valget:return attrs["width"]# 矩形高度
var height:String:set(val):attrs["height"] = valget:return attrs["height"]
# ---------------------- 圆角 ----------------------
# 矩形圆角半径(水平方向)
var rx:String:set(val):attrs["rx"] = valget:return attrs["rx"]# 矩形圆角半径(垂直方向)
var ry:String:set(val):attrs["ry"] = valget:return attrs["ry"]# ====================== 初始化 ======================
func _init() -> void:super() # 初始化父类,否则无法继承相关的默认属性tag_name = "rect"# HTML标签通用属性attrs["x"] = "0"attrs["y"] = "0"attrs["width"] = "100"attrs["height"] = "100"attrs["rx"] = "0"attrs["ry"] = "0"
测试代码:
@tool
extends EditorScriptfunc _run() -> void:var svg = SVG.new() # 创建SVG标签var rect = SVGRect.new() # 创建矩形svg.append(rect)print(svg)
获得的SVG代码:
<svg version="1.1" baseProfile="full" width="200" height="200" xmlns="http://www.w3.org/2000/svg" >
<rect fill="#fff" stroke="#000" stroke-width="1" x="0" y="0" width="100" height="100" rx="0" ry="0" ></rect></svg>
SVG预览如下:
@tool
extends EditorScriptfunc _run() -> void:var svg = SVG.new(100,200) # 创建SVG标签var rect = SVGRect.new(0,0,100,200,12,12) # 创建矩形# 设定矩形属性rect.stroke = "red"rect.stroke_width = 2# 将矩形追加到svg内容的末尾svg.append(rect)print(svg) # 打印SVG代码
获得的SVG代码:
<svg version="1.1" baseProfile="full" width="100" height="200" xmlns="http://www.w3.org/2000/svg" >
<rect fill="#fff" stroke="red" stroke-width="2" x="0" y="0" width="100" height="200" rx="12" ry="12" ></rect></svg>
预览如下:
总结
- 纯面向对象的设计,尤其是基于继承的多个类组成的体系在某些方面还是很有用的。比如HTML、XML、SVG这样本身就很明显的继承设计。
- 基于继承或许会写出一堆类,但是辅以类图和文档,还是能让别人比较轻松的理解和掌握的。
- 静态函数库则完全是一个很差的设计形式,很有可能会被一堆函数搞得特别臃肿。
- 适当的用类和类的继承形式取代静态函数库形式是我正在做的尝试
相关文章:

【Godot4.2】MLTag类:HTML、XML通用标签类
概述 HTML和XML采用类似的标签形式。 之前在Godot中以函数库形式实现了网页标签和内容生成。能用,但是缺点也很明显。函数之间没有从属关系,但是多有依赖,而且没有划分出各种对象和类型。 如果以完全的面向对象形式来设计标签类或者元素类…...

美式键盘 QWERTY 布局的起源
注:机翻,未校对。 The QWERTY Keyboard Is Tech’s Biggest Unsolved Mystery QWERTY 键盘是科技界最大的未解之谜 It’s on your computer keyboard and your smartphone screen: QWERTY, the first six letters of the top row of the standard keybo…...

【JavaEE】HTTP(2)
🤡🤡🤡个人主页🤡🤡🤡 🤡🤡🤡JavaEE专栏🤡🤡🤡 🤡🤡🤡下一篇文章:【JavaEE】HTTP协议(…...

LinuxShell编程2——shell搭建Discuzz论坛网站
目录 一、环境准备 ①准备一台虚拟机 ②初始化虚拟机 1、关闭防火墙 2、关闭selinux 3、配置yum源 4、修改主机名 二、搭建LAMP环境 ①安装httpd(阿帕奇apache)服务器 查看是否安装过httpd 启动httpd 设置开机启动 查看状态 安装网络工具 测试 ②安装…...

.NET MAUI开源架构_1.学习资源分享
最近需要开发Android的App,想预研下使用.NET开源架构.NET MAUI来开发App程序。因此网上搜索了下相关资料,现在把我查询的结果记录下,方便后面学习。 1.官方文档 1.1MAUI官方学习网站 .NET Multi-Platform App UI 文档 - .NET MAUI | Micro…...
Unsloth 微调 Llama 3
本文参考: https://colab.research.google.com/drive/135ced7oHytdxu3N2DNe1Z0kqjyYIkDXp 改编自:https://blog.csdn.net/qq_38628046/article/details/138906504 文章目录 一、项目说明安装相关依赖下载模型和数据 二、训练1、加载 model、tokenizer2、…...
热修复的原理
热修复的原理 水一篇哈,完事儿后删掉热修复的原理 水一篇哈,完事儿后删掉 热修复的原理 Java虚拟机 —— JVM 是加载类的class文件的,而Android虚拟机——Dalvik/ART VM 是加载类的dex文件,而他们加载类的时候都需要ClassLoader,…...

【对顶堆 优先队列】2102. 序列顺序查询
本文涉及知识点 对顶堆 优先队列 LeetCode 2102. 序列顺序查询 一个观光景点由它的名字 name 和景点评分 score 组成,其中 name 是所有观光景点中 唯一 的字符串,score 是一个整数。景点按照最好到最坏排序。景点评分 越高 ,这个景点越好。…...
Go 语言中的互斥锁 Mutex
Mutex 是一种互斥锁,名称来自 mutual exclusion,是一种用于控制多线程对共享资源的竞争访问的同步机制。在有的编程语言中,也将其称为锁(lock)。当一个线程获取互斥锁时,它将阻止其他线程对该资源的访问,直到该线程释放锁。这可以防止多个线程对共享资源进行冲突访问,从而…...

CSS 中的 ::before 和 ::after 伪元素
目录 一、CSS 伪元素 二、::before ::after 介绍 1、::before 2、::after 3、content 常用属性值 三、::before ::after 应用场景 1、设置统一字符 2、通过背景添加图片 3、添加装饰线 4、右侧展开箭头 5、对话框小三角 6、插入icon图标 一、CSS 伪元素 CSS伪元…...

JuiceFS缓存特性
缓存 对于一个由对象存储和数据库组合驱动的文件系统,缓存是本地客户端与远端服务之间高效交互的重要纽带。读写的数据可以提前或者异步载入缓存,再由客户端在后台与远端服务交互执行异步上传或预取数据。相比直接与远端服务交互,采用缓存技…...

R语言实现SVM算法——分类与回归
### 11.6 基于支持向量机进行类别预测 ### # 构建数据子集 X <- iris[iris$Species! virginica,2:3] # 自变量:Sepal.Width, Petal.Length y <- iris[iris$Species ! virginica,Species] # 因变量 plot(X,col y,pch as.numeric(y)15,cex 1.5) # 绘制散点图…...
React@16.x(57)Redux@4.x(6)- 实现 bindActionCreators
目录 1,分析1,直接传入函数2,传入对象 2,实现 1,分析 一般情况下,action 并不是一个写死的对象,而是通过函数来获取。 而 bindActionCreators 的作用:为了更方便的使用创建 action…...

【深度学习入门篇 ⑦】PyTorch池化层
【🍊易编橙:一个帮助编程小伙伴少走弯路的终身成长社群🍊】 大家好,我是小森( ﹡ˆoˆ﹡ ) ! 易编橙终身成长社群创始团队嘉宾,橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官…...

【Pytorch】数据集的加载和处理(一)
Pytorch torchvision 包提供了很多常用数据集 数据按照用途一般分为三组:训练(train)、验证(validation)和测试(test)。使用训练数据集来训练模型,使用验证数据集跟踪模型在训练期间…...

论文翻译:Explainability for Large Language Models: A Survey
https://arxiv.org/pdf/2309.01029 目录 可解释性在大型语言模型中:一项调查摘要1 引言2 LLMs的训练范式2.1 传统微调范式2.2 提示范式 3 传统微调范式的解释3.1 局部解释3.1.1 基于特征归因的解释3.1.2 基于注意力的解释3.1.3 基于示例的解释 3.2 全局解释3.2.1 基…...
38 IRF+链路聚合+ACL+NAT组网架构
38 IRF+链路聚合+ACL+NAT组网架构 参考文献 34 IRF的实例-CSDN博客 35 解决单条链路故障问题-华三链路聚合-CSDN博客 36 最经典的ACL控制-CSDN博客 37 公私网转换技术-NAT基础-CSDN博客 32 华三vlan案例+STP-CSDN博客 一 网络架构...
【昇思学习打卡营打卡-第二十八天】MindNLP ChatGLM-6B StreamChat
MindNLP ChatGLM-6B StreamChat 本案例基于MindNLP和ChatGLM-6B实现一个聊天应用。 安装mindnlp pip install mindnlp安装mdtex2html pip install mdtex2html配置网络线路 export HF_ENDPOINThttps://hf-mirror.com代码开发 下载权重大约需要10分钟 from mindnlp.transf…...
前端打包部署后源码安全问题总结
随着现代Web应用越来越依赖于客户端技术,前端安全问题也随之突显。源码泄露是一个严重的安全问题,它不仅暴露了应用的内部逻辑和业务关键信息,还可能导致更广泛的安全风险。本文将详细介绍源码泄露的潜在风险,并提供一系列策略和工…...
扩展你的App:Xcode中App Extensions的深度指南
扩展你的App:Xcode中App Extensions的深度指南 在iOS开发的世界中,App Extensions提供了一种强大的方式,允许你的应用程序与系统和其他应用更紧密地集成。从今天起,我们将探索Xcode中App Extensions的神秘领域,学习如…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...