Before this lesson

Understand HTML tags, character references and encoding declarations. The dynamic display lab also uses textContent.

What you will be able to do

Distinguish encoding, parsing and display to diagnose garbled text and render code as text.

Understand the mechanism

The browser decodes response bytes into characters before parsing HTML into a DOM. Save the file as UTF-8 and declare that encoding. Changing metadata cannot repair bytes already saved incorrectly. Inspect the editor encoding and response headers before altering the declaration.

A less-than sign can start a tag and an ampersand a character reference. Encode a literal tag when placing it in HTML source. pre preserves whitespace and code identifies code, but neither automatically escapes markup. A real script inside pre can still execute.

Use textContent for dynamic text and character references in static HTML source. textContent accepts the original string; pre-encoding it causes visible entity text. URL encoding serves URL components and is not a substitute for HTML escaping.

Whitespace normally collapses in HTML. Express spacing and alignment with CSS instead of repeated nonbreaking spaces. Use nonbreaking spaces only when a text segment truly must stay together; excessive use damages narrow-screen wrapping.

Runnable example

Run HTML examples as separate .html files in a modern browser. Prepare resource files and multi-file modules as described in the lesson.

<!doctype html><html lang="zh-CN"><meta charset="utf-8"><title>文本与代码</title>
<h1>字符与代码</h1>
<p>价格:¥12;关系:3 &lt; 5;符号:A &amp; B</p>
<pre><code>&lt;p&gt;Hello&lt;/p&gt;</code></pre>
<pre><code id="example"></code></pre>
<script>
document.querySelector('#example').textContent = '<img src="missing" alt="example">';
</script></html>

Trace and verify

First confirm Chinese, currency and comparison symbols display. Inspect both code elements: neither contains a p or img child. In the isolated exercise, replace textContent with innerHTML and observe the image element and failed request, then restore the safe version.

Common mistakes and boundaries

Browsers can repair invalid markup, so a plausible display does not prove valid source. Do not invent a universal filter that only replaces less-than signs. Output contexts differ; use native text APIs for text nodes.

Practice challenge

Display a tag, an ampersand and two indented lines. Copied code must preserve original characters without creating unexpected image or script nodes.

Reference solution and reasoning

Assign the original source to code.textContent inside pre. Read textContent back and compare strictly with the source to detect double escaping, rather than relying only on a screenshot.

Lab: escape at the correct boundary

Parsing markup and assigning a text node are different operations. Entity-encoding before textContent produces visible encoding artifacts. These detached elements demonstrate the distinction without external requests or executable payloads.

Run this separate experiment in a modern browser Console; it is not a replacement for the main example above.

const raw = '<strong>A & B</strong>';
const text = document.createElement('div');
text.textContent = raw;
const markup = new DOMParser().parseFromString(raw, 'text/html').body;
const doubled = document.createElement('div');
doubled.textContent = '&lt;strong&gt;A &amp; B&lt;/strong&gt;';
console.log(text.children.length, markup.children.length);
console.log(text.textContent, markup.textContent);
console.log(doubled.textContent);
console.assert(text.textContent === raw);
console.assert(markup.firstElementChild.tagName === 'STRONG');

Expected observations

Element-child counts are 0 and 1. text preserves the literal tags, markup reads back A & B, and doubled displays entity sequences such as &lt; literally.

Why this happens and where it stops applying

Serializing the text node as innerHTML introduces the entities needed to represent it in markup; that does not mean the logical text changed. Compare text with textContent and structure with element relationships. HTML escaping is not SQL parameterization or URL component encoding. If a product genuinely accepts rich text, define an allowed element/attribute policy and use a maintained sanitizer rather than treating chained replacements as a complete security boundary.

Extension challenge

Should a code-copy button read innerHTML or textContent? How would you detect double escaping?

Reasoned solution

Read code.textContent for the displayed source characters. Compare the copied string exactly with the original, using a fixture containing angle brackets, ampersands, quotes, Chinese text and newlines.

Further reading