我需要一个可靠的JavaScript库/函数来检查超文本标记语言片段是否有效,我可以从我的代码中调用。例如,它应该检查打开的标签和引号是否关闭,嵌套是否正确等。
我不希望验证失败,因为有些东西不是100%标准的(但无论如何都会工作)。
到目前为止,没有一个解决方案能很好地回答最初的问题,尤其是在涉及到
我不希望验证失败,因为有些东西不是百分之百的标准(但无论如何都会有效)。
太长,读不下去了
所以我使用了关于这个主题的答案和评论的输入,并创建了一个执行以下操作的方法:
退换商品
规范化意味着,在渲染时,浏览器有时会忽略或修复输入的特定部分(例如为<代码>
大多数时候,规范化只会返回对原始html字符串稍加修改的版本,但有时结果会大相径庭。因此,在将用户输入保存到db或盲目渲染之前,应使用此选项标记用户输入以供进一步审查。(有关规范化的示例,请参见JSFIDLE)
检查会考虑以下例外情况
.
function simpleValidateHtmlStr(htmlStr, strictBoolean) {
if (typeof htmlStr !== "string")
return false;
var validateHtmlTag = new RegExp("<[a-z]+(\s+|\"[^\"]*\"\s?|'[^']*'\s?|[^'\">])*>", "igm"),
sdom = document.createElement('div'),
noSrcNoAmpHtmlStr = htmlStr
.replace(/ src=/, " svhs___src=") // disarm src attributes
.replace(/&/igm, "#svhs#amp##"), // 'save' encoded ampersands
noSrcNoAmpIgnoreScriptContentHtmlStr = noSrcNoAmpHtmlStr
.replace(/\n\r?/igm, "#svhs#nl##") // temporarily remove line breaks
.replace(/(<script[^>]*>)(.*?)(<\/script>)/igm, "$1$3") // ignore script contents
.replace(/#svhs#nl##/igm, "\n\r"), // re-add line breaks
htmlTags = noSrcNoAmpIgnoreScriptContentHtmlStr.match(/<[a-z]+[^>]*>/igm), // get all start-tags
htmlTagsCount = htmlTags ? htmlTags.length : 0,
tagsAreValid, resHtmlStr;
if(!strictBoolean){
// ignore <br/> conversions
noSrcNoAmpHtmlStr = noSrcNoAmpHtmlStr.replace(/<br\s*\/>/, "<br>")
}
if (htmlTagsCount) {
tagsAreValid = htmlTags.reduce(function(isValid, tagStr) {
return isValid && tagStr.match(validateHtmlTag);
}, true);
if (!tagsAreValid) {
return false;
}
}
try {
sdom.innerHTML = noSrcNoAmpHtmlStr;
} catch (err) {
return false;
}
// compare rendered tag-count with expected tag-count
if (sdom.querySelectorAll("*").length !== htmlTagsCount) {
return false;
}
resHtmlStr = sdom.innerHTML.replace(/&/igm, "&"); // undo '&' encoding
if(!strictBoolean){
// ignore empty attribute normalizations
resHtmlStr = resHtmlStr.replace(/=""/, "")
}
// compare html strings while ignoring case, quote-changes, trailing spaces
var
simpleIn = noSrcNoAmpHtmlStr.replace(/["']/igm, "").replace(/\s+/igm, " ").toLowerCase().trim(),
simpleOut = resHtmlStr.replace(/["']/igm, "").replace(/\s+/igm, " ").toLowerCase().trim();
if (simpleIn === simpleOut)
return true;
return resHtmlStr.replace(/ svhs___src=/igm, " src=").replace(/#svhs#amp##/, "&");
}
在这里,您可以在JSFiddlehttps://jsfiddle.net/abernh/twgj8bev/中找到它,以及不同的测试用例,包括
"<a href='blue.html id='green'>missing attribute quotes</a>" // FAIL
"<a>hell<B>o</B></a>" // PASS
'<a href="test.html">hell<b>o</b></a>' // PASS
'<a href=test.html>hell<b>o</b></a>', // PASS
"<a href='test.html'>hell<b>o</b></a>", // PASS
'<ul><li>hell</li><li>hell</li></ul>', // PASS
'<ul><li>hell<li>hell</ul>', // PASS
'<div ng-if="true && valid">ampersands in attributes</div>' // PASS
.
好吧,这段代码:
function tidy(html) {
var d = document.createElement('div');
d.innerHTML = html;
return d.innerHTML;
}
这将尽浏览器的最大能力“纠正”格式错误的HTML。如果这对您有帮助,那么这比尝试验证HTML要容易得多。
更新:此答案有限-请参阅下面的编辑。
扩展@kolink的答案,我使用:
var checkHTML = function(html) {
var doc = document.createElement('div');
doc.innerHTML = html;
return ( doc.innerHTML === html );
}
也就是说,我们使用超文本标记语言创建一个临时div。为了做到这一点,浏览器将根据超文本标记语言字符串创建一个DOM树,这可能涉及关闭标签等。
将div的HTML内容与原始HTML进行比较将告诉我们浏览器是否需要更改任何内容。
checkHTML('<a>hell<b>o</b>')
返回false。
checkHTML('<a>hell<b>o</b></a>')
返回true。
编辑:正如@Quentin在下面指出的那样,由于各种原因,这一点过于严格:浏览器通常会修复省略的结束标记,即使结束标记对于该标记是可选的。如:
<p>one para
<p>second para
...被认为是有效的(因为Ps可以省略结束标记),但checkHTML将返回false。浏览器还将规范化标记大小写,并更改空白。在决定使用此方法时,您应该了解这些限制。
问题内容: 我有一个安排计时器的游戏。我有这个CoresManager文件: 我在游戏中使用这个: 如果播放器注销并且服务器重新启动,CoresManager计时器将停止运行。为了使其再次运行,我添加了代码以使其在您再次登录后再次执行startTimer()。但是,由于如果服务器未注销,计时器仍在运行,因此计时器开始运行两次。根据您注销和登录的次数,计时器开始减去2或更多。我认为,如果有代码确定计
我正在将带有用户信息的对象从客户端发送到我的服务器: 我害怕一个“坏用户”,试图黑我的系统修改客户端,就像这样: 然后,如果我在服务器中得到这个对象,并更新数据库,用户就会很有名,而且是溢价的。 在服务器端,我只需要字段“name”、“username”、“gender”和“avatar”。 如果对象“NewUserData”有其他意外的字段,我如何签入node.js? 注意:我正在寻找一个通用的
问题内容: 如何检查值是否是JavaScript中的Object? 问题答案: 更新 : 这个答案是不完整的,并且会产生误导性的结果 。例如,在JavaScript中也被视为类型,更不用说其他几种极端情况了。请遵循以下建议,然后转到其他 原始答案 : 尝试使用和/或。 编辑:这个答案给出了一个如何检查变量属性的想法,但是它不是一个防弹配方(毕竟根本没有配方!)来检查它是否是一个对象,而不是对象。由
在查看几个不同的文档时,我只看到地图(ECMAScript6)键是布尔值、字符串或整数。有没有一种方法可以使用另一个定制的对象(用新的CustomObject(x, y)构造函数调用调用)作为键添加? 我可以添加一个对象作为密钥,但无法检查地图是否有所述对象。 有办法解决这个问题吗? https://developer.mozilla.org/en-US/docs/Web/JavaScript/R
这里有几个关于如何检查对象中是否存在属性的答案。 我一直在使用 但我想知道这和
本文向大家介绍JavaScript / Typescript对象是否为空检查?,包括了JavaScript / Typescript对象是否为空检查?的使用技巧和注意事项,需要的朋友参考一下 对于null检查,可以使用!健康)状况。 示例 以下是代码- 要运行以上程序,您需要使用以下命令- 在这里,我的文件名为demo305.js。 输出结果 这将产生以下输出-