dotnet / dotnet/docs

The code source inclusion mechanism does not escape HTML found in the source file, breaking included examples

Open
#47,723 2 comments 0 reactions 1 assignee Claimed by @gewarren View on GitHub
:watch: Not Triaged
Dominant language
No language data
Stars
4.8k
Forks
6.1k
Avg merge
19h 10m
Merged PRs (30d)
268

Description

### Describe the issue or suggestion

The code source inclusion mechanism does not escape HTML found in the source file, resulting in the code displayed on the documentation website being incorrect.

Example source file: https://github.com/dotnet/docs/blob/56d3b7dd7af78a0d7c3c4ea86dce22c847bded07/docs/standard/linq/snippets/preserve-white-space-serializing/RoundtrippingSolution.cs

```cs
using System;
using System.IO;
using System.Xml;
using System.Xml.Linq;

public static class RoundtrippingSolution
{
public static void Example()
{
//
string xmlWithCR = """
a
b
c
""";

XDocument doc = XDocument.Parse(xmlWithCR);

// Create XmlWriter settings with NewLineHandling.Entitize
XmlWriterSettings settings = new XmlWriterSettings
{
NewLineHandling = NewLineHandling.Entitize,
OmitXmlDeclaration = true
};

// Serialize using XmlWriter
using StringWriter stringWriter = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(stringWriter, settings))
{
doc.WriteTo(writer);
}

string roundtrippedXml = stringWriter.ToString();
Console.WriteLine($"Roundtripped XML: {roundtrippedXml}");
// Output: a
// b
// c

// Verify roundtripping preserves the original value
XDocument roundtrippedDoc = XDocument.Parse(roundtrippedXml);
bool valuesMatch = doc.Root!.Value == roundtrippedDoc.Root!.Value;
Console.WriteLine($"Values match after roundtripping: {valuesMatch}");
//
// Output: True
}
}
```

Rendering: https://learn.microsoft.com/en-us/dotnet/standard/linq/preserve-white-space-serializing#solution-use-xmlwriter-with-newlinehandlingentitize

```cs
string xmlWithCR = """
a
b
c

""";

XDocument doc = XDocument.Parse(xmlWithCR);

// Create XmlWriter settings with NewLineHandling.Entitize
XmlWriterSettings settings = new XmlWriterSettings
{
NewLineHandling = NewLineHandling.Entitize,
OmitXmlDeclaration = true
};

// Serialize using XmlWriter
using StringWriter stringWriter = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(stringWriter, settings))
{
doc.WriteTo(writer);
}

string roundtrippedXml = stringWriter.ToString();
Console.WriteLine($"Roundtripped XML: {roundtrippedXml}");
// Output: a
// b
// c

// Verify roundtripping preserves the original value
XDocument roundtrippedDoc = XDocument.Parse(roundtrippedXml);
bool valuesMatch = doc.Root!.Value == roundtrippedDoc.Root!.Value;
Console.WriteLine($"Values match after roundtripping: {valuesMatch}");
```

Because the entity is treated as an actual carriage return instead of the sequence of characters «ampersand» «hash» «x» «D» «semicolon», the rendered example reinterprets the entity as a newline, breaking the example in two ways:

* The sample is no longer readable because characters were replaced.
* The sample no longer compiles because one of the replacements was in the middle of a comment and the result is that some text which should be part of the comment is now not in a comment, causing a syntax error (this is not as important of an issue but it at least makes it obvious that there is an actual issue because the original file compiles).

This affects the example added by #47034 for context.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.