Skip to content

Commit

Permalink
Fix dotnet#1737 decode >
Browse files Browse the repository at this point in the history
  • Loading branch information
vicancy committed Jun 13, 2017
1 parent c4db5a4 commit cf22445
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ private string GetXmlValue(XPathNavigator node)
var lineInfo = node as IXmlLineInfo;
int column = lineInfo.HasLineInfo() ? lineInfo.LinePosition - 2 : 0;

return NormalizeXml(RemoveLeadingSpaces(node.InnerXml), column);
return NormalizeXml(RemoveLeadingSpaces(GetInnerXml(node)), column);
}

/// <summary>
Expand Down Expand Up @@ -644,5 +644,45 @@ private static string NormalizeXml(string xml, int parentIndex)
return m.Value.Replace(group.ToString(), group.ToString().Trim('\n'));
});
}

/// <summary>
/// `>` is always encoded to `&gt;` in XML, when triple-slash-comments is considered as Markdown content, `>` is considered as blockquote
/// Decode `>` to enable the Markdown syntax considering `>` is not a Must-Encode in Text XElement
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
private static string GetInnerXml(XPathNavigator node)
{
using (var sw = new MemoryStream())
{
using (var tw = new XmlWriterWithGtDecoded(sw, Encoding.UTF8))
{
if (node.MoveToFirstChild())
{
do
{
tw.WriteNode(node, true);
} while (node.MoveToNext());
node.MoveToParent();
}
tw.Flush();
sw.Position = 0;
using (var sr = new StreamReader(sw))
{
return sr.ReadToEnd();
}
}
}
}

private sealed class XmlWriterWithGtDecoded : XmlTextWriter
{
public XmlWriterWithGtDecoded(Stream w, Encoding encoding) : base(w, encoding) { }
public override void WriteString(string text)
{
var encoded = text.Replace("&", "&amp;").Replace("<", "&lt;").Replace("'", "&apos;").Replace("\"", "&quot;");
base.WriteRaw(encoded);
}
}
}
}
3 changes: 3 additions & 0 deletions src/docfx/Models/FileMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ namespace Microsoft.DocAsCode
/// 2. Compact form
/// This form supports multiple file patterns in an array
/// e.g. `projects: ["file1", "file2"]`
/// 2. Object form
/// If the Array form contains only one item, it can be shortened to an object
/// e.g. `projects: ["file1", "file2"]`
/// </summary>
[JsonConverter(typeof(FileMappingConverter))]
[Serializable]
Expand Down
8 changes: 4 additions & 4 deletions src/docfx/Models/FileMappingConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
{
jItems = JArray.Load(reader);
}
else if (reader.TokenType == JsonToken.StartObject)
{
jItems = JContainer.Load(reader);
}
else if (reader.TokenType == JsonToken.String)
{
jItems = JRaw.Load(reader);
Expand All @@ -42,6 +38,10 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
{
model.Add(FileModelParser.ParseItem(jItems.ToString()));
}
else if (jItems is JObject)
{
model.Add(FileModelParser.ParseItem((JToken)jItems));
}
else
{
foreach (var item in jItems)
Expand Down
2 changes: 1 addition & 1 deletion src/docfx/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static int Main(string[] args)
}
}

private static int ExecSubCommand(string[] args)
internal static int ExecSubCommand(string[] args)
{
var consoleLogListener = new ConsoleLogListener();
var replayListener = new ReplayLogListener();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ Classes in assemblies are by definition complete.
<pre><code class=""c#"">public class XmlElement
: XmlLinkedNode</code></pre>
<ol><li>
word inside list-&gt;listItem-&gt;list-&gt;listItem-&gt;para.&gt;
word inside list->listItem->list->listItem->para.>
the second line.
</li><li>item2 in numbered list</li></ol>
</li><li>item2 in bullet list</li></ul>
Expand Down
96 changes: 96 additions & 0 deletions test/docfx.Tests/CompositeCommandTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DocAsCode.Tests
{
using System;
using System.Collections.Generic;
using System.IO;

using Xunit;

using Microsoft.DocAsCode.Common;
using Microsoft.DocAsCode.DataContracts.Common;
using Microsoft.DocAsCode.DataContracts.ManagedReference;
using Microsoft.DocAsCode.SubCommands;
using Microsoft.DocAsCode.Tests.Common;
using HtmlAgilityPack;

[Collection("docfx STA")]
public class CompositeCommandTest : TestBase
{
/// <summary>
/// Use MetadataCommand to generate YAML files from a c# project and a VB project separately
/// </summary>
private string _outputFolder;
private string _projectFolder;

public CompositeCommandTest()
{
_outputFolder = Path.GetFullPath(GetRandomFolder());
_projectFolder = Path.GetFullPath(GetRandomFolder());
}

[Fact]
[Trait("Related", "docfx#428")]
[Trait("Language", "CSharp")]
public void TestCommandFromCSCodeToHtml()
{
// Create source file
var sourceCode = @"
public namespace Hello{
/// <summary>
/// The class &lt; &gt; > description goes here...
/// </summary>
/// <example>
/// Here is some &lt; encoded &gt; example...
/// > [!NOTE]
/// > This is *note*
///
/// <code>
/// var handler = DateTimeHandler();
/// for (var i = 0; i &lt; 10; i++){
/// date = date.AddMonths(1);
/// }
/// </code>
/// </example>
public class HelloWorld(){}}
";
var sourceFile = Path.Combine(_projectFolder, "test.cs");
File.WriteAllText(sourceFile, sourceCode);

var docfxJson = $@"{{
""metadata"": [
{{
""src"": ""test.cs"",
""cwd"": ""{_projectFolder.ToNormalizedPath()}"",
""dest"": ""{_outputFolder.ToNormalizedPath()}/api""
}}
],
""build"": {{
""content"": {{
""files"": ""api/*.yml"",
""cwd"": ""../{Path.GetFileName(_outputFolder)}""
}},
""dest"": ""{_outputFolder.ToNormalizedPath()}/site""
}}
}}";
var docfxJsonFile = Path.Combine(_projectFolder, "docfx.json");
File.WriteAllText(docfxJsonFile, docfxJson);
Program.ExecSubCommand(new string[] { docfxJsonFile });
var filePath = Path.Combine(_outputFolder, "site", "api", "Hello.HelloWorld.html");
Assert.True(File.Exists(filePath));
var html = new HtmlDocument();
html.Load(filePath);
var summary = html.DocumentNode.SelectSingleNode("//div[contains(@class, 'summary')]/p").InnerHtml;
Assert.Equal("The class &lt; &gt; &gt; description goes here...", summary.Trim());
var note = html.DocumentNode.SelectSingleNode("//div[@class='NOTE']").InnerHtml;
Assert.Equal("<h5>Note</h5><p>This is <em>note</em></p>", note.Trim());
var code = html.DocumentNode.SelectNodes("//pre/code")[1].InnerHtml;
Assert.Equal(@"var handler = DateTimeHandler();
for (var i = 0; i &lt; 10; i++){
date = date.AddMonths(1);
}".Replace("\r\n", "\n"), code);
}
}
}

0 comments on commit cf22445

Please sign in to comment.