Singularity Engine

Singularity Engine 是一个为 Vue 3 设计的响应式语法渲染引擎,支持变量插值和 LaTeX 数学公式渲染。
✨ 特性
- 响应式渲染: 数据变化时自动更新渲染结果
- 变量插值: 支持
{variable} 语法进行变量替换
- 数学公式: 支持
$LaTeX$ 语法渲染数学公式
- Vue 3 集成: 提供组件和 Composable 两种使用方式
- TypeScript 支持: 完整的类型定义
🚀 核心设计思想
- 模板驱动: 用户提供一个包含特殊语法的字符串模板
- 数据绑定: 用户提供一个响应式的数据对象
- 自动更新: 当数据对象中的值变化时,渲染结果自动、高效地更新
- 语法扩展: 支持普通文本、变量占位符 (
{var}) 和数学公式 ($...$)
📦 安装
yarn add singularity-engine
npm install singularity-engine
pnpm add singularity-engine
🚀 快速开始
在 Vue 3 项目中使用
import { createApp } from 'vue'
import { sEnginePlugin } from 'singularity-engine'
import App from './App.vue'
const app = createApp(App)
app.use(sEnginePlugin)
app.mount('#app')
使用方式一:<SRenderer> 组件 (推荐)
这是最简单、最直观的方式。
<!-- In YourApp.vue or any component -->
<template>
<div>
<h3>动态几何报告</h3>
<p>
<SRenderer :template="reportTemplate" :variables="geoData" />
</p>
<p>
<label>
边长 'a':
<input type="range" v-model.number="geoData.side_a" min="1" max="100">
</label>
</p>
<p>
<label>
边长 'b':
<input type="range" v-model.number="geoData.side_b" min="1" max="100">
</label>
</p>
<p>
<label>
更新模板:
<input type="text" v-model="reportTemplate" style="width: 400px;">
</label>
</p>
</div>
</template>
<script setup>
import { ref, reactive, computed } from 'vue';
import { SRenderer } from 'singularity-engine'; // 如果没有全局注册,需要导入
// 模板字符串,也可以是 ref
const reportTemplate = ref(
"一个矩形,边长为 {side_a} 和 {side_b}。它的面积是 {area},周长是 {perimeter}。面积公式是 $A = a \\times b$。"
);
// 响应式数据源
const geoData = reactive({
side_a: 10,
side_b: 20,
// 使用 computed 属性实现自动计算
area: computed(() => geoData.side_a * geoData.side_b),
perimeter: computed(() => 2 * (geoData.side_a + geoData.side_b)),
});
</script>
使用方式二:useSEngine Composable (高级)
当你需要对渲染结果进行更精细的控制,而不是直接渲染为 HTML 时,可以使用此方法。
<template>
<div>
<!-- 手动渲染 -->
<template v-for="part in myRenderedParts">
<strong v-if="part.type === 'text'">{{ part.content }}</strong>
<div v-else class="math-block" v-html="part.html"></div>
</template>
</div>
</template>
<script setup>
import { reactive } from 'vue';
import { useSEngine } from 'singularity-engine';
const template = "The result is $x = {result}$";
const data = reactive({ result: 42 });
// 直接获取渲染后的部分数组
const { renderedParts: myRenderedParts } = useSEngine(template, data);
</script>
<style>
.math-block {
border: 1px solid #ccc;
padding: 1em;
}
</style>
使用方式三:直接使用 SEngine 类
import { SEngine } from 'singularity-engine'
const template = "当 x = {x} 时,$f(x) = x^2 + {a}x + {b} = {result}$"
const variables = { x: 5, a: 2, b: 3, result: 38 }
const engine = new SEngine(template)
const parts = engine.render(variables)
console.log(parts)
📖 API 文档
SRenderer 组件
Props
template | string | Ref<string> | - | 模板字符串,支持变量和数学公式 |
variables | Record<string, any> | Ref<Record<string, any>> | - | 变量对象 |
tag | string | 'span' | 渲染的 HTML 标签 |
示例
<template>
<SRenderer
:template="'结果是 {value},公式为 $y = {a}x + {b}$'"
:variables="{ value: 42, a: 2, b: 3 }"
tag="div"
/>
</template>
useSEngine Composable
function useSEngine(
template: Ref<string> | string,
variables: Ref<Record<string, any>> | Record<string, any>
): {
renderedParts: ComputedRef<RenderedPart[]>
}
返回值
renderedParts: 渲染后的部分数组,每个部分包含 type 和内容
SEngine 类
class SEngine {
constructor(template: string)
render(variables: Record<string, any>): RenderedPart[]
}
方法
render(variables): 渲染模板,返回渲染部分数组
🎯 语法说明
变量插值
使用 {variableName} 语法插入变量:
const template = "Hello {name}, you are {age} years old!"
const variables = { name: "Alice", age: 25 }
数学公式
使用 $LaTeX$ 语法插入数学公式:
const template = "二次方程 $ax^2 + bx + c = 0$ 的解为 $x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}$"
混合使用
const template = "当 a = {a}, b = {b}, c = {c} 时,判别式 $\\Delta = b^2 - 4ac = {discriminant}$"
const variables = { a: 1, b: -3, c: 2, discriminant: 1 }
🎨 样式自定义
引入 KaTeX CSS
<script setup>
import { katexCSS } from 'singularity-engine'
</script>
<style>
/* 如果需要在 Shadow DOM 或特殊环境中使用 */
v-html {
/* katexCSS 包含完整的 KaTeX 样式 */
}
</style>
自定义数学公式样式
.katex {
font-size: 1.2em;
color: #2c3e50;
}
.katex-display {
margin: 1em 0;
text-align: center;
}
🔧 高级用法
动态模板
<template>
<div>
<input v-model="template" placeholder="输入模板">
<SRenderer :template="template" :variables="data" />
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const template = ref("结果: {result}")
const data = reactive({ result: 42 })
</script>
计算属性集成
<script setup>
import { reactive, computed } from 'vue'
const data = reactive({
a: 3,
b: 4,
// 自动计算的属性
hypotenuse: computed(() => Math.sqrt(data.a ** 2 + data.b ** 2))
})
const template = "直角三角形的两边为 {a} 和 {b},斜边长度为 {hypotenuse},根据勾股定理 $c = \\sqrt{a^2 + b^2}$"
</script>
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
MIT License