Thymeleaf在'noscript'标签之前打破了HTML

时间:2014-08-26 08:01:03

标签: html5 thymeleaf noscript

考虑这个标记:

<!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>

如何防止此行为?

4 个答案:

答案 0 :(得分:4)

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

但是,这并不是全部,所有高级版本都不允许在头部内,使用带有子元素的元素,因此头部中的noscript不能支持其中的链接标记。使用您的代码,结果必须是:

<!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元素的内容,因此被视为文本,以便使用百里香叶的动态代码,设置:noscript开始标记中的内联属性到文本,并在内部使用标记 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)) {

优点:让你为百里香的头部定义th:block标签。

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

答案 1 :(得分:0)

将脚本移到noscript样式表上方

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

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

fragments / 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解释的那样,导致此错误的原因似乎没有,它不是“链接”该错误,而是通过间接插入它似乎可以正常工作。