让 HTML 网页打印自己的源代码 - HTML的 Quine 程序实现

简介: Quine 程序是指一个能够输出自身代码的计算机程序。在这篇文章中,我们将用HTML代码来实现一个Quine程序。我们把这个任务分成两步,首先让`<head>`标签中的内容显示出来,然后显示元素的标签

Quine 程序是指一个能够输出自身代码的计算机程序。Quine 程序的实现是计算机科学中一个有趣的问题,不同语言中有不同的实现方式,常见的技巧包括代码注入、字符串插值或反射等。实现 Quine 程序可以帮助我们对平常所使用的编程语言产生更深入的理解。

在这篇文章中,我们将用HTML代码来实现一个Quine程序。严格意义上讲,HTML并不是一门编程语言,但我们同样可以让一个HTML网页打印出自己的全部源代码。我们把这个任务分成两步,首先让<head>标签中的内容显示出来,然后让所有的html元素都显示出自己的标签。

1. head 标签中的内容打印

我们首先写一段简单的HTML,其中包括了两个<p>段落和一个<a>标签。

<html>
<head>
  <title>HTML Quine</title>
</head>
<body>
  <p>这个网页显示了自己的源代码</p>
  <p>灵感来源于
    <a href="https://www.youtube.com/watch?v=6avJHaC3C2U">这个讲座</a>
  </p>
</body>
</html>

运行页面效果如图所示:

frame_chrome_mac_dark (32).png

现在我们来思考一下:通常网页中展示的都是<body>标签中的内容,要显示网页的所有源代码意味着<head>标签中的内容也要被展示出来,这要怎么办呢?

大家回想一下浏览器渲染页面的过程,第一步叫做“根据HTML代码构建DOM树”,也就是说其实<head>标签的内容也是在DOM树中的,我们不妨打开浏览器控制台验证一下这一点。

image.png

那为什么<head>标签的内容不会被展示出来呢?我们接着顺着浏览器引擎的渲染过程往下走,接下来它会解析页面的CSS文件,我们这个网页没有任何自定义的CSS,但是浏览器本身是有自带的CSS的,这个叫做 user agent stylesheet,是浏览器给我们的网页提供的一套默认的CSS。不同浏览器的这套样式会有所不同,例如 chrome 就会有一个默认的网页内边距,所以我们才会需要 reset-css 这样的解决方案来磨平这些默认样式的差异。

而我们的 <head> 标签的内容没有被显示出来其实也正是这个 user agent stylesheet 搞的鬼。在控制台中选中 <head> 标签,我们可以通过右侧(或者下方)的 styles 面板来看浏览器最终计算得出的该元素的样式规则。

image.png

可以看到正是user agent stylesheet让我们的head标签display: none,所以才啥也看不见。那如果我们把它改成 display: block 呢?(点击上面的element.style那一栏可以添加自定义的样式,这也是一个 debug 的好方法)

image.png

还是啥也没有!但这是因为<title>也被设置为display: none了。我们再把<title>元素也改为display: block试试。

image.png

真的出现了!那么我们只要把让<head>中的所有元素显示出来的样式代码添加到HTML中就可以完成第一步了。为了方便,我们直接通过通配符来让所有的元素都display: block即可。同时,为了让打印出来的源代码更像代码,我们还设置了一个等宽字体。

<style>
    * {
    
     display: block; font-family: monospace; }
</style>

2. 打印元素标签和属性

现在我们距离成功打印网页的源代码只差了标签文本的显示了。HTML的标签起到了标记文本的作用,并不会作为网页本身的文本呈现,所以要把它们显示出来只能自己手动添加了。我们要做的就是想办法在网页中的每一个元素前后的显示它们的标签文本。emm...在元素的前后添加东西,这不就是beforeafter伪元素吗!以 <p> 标签的显示为例:

p::before {
   
    content: '<p>'; } p::after {
   
    content: '</p>'; }

frame_chrome_mac_dark (37).png
可以看到两个段落的 <p> 标签都显示出来了。同理,我们只需要枚举我们的网页中包含的所有标签就可以把完整的网页源代码打印出来了。

html::before {
   
    content: "<html>"; }
html::after {
   
    content: "</html>"; }

head::before {
   
    content: "<head>"; }
head::after {
   
    content: "</head>"; }

title::before {
   
    content: "<title>"; }
title::after {
   
    content: "<\title>"; }

style::before {
   
    content: "<style>"; }
style::after {
   
    content: "<\/style>"; }

body::before {
   
    content: "<body>"; }
body::after {
   
    content: "</body>"; }

p::before {
   
    content: "<p>"; }
p::after {
   
    content: "</p>"; }

a::before {
   
    content: "<a>" }
a::after {
   
    content: "</a>" }

frame_chrome_mac_dark (33).png

可以看到我们已经把源代码成功显示出来了,但还有几个地方不太符合预期。

首先是<a>标签的href属性没有显示出来,我们可以通过attr函数来获取href属性的内容,再把它拼接到a标签的before文本中。

a::before {
   
    content: "<a href='" attr(href)  "'>"; }

image.png

第二是<style>的内容被挤到了一行里面,没有像我们输入时那样格式化地展示。这是因为HTML解析时会默认忽略源代码中的换行符和空格,我们可以通过white-space: pre-wrap这条规则来让它保留源代码中的空白。

style {
   
    white-space: pre-wrap; }

第三是<body>标签的内容和<head>标签对的不是很齐,还记得我刚刚说过chrome会有一个默认的网页内边距吗,这就是它干的好事!因为正常情况下HTML网页显示的都是<body>标签的内容,所以这个默认的margin就是加在<body>标签身上的,我们把它清除一下就行了。

body {
   
    margin: 0; }

此时的页面效果如图所示:
frame_chrome_mac_dark (35).png

最后还有一个问题是<html>的闭合标签不知所踪,其实是因为它被放到了页面的底部,要滚动一下才能看到。我们可以通过把<html>元素的高度减小来解决这个问题。同时为了让页面更美观一点,我们再给它加上一个16px的内边距。

html {
   
    margin: 16px; height: 1%; }

frame_chrome_mac_dark (36).png

大功告成!我们写的这个HTML网页完完整整地打印出了自己的源代码,并且也保留了原有的代码缩进和换行。最终完整的代码如下:

<html>
<head>
  <title>HTML Quine</title>
  <style>
    * {
    
     display: block; font-family: monospace; }

    html {
    
     margin: 16px; height: 1%; }
    html::before {
    
     content: "<html>"; }
    html::after {
    
     content: "</html>"; }

    head::before {
    
     content: "<head>"; }
    head::after {
    
     content: "</head>"; }

    title::before {
    
     content: "<title>"; }
    title::after {
    
     content: "<\title>"; }

    style {
    
     white-space: pre-wrap; }
    style::before {
    
     content: "<style>"; }
    style::after {
    
     content: "<\/style>"; }

    body {
    
     margin: 0; }
    body::before {
    
     content: "<body>"; }
    body::after {
    
     content: "</body>"; }

    p::before {
    
     content: "<p>"; }
    p::after {
    
     content: "</p>"; }

    a::before {
    
     content: "<a href='" attr(href)  "'>"; }
    a::after {
    
     content: "</a>" }
  </style>
</head>
<body>
  <p>这个网页显示了自己的源代码</p>
  <p>灵感来源于
    <a href="https://www.youtube.com/watch?v=6avJHaC3C2U">这个讲座</a>
  </p>
</body>
</html>

总结

  1. <head>标签的内容没有显示出来是因为浏览器自定义的样式表隐藏了其内容,我们可以自定义样式覆盖浏览器定义的规则,就可以让其显示出来。
  2. 元素标签的显示可以通过伪元素实现,元素属性的内容可以通过attr函数获取并展示。

本文作者wzkMaster,如果对你有帮助的话欢迎点赞收藏~

相关文章
|
2月前
|
存储 移动开发 前端开发
HTML基础知识:构建网页的基石
【10月更文挑战第11天】HTML基础知识:构建网页的基石
133 0
|
5天前
|
数据采集 前端开发 数据挖掘
利用 html_table 函数轻松获取网页中的表格数据
本文介绍了如何使用 R 语言中的 `html_table` 函数结合代理 IP 技术,轻松提取网页表格数据并规避反爬机制。通过设置代理和请求头,示例代码展示了如何从 58 同城采集租房信息并保存为 CSV 文件。该方法适用于需要频繁采集数据的场景,确保数据采集的高效和稳定性。
利用 html_table 函数轻松获取网页中的表格数据
|
4月前
|
数据采集 移动开发 前端开发
HTML代码的革命:语义化标签的魅力,让你的网页结构焕然一新!
【8月更文挑战第26天】本文探讨了Web前端开发中的语义化标签概念及其重要性。语义化标签通过使用具有明确含义的HTML标签来构建页面结构,提升了网页的可访问性及搜索引擎优化效果,并增强了代码的可读性和维护性。文章还讨论了实际开发中遇到的问题及未来发展趋势。
64 0
|
3月前
|
JavaScript 前端开发 容器
用HTML DOM实现有条件地渲染网页元素(上)
用HTML DOM实现有条件地渲染网页元素(上)
|
3月前
|
存储 JavaScript 前端开发
用HTML DOM实现有条件地渲染网页元素(下)
用HTML DOM实现有条件地渲染网页元素(下)
|
2月前
|
数据安全/隐私保护 C++
【HTML】构建网页的基石
本文介绍了HTML的基本概念和常用标签,包括HTML文件的基本结构、常见标签(如标题、段落、换行、图片、超链接等)、表格与表单的使用方法,以及无语义标签div和span的特性。通过具体示例展示了如何在VS Code中快速生成HTML框架及各标签的应用场景,帮助初学者快速掌握HTML的基础知识。
55 1
【HTML】构建网页的基石
|
3月前
|
Web App开发 前端开发 JavaScript
HTML/CSS/JS学习笔记 Day3(HTML--网页标签 下)
HTML/CSS/JS学习笔记 Day3(HTML--网页标签 下)
|
3月前
|
移动开发 前端开发 数据挖掘
用HTML5中的 画布(Canvas)在“圳品”信息系统网页上绘制显示饼图
用HTML5中的 画布(Canvas)在“圳品”信息系统网页上绘制显示饼图
|
4月前
|
移动开发 数据安全/隐私保护 UED
HTML表单标签详解:如何用HTML标签打造互动网页?
通过合理使用HTML表单标签,可以构建功能丰富、用户友好的互动网页。HTML表单的元素和属性提供了丰富的输入选项和验证功能,使得收集和处理用户输入成为可能。随着HTML5的发展,表单元素的功能性和用户体验将继续得到提升。开发者应充分利用这些工具,为用户打造流畅、互动性强的网页体验。
54 4
|
4月前
|
数据安全/隐私保护
新年快乐鞭炮祝福html网页源码
新年快乐鞭炮祝福html网页源码,动态点燃鞭炮动画祝福新年快乐,带新年背景音乐,无加密完整可用,源码由HTML+CSS+JS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面,重定向这个界面。
53 0
新年快乐鞭炮祝福html网页源码