Skip to content

Commit 04d2c15

Browse files
authored
Merge branch 'develop' into chakraui
2 parents 8e07d46 + 1d68188 commit 04d2c15

183 files changed

Lines changed: 4221 additions & 2483 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/drafts/optimize_svg.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ jobs:
66
peek:
77
name: Optimize the added/changed svgs
88
if: github.event.label.name == 'bot:optimize'
9-
runs-on: ubuntu-18.04
9+
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/checkout@v2
11+
- uses: actions/checkout@v3
1212
with:
1313
ref: ${{ github.head_ref }}
1414

.github/drafts/stale.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55

66
jobs:
77
stale:
8-
runs-on: ubuntu-latest
8+
runs-on: ubuntu-latestlatest
99
steps:
1010
- uses: actions/stale@main
1111
with:

.github/scripts/build_assets/api_handler.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,19 @@ def get_issues_by_labels(token: str, labels: List[str]):
180180
issues.extend(issues_only)
181181

182182
return issues
183+
184+
185+
def get_pr_by_number(token: str, pr_num: str):
186+
url = base_url + "pulls/" + pr_num
187+
headers = {
188+
"Authorization": f"token {token}"
189+
}
190+
191+
print(f"Querying the GitHub API for requests")
192+
response = requests.get(url, headers=headers)
193+
if not response:
194+
print(f"Can't query the GitHub API. Status code is {response.status_code}. Message is {response.text}")
195+
sys.exit(1)
196+
197+
pr = response.json()
198+
return pr

.github/scripts/build_assets/arg_getters.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from build_assets.PathResolverAction import PathResolverAction
33

44

5-
def get_selenium_runner_args(peek_mode=False):
5+
def get_selenium_runner_args(has_token=True, peek_mode=False):
66
"""
77
Get the commandline arguments for the icomoon_peek.py and
88
icomoon_build.py.
@@ -36,7 +36,7 @@ def get_selenium_runner_args(peek_mode=False):
3636
if peek_mode:
3737
parser.add_argument("pr_title",
3838
help="The title of the PR that we are peeking at")
39-
else:
39+
if has_token != False:
4040
parser.add_argument("token",
4141
help="The GitHub token to access the GitHub REST API.")
4242

@@ -82,7 +82,7 @@ def get_in_develop_labeler_args():
8282
help="The GitHub token to access the GitHub REST API.",
8383
type=str)
8484

85-
parser.add_argument("body",
86-
help="The PR's initial comment by the author AKA the `body` attribute of the `pull_request` API object.",
85+
parser.add_argument("pr_num",
86+
help="The PR's number",
8787
type=str)
8888
return parser.parse_args()
Binary file not shown.

.github/scripts/build_assets/geckodriver-v0.30.0-win64/README.md renamed to .github/scripts/build_assets/geckodriver-v0.32.2-win64/README.md

File renamed without changes.
Binary file not shown.

.github/scripts/build_assets/util.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from pathlib import Path
23
import re
34
from typing import List
45
import platform
@@ -71,11 +72,23 @@ def find_object_added_in_pr(icons: List[dict], pr_title: str):
7172
raise Exception(message)
7273

7374

75+
def is_svg_in_font_attribute(svg_file_path: Path, devicon_object: dict):
76+
"""
77+
Check if svg is in devicon.json's font attribute.
78+
:param svg_file_path, the path to a single svg icon
79+
:devicon_object, an object for a single icon inside devicon.json
80+
:return true if the svg exists in the devicon_object's font attribute, false if it doesn't
81+
"""
82+
icon_version = Path(svg_file_path).stem.split('-', 1)[1]
83+
font_object = devicon_object["versions"]["font"]
84+
return icon_version in font_object
85+
86+
7487
valid_svg_filename_pattern = re.compile(r"-(original|plain|line)(-wordmark)?\.svg$")
7588
def is_svg_name_valid(filename: str):
7689
return valid_svg_filename_pattern.search(filename) is not None
7790

91+
7892
valid_svg_version_pattern = re.compile(r"^(original|plain|line)(-wordmark)?$")
7993
def is_svg_version_valid(version):
8094
return valid_svg_version_pattern.search(version) is not None
81-

.github/scripts/check_icon_pr.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def main():
4242
print("No SVGs to check, ending script.")
4343
svg_err_msg = "Error checking SVGs: no SVGs to check. Might be caused by above issues."
4444
else:
45-
svg_err_msg = check_svgs(svgs)
45+
svg_err_msg = check_svgs(svgs, filtered_icon)
4646

4747
err_msg = []
4848
if devicon_err_msg != []:
@@ -163,7 +163,7 @@ def check_devicon_object(icon: dict):
163163
return ""
164164

165165

166-
def check_svgs(svg_file_paths: List[Path]):
166+
def check_svgs(svg_file_paths: List[Path], devicon_object: dict):
167167
"""
168168
Check the width, height, viewBox and style of each svgs passed in.
169169
The viewBox must be '0 0 128 128'.
@@ -195,10 +195,11 @@ def check_svgs(svg_file_paths: List[Path]):
195195
err_msg.append("- 'viewBox' is not '0 0 128 128' -> Set it or scale the file using https://www.iloveimg.com/resize-image/resize-svg.")
196196

197197
# goes through all elems and check for strokes
198-
for child in tree.iter():
199-
if child.get("stroke") != None:
200-
err_msg.append("- SVG contains `stroke` property. This will get ignored by Icomoon. Please convert them to fills.")
201-
break
198+
if util.is_svg_in_font_attribute(svg_path, devicon_object):
199+
for child in tree.iter():
200+
if child.get("stroke") != None:
201+
err_msg.append("- SVG contains `stroke` property. This will get ignored by Icomoon. Please convert them to fills.")
202+
break
202203

203204
if len(err_msg) > 1:
204205
err_msgs.append("\n".join(err_msg))
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
from pathlib import Path
2+
import sys
3+
from selenium.common.exceptions import TimeoutException
4+
import re
5+
import subprocess
6+
import json
7+
from typing import List, Dict
8+
from io import FileIO
9+
10+
# pycharm complains that build_assets is an unresolved ref
11+
# don't worry about it, the script still runs
12+
from build_assets.selenium_runner.BuildSeleniumRunner import BuildSeleniumRunner
13+
from build_assets import filehandler, arg_getters, util, api_handler
14+
15+
def main():
16+
"""
17+
Build the icons using Icomoon. Also optimize the svgs.
18+
"""
19+
runner = None
20+
logfile = open("log.txt", "w")
21+
try:
22+
args = arg_getters.get_selenium_runner_args(has_token=False)
23+
new_icons = get_icons_for_building(args.icomoon_json_path, args.devicon_json_path, logfile)
24+
if len(new_icons) == 0:
25+
sys.exit("No files need to be uploaded. Ending script...")
26+
27+
print(f"There are {len(new_icons)} icons to be build. Here are they:", *new_icons, sep = "\n", file=logfile)
28+
29+
print("Begin optimizing files...", file=logfile)
30+
optimize_svgs(new_icons, args.icons_folder_path, logfile=logfile)
31+
32+
print("Updating the icomoon json...", file=logfile)
33+
update_icomoon_json(new_icons, args.icomoon_json_path, logfile)
34+
35+
print("Start the building icons process...", file=logfile)
36+
icon_svgs = filehandler.get_svgs_paths(
37+
new_icons, args.icons_folder_path, icon_versions_only=True)
38+
zip_name = "devicon-v1.0.zip"
39+
zip_path = Path(args.download_path, zip_name)
40+
screenshot_folder = filehandler.create_screenshot_folder("./")
41+
42+
runner = BuildSeleniumRunner(args.download_path,
43+
args.geckodriver_path, args.headless, log_output=logfile)
44+
print("Building icons...", file=logfile)
45+
runner.build_icons(args.icomoon_json_path, zip_path,
46+
icon_svgs, screenshot_folder)
47+
48+
print("Extracting files...", file=logfile)
49+
filehandler.extract_files(str(zip_path), args.download_path, logfile)
50+
print("Renaming extracted files...", file=logfile)
51+
filehandler.rename_extracted_files(args.download_path, logfile)
52+
53+
print("Task completed!", file=logfile)
54+
except TimeoutException as e:
55+
util.exit_with_err(Exception("Selenium Time Out Error: \n" + str(e)), logfile)
56+
except Exception as e:
57+
util.exit_with_err(e, logfile)
58+
finally:
59+
print("Exiting", file=logfile)
60+
if runner is not None:
61+
runner.close()
62+
logfile.close()
63+
64+
65+
def get_icons_for_building(icomoon_json_path: str, devicon_json_path: str, logfile: FileIO):
66+
"""
67+
Get the icons for building.
68+
:param icomoon_json_path - the path to the `icomoon.json`.
69+
:param devicon_json_path - the path to the `devicon.json`.
70+
:param logfile.
71+
:return a list of dict containing info on the icons. These are
72+
from the `devicon.json`.
73+
"""
74+
75+
new_icons = []
76+
77+
# get any icons that might not have been found by the API
78+
# sometimes happen due to the PR being opened before the latest build release
79+
new_icons_from_devicon_json = filehandler.find_new_icons_in_devicon_json(
80+
devicon_json_path, icomoon_json_path)
81+
82+
for icon in new_icons_from_devicon_json:
83+
if icon not in new_icons:
84+
new_icons.append(icon)
85+
86+
return new_icons
87+
88+
89+
def optimize_svgs(new_icons: List[str], icons_folder_path: str, logfile: FileIO):
90+
"""
91+
Optimize the newly added svgs. This is done in batches
92+
since the command line has a limit on characters allowed.
93+
:param new_icons - the new icons that need to be optimized.
94+
:param icons_folder_path - the path to the /icons folder.
95+
:param logfile - the file obj to store logging info in.
96+
"""
97+
svgs = filehandler.get_svgs_paths(new_icons, icons_folder_path, icon_versions_only=False)
98+
start = 0
99+
step = 10
100+
for i in range(start, len(svgs), step):
101+
batch = svgs[i:i + step]
102+
print(f"Optimizing these files\n{batch}", file=logfile)
103+
subprocess.run(["npm", "run", "optimize-svg", "--", f"--svgFiles={json.dumps(batch)}"], shell=True)
104+
105+
106+
def update_icomoon_json(new_icons: List[str], icomoon_json_path: str, logfile: FileIO):
107+
"""
108+
Update the `icomoon.json` if it contains any icons
109+
that needed to be updated. This will remove the icons
110+
from the `icomoon.json` so the build script will reupload
111+
it later.
112+
"""
113+
icomoon_json = filehandler.get_json_file_content(icomoon_json_path)
114+
cur_len = len(icomoon_json["icons"])
115+
messages = []
116+
117+
wrapper_function = lambda icomoon_icon : find_icomoon_icon_not_in_new_icons(
118+
icomoon_icon, new_icons, messages)
119+
icons_to_keep = filter(wrapper_function, icomoon_json["icons"])
120+
icomoon_json["icons"] = list(icons_to_keep)
121+
122+
new_len = len(icomoon_json["icons"])
123+
print(f"Update completed. Removed {cur_len - new_len} icons:", *messages, sep='\n', file=logfile)
124+
filehandler.write_to_file(icomoon_json_path, json.dumps(icomoon_json))
125+
126+
127+
def find_icomoon_icon_not_in_new_icons(icomoon_icon: Dict, new_icons: List, messages: List):
128+
"""
129+
Find all the icomoon icons that are not listed in the new icons.
130+
This also add logging for which icons were removed.
131+
:param icomoon_icon - a dict object from the icomoon.json's `icons` attribute.
132+
:param new_icons - a list of new icons. Each element is an object from the `devicon.json`.
133+
:param messages - an empty list where the function can attach logging on which
134+
icon were removed.
135+
"""
136+
for new_icon in new_icons:
137+
pattern = re.compile(f"^{new_icon['name']}-")
138+
if pattern.search(icomoon_icon["properties"]["name"]):
139+
message = f"-'{icomoon_icon['properties']['name']}' cause it matches '{new_icon['name']}'"
140+
messages.append(message)
141+
return False
142+
return True
143+
144+
if __name__ == "__main__":
145+
main()

0 commit comments

Comments
 (0)