Validate a Material icon shortcode and return the icon in normalized format if valid.
(maybe_material_icon: str | None)
| 91 | |
| 92 | |
| 93 | def validate_material_icon(maybe_material_icon: str | None) -> str: |
| 94 | """Validate a Material icon shortcode and return the icon in |
| 95 | normalized format if valid. |
| 96 | """ |
| 97 | |
| 98 | supported_icon_packs = [ |
| 99 | "material", |
| 100 | ] |
| 101 | |
| 102 | if maybe_material_icon is None: |
| 103 | return "" |
| 104 | |
| 105 | icon_regex = r"^\s*:(.+)\/(.+):\s*$" |
| 106 | icon_match = re.match(icon_regex, maybe_material_icon) |
| 107 | # Since our markdown processing needs to change the `/` to `_` in order to |
| 108 | # correctly render the icon, we need to add a zero-width space before the |
| 109 | # `/` to avoid this transformation here. |
| 110 | invisible_white_space = "\u200b" |
| 111 | |
| 112 | if not icon_match: |
| 113 | raise StreamlitAPIException( |
| 114 | f'The value `"{maybe_material_icon.replace("/", invisible_white_space + "/")}"` is ' |
| 115 | "not a valid Material icon. Please use a Material icon shortcode like " |
| 116 | f"**`:material{invisible_white_space}/thumb_up:`**" |
| 117 | ) |
| 118 | |
| 119 | pack_name, icon_name = icon_match.groups() |
| 120 | |
| 121 | if ( |
| 122 | pack_name not in supported_icon_packs |
| 123 | or not icon_name |
| 124 | or not is_material_icon(icon_name) |
| 125 | ): |
| 126 | raise StreamlitAPIException( |
| 127 | f'The value `"{maybe_material_icon.replace("/", invisible_white_space + "/")}"` is not a ' |
| 128 | "valid Material icon. Please use a Material icon shortcode like " |
| 129 | f"**`:material{invisible_white_space}/thumb_up:`**." |
| 130 | ) |
| 131 | |
| 132 | return f":{pack_name}/{icon_name}:" |
| 133 | |
| 134 | |
| 135 | def extract_leading_emoji(text: str) -> tuple[str, str]: |
no test coverage detected
searching dependent graphs…