# scriptparser **Repository Path**: shenguz/scriptparser ## Basic Information - **Project Name**: scriptparser - **Description**: 一款在.net环境下,解析执行Javascript的开源组件。 - **Primary Language**: C# - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 90 - **Forks**: 19 - **Created**: 2020-12-01 - **Last Updated**: 2025-06-20 ## Categories & Tags **Categories**: utils **Tags**: None ## README # 简介 ScriptParser是一款可以在.net的环境下,解析执行`javascript`语法的开源组件,其主要定位如下: 1. 在.net环境下,动态执行部分业务逻辑,以实现在不修改原生程序的基础上,动态的扩展一些功能。 2. 提供一套可以用`javascript`来控制逻辑的模板机制,以便在.net环境下,可以动态生成文本(比如:某些情况下,代替.aspx生成html页面等) ## 支持语法 目前`ECMAScript 5`的语法,除了`with语法、Property`等个别语法之外,其它的都有支持。 支持的预设类型:`Object、Array、Number、String、Date`,以及部分预设方法:`parseInt、parseFloat、stringify、eval`等。 因为模板的需要,支持几个`ECMAScript 6`的语法:for...of...表达式,箭头表达式,`let、const`语法。 支持对`DataTable`的访问。 支持开发者根据需要,添加需要在`javascript`中调用的类、对象、方法及属性。 ## 其它 1. 由于`javascript`对象的特殊性,所有需要传入到`javascript`中去访问的对象、方法,都需要直接或间接的转化成继承于IScriptObject的对象。 > .net中的对象,如果没有特别处理,会使用`ScriptType`、`ScriptNativeObject`、`ScriptNativeArray`、`ScriptNativeFunction`进行包装后,供`javascript`的语句中调用。 2. 该组件的解析和执行过程,使用内存结构来模拟线程栈的操作,以避免解析到恶意嵌套的语法,引发堆栈溢出,从而导致进程中止。 3. 该组件在执行时,有支持暂停执行/继续执行的功能,在批量执行脚本时,可以支持类似于纤程的功能。 > `ScriptParser`在`Execute`时,可以调用`ScriptContext.Pause`方法,此时,会保存上下文环境并退出`Execute`方法,下次可以调用`ScriptContext.Continue`恢复执行。在批量执行脚本时,可以对一些执行时间比较长的方法,执行异步操作(比如:网络语法等),并调用`ScriptContext.Pause`中断执行,在异步回调中,再调用`ScriptContext.Continue`恢复。 # Demo 请参见ScriptTest项目 ## JavaScript的解析过程 ````C# //创建执行上下文:ScriptContext ScriptContext context = new ScriptContext(); //添加变量,以及方法映射 context.AddValue("inc", 100); //获取执行结果 object result = ScriptUtils.ExecuteScript(context, "var i = 0; return i + inc;"); ```` ## 模板的解析过程 ````C# //创建执行上下文:ScriptContext ScriptContext context = new ScriptContext(); //添加变量,以及方法映射 context.AddValue("status", 2); string template = @" 状态码: <@switch code="status"> <@case code="1">@{"正常"} <@case code="2">@{"冻结"} <@default>其它状态 "; string result = ScriptUtils.ExecuteTemplate(context, template); ```` # 模板解析标签 ## 标签简介 1. ScriptParser的模板解析过程,是先将带特殊标签的模板,转化成一段可执行的`javascript`脚本,再执行脚本,生成最终的结果。所以,ScriptParser的模板支持在模板中编写`javascript`语法 2. 标签格式:除了写入单值的语法(`@{***}`)之外,所有的逻辑标签都是以`<@***>`开始,以及``结束 3. 逻辑标签,代表一个`javascript`的关键字(如:if/for/while/switch等),关键字的括号部分(如:`if(***)`、`for(***)`等)的内容,基本上都写在code属性中。只有两个例外:`do{...}while(***)`、`else if(***){}` ## if...else if...else... 1. if/else语法,if/else if/else节点之间,除了空格和换行之外,不能有其它内容 2. else if节点表示为:`<@else if="***">` ````html <@if code="status==1"> 状态:@{"正常"} <@else if="statue==2"> 状态:@{"冻结"} <@else> @{"其它状态"} ```` ## for(...; ...; ...) ````html <@for code="var i = 0; i < 100; i++"> 计数:@{i}
```` ## for...in ````html <@for code="var index in list"> 元素:@{list[index]}
```` ## for...of ````html <@for code="var item of list"> 元素:@{item}
```` ## while ````html <@while code="i++ < 10"> i的值:@{i} ```` ## do...while 节点结构:` ` ````html <@do while="i++ < 10"> i的值:@{i} ```` ## switch...case...default... 1. case和default的节点,在生成`javascript`语法时,会自动在最后加上`break;` 2. 如果需要不需要加`break;`,可以将case节点编写为:`<@case code="***" />`,或者:`<@case code="***" ignoreBreak="true">` ````html <@switch code="status"> <@case code="1"> 状态:@{"正常"} <@case code="2"> 状态:@{"冻结"} <@default> @{"其它状态"} ```` ## break/continue ````html <@while code="true"> <@if code="i<0"> <@break /> <@else if="i>0"> <@continue /> <@else> <@line code="i--" /> ```` ## try...catch...finally... ````html <@try> 正常执行 <@catch code="e">
错误信息:@{e} <@finally>
最终执行 ```` ## @{***} 代表将内部的表达式输出来(注意:内部必须是一个表达式) ````html @{i > 0 ? i : "异常状态"} ```` ## `<@line />` 单行语法,在生成`javascript`语法时,会在最后自动加上“;” ````html <@line code="i++" /> ```` ## `<@code>...`(`<@>...`) 自由语法,可以在节点之间,任意编写`javascript`脚本,这些脚本在生成`javascript`时,会被原封不动的保留下来 ````html <@code> var i = 0; var list = []; for (var i = 0; i < 100; i++) { list.push(i); } ```` ## `<@nowrap>...` 不换行节点,这个节点之间的文本(不包括通过`javascript`脚本动态输出的脚本)换行符不输出 ````html <@nowrap> 状态: <@if code='status==0'>未开始 <@else if='status==1'>已进场 <@else if='status==2'>已出场 <@else>异常离场 ```` # QQ交流群 1. 792893075[![快速加群](https://pub.idqqimg.com/wpa/images/group.png)](https://jq.qq.com/?_wv=1027&k=DeLntNXe)