部分运行代码为html和文本

Jor*_*rdy 19 html javascript jquery templates escaping

介绍

我目前正在创建一个模板构建器,用户可以在其中为应用程序构建模板.用户可以拖放多个块,例如文本块和"自定义代码"块.该模板将在应用程序中解析.现在,模板看起来像这样:

<section>
    <div class="row">
        <div class="col-sm-12">
            <section data-type="code">
                <#code></#code>
            </section>
        </div>
    </div>
    <div class="row">
        <div class="col-sm-12" data-type="container-content">
            <section data-type="text">
                <u>Lorem</u> ipsum
            </section>
        </div>
    </div>
</section>
Run Code Online (Sandbox Code Playgroud)

因此,此模板包含两个元素(请参阅data-type属性):一部分是自定义编写的代码.在这里,用户编写了自定义代码,包括Apache Freemarker代码.第二部分是自定义书面文字.

情况

上面的代码将以两种不同的方式使用.

  • 确切地说,这段代码将在使用模板的应用程序中使用(这就是为什么他们应该能够编写Freemarker代码,因为这将被解析).
  • 在我的网站上,用户应该能够编辑此模板.因为代码存储在数据库中,如上所述,存在一个问题:

问题

当我在Web界面中直接渲染模板时,该text部件将使用<u></u>标签正确呈现,但该code部件也将呈现为html,这可能会导致奇怪的行为(例如freemarker表示法</#list>被自动转换为<!--#list-->).

但是,如果我将完整模板仅渲染为文本,则text带有<u></u>标记的部分也不会被渲染.

预期结果

我想用JavaScript/jQuery读取模板变量,然后data-typetexthtml和codetext 解析每个变量.

我如何循环模板并执行此操作?

Edu*_*oço 9

有一种替代语法使用方括号而不是尖括号.

检查它是否解决了您的标签识别问题,而不会弄乱任何其他功能.

https://freemarker.apache.org/docs/dgui_misc_alternativesyntax.html

编辑1

要在解析HTML时在<#code>标记内显示源代码,您可以在数据库中转义它(转义html特殊字符,如<,>和&到<>和&).因此,在渲染时,代码内容中不会创建任何html标记,并且文档不会被搞砸.

然后,您可以直接将所有数据库内容呈现为HTML:文本将保留标记,代码将是文本.

要进行此修改,您可以使用正则表达式查找<#code>标记所包含的内容,并替换为HTML转义的等效项.确切的方法取决于您将用于工作的语言,因为RegExes和可用的转义功能存在一些差异.

编辑2

如果您使用AJAX加载内容,则可以在javascript中应用替换,在从服务器获取内容之后,保持数据库不变.


use*_*291 2

问题回顾

\n\n

为了在 javascript 中解析 HTML,通常使用DOMParser对象(IE10+ 支持)。

\n\n

就像你说的,解析在该data-type="code"部分内失败,因为它不知道如何处理</#...>标签......

\n\n

\r\n
\r\n
const templ = `<section><div class="row"><div class="col-sm-12"><section data-type="code"><#code></#code></section></div></div><div class="row"><div class="col-sm-12" data-type="container-content"><section data-type="text"><u>Lorem</u> ipsum</section></div></div></section>`;\r\nconst parser = new DOMParser();\r\nconst doc = parser.parseFromString(templ, "text/html");\r\n\r\nconsole.log(\r\n  "Wrongly parsed </#code> tag:\\n",\r\n  doc.querySelector("[data-type=\'code\']").innerHTML\r\n);
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

寻找解决办法

\n\n

现在,尝试对需要转义的字符进行快速正则表达式查找和替换可能听起来是个好主意,但我不推荐它......

\n\n

据我所知,没有办法“闯入”解析过程或传递某些类型元素的策略......

\n\n

我想说这给你留下了两个选择。任何一个:

\n\n
    \n
  1. 不要在代码部分中使用不可解析的语法,如用户Eduardo Po\xc3\xa7o中的建议其答案中所建议的那样
  2. \n
\n\n

或者,(我喜欢的方向),尝试

\n\n
    \n
  1. 修改模板本身以停止解析所有代码段的内容
  2. \n
\n\n

使用修改后的模板

\n\n

HTML 中有一个类似于“脚本”内容的标签!不出所料,这就是标签<script>。让我们将它注入到我们的code部分中:

\n\n
<section data-type="code">\n    <script type="text">\n        <#code></#code>\n    </script>\n</section>\n
Run Code Online (Sandbox Code Playgroud)\n\n

不会DOMParser触及此标签,使其保持原样:

\n\n

\r\n
\r\n
<section data-type="code">\n    <script type="text">\n        <#code></#code>\n    </script>\n</section>\n
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

请注意,我必须将两个部分的模板字符串连接起来,以确保 stackoverflow 的代码片段不会中断。他们遇到类似的问题吗?:-o

\n\n
\n\n

现在,我们所要做的就是使用通用 DOM 方法,包括innerText innerHTML)将脚本的内部内容返回到 DOM 的可见部分:

\n\n

\r\n
\r\n
const templ = \'<section><div class="row"><div class="col-sm-12"><section data-type="code"><script type="text"><#code></#code></\' + \'script></section></div></div><div class="row"><div class="col-sm-12" data-type="container-content"><section data-type="text"><u>Lorem</u> ipsum</section></div></div></section>\';\r\n\r\nconst parser = new DOMParser();\r\nconst doc = parser.parseFromString(templ, "text/html");\r\n\r\nconsole.log(\r\n  "Now, there\'s a <script> tag:\\n",\r\n  doc.querySelector("[data-type=\'code\']").innerHTML\r\n);
Run Code Online (Sandbox Code Playgroud)\r\n
var templ = \'<section><div class="row"><div class="col-sm-12"><section data-type="code"><script type="text"><#code></#code></\' + \'script></section></div></div><div class="row"><div class="col-sm-12" data-type="container-content"><section data-type="text"><u>Lorem</u> ipsum</section></div></div></section>`;\'\r\n\r\nvar parser = new DOMParser();\r\nvar doc = parser.parseFromString(templ, "text/html");\r\n\r\nArray\r\n  .from(doc.querySelectorAll(\r\n    "[data-type=\'code\'] > script")\r\n  )\r\n  .forEach(script => {\r\n      const codeTag = document.createElement("code");\r\n      codeTag.innerText = script.innerHTML;\r\n      script.replaceWith(codeTag);\r\n  });\r\n\r\ndocument.getElementById("wrapper").appendChild(doc.body.firstChild);
Run Code Online (Sandbox Code Playgroud)\r\n
code { background: #efefef; }
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n