Docs: correctly slugify escaped chars

md_browser wasn't correctly slugifying escaped characters in header names.
Gitiles shows the literal character (ex. "\_" shows as "_"), but md_browser
previously slugified to "_95_" as an artifact of the python library
encoding escaped chars as "\x02 (ASCII code for escaped char) \x03", where
\x02 & \x03 are "start of text" and "end of text" respectively.

This adds a step to decode decimal codes in-between \x02 & \x03.

Bug: 974025
Test: tools/md_browser/ (click "Figuring out target_cpu")
Test: I also tested this by comparing against
Change-Id: I561be6f0742d11ac5188e5680573ce112b8883fc
Reviewed-by: Dirk Pranke <>
Commit-Queue: Nate Fischer <>
Cr-Original-Commit-Position: refs/heads/master@{#670287}
Cr-Mirrored-Commit: 04d1322f71067436427a297722eb663ae4d1f715
diff --git a/ b/
index 358a110..39fef4f 100755
--- a/
+++ b/
@@ -107,7 +107,14 @@
   # some library. For now we just make accented characters turn into
   # underscores, just like other non-ASCII characters.
+  def decode_escaped_chars(regex_match):
+    # Python-Markdown encodes escaped sequences (ex. "\_") as "\x02 (integer
+    # ascii code) \x03". We decode the integer ascii code to align with Gitiles
+    # behavior (ex. 95 -> '_').
+    return chr(int(
   value = value.encode('ascii', 'replace')  # Non-ASCII turns into '?'.
+  value = re.sub(u'\x02(\\d+)\x03', decode_escaped_chars, value)
   value = re.sub(r'[^- a-zA-Z0-9]', '_', value)  # Non-alphanumerics to '_'.
   value = value.replace(u' ', u'-')
   value = re.sub(r'([-_])[-_]+', r'\1', value)  # Fold hyphens and underscores.