mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-03 04:36:09 +01:00
fix(docs): attempt to sanitise user strings from yaml
User strings were used as-is in certain parts since they were taken directly from `info.yaml`, but this could sometimes cause the datasheet build to fail since they've found a way (intentionally or not) to escape the content box that they were in. This commit attempts to address this issue by: - Sanitising user input using regex - Using Typst's `str()` function instead of content boxes where possible - Clarifying syntax in certain sections Hopefully these changes will remove (or at least reduce) the chances of someone breaking the build.
This commit is contained in:
committed by
Uri Shaked
parent
3c092caeed
commit
bfd5020b4c
+36
-14
@@ -9,6 +9,9 @@ import matplotlib as mpl
|
|||||||
|
|
||||||
from config import Config, DatasheetConfig
|
from config import Config, DatasheetConfig
|
||||||
|
|
||||||
|
# look for both literal escape characters and in-text escape characters
|
||||||
|
ESCAPE_CHARACTERS_RE = re.compile(r"\n|\\n|\r|\\r|\t|\\t")
|
||||||
|
|
||||||
|
|
||||||
class DocsHelper:
|
class DocsHelper:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -78,11 +81,25 @@ class DocsHelper:
|
|||||||
"""
|
"""
|
||||||
Helper function to escape characters in strings
|
Helper function to escape characters in strings
|
||||||
|
|
||||||
- Escapes double quotation mark
|
- Escapes double quotation marks, backslashes
|
||||||
- Removes newlines, carrige returns
|
- Removes newlines, carrige returns, tabs
|
||||||
"""
|
"""
|
||||||
|
return (
|
||||||
|
ESCAPE_CHARACTERS_RE.sub("", text).replace("\\", "\\\\").replace('"', '\\"')
|
||||||
|
)
|
||||||
|
|
||||||
return text.replace('"', '\\"').replace("\n", "").replace("\r", "")
|
@staticmethod
|
||||||
|
def _as_str_or_content(text: str) -> str:
|
||||||
|
"""
|
||||||
|
Return empty Typst content block or format given string as Typst string
|
||||||
|
|
||||||
|
Empty cells in pinout tables are formatted to show a faint dash when there is no content, but this cannot
|
||||||
|
happen when we pass a Typst `str()` object. If `text == ""` then return Typst content block.
|
||||||
|
"""
|
||||||
|
if text == "":
|
||||||
|
return "[]"
|
||||||
|
else:
|
||||||
|
return f'str("{text}")'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_digital_pins(pins: dict) -> str:
|
def format_digital_pins(pins: dict) -> str:
|
||||||
@@ -91,11 +108,18 @@ class DocsHelper:
|
|||||||
"""
|
"""
|
||||||
pin_table = ""
|
pin_table = ""
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
ui_text = DocsHelper._escape_characters_in_content(pin["ui"])
|
ui_text = DocsHelper._as_str_or_content(
|
||||||
uo_text = DocsHelper._escape_characters_in_content(pin["uo"])
|
DocsHelper._escape_characters_in_string(pin["ui"])
|
||||||
uio_text = DocsHelper._escape_characters_in_content(pin["uio"])
|
)
|
||||||
|
uo_text = DocsHelper._as_str_or_content(
|
||||||
|
DocsHelper._escape_characters_in_string(pin["uo"])
|
||||||
|
)
|
||||||
|
uio_text = DocsHelper._as_str_or_content(
|
||||||
|
DocsHelper._escape_characters_in_string(pin["uio"])
|
||||||
|
)
|
||||||
|
|
||||||
pin_table += (
|
pin_table += (
|
||||||
f"[`{pin['pin_index']}`], [{ui_text}], [{uo_text}], [{uio_text}],\n"
|
f'raw("{pin["pin_index"]}"), {ui_text}, {uo_text}, {uio_text},\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
return pin_table
|
return pin_table
|
||||||
@@ -107,10 +131,10 @@ class DocsHelper:
|
|||||||
"""
|
"""
|
||||||
pin_table = ""
|
pin_table = ""
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
desc_text = DocsHelper._escape_characters_in_content(pin["desc"])
|
desc_text = DocsHelper._as_str_or_content(
|
||||||
pin_table += (
|
DocsHelper._escape_characters_in_string(pin["desc"])
|
||||||
f"[`{pin['ua_index']}`], [`{pin['analog_index']}`], [{desc_text}],\n"
|
|
||||||
)
|
)
|
||||||
|
pin_table += f'raw("{pin["ua_index"]}"), raw("{pin["analog_index"]}"), str("{desc_text}"),\n'
|
||||||
return pin_table
|
return pin_table
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -292,12 +316,10 @@ class DocsHelper:
|
|||||||
"""
|
"""
|
||||||
content = {
|
content = {
|
||||||
"template_version": template_version,
|
"template_version": template_version,
|
||||||
"project_title": DocsHelper._escape_characters_in_string(info["title"]),
|
"project_title": f'str("{DocsHelper._escape_characters_in_string(info["title"])}")',
|
||||||
"project_author": f"({DocsHelper.format_authors(info['author'])})",
|
"project_author": f"({DocsHelper.format_authors(info['author'])})",
|
||||||
"project_repo_link": info["git_url"],
|
"project_repo_link": info["git_url"],
|
||||||
"project_description": DocsHelper._escape_characters_in_string(
|
"project_description": f'str("{DocsHelper._escape_characters_in_string(info["description"])}")',
|
||||||
info["description"]
|
|
||||||
),
|
|
||||||
"project_address": DocsHelper.pretty_address(info["address"]),
|
"project_address": DocsHelper.pretty_address(info["address"]),
|
||||||
"project_clock": DocsHelper.pretty_clock(info["clock_hz"]),
|
"project_clock": DocsHelper.pretty_clock(info["clock_hz"]),
|
||||||
"project_type": DocsHelper.get_project_type(
|
"project_type": DocsHelper.get_project_type(
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
#let blockquote = tt.lib.blockquote
|
#let blockquote = tt.lib.blockquote
|
||||||
|
|
||||||
#show: tt.datasheet.project.with(
|
#show: tt.datasheet.project.with(
|
||||||
title: "{{&project_title}}",
|
title: {{&project_title}},
|
||||||
author: {{&project_author}},
|
author: {{&project_author}},
|
||||||
repo_link: "{{project_repo_link}}",
|
repo_link: "{{project_repo_link}}",
|
||||||
description: "{{&project_description}}",
|
description: {{&project_description}},
|
||||||
address: "{{&project_address}}",
|
address: "{{&project_address}}",
|
||||||
clock: "{{project_clock}}",
|
clock: "{{project_clock}}",
|
||||||
type: "{{project_type}}",
|
type: "{{project_type}}",
|
||||||
|
|||||||
Reference in New Issue
Block a user