Escape < and > in non-code markdown output. Bug: gn:8 Change-Id: I0689922ffc7677913d0afb64c6c15c476c04f358 Reviewed-on: https://gn-review.googlesource.com/2703 Commit-Queue: Brett Wilson <brettw@chromium.org> Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/docs/reference.md b/docs/reference.md index cb9632b..d73a94f 100644 --- a/docs/reference.md +++ b/docs/reference.md
@@ -150,7 +150,7 @@ ## <a name="commands"></a>Commands -### <a name="analyze"></a>**gn analyze <out_dir> <input_path> <output_path>** +### <a name="analyze"></a>**gn analyze <out_dir> <input_path> <output_path>** ``` Analyze which targets are affected by a list of files. @@ -220,7 +220,7 @@ tries really hard to always write something to the output JSON and convey errors that way rather than via return codes. ``` -### <a name="args"></a>**gn args <out_dir> [\--list] [\--short] [\--args] [\--overrides-only]** +### <a name="args"></a>**gn args <out_dir> [\--list] [\--short] [\--args] [\--overrides-only]** ``` See also "gn help buildargs" for a more high-level overview of how @@ -305,7 +305,7 @@ given arguments set (which may affect the values of other arguments). ``` -### <a name="check"></a>**gn check <out_dir> [<label_pattern>] [\--force]** +### <a name="check"></a>**gn check <out_dir> [<label_pattern>] [\--force]** ``` GN's include header checker validates that the includes for C-like source @@ -420,13 +420,13 @@ gn check out/Default "//foo/* Check only the files in targets in the //foo directory tree. ``` -### <a name="clean"></a>**gn clean <out_dir>** +### <a name="clean"></a>**gn clean <out_dir>** ``` Deletes the contents of the output directory except for args.gn and creates a Ninja build environment sufficient to regenerate the build. ``` -### <a name="desc"></a>**gn desc <out_dir> <label or pattern> [<what to show>] [\--blame] "** +### <a name="desc"></a>**gn desc <out_dir> <label or pattern> [<what to show>] [\--blame] "** #### **[\--format=json]** ``` @@ -438,7 +438,7 @@ targets. ``` -#### **Possibilities for <what to show>** +#### **Possibilities for <what to show>** ``` (If unspecified an overall summary will be displayed.) @@ -585,7 +585,7 @@ Shows defines set for the //base:base target, annotated by where each one was set from. ``` -### <a name="format"></a>**gn format [\--dump-tree] (\--stdin | <build_file>)** +### <a name="format"></a>**gn format [\--dump-tree] (\--stdin | <build_file>)** ``` Formats .gn file to a standard format. @@ -628,7 +628,7 @@ gn format /abspath/some/BUILD.gn gn format --stdin ``` -### <a name="gen"></a>**gn gen [\--check] [<ide options>] <out_dir>** +### <a name="gen"></a>**gn gen [\--check] [<ide options>] <out_dir>** ``` Generates ninja files from the current tree and puts them in the given output @@ -758,7 +758,7 @@ used for various Clang-based tooling, allowing for the replay of individual compilations independent of the build system. ``` -### <a name="help"></a>**gn help <anything>** +### <a name="help"></a>**gn help <anything>** ``` Yo dawg, I heard you like help on your help so I put help on the help in the @@ -780,7 +780,7 @@ gn help --markdown all Dump all help to stdout in markdown format. ``` -### <a name="ls"></a>**gn ls <out_dir> [<label_pattern>] [\--all-toolchains] [\--as=...]** +### <a name="ls"></a>**gn ls <out_dir> [<label_pattern>] [\--all-toolchains] [\--as=...]** ``` [--type=...] [--testonly=...] @@ -853,7 +853,7 @@ Lists all variants of the target //base:base (it may be referenced in multiple toolchains). ``` -### <a name="path"></a>**gn path <out_dir> <target_one> <target_two>** +### <a name="path"></a>**gn path <out_dir> <target_one> <target_two>** ``` Finds paths of dependencies between two targets. Each unique path will be @@ -898,7 +898,7 @@ ``` gn path out/Default //base //tools/gn ``` -### <a name="refs"></a>**gn refs <out_dir> (<label_pattern>|<label>|<file>|@<response_file>)*** +### <a name="refs"></a>**gn refs <out_dir> (<label_pattern>|<label>|<file>|@<response_file>)*** ``` [--all] [--all-toolchains] [--as=...] [--testonly=...] [--type=...]
diff --git a/tools/gn/command_help.cc b/tools/gn/command_help.cc index cff2052..6e816ce 100644 --- a/tools/gn/command_help.cc +++ b/tools/gn/command_help.cc
@@ -120,20 +120,26 @@ OutputString("\n"); - if (is_markdown) - OutputString("## <a name=\"commands\"></a>Commands\n\n"); + if (is_markdown) { + OutputString("## <a name=\"commands\"></a>Commands\n\n", DECORATION_NONE, + NO_ESCAPING); + } for (const auto& c : commands::GetCommands()) PrintLongHelp(c.second.help); - if (is_markdown) - OutputString("## <a name=\"targets\"></a>Target declarations\n\n"); + if (is_markdown) { + OutputString("## <a name=\"targets\"></a>Target declarations\n\n", + DECORATION_NONE, NO_ESCAPING); + } for (const auto& f : functions::GetFunctions()) { if (f.second.is_target) PrintLongHelp(f.second.help); } - if (is_markdown) - OutputString("## <a name=\"functions\"></a>Buildfile functions\n\n"); + if (is_markdown) { + OutputString("## <a name=\"functions\"></a>Buildfile functions\n\n", + DECORATION_NONE, NO_ESCAPING); + } for (const auto& f : functions::GetFunctions()) { if (!f.second.is_target) PrintLongHelp(f.second.help); @@ -142,7 +148,8 @@ if (is_markdown) { OutputString( "## <a name=\"predefined_variables\"></a>" - "Built-in predefined variables\n\n"); + "Built-in predefined variables\n\n", + DECORATION_NONE, NO_ESCAPING); } for (const auto& v : variables::GetBuiltinVariables()) PrintLongHelp(v.second.help); @@ -150,13 +157,16 @@ if (is_markdown) { OutputString( "## <a name=\"target_variables\"></a>" - "Variables you set in targets\n\n"); + "Variables you set in targets\n\n", + DECORATION_NONE, NO_ESCAPING); } for (const auto& v : variables::GetTargetVariables()) PrintLongHelp(v.second.help); - if (is_markdown) - OutputString("## <a name=\"other\"></a>Other help topics\n\n"); + if (is_markdown) { + OutputString("## <a name=\"other\"></a>Other help topics\n\n", + DECORATION_NONE, NO_ESCAPING); + } PrintLongHelp(kBuildArgs_Help, "buildargs"); PrintLongHelp(kDotfile_Help, "dotfile"); PrintLongHelp(kExecution_Help, "execution"); @@ -170,8 +180,10 @@ PrintLongHelp(kRuntimeDeps_Help, "runtime_deps"); PrintLongHelp(kSourceExpansion_Help, "source_expansion"); - if (is_markdown) - OutputString("## <a name=\"switches\"></a>Command Line Switches\n\n"); + if (is_markdown) { + OutputString("## <a name=\"switches\"></a>Command Line Switches\n\n", + DECORATION_NONE, NO_ESCAPING); + } PrintSwitchHelp(); }
diff --git a/tools/gn/standard_out.cc b/tools/gn/standard_out.cc index 6dd6a6a..d2ff52e 100644 --- a/tools/gn/standard_out.cc +++ b/tools/gn/standard_out.cc
@@ -35,6 +35,9 @@ bool is_markdown = false; +// True while output is going into a markdown ```...``` code block. +bool in_body = false; + void EnsureInitialized() { if (initialized) return; @@ -96,7 +99,9 @@ #if defined(OS_WIN) -void OutputString(const std::string& output, TextDecoration dec) { +void OutputString(const std::string& output, + TextDecoration dec, + HtmlEscaping escaping) { EnsureInitialized(); DWORD written = 0; @@ -135,6 +140,12 @@ // at least escape the instances where this shows up in a heading. base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "--", "\\--"); } + if (is_markdown && !in_body && escaping == DEFAULT_ESCAPING) { + // Markdown auto-escapes < and > in code sections (and converts < to + // &tl; there), but not elsewhere. + base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "<", "<"); + base::ReplaceSubstringsAfterOffset(&tmpstr, 0, ">", ">"); + } ::WriteFile(hstdout, tmpstr.c_str(), static_cast<DWORD>(tmpstr.size()), &written, nullptr); @@ -147,7 +158,9 @@ #else -void OutputString(const std::string& output, TextDecoration dec) { +void OutputString(const std::string& output, + TextDecoration dec, + HtmlEscaping escaping) { EnsureInitialized(); if (is_markdown) { OutputMarkdownDec(dec); @@ -181,6 +194,12 @@ // at least escape the instances where this shows up in a heading. base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "--", "\\--"); } + if (is_markdown && !in_body && escaping == DEFAULT_ESCAPING) { + // Markdown auto-escapes < and > in code sections (and converts < to + // &tl; there), but not elsewhere. + base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "<", "<"); + base::ReplaceSubstringsAfterOffset(&tmpstr, 0, ">", ">"); + } WriteToStdOut(tmpstr.data()); if (is_markdown) { @@ -248,7 +267,7 @@ EnsureInitialized(); bool first_header = true; - bool in_body = false; + in_body = false; std::size_t empty_lines = 0; for (const std::string& line : base::SplitString( text, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) { @@ -279,7 +298,8 @@ the_tag = line.substr(0, line.find(':')); } } - OutputString("### <a name=\"" + the_tag + "\"></a>", DECORATION_NONE); + OutputString("### <a name=\"" + the_tag + "\"></a>", DECORATION_NONE, + NO_ESCAPING); first_header = false; } else { OutputString("#### ", DECORATION_NONE);
diff --git a/tools/gn/standard_out.h b/tools/gn/standard_out.h index f2bb733..c793b29 100644 --- a/tools/gn/standard_out.h +++ b/tools/gn/standard_out.h
@@ -16,8 +16,17 @@ DECORATION_YELLOW }; +enum HtmlEscaping { + NO_ESCAPING, + + // Convert < and > to < and > when writing markdown output in non-code + // sections. + DEFAULT_ESCAPING, +}; + void OutputString(const std::string& output, - TextDecoration dec = DECORATION_NONE); + TextDecoration dec = DECORATION_NONE, + HtmlEscaping = DEFAULT_ESCAPING); // If printing markdown, this generates table-of-contents entries with // links to the actual help; otherwise, prints a one-line description.