制作一个“查看源代码”按钮

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。从 价值 200 美元的免费积分 开始!

Remy Sharp 为 HTML5 演示 创建了一个很酷的网站,每个 单独的演示 页面上都包含一个“查看源代码”按钮。点击它,您就可以看到您正在查看的页面的完整源代码。它不是弹出窗口或新标签页,而是直接在页面上显示源代码。我认为这很酷,所以我决定用自己的方式重新创建它。

花哨的方法

查看演示   下载文件

第一个想到的想法是使用 CSS3 的 :target 伪类。我们之前在导出 CSS3 标签 时讨论过这些。这个想法是使用一个链接到 #source-code 哈希标签的链接。这会将 #source-code 添加到 URL 的末尾,并允许 :target 选择器匹配并应用样式。基础知识

<a href="#source-code">View Source</a>
#source-code { display: none; }
#source-code:target { display: block; }

现在,只需要将 #source-code 元素填充为实际的源代码。这是 JavaScript 的领域,因为我们要动态获取代码,而不是为了显示而实际重复源代码。这样,无论何时更改页面,我们都不需要调整任何内容,我们的“查看源代码”按钮将显示所写的更新后的源代码。我们可以依靠 jQuery 来帮助我们

var html = $("html").html();

这将为我们提供页面的所有 HTML,只排除 DOCTYPE 和实际的 <html> 标签。您也可以通过 document.documentElement.innerHTML 来访问它,但是,如果我们要使用 jQuery,就只使用它。我们将创建一个全新的 <pre> 元素,用“伪造”的 DOCTYPE 和 html 标签填充它,然后将刚刚从页面收集的 HTML 放入其中。

收集的 HTML 有几个需要考虑的地方:1) 让我们对 <’s 进行转义,以便它们在页面上正确显示,而不会尝试渲染为实际的 HTML。2) 让我们“链接化”它找到的任何链接,以便它们可以被点击(部分摘自 这里)。

然后,我们将新建的 <pre> 放置到我们的 #source-code div 中。

$(function() {
	$("<pre />", {
		"html":   '&lt;!DOCTYPE html>\n&lt;html>\n' + 
				$("html")
					.html()
					.replace(/[<>]/g, function(m) { return {'<':'&lt;','>':'&gt;'}[m]})
					.replace(/((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi,'<a href="$1">$1</a>') + 
				'\n&lt;/html>'
	}).appendTo("#source-code");
});

关闭源代码非常简单。因为“查看源代码”按钮在被点击时会在页面上添加一个哈希标签,这意味着浏览器中的“后退”按钮会起作用。按下它会删除哈希标签,因此 #source-code 就不再是 :target,它会自动被 CSS 隐藏。#source-code div 中还有一个简单的“X”图形,它链接到哈希标签“#”,具有完全相同的效果。

这只是链接到“#”,它将我们的源代码查看元素移出 :target,从而立即隐藏它。

对代码进行样式设置

对代码应用语法高亮的其中一个最简单的方法是使用 google-code-prettify 项目。这是一个基于 JavaScript 的高亮器。基本上,您需要链接到下载中附带的 JavaScript 文件和 CSS 文件

<link rel='stylesheet' href='css/prettify.css' />
<script src="prettify/prettify.js"></script>

确保您的 <pre> 标签具有“prettyprint”类。我将其添加到我们用于创建 <pre> 的元素创建语法中

"class": "prettyprint"

并在页面准备就绪时调用 prettyPrint() 函数。他们建议在 body 标签中添加 onload,但是,由于我们使用的是 jQuery DOM ready 函数,因此我们只需在其中调用它即可。

我稍微调整了颜色,以便在深色背景上使用。这是 prettify.css 文件的顶部部分

.str { color: #61ff74; }
.kwd { color: #ea5eff; }
.com { color: white; }
.typ { color: red; }
.lit { color: red; }
.pun { color: white; }
.pln { color: white; }
.tag { color: #ffab58; }
.atn { color: #fabb4e; }
.atv { color: #ffd996; }
.dec { color: red; }

Prettify 通过将代码的各个部分包装在跨度中来工作,从而对该部分进行着色。还要注意正确转义的字符。

兼容性

几乎所有现代浏览器都支持它,只要它支持 CSS3 :target 即可。在 IE 8 及更低版本中存在问题,但在 IE 9 中则可以正常工作。

原始方法

Firefox 和 Chrome 支持 URL 协议“view-source:”,它会打开其本地的源代码查看器。如果您只为自己创建这些链接,您可以执行以下操作

<a class="button" onClick='window.location="view-source:" + window.location.href'>View Source</a>

Remy 的方法

事实证明,我的做法与在 HTML5 演示页面 上的做法大不相同。这是我对他的技术进行解释的尝试

  1. 监视所有点击
  2. 如果点击的是一个带有哈希标签 #view-source 的链接…
  3. 在 body 中添加一个名为 .view-source 的类名(此类会显示原本隐藏的 <pre>)。
  4. 如果还没有,则将一个 <pre> 附加到 body 中,ID 为 #view-source
  5. <pre> 用从 document.documentElement.innerHTML 获取的 HTML 填充。
  6. 设置一个计时器,每 200 毫秒检查一次,看 URL 中是否仍然包含哈希标签 #view-source。
  7. 如果哈希标签消失了或发生了变化,则从 body 中删除类名(隐藏 <pre>)并取消计时器。
(function () {

var pre = document.createElement('pre');
pre.id = "view-source"

// private scope to avoid conflicts with demos
addEvent(window, 'click', function (event) {
  if (event.target.hash == '#view-source') {
    // event.preventDefault();
    if (!document.getElementById('view-source')) {
      pre.innerHTML = ('<!DOCTYPE html>\n<html>\n' + document.documentElement.innerHTML + '\n</html>').replace(/[<>]/g, function (m) { return {'<':'&lt;','>':'&gt;'}[m]});
      document.body.appendChild(pre);      
    }
    document.body.className = 'view-source';
    
    var sourceTimer = setInterval(function () {
      if (window.location.hash != '#view-source') {
        clearInterval(sourceTimer);
        document.body.className = '';
      }
    }, 200);
  }
});
  
})();

然后是巧妙的 CSS 代码,它允许源代码在正常情况下隐藏,并在 body 获得 .view-source 类时接管屏幕。

#view-source {
  display: none;
}

body.view-source > * {
  display: none;
}

body.view-source #view-source {
  display: block !important;
}

重大优势

Remy 的方法最酷的地方在于,它比我的想法跨浏览器兼容性强得多。它使用的是纯 JavaScript,因此它完全不依赖于库,并且不使用任何“花哨”的技术,这些技术在较旧的浏览器中无法正常工作。例如,他本可以使用 hashchange 事件来监视 #view-source 何时消失,但它在一些较旧的浏览器中不受支持,因此即使这一点也得到了很好的处理。

用法

当然,您可以随意使用它。

查看演示   下载文件

以其目前的形态,这段代码依赖于页面上的特定标记,即按钮本身和 #view-source div。这肯定可以转换为一个插件,该插件会自动附加这些内容,从而使它更容易实现。我可能最终会这样做。

这也让我想到了两件事:1) 我真的需要尽快将语法高亮功能添加到 CSS-Tricks 上的博客设计中,2) 我应该在所有演示页面上使用“查看源代码”功能。这两件事都会及时完成。

另一件很酷的事情是将其制作成书签。这对于 Safari 来说尤其酷,因为它具有糟糕的“查看源代码”功能(虽然有一个 扩展程序 可以解决这个问题)。尽管如此,没有一个浏览器在模式窗口中显示源代码,我认为这有时比打开新窗口或新标签页更好。