From 3a998b4598e551f398ba66c1c1d1be4b10db306e Mon Sep 17 00:00:00 2001 From: Wen Junhua Date: Mon, 25 Dec 2023 22:17:25 +0900 Subject: [PATCH 1/5] feat: add script to auto update icons --- scripts/update_icon.py | 127 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 scripts/update_icon.py diff --git a/scripts/update_icon.py b/scripts/update_icon.py new file mode 100644 index 00000000..a7159b06 --- /dev/null +++ b/scripts/update_icon.py @@ -0,0 +1,127 @@ +import argparse +import bs4 +import re +import logging +import requests +import os + +from typing import Tuple + + +DEFAULT_FONTAWESOME_VERSION = "v6.5.1" +DEFAULT_BASE_URL = ( + "https://site-assets.fontawesome.com/releases/%s/svgs/brands/" + % DEFAULT_FONTAWESOME_VERSION + + "%s.svg" +) +DEFAULT_ICON_PATH = os.path.join( + os.getcwd(), + "..", + "assets", + "icons", +) +DEFAULT_SVG_ATTR = {"fill": "currentColor"} + + +def download_icon(download_url: str) -> None: + """Downloads the icon based on the URL""" + with requests.Session() as s: + return s.get(download_url).content + + +def update_svg_to_theme(svg: bytes) -> bytes: + """Update the current color of SVG to match theme""" + soup = bs4.BeautifulSoup(svg, features="html.parser") + + # Update attrs + svg_elem = soup.find("svg").find("path") + for k, v in DEFAULT_SVG_ATTR.items(): + svg_elem[k] = v + + # Remove comments + return re.sub(r'','', str(soup)) + + + +def save_file(name: str, svg: str) -> None: + file_name = f"{name}.svg" + logging.debug(f"saving icon to {file_name}") + with open( + os.path.join( + DEFAULT_ICON_PATH, + file_name, + ), + "w", + ) as file: + file.write(svg) + + +def parse_args() -> Tuple[str, str, int]: + """ + Parse arguments. + Returns the following: + 1. Icon URL: str + 2. Icon Representation :str + 3. Log Level: int + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "-v", + "--verbose", + help="show debug messages during script execution", + required=False, + default=False, + action="store_true", + ) + + parser.add_argument( + "-u", + "--url", + help="full url of the icon svg, defaults to fortawesome url", + required=False, + nargs=1, + ) + + parser.add_argument( + "name", + help="name of the icon to be added. EG: `github`", + ) + + parse_res = parser.parse_args() + url = DEFAULT_BASE_URL % parse_res.name + if parse_res.url is not None: + if len(parse_res.url) != 1: + raise ValueError("Invalid URL arguments. Use -h for help.") + url = parse_res.url[0] + + log_level = logging.DEBUG if parse_res.verbose else logging.INFO + return url, parse_res.name, log_level + + +if __name__ == "__main__": + icon_url, icon_name, log_level = parse_args() + + # Setup logging + logging.basicConfig( + level=log_level, + format="%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + logging.debug(f"Using default base URL: {DEFAULT_BASE_URL}") + logging.info(f"Using Log Level: {logging.getLevelName(log_level)}") + logging.info(f"Using URL: {icon_url}") + logging.info(f"Using Icon Name: {icon_name}") + + # Download Icon + logging.debug(f"fetching icon at {icon_url}") + svg_content = download_icon(icon_url) + + # Patch svg attrs + logging.debug(f"updating svg attrs") + final_svg = update_svg_to_theme(svg_content) + + # Save file + logging.debug("saving icon to assets") + save_file(icon_name, final_svg) + + # Write to docs (TODO) From eb527de54bb989bf1938dc09e402710f4594bc33 Mon Sep 17 00:00:00 2001 From: Wen Junhua Date: Mon, 25 Dec 2023 23:13:32 +0900 Subject: [PATCH 2/5] feat: add docs update --- scripts/update_icon.py | 63 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/scripts/update_icon.py b/scripts/update_icon.py index a7159b06..2b52319e 100644 --- a/scripts/update_icon.py +++ b/scripts/update_icon.py @@ -5,7 +5,7 @@ import logging import requests import os -from typing import Tuple +from typing import Tuple, List DEFAULT_FONTAWESOME_VERSION = "v6.5.1" @@ -14,13 +14,17 @@ DEFAULT_BASE_URL = ( % DEFAULT_FONTAWESOME_VERSION + "%s.svg" ) +DEFAULT_BASE_PATH = os.path.join(os.getcwd(), "..") DEFAULT_ICON_PATH = os.path.join( - os.getcwd(), - "..", + DEFAULT_BASE_PATH, "assets", "icons", ) DEFAULT_SVG_ATTR = {"fill": "currentColor"} +DEFAULT_ICON_DOCS = os.path.join( + DEFAULT_BASE_PATH, "exampleSite", "content", "samples", "icons" +) +DEFAULT_TABLE_DELIMITER = "| -------------------- | --------------------------------- |" def download_icon(download_url: str) -> None: @@ -39,9 +43,56 @@ def update_svg_to_theme(svg: bytes) -> bytes: svg_elem[k] = v # Remove comments - return re.sub(r'','', str(soup)) + return re.sub(r"", "", str(soup)) +def update_docs(icon_name: str) -> None: + """Update icon to docs""" + files = get_folder_md(DEFAULT_ICON_DOCS) + for file in files: + # Parse Table + logging.debug(f"reading {file}") + with open(file) as f: + file_data = f.read() + table_fmt, table = parse_table(file_data) + table.append(str(table[0]).replace("amazon", icon_name)) + + # Write Doc + print(table_fmt) + with open(file, "w") as f: + f.write( + "\n".join( + ( + table_fmt, + DEFAULT_TABLE_DELIMITER, + "\n".join(sorted(table)), + ) + ) + ) + + +def get_folder_md(dir_path: str) -> List[str]: + return list( + map( + lambda path: os.path.join(dir_path, path), + filter(lambda x: x.endswith(".md"), os.listdir(dir_path)), + ) + ) + + +def parse_table(table_str: str) -> Tuple[str, List[str]]: + """Parse the table to a list of (article_fmt, (icon_name, icon_shortcode))""" + headers, table = table_str.split(DEFAULT_TABLE_DELIMITER) + return headers.strip(), list( + filter( + lambda x: len(x.strip()) > 0, + map( + lambda x: x.strip(), + table.split("\n"), + ), + ) + ) + def save_file(name: str, svg: str) -> None: file_name = f"{name}.svg" @@ -125,3 +176,7 @@ if __name__ == "__main__": save_file(icon_name, final_svg) # Write to docs (TODO) + logging.debug("updating") + update_docs(icon_name) + + logging.info("done!") From 3c81e00bedd9463c64b358a28678f3ed5f44f892 Mon Sep 17 00:00:00 2001 From: Wen Junhua Date: Mon, 25 Dec 2023 23:17:40 +0900 Subject: [PATCH 3/5] chore: clean up code --- scripts/update_icon.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/update_icon.py b/scripts/update_icon.py index 2b52319e..ccb76877 100644 --- a/scripts/update_icon.py +++ b/scripts/update_icon.py @@ -15,7 +15,7 @@ DEFAULT_BASE_URL = ( + "%s.svg" ) DEFAULT_BASE_PATH = os.path.join(os.getcwd(), "..") -DEFAULT_ICON_PATH = os.path.join( +DEFAULT_ICON_DIR_PATH = os.path.join( DEFAULT_BASE_PATH, "assets", "icons", @@ -99,7 +99,7 @@ def save_file(name: str, svg: str) -> None: logging.debug(f"saving icon to {file_name}") with open( os.path.join( - DEFAULT_ICON_PATH, + DEFAULT_ICON_DIR_PATH, file_name, ), "w", @@ -141,8 +141,6 @@ def parse_args() -> Tuple[str, str, int]: parse_res = parser.parse_args() url = DEFAULT_BASE_URL % parse_res.name if parse_res.url is not None: - if len(parse_res.url) != 1: - raise ValueError("Invalid URL arguments. Use -h for help.") url = parse_res.url[0] log_level = logging.DEBUG if parse_res.verbose else logging.INFO @@ -175,7 +173,7 @@ if __name__ == "__main__": logging.debug("saving icon to assets") save_file(icon_name, final_svg) - # Write to docs (TODO) + # Write to docs logging.debug("updating") update_docs(icon_name) From db07288d0128a5504f680cd19e64430d44eb507d Mon Sep 17 00:00:00 2001 From: Wen Junhua Date: Mon, 25 Dec 2023 23:24:47 +0900 Subject: [PATCH 4/5] chore: clean up code --- scripts/update_icon.py | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/scripts/update_icon.py b/scripts/update_icon.py index ccb76877..22450a6f 100644 --- a/scripts/update_icon.py +++ b/scripts/update_icon.py @@ -21,7 +21,7 @@ DEFAULT_ICON_DIR_PATH = os.path.join( "icons", ) DEFAULT_SVG_ATTR = {"fill": "currentColor"} -DEFAULT_ICON_DOCS = os.path.join( +DEFAULT_ICON_DOCS_DIR = os.path.join( DEFAULT_BASE_PATH, "exampleSite", "content", "samples", "icons" ) DEFAULT_TABLE_DELIMITER = "| -------------------- | --------------------------------- |" @@ -48,7 +48,7 @@ def update_svg_to_theme(svg: bytes) -> bytes: def update_docs(icon_name: str) -> None: """Update icon to docs""" - files = get_folder_md(DEFAULT_ICON_DOCS) + files = get_folder_md(DEFAULT_ICON_DOCS_DIR) for file in files: # Parse Table logging.debug(f"reading {file}") @@ -58,7 +58,6 @@ def update_docs(icon_name: str) -> None: table.append(str(table[0]).replace("amazon", icon_name)) # Write Doc - print(table_fmt) with open(file, "w") as f: f.write( "\n".join( @@ -161,20 +160,25 @@ if __name__ == "__main__": logging.info(f"Using URL: {icon_url}") logging.info(f"Using Icon Name: {icon_name}") - # Download Icon - logging.debug(f"fetching icon at {icon_url}") - svg_content = download_icon(icon_url) + try: + # Download Icon + logging.debug(f"fetching icon at {icon_url}") + svg_content = download_icon(icon_url) - # Patch svg attrs - logging.debug(f"updating svg attrs") - final_svg = update_svg_to_theme(svg_content) + # Patch svg attrs + logging.debug( + f"remove svg comments and update svg attrs with {DEFAULT_SVG_ATTR}" + ) + final_svg = update_svg_to_theme(svg_content) - # Save file - logging.debug("saving icon to assets") - save_file(icon_name, final_svg) + # Save file + logging.debug(f"saving icon to {DEFAULT_ICON_DIR_PATH}") + save_file(icon_name, final_svg) - # Write to docs - logging.debug("updating") - update_docs(icon_name) - - logging.info("done!") + # Write to docs + logging.debug(f"updating docs from {DEFAULT_ICON_DOCS_DIR} dir") + update_docs(icon_name) + except Exception as e: + logging.critical(f"error adding icon {str(e)}") + else: + logging.info(f"{icon_name} added successfully") From 679898570c8c1d09c2e2312ca19ad1bc4201902b Mon Sep 17 00:00:00 2001 From: Wen Junhua Date: Mon, 25 Dec 2023 23:27:14 +0900 Subject: [PATCH 5/5] docs: update script docs --- scripts/update_icon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_icon.py b/scripts/update_icon.py index 22450a6f..24664101 100644 --- a/scripts/update_icon.py +++ b/scripts/update_icon.py @@ -114,7 +114,7 @@ def parse_args() -> Tuple[str, str, int]: 2. Icon Representation :str 3. Log Level: int """ - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(description="This script adds an icon to this congo theme and updates the relevant documentation.") parser.add_argument( "-v", "--verbose",