-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathHtmlUsageWriter.cs
More file actions
136 lines (121 loc) · 4.4 KB
/
HtmlUsageWriter.cs
File metadata and controls
136 lines (121 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using Ookii.CommandLine;
using System.Net;
namespace WpfSample;
// This custom UsageWriter outputs usage as HTML.
internal class HtmlUsageWriter : UsageWriter
{
// This is intended for use with GetUsage() only so no way to specify a writer.
public HtmlUsageWriter()
: base(null, TriState.False)
{
// The indents and blank lines don't alter how the output looks (whitespace is ignored in
// HTML after all), but they're not needed either.
SyntaxIndent = 0;
ArgumentDescriptionIndent = 0;
BlankLineAfterDescription = false;
}
// Wrap the entire usage in an HTML page.
protected override void WriteParserUsageCore(UsageHelpRequest request)
{
Writer.WriteLine(HtmlHeader);
base.WriteParserUsageCore(request);
Writer.WriteLine(HtmlFooter);
}
// Header and paragraph for the description.
protected override void WriteApplicationDescription(string description)
{
Writer.WriteLine("<h1>Description</h1>");
Writer.Write("<p>");
Write(description);
Writer.Write("</p>");
}
// Header and paragraph for the syntax.
protected override void WriteParserUsageSyntax()
{
Writer.WriteLine("<h1>Usage</h1>");
Writer.Write("<p id=\"usage\"><code>");
base.WriteParserUsageSyntax();
Writer.Write("</code></p>");
}
// Omit "Usage:" (we use a header instead), and render the executable name in bold.
protected override void WriteUsageSyntaxPrefix()
{
Writer.Write($"<strong>{ExecutableName}</strong>");
// This application doesn't use subcommands, so we don't need to worry about the command
// name.
}
// Prevent wrapping an argument name after the argument name prefix.
protected override void WriteArgumentName(string argumentName, string prefix)
{
Writer.Write("<span class=\"argument\">");
base.WriteArgumentName(argumentName, prefix);
Writer.Write("</span>");
}
// Header and description list for descriptions.
protected override void WriteArgumentDescriptions()
{
// The header is written here, and not in WriteArgumentDescriptionListHeader, because if we
// did it there it would be inside the <dl>.
Writer.Write("<h1>Arguments</h1>");
Writer.Write("<dl>");
base.WriteArgumentDescriptions();
Writer.Write("</dl>");
}
// Wrap the argument name, value description, and aliases in a description term.
protected override void WriteArgumentDescriptionHeader(CommandLineArgument argument)
{
Writer.Write("<dt>");
base.WriteArgumentDescriptionHeader(argument);
Writer.Write("</dt>");
}
// Wrap the description itself in a description definition.
protected override void WriteArgumentDescriptionBody(CommandLineArgument argument)
{
Writer.Write("<dd>");
base.WriteArgumentDescriptionBody(argument);
Writer.Write("</dd>");
}
// Prevent wrapping after the argument name prefix.
protected override void WriteArgumentNameForDescription(string argumentName, string prefix)
=> WriteArgumentName(argumentName, prefix);
// Make sure all text is HTML encoded.
protected override void Write(string? value)
{
WebUtility.HtmlEncode(value, Writer);
}
// Also HTML encode single character writes.
protected override void Write(char value) => Write(value.ToString());
private const string HtmlHeader = @"<!DOCTYPE html>
<html xmlns=""http://www.w3.org/1999/xhtml"" lang=""en"" xml:lang=""en"">
<head>
<title>Usage help</title>
<style type=""text/css"">
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
background-color: #1e1e1e;
margin: 1em 2em;
}
h1 {
font-size: 100%;
margin-left: -1em;
color: deepskyblue;
}
dt {
color: lightgreen;
}
dd {
margin-bottom: 1em;
}
#usage {
text-indent: -2em;
margin-left: 2em;
}
.argument {
white-space: nowrap;
}
</style>
</head>
<body>";
private const string HtmlFooter = "</body></html>";
}