diff --git a/build-support/bin/docs_templates/target_reference.md.mustache b/build-support/bin/docs_templates/target_reference.md.mustache index 4f520d58d84..18cf13b3dfe 100644 --- a/build-support/bin/docs_templates/target_reference.md.mustache +++ b/build-support/bin/docs_templates/target_reference.md.mustache @@ -1,5 +1,4 @@ -{{! Mark as a paragraph to render as plain text, rather than markdown. The spaces matter. }} -
{{{description}}}
+{{{description}}} {{#fields}} ##{{alias}}
@@ -7,7 +6,6 @@
type: {{type_hint}}
{{{default_or_required}}}
-{{! Mark as a paragraph to render as plain text, rather than markdown. The spaces matter. }}
-{{{description}}}
+{{{description}}} {{/fields}} diff --git a/build-support/bin/generate_docs.py b/build-support/bin/generate_docs.py index fbe3b5e8f5f..10e301bd983 100644 --- a/build-support/bin/generate_docs.py +++ b/build-support/bin/generate_docs.py @@ -79,6 +79,18 @@ def html_safe(s: str) -> str: return _backtick_re.sub(r"\1
", html.escape(s))
+def description_safe(s: str) -> str:
+ """Escapes special characters in description text.
+
+ Descriptions are generally treated as plain text, not as markdown. But readme.com still renders
+ indented lines as blockquotes, so we must take care not to html-quote inside those.
+ """
+ safe_lines = [line if line.startswith(" ") else html_safe(line) for line in s.splitlines()]
+ safe_lines_str = "\n".join(safe_lines)
+ # Mark as a paragraph to render as plain text, rather than markdown. The spaces matter.
+ return f"{safe_lines_str}
" + + def create_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Generate the Pants reference markdown files.") parser.add_argument( @@ -218,11 +230,9 @@ def process_targets_input(cls, help_info: Dict) -> Dict[str, Dict[str, Any]]: field["default_or_required"] = ( "required" if field["required"] else f"default:{default_str}
"
)
- # Description is not rendered as markdown, so we don't want to escape
- # markdown special characters here (or the escapes will be visible).
- field["description"] = html_safe(str(field["description"]))
+ field["description"] = description_safe(str(field["description"]))
target["fields"] = sorted(target["fields"], key=lambda fld: cast(str, fld["alias"]))
- target["description"] = html_safe(str(target["description"]))
+ target["description"] = description_safe(str(target["description"]))
return cast(Dict[str, Dict[str, Any]], target_info)
diff --git a/src/python/pants/core/target_types.py b/src/python/pants/core/target_types.py
index 12369e86a4f..ca5078b301c 100644
--- a/src/python/pants/core/target_types.py
+++ b/src/python/pants/core/target_types.py
@@ -80,9 +80,8 @@ class RelocatedFilesSrcField(StringField):
required = True
help = (
"The original prefix that you want to replace, such as `src/resources`.\n\nYou can set "
- "this field to `"
- "` to preserve the original path; the value in the `dest` field will "
- "then be added to the beginning of this original path."
+ "this field to the empty string to preserve the original path; the value in the `dest` "
+ "field will then be added to the beginning of this original path."
)
@@ -91,8 +90,8 @@ class RelocatedFilesDestField(StringField):
required = True
help = (
"The new prefix that you want to add to the beginning of the path, such as `data`.\n\nYou "
- 'can set this field to "" to avoid adding any new values to the path; the value in the '
- "`src` field will then be stripped, rather than replaced."
+ "can set this field to the empty string to avoid adding any new values to the path; the "
+ "value in the `src` field will then be stripped, rather than replaced."
)