diff --git a/.github/scripts/build_assets/SeleniumRunner.py b/.github/scripts/build_assets/SeleniumRunner.py index da5091ae..4c659a2b 100644 --- a/.github/scripts/build_assets/SeleniumRunner.py +++ b/.github/scripts/build_assets/SeleniumRunner.py @@ -75,12 +75,14 @@ class SeleniumRunner: self.driver = WebDriver(options=options, executable_path=geckodriver_path) self.driver.get(self.ICOMOON_URL) assert "IcoMoon App" in self.driver.title - # wait until the whole web page is loaded by testing the hamburger input - WebDriverWait(self.driver, self.LONG_WAIT_IN_SEC).until( - ec.element_to_be_clickable((By.XPATH, "(//i[@class='icon-menu'])[2]")) - ) - print("Accessed icomoon.io") + # wait until the whole web page is loaded by testing the hamburger input + hamburger_input = WebDriverWait(self.driver, SeleniumRunner.LONG_WAIT_IN_SEC).until( + ec.element_to_be_clickable((By.CSS_SELECTOR, + "button.btn5.lh-def.transparent i.icon-menu")) + ) + hamburger_input.click() + print("Accessed icomoon.io") def upload_icomoon(self, icomoon_json_path: str): """ @@ -90,16 +92,11 @@ class SeleniumRunner: """ print("Uploading icomoon.json file...") try: - self.click_hamburger_input() - # find the file input and enter the file path - import_btn = self.driver.find_element(By.XPATH, "(//li[@class='file'])[1]//input") + import_btn = WebDriverWait(self.driver, SeleniumRunner.LONG_WAIT_IN_SEC).until( + ec.element_to_be_clickable((By.CSS_SELECTOR, "div#file input")) + ) import_btn.send_keys(icomoon_json_path) - except SeleniumTimeoutException as e: - print(e.stacktrace) - print("Selenium timed out. Couldn't find import button.") - self.close() - raise e except Exception as e: self.close() raise e @@ -162,8 +159,8 @@ class SeleniumRunner: :return: None. """ try: - hamburger_input = self.driver.find_element_by_xpath( - "(//i[@class='icon-menu'])[2]" + hamburger_input = self.driver.find_element_by_css_selector( + "button.btn5.lh-def.transparent i.icon-menu" ) menu_appear_callback = ec.element_to_be_clickable( diff --git a/.github/scripts/build_assets/util.py b/.github/scripts/build_assets/util.py deleted file mode 100644 index 1c31e777..00000000 --- a/.github/scripts/build_assets/util.py +++ /dev/null @@ -1,33 +0,0 @@ -from pathlib import Path -from argparse import ArgumentParser -from build_assets.PathResolverAction import PathResolverAction - -def get_commandline_args(): - parser = ArgumentParser(description="Upload svgs to Icomoon to create icon files.") - - parser.add_argument("--headless", - help="Whether to run the browser in headless/no UI mode", - action="store_true") - - parser.add_argument("geckodriver_path", - help="The path to the firefox executable file", - action=PathResolverAction) - - parser.add_argument("icomoon_json_path", - help="The path to the icomoon.json aka the selection.json created by Icomoon", - action=PathResolverAction) - - parser.add_argument("devicon_json_path", - help="The path to the devicon.json", - action=PathResolverAction) - - parser.add_argument("icons_folder_path", - help="The path to the icons folder", - action=PathResolverAction) - - parser.add_argument("download_path", - help="The path where you'd like to download the Icomoon files to", - action=PathResolverAction) - - - return parser.parse_args() \ No newline at end of file diff --git a/.github/scripts/icomoon_build.py b/.github/scripts/icomoon_build.py deleted file mode 100644 index 6b3eb352..00000000 --- a/.github/scripts/icomoon_build.py +++ /dev/null @@ -1,42 +0,0 @@ -from pathlib import Path -from selenium.common.exceptions import TimeoutException - -# pycharm complains that build_assets is an unresolved ref -# don't worry about it, the script still runs -from build_assets.SeleniumRunner import SeleniumRunner -from build_assets import filehandler, util - - -def main(): - args = util.get_commandline_args() - new_icons = filehandler.find_new_icons(args.devicon_json_path, args.icomoon_json_path) - if len(new_icons) == 0: - print("No files need to be uploaded. Ending script...") - return - - # print list of new icons - print("List of new icons:", *new_icons, sep = "\n") - - runner = None - try: - runner = SeleniumRunner(args.download_path, - args.geckodriver_path, args.headless) - runner.upload_icomoon(args.icomoon_json_path) - svgs = filehandler.get_svgs_paths(new_icons, args.icons_folder_path) - runner.upload_svgs(svgs) - - zip_name = "devicon-v1.0.zip" - zip_path = Path(args.download_path, zip_name) - runner.download_icomoon_fonts(zip_path) - filehandler.extract_files(str(zip_path), args.download_path) - filehandler.rename_extracted_files(args.download_path) - print("Task completed.") - except TimeoutException as e: - print(e) - print(e.stacktrace) - finally: - runner.close() - - -if __name__ == "__main__": - main() diff --git a/.github/scripts/icomoon_peek.py b/.github/scripts/icomoon_peek.py index 6fd55f59..d2dea007 100644 --- a/.github/scripts/icomoon_peek.py +++ b/.github/scripts/icomoon_peek.py @@ -1,31 +1,61 @@ +from pathlib import Path +from argparse import ArgumentParser from selenium.common.exceptions import TimeoutException # pycharm complains that build_assets is an unresolved ref # don't worry about it, the script still runs from build_assets.SeleniumRunner import SeleniumRunner -from build_assets import filehandler, util +from build_assets import filehandler +from build_assets.PathResolverAction import PathResolverAction def main(): - args = util.get_commandline_args() + parser = ArgumentParser(description="Upload svgs to Icomoon to create icon files.") + + parser.add_argument("--headless", + help="Whether to run the browser in headless/no UI mode", + action="store_true") + + parser.add_argument("geckodriver_path", + help="The path to the firefox executable file", + action=PathResolverAction) + + parser.add_argument("icomoon_json_path", + help="The path to the icomoon.json aka the selection.json created by Icomoon", + action=PathResolverAction) + + parser.add_argument("devicon_json_path", + help="The path to the devicon.json", + action=PathResolverAction) + + parser.add_argument("icons_folder_path", + help="The path to the icons folder", + action=PathResolverAction) + + parser.add_argument("download_path", + help="The path where you'd like to download the Icomoon files to", + action=PathResolverAction) + + args = parser.parse_args() + new_icons = filehandler.find_new_icons(args.devicon_json_path, args.icomoon_json_path) if len(new_icons) == 0: - print("No files need to be uploaded. Ending script...") + print("No files need to be peek. Ending script...") return - # print list of new icons - print("List of new icons:", *new_icons, sep = "\n") - - runner = None + # print list of new icons, separated by comma + print("List of new icons:") + print(*new_icons, sep = "\n") try: - runner = SeleniumRunner(args.download_path, args.geckodriver_path, args.headless) + runner = SeleniumRunner(args.download_path, + args.geckodriver_path, args.headless) svgs = filehandler.get_svgs_paths(new_icons, args.icons_folder_path) runner.upload_svgs(svgs) + runner.close() print("Task completed.") except TimeoutException as e: print(e) print(e.stacktrace) - finally: runner.close() diff --git a/.github/scripts/icomoon_upload.py b/.github/scripts/icomoon_upload.py new file mode 100644 index 00000000..68e49ab4 --- /dev/null +++ b/.github/scripts/icomoon_upload.py @@ -0,0 +1,71 @@ +from pathlib import Path +from argparse import ArgumentParser +from selenium.common.exceptions import TimeoutException + +# pycharm complains that build_assets is an unresolved ref +# don't worry about it, the script still runs +from build_assets.SeleniumRunner import SeleniumRunner +from build_assets import filehandler +from build_assets.PathResolverAction import PathResolverAction + + +def main(): + parser = ArgumentParser(description="Upload svgs to Icomoon to create icon files.") + + parser.add_argument("--headless", + help="Whether to run the browser in headless/no UI mode", + action="store_true") + + parser.add_argument("geckodriver_path", + help="The path to the firefox executable file", + action=PathResolverAction) + + parser.add_argument("icomoon_json_path", + help="The path to the icomoon.json aka the selection.json created by Icomoon", + action=PathResolverAction) + + parser.add_argument("devicon_json_path", + help="The path to the devicon.json", + action=PathResolverAction) + + parser.add_argument("icons_folder_path", + help="The path to the icons folder", + action=PathResolverAction) + + parser.add_argument("download_path", + help="The path where you'd like to download the Icomoon files to", + action=PathResolverAction) + + args = parser.parse_args() + + new_icons = filehandler.find_new_icons(args.devicon_json_path, args.icomoon_json_path) + if len(new_icons) == 0: + print("No files need to be uploaded. Ending script...") + return + + # print list of new icons, separated by comma + print("List of new icons:") + print(*new_icons, sep = "\n") + try: + runner = SeleniumRunner(args.download_path, + args.geckodriver_path, args.headless) + runner.upload_icomoon(args.icomoon_json_path) + svgs = filehandler.get_svgs_paths(new_icons, args.icons_folder_path) + runner.upload_svgs(svgs) + + + zip_name = "devicon-v1.0.zip" + zip_path = Path(args.download_path, zip_name) + runner.download_icomoon_fonts(zip_path) + filehandler.extract_files(str(zip_path), args.download_path) + filehandler.rename_extracted_files(args.download_path) + runner.close() + print("Task completed.") + except TimeoutException as e: + print(e) + print(e.stacktrace) + runner.close() + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/build_icons.yml b/.github/workflows/build_icons.yml index 33a764e6..2719cce7 100644 --- a/.github/workflows/build_icons.yml +++ b/.github/workflows/build_icons.yml @@ -18,8 +18,11 @@ jobs: python -m pip install --upgrade pip pip install -r ./.github/scripts/requirements.txt npm install - - name: Executing build and create fonts via icomoon - run: npm run build + - name: Run icomoon_upload.py + run: > + python ./.github/scripts/icomoon_upload.py + ./.github/scripts/build_assets/geckodriver-v0.27.0-win64/geckodriver.exe + ./icomoon.json ./devicon.json ./icons ./ --headless - name: Upload geckodriver.log for debugging purposes uses: actions/upload-artifact@v2 if: ${{failure()}} @@ -32,7 +35,7 @@ jobs: with: name: new_icons path: ./new_icons.png - - name: Build devicon.min.css + - name: Running npm task for building devicon.min.css if: ${{ success() }} run: npm run build-css - name: Create Pull Request diff --git a/.github/workflows/peek_icons.yml b/.github/workflows/peek_icons.yml index 5bc2953a..9f9af857 100644 --- a/.github/workflows/peek_icons.yml +++ b/.github/workflows/peek_icons.yml @@ -16,12 +16,16 @@ jobs: uses: actions/setup-python@v2 with: python-version: 3.8 - - name: Install dependencies (python, pip) + - name: Install dependencies (python, pip, npm) run: | python -m pip install --upgrade pip pip install -r ./.github/scripts/requirements.txt + npm install - name: Run icomoon_peek.py - run: npm run peek + run: > + python ./.github/scripts/icomoon_peek.py + ./.github/scripts/build_assets/geckodriver-v0.27.0-win64/geckodriver.exe + ./icomoon.json ./devicon.json ./icons ./ --headless - name: Upload geckodriver.log for debugging purposes uses: actions/upload-artifact@v2 if: ${{failure()}} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3739a665..99b60aab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,7 +51,7 @@ The plain and line versions (with or without wordmark) are designe The original version are only available in svg format, so they do not need to be as simple and can contain numerous colors.

-Some icons are really simple (like the Apple one), so the original version can be used as the plain version and as the icon font. In this case, you'll only need to make only one of the version (either "original" or "plain"). You can then add an alias in the devicon.json so they can be found with either the "original" or "plain" naming convention. Note that this only applies to font icon versions only, not the SVG versions. SVG versions don't need aliases. +Some icons are really simple (like the Apple one), so the original version can be used as the plain version and as the icon font. In this case, you'll only need to make only one of the version (either "original" or "plain"). You can then add an alias in the devicon.json so they can be found with either the "original" or "plain" naming convention.


@@ -62,9 +62,9 @@ Some icons are really simple (like the Apple one), so the original version can b
  • The plain and line versions (with or without wordmark) need to stay as simple as possible. They must have only one color and the paths are united before exporting to svg.
  • Optimize/compress your SVGs. You can use a service like compressor or SVG Editor.
  • -
  • The icon's strokes and texts must be fills. We use Icomoon to make our icon, which has its requirements.
  • -
  • Each .svg file contains one version of an icon in a 0 0 128 128 viewbox.
  • -
  • The naming convention for the svg file is the following: (icon name)-(original|plain|line)(-wordmark?).
  • +
  • The icon's strokes and texts must be fills. We use Icomoon to make our icon, which has its requirements
  • +
  • Each .svg file contains one version of an icon in a 0 0 128 128 viewbox
  • +
  • The naming convention for the svg file is the following: (icon name)-(original|plain|line)-(wordmark)

  • @@ -87,28 +87,18 @@ Some icons are really simple (like the Apple one), so the original version can b
       
         {
    -        "name": string, // the official name of the technology. Must be lower case, no space and don't have the dash '-' character.
    +        "name": string, // the official name of the technology. Must be lower case, no space or use the dash '-' character.
             "tags": string[], // list of tags relating to the technology for search purpose
             "versions": {
                 "svg": VersionString[], // list the svgs that you have 
                 "font": VersionString[] // list the fonts acceptable versions that you have
             },
             "color": string, // the main color of the logo. Only track 1 color
    -        "aliases": AliasObj[] // keeps track of the aliases for the font versions ONLY
    +        "aliases": AliasObj[] // keeps track of the aliases
         }
       
     
    -

    - Here is what VersionString means: -

    -
      -
    1. It's the version part of an `svg` file's name
    2. -
    3. If you have "html5-original", the version string would be "original"
    4. -
    5. If you have "react-line-wordmark", the version string would be "line-wordmark"
    6. -
    7. See naming conventions section for more details
    8. -
    -

    Here is the AliasObj interface:

    @@ -120,14 +110,23 @@ Some icons are really simple (like the Apple one), so the original version can b } -
    +

    + Here is what VersionString means: +

    +
      +
    1. If you have "html5-original", the version string would be "original"
    2. +
    3. If you have "react-line-wordmark", the version string would be "line-wordmark"
    4. +
    5. See Icon Formats and Naming Conventions for more details
    6. +
    + +

    Example

    -As an example, let's assume you have created the svgs for Redhat and Amazon Web Services logos. +As an example, let's assume you have created the svgs for Amazon Web Services and Redhat logos.

    -

    For the Redhat svg, you have the "original", "original-wordmark", "plain", and "plain-wordmark" versions.

    -

    For the Amazon Web Services svgs, you have the following versions: "original", "original-wordmark", "plain-wordmark". The "original" version is simple enough to be a "plain" version as well. Note that we are not using the acronym AWS.

    +

    For the Amazon Web Services svgs, you have the following versions: "original", "original-wordmark", "plain-wordmark". However, the "original" version is simple enough to be a "plain" version as well. Note that we are not using the acronym AWS.

    +

    For the Redhat svg, you have the "original", "original-wordmark", "plain", "plain-wordmark" versions.

    1. Put the svgs for each logo that you have into its own folders in /icons @@ -139,33 +138,6 @@ As an example, let's assume you have created the svgs for Redhat and Amazon Web
    2. Update the devicon.json to include the icon (or variations)
    3. -
    4. Create a separate pull request (PR) for each icon (no matter how many variations). +
    5. Create a separated pull request (PR) for each icon (no matter how many variations).
    6. diff --git a/devicon.json b/devicon.json index a20801b9..71d05136 100644 --- a/devicon.json +++ b/devicon.json @@ -523,12 +523,15 @@ "line-wordmark" ], "font": [ - "line", - "line-wordmark" + "line" ] }, "color": "#000000", "aliases": [ + { + "base": "original", + "alias": "original-wordmark" + }, { "base": "line", "alias": "plain" @@ -2254,7 +2257,6 @@ "original" ] }, - "color": "#764abc", "aliases": [ { "base": "original", diff --git a/package.json b/package.json index 602e5c48..01b2b98f 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,7 @@ "description": "Programming related icons collection", "main": "devicon.min.css", "scripts": { - "build-css": "gulp updateCss && gulp clean", - "build": "python ./.github/scripts/icomoon_build.py ./.github/scripts/build_assets/geckodriver-v0.27.0-win64/geckodriver.exe ./icomoon.json ./devicon.json ./icons ./ --headless", - "peek": "python ./.github/scripts/icomoon_peek.py ./.github/scripts/build_assets/geckodriver-v0.27.0-win64/geckodriver.exe ./icomoon.json ./devicon.json ./icons ./ --headless" + "build-css": "gulp updateCss && gulp clean" }, "repository": { "type": "git",