个性化阅读
专注于IT技术分析

如何区分HTML并使用JavaScript在HTML中生成输出

本文概述

你的用户想知道他过去编写的内容的不同之处, 想在浏览器中突出显示, 但是他编写的内容是HTML格式的吗?甚至不要考虑遍历DOM的每个元素, 检索文本并将其与其他节点进行比较, 因为这可能无法按预期工作, 并且将花费大量时间来实现它。如果你正在考虑一种快速解决方案, 并且被允许使用第三方脚本, 则可能需要使用htmldiff脚本。可以使用此功能的最有用的情况是, 当你想为用户实现差异视图但内容为HTML格式时(例如, 已使用WYSIWYG编辑器存储了内容)。

在本文中, 我们将向你展示如何轻松地在Web项目中实现htmldiff。

1.获取htmldiff.js的副本

Htmldiff.js是一个很棒的diff脚本, 可以理解HTML, 并使用CoffeScript编写。该库本身是用Ruby编写的原始脚本的端口。你可以使用我们从CoffeScript编译的以下代码来获取htmldiff.js的副本:

/**
 * htmldiff.js a diff algorithm that understands HTML, and produces HTML in the browser.
 * 
 * @author https://github.com/tnwinc
 * @see https://github.com/tnwinc/htmldiff.js
 */
!function(){var e, n, t, r, i, f, _, a, o, s, u, h, l, c, d, b, p;o=function(e){return">"===e}, s=function(e){return"<"===e}, h=function(e){return/^\s+$/.test(e)}, u=function(e){return/^\s*<[^>]+>\s*$/.test(e)}, l=function(e){return!u(e)}, e=function(){return function(e, n, t){this.start_in_before=e, this.start_in_after=n, this.length=t, this.end_in_before=this.start_in_before+this.length-1, this.end_in_after=this.start_in_after+this.length-1}}(), a=function(e){var n, t, r, i, f, _;for(f="char", t="", _=[], r=0, i=e.length;r<i;r++)switch(n=e[r], f){case"tag":o(n)?(t+=">", _.push(t), t="", f=h(n)?"whitespace":"char"):t+=n;break;case"char":s(n)?(t&&_.push(t), t="<", f="tag"):/\s/.test(n)?(t&&_.push(t), t=n, f="whitespace"):/[\w\#@]+/i.test(n)?t+=n:(t&&_.push(t), t=n);break;case"whitespace":s(n)?(t&&_.push(t), t="<", f="tag"):h(n)?t+=n:(t&&_.push(t), t=n, f="char");break;default:throw new Error("Unknown mode "+f)}return t&&_.push(t), _}, f=function(n, t, r, i, f, _, a){var o, s, u, h, l, c, d, b, p, g, w, v, k, m, y;for(s=i, o=_, u=0, w={}, c=h=m=i, y=f;m<=y?h<y:h>y;c=m<=y?++h:--h){for(k={}, d=0, b=(p=r[n[c]]).length;d<b;d++)if(!((l=p[d])<_)){if(l>=a)break;null==w[l-1]&&(w[l-1]=0), v=w[l-1]+1, k[l]=v, v>u&&(s=c-v+1, o=l-v+1, u=v)}w=k}return 0!==u&&(g=new e(s, o, u)), g}, d=function(e, n, t, r, i, _, a, o){var s;return null!=(s=f(e, 0, t, r, i, _, a))&&(r<s.start_in_before&&_<s.start_in_after&&d(e, n, t, r, s.start_in_before, _, s.start_in_after, o), o.push(s), s.end_in_before<=i&&s.end_in_after<=a&&d(e, n, t, s.end_in_before+1, i, s.end_in_after+1, a, o)), o}, r=function(e){var n, t, r, i, f, _;if(null==e.find_these)throw new Error("params must have find_these key");if(null==e.in_these)throw new Error("params must have in_these key");for(r={}, n=0, i=(f=e.find_these).length;n<i;n++)for(r[_=f[n]]=[], t=e.in_these.indexOf(_);-1!==t;)r[_].push(t), t=e.in_these.indexOf(_, t+1);return r}, _=function(e, n){var t, i;return i=[], t=r({find_these:e, in_these:n}), d(e, n, t, 0, e.length, 0, n.length, i)}, n=function(n, t){var r, i, f, a, o, s, u, h, l, c, d, b, p, g, w, v;if(null==n)throw new Error("before_tokens?");if(null==t)throw new Error("after_tokens?");for(w=g=0, p=[], r={"false, false":"replace", "true, false":"insert", "false, true":"delete", "true, true":"none"}, (d=_(n, t)).push(new e(n.length, t.length, 0)), a=f=0, h=d.length;f<h;a=++f)"none"!==(i=r[[w===(c=d[a]).start_in_before, g===c.start_in_after].toString()])&&p.push({action:i, start_in_before:w, end_in_before:"insert"!==i?c.start_in_before-1:void 0, start_in_after:g, end_in_after:"delete"!==i?c.start_in_after-1:void 0}), 0!==c.length&&p.push({action:"equal", start_in_before:c.start_in_before, end_in_before:c.end_in_before, start_in_after:c.start_in_after, end_in_after:c.end_in_after}), w=c.end_in_before+1, g=c.end_in_after+1;for(v=[], u={action:"none"}, o=function(e){return"equal"===e.action&&(e.end_in_before-e.start_in_before==0&&/^\s$/.test(n.slice(e.start_in_before, +e.end_in_before+1||9e9)))}, s=0, l=p.length;s<l;s++)o(b=p[s])&&"replace"===u.action||"replace"===b.action&&"replace"===u.action?(u.end_in_before=b.end_in_before, u.end_in_after=b.end_in_after):(v.push(b), u=b);return v}, t=function(e, n, t){var r, i, f, _, a, o;for(_=void 0, f=i=0, a=(n=n.slice(e, +n.length+1||9e9)).length;i<a&&(o=n[f], !0===(r=t(o))&&(_=f), !1!==r);f=++i);return null!=_?n.slice(0, +_+1||9e9):[]}, p=function(e, n){var r, i, f, _, a;for(_="", f=0, r=n.length;;){if(f>=r)break;if(i=t(f, n, l), f+=i.length, 0!==i.length&&(_+="<"+e+">"+i.join("")+"</"+e+">"), f>=r)break;f+=(a=t(f, n, u)).length, _+=a.join("")}return _}, (c={equal:function(e, n, t){return n.slice(e.start_in_before, +e.end_in_before+1||9e9).join("")}, insert:function(e, n, t){var r;return r=t.slice(e.start_in_after, +e.end_in_after+1||9e9), p("ins", r)}, delete:function(e, n, t){var r;return r=n.slice(e.start_in_before, +e.end_in_before+1||9e9), p("del", r)}}).replace=function(e, n, t){return c.delete(e, n, t)+c.insert(e, n, t)}, b=function(e, n, t){var r, i, f, _;for(_="", r=0, i=t.length;r<i;r++)f=t[r], _+=c[f.action](f, e, n);return _}, (i=function(e, t){var r;return e===t?e:(e=a(e), t=a(t), r=n(e, t), b(e, t, r))}).html_to_tokens=a, i.find_matching_blocks=_, _.find_match=f, _.create_index=r, i.calculate_operations=n, i.render_operations=b, "function"==typeof define?define([], function(){return i}):"undefined"!=typeof module&&null!==module?module.exports=i:"undefined"!=typeof window&&(window.htmldiff=i)}();

注意

你可以使用在线转换器(如js2.coffee)构建自己的js文件, 只需粘贴原始的CoffeScript代码即可。

该脚本可识别多模块, 这意味着它应作为Node.js模块或AMD(RequireJS)模块, 甚至可以作为脚本标签(窗口)使用。有关此脚本的更多信息, 请访问Github上的官方存储库。

2.使用脚本

在此示例中, 请使用单个脚本标记以旧方式在浏览器中很好地使用它:

<script src="htmldiff.js"></script>

该脚本再简单不过了, 要使用它, 你只需要使用需要2个参数的htmldiff函数, 即将旧版本的HTML作为第一个参数, 将要比较的版本作为第二个参数。该函数是同步的, 因此它将立即返回diff输出。例如, 给出以下片段:

let originalHTML = `
    <p>Hello Mr. Wayne, decide what to do:</p>
    <ul>
        <li>Call Alfred</li>
        <li>Take Thalia Al Gul to the cinema</li>
        <li>Save Gotham</li>
    </ul>
    <span>Use the mouse to choose an option.</span>
`;

let newHTML = `
<p>Hello Batman, decide what to do:</p>
<ul>
    <li>Kill The Joker</li>
    <li>Save Thalia Al Gul</li>
    <li>Save Gotham</li>
</ul>
<span>Use the batarang to choose an option.</span>
`;

// Diff HTML strings
let output = htmldiff(originalHTML, newHTML);

// Show HTML diff output as HTML (crazy right?)!
document.getElementById("output").innerHTML = output;

并为diff标签提供了以下CSS规则(ins和del标签):

ins {
    text-decoration: none;
    background-color: #d4fcbc;
}

del {
    text-decoration: line-through;
    background-color: #fbb6c2;
    color: #555;
}

将显示HTML的output元素将显示:

区分HTML并使用JavaScript将其生成为HTML

太棒了吧?如你所见, 从所见即所得编辑器中比较内容而无需创建复杂的代码来比较所需元素中的每个单个节点从未如此简单。多亏了htmldiff, 你可以在几分钟内实现!

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何区分HTML并使用JavaScript在HTML中生成输出

评论 抢沙发

评论前必须登录!