【问题标题】:Thymeleaf breaks the HTML before ´noscript´ tagThymeleaf 在“noscript”标签之前破坏了 HTML
【发布时间】:2014-08-26 08:01:02
【问题描述】:

考虑到这个标记:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>Page title</title>
    <link rel="stylesheet" href="css/layouts.css" type="text/css" media="all">
        <noscript>
        <link rel="stylesheet" href="css/layouts_nojs.css" type="text/css" media="all">
    </noscript>
    <script src="js/jquery.min.js" charset="utf-8"></script>
</head>
<body>

我使用 Thymeleaf 作为引擎,但输出代码结果如下:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>Page title</title>
    <link rel="stylesheet" href="css/layouts.css" type="text/css" media="all">
 </head>
 <body>
    <noscript>
         <link rel="stylesheet" href="css/layouts_nojs.css" type="text/css" media="all">
    </noscript>
    <script src="js/jquery.min.js" charset="utf-8"></script>

如何防止这种行为?

【问题讨论】:

    标签: html thymeleaf noscript


    【解决方案1】:

    Thymeleaf 最后一个版本,2.1.3,使用 nekohtml 库,对于 1.9.14 之前的一些版本,这个库有一个错误,可以避免在 head 中使用 noscript,所以可能你使用的是旧版本,检查你的依赖项。

    但是,这还不是全部,所有的上级版本都不允许在head内使用带有children的元素,所以head中的noscript不能支持它里面的link标签。使用您的代码,结果必须是这样的:

    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Page title</title>
        <link rel="stylesheet" href="css/layouts.css" type="text/css" media="all">          
        <noscript>             
        </noscript><link rel="stylesheet" href="css/layouts_nojs.css" type="text/css" media="all">
        <script src="js/jquery.min.js" charset="utf-8"></script>
    </head>
    <body>
    

    这个问题解决起来比较复杂,需要更深层次的改变。

    解决方法:

    1 - 使用自定义的 LegacyHtml5TemplateParser,您可以在 nekohtml 库的 HTMLConfiguration 中将“http://cyberneko.org/html/features/parse-noscript-content”功能设置为 false,这使得不解析 noscript 元素的内容,因此被视为文本,以利用动态thymeleaf 的代码,将 th:inline 属性设置为 noscript 开始标签中的文本,并使用里面的标记,如 in
    Tutorial: Using Thymeleaf, 12.1 Text inlining

    一个例子:

    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Page title</title>
        <link rel="stylesheet" href="css/layouts.css" type="text/css" media="all">     
        <noscript th:inline="text">
           <link rel="stylesheet" href="[[@{css/layouts_nojs.css}]]" type="text/css" media="all">  
        </noscript>
        <script src="js/jquery.min.js" charset="utf-8"></script>
     </head>
     <body>
    

    2 - 另一种可能性,更复杂,需要为 thymeleaf 使用自定义 LegacyHtml5TemplateParser,为 nekohtml 使用自定义 HTMLTagBalancer,因此您可以控制 head 是否可以包含带有子元素的元素。这涉及创建一系列类来覆盖 nekohtml 行为,这些类如下:

    HTMLAugmentations、HTMLConfiguration、HTMLScanner、HTMLTagBalancer、LostText、ObjectFactory、SecuritySupport、SecuritySupport12。

    您必须从包中的 nekohtml 库中复制原始源代码,并根据此包更改相应地修改它们,并在 LegacyHtml5TemplateParser 中使用您的新 HTMLConfiguration 类。

    对于此解决方法,在 HTMLTagBalancer 中更改以下行:

    if ((fElementStack.top > 1 && fElementStack.peek().element.code == HTMLElements.SCRIPT) 
    || (fElementStack.top > 2 && fElementStack.data[fElementStack.top-2].element.code == HTMLElements.HEAD)) {
    

    与其他人:

    if (fElementStack.top > 1 && fElementStack.peek().element.code == HTMLElements.SCRIPT) {
    //|| (fElementStack.top > 2 && fElementStack.data[fElementStack.top-2].element.code == HTMLElements.HEAD)) {
    

    优点:让您可以在 head 中为 thymeleaf 定义 th:block 标签。

    缺点:如果要将 nekohtml 库版本更改为较新的版本,则必须确保更改不会影响您的代码。

    【讨论】:

    【解决方案2】:

    将脚本移到 noscript 样式表上方

    【讨论】:

    • 如果您正在尝试做出答案,请努力提供更详细和解释。此外,它看起来像解决方法,没有任何信息为什么它应该起作用。
    【解决方案3】:

    在页面解析 html 并执行 javascript 时将 noscript 写入文档。

    <script type="text/javascript">
        document.write('<noscript><div>example</div></noscript>');
    </script>
    

    【讨论】:

    • 对我来说,添加脚本来添加 noscript 标签是没有意义的,因为
    【解决方案4】:

    6 年后,我在尝试实现 Facebook Pixel No Script Tag 时遇到了同样的问题。

    好吧,这是我的解决方法:

    片段/general.html

    <head th:fragment="headFragment">
        <!-- [...] -->
        <th:block th:insert="~{fragments/general :: fbpNoScriptFragment}" />
        <!-- [...] -->
    </head>
    <!-- The noscript below will be inserted in the <head> fragment above, just not directly -->
    <noscript th:fragment="fbpNoScriptFragment">
        <img height="1" width="1" style="display:none" 
             th:attr="src='https://www.facebook.com/tr?id=' + ${fbp_id} + '&ev=PageView&noscript=1'"/>
    </noscript>
    

    在我的“主”模板文件中:

    <head>
        <!-- [...] -->
        <th:block th:include="fragments/general.html :: headFragment" />
        <!-- [...] -->
    </head>
    

    现在它可以工作了,所以看起来像@Jack Froilson 解释的那样导致这个错误的原因,它不会“链接”错误,通过间接插入它似乎可以正常工作。

    【讨论】:

      猜你喜欢
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 2017-01-16
      相关资源
      最近更新 更多