2017-12-27 922 views
0

下面是代码为什么JSDOM更改html结构?

var fs = require('fs') 
var htmlSource = fs.readFileSync("public/html/index.html", "utf8") 
var jsdom = require('jsdom'); 
const {JSDOM} = jsdom; 
const dom = new JSDOM(htmlSource); 
htmlSource = dom.window.document.querySelector("html").outerHTML 
console.log(htmlSource) 
<!-- This is a public/html/index.html --> 
<!DOCTYPE html> 
<html> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> 
<script type="text/javascript" src="js/main.js"></script> 
<head> 
    <title>Home Electricity Manager</title> 
</head> 
<body ng-app="myApp"> 
    <h1 id="the-header">Wellcome to home electricity manager!</h1> 
    <div add-row ng-controller="myController" style="text-align: center; display: inline-block;"> 
     <span style="white-space:pre;">Button text</span><br/> 
     <button id="first-button" ng-style="myStyle" ng-click="toggleRelay()" id="switch-cirquit-1">{{ButtonStatus}}</button> 
    </div> 
    <div add-row ng-controller="myController" style="text-align: center; display: inline-block;"> 
     <span id="second-button" style="white-space:pre;">{{buttonOneText}}</span><br/> 
     <button ng-style="myStyle" ng-click="toggleRelay()" id="switch-cirquit-1">{{ButtonStatus}}</button> 
    </div> 
    <div ng-controller="postController" style="text-align: center; display: inline-block;"> 
     <button ng-click="post()">{{buttonName}}</button> 
    </div> 
</body> 
</html> 

<!-- src="js/directives/add-row.js" --> 

而结果形成线console.log(htmlSource)是:

<html><head><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> 
<script type="text/javascript" src="js/main.js"></script> 

    <title>Home Electricity Manager</title> 
</head> 
<body ng-app="myApp"> 
    <h1 id="the-header">Wellcome to home electricity manager!</h1> 
    <div add-row="" ng-controller="myController" style="text-align: center; display: inline-block;"> 
     <span style="white-space:pre;">Button text</span><br> 
     <button id="first-button" ng-style="myStyle" ng-click="toggleRelay()">{{ButtonStatus}}</button> 
    </div> 
    <div add-row="" ng-controller="myController" style="text-align: center; display: inline-block;">  
     <span id="second-button" style="white-space:pre;">{{buttonOneText}}</span><br> 
     <button ng-style="myStyle" ng-click="toggleRelay()" id="switch-cirquit-1">{{ButtonStatus}}</button> 
    </div> 
    <div ng-controller="postController" style="text-align: center; display: inline-block;"> 
     <button ng-click="post()">{{buttonName}}</button> 
    </div> 



</body></html> 

请注意,script元素从<html>孩子移居到了<head>儿童。这是自动发生的。此外,一些新的行似乎被添加到新创建的dom文件。请看两个html文件的区别。为什么是这种变化?

+1

每规范,允许作为一个'html'元素的直接孩子的唯一标签是'head'和'body'。 – Amy

+1

''里面html' script'是无效的HTML。 – Claies

+1

这是无效的HTML有脚本漂浮作为''直接孩子。它可能会做一些简单的验证检查,例如为指令属性添加空值。 – Phix

回答

1

一般而言,转动一个HTML串行化为一个DOM树,和序列化所得到的树将不能保证最终序列将是相同的原来的一个。无论您的HTML是否符合规范,都是如此。

但是,在您的具体情况下,您的HTML不符合标准指定的结构。当一致性解析器遇到不合格的HTML时,它必须遵循一系列步骤来解决问题。这实际上是尝试了解运行中不符合要求的HTML。在你的情况下的流程是这样的:

  1. 开始在initial解析模式,遇到DOCTYPE
  2. 移动到before html模式。
  3. 当遇到<html>时,移至before head模式。
  4. 插入head元素,并在遇到script时移至in head

上面列举的最后一步是在浏览器中修改文档结构,使其符合。如果您在规范中检查rules,您会发现在before head模式中遇到script元素时,会匹配“其他”规则,从而导致将head元素附加到DOM树并移至in head模式。 script元素然后在in head模式中重新处理,并且仅添加到新创建的head元素中。

当分析器跑进<head>标签你把你的HTML文件中,这个标签只是忽略,因为解析器已经在in head模式,由于较早script元素。


您得到的间距是应用规范中的规则。要指出的几个突出的案例:

  1. <head>前不换行,因为before head模式的任何空间将被忽略。
  2. <head>之后没有新行,因为当解析器创建了一个head元素来修复您的HTML时,它没有插入换行符。(这只是不是规则的一部分。)
  3. <title>之前看到的空行的序列化是在原始的HTML由这似乎与之前的新行后<head>。解析器忽略了你的<head>标签(如上所述),但它一直这是周围的间距。