Added additional checks for boards and images
7
.github/workflows/build.yml
vendored
|
|
@ -43,8 +43,11 @@ jobs:
|
|||
gem install bundler:1.17.3
|
||||
bundle install --full-index
|
||||
pip install python-frontmatter
|
||||
- name: Check feature names
|
||||
run: python3 check-features.py
|
||||
pip install pillow
|
||||
- name: Check feature names and other data
|
||||
run: python3 check-boards.py
|
||||
- name: Check Image Dimensions
|
||||
run: python3 check-images.py
|
||||
- name: Build site with jekyll
|
||||
run: |
|
||||
bundle exec jekyll build -d build
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "SEEED"
|
|||
board_url: "https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html"
|
||||
board_image: "Seeed_XIAO_nRF52840_Sense.jpg"
|
||||
date_added: 2021-12-29
|
||||
family: nrf52840
|
||||
downloads_display: true
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ board_url: "https://www.crowdsupply.com/diodes-delight/piunora"
|
|||
board_image: "diodes_delight_piunora.jpg"
|
||||
download_instructions:
|
||||
date_added: 2021-2-14
|
||||
family: raspberrypi
|
||||
features:
|
||||
- Wi-Fi
|
||||
- Bluetooth/BTLE
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ name: "DynaLoRa-USB"
|
|||
manufacturer: "BH Dynamics"
|
||||
board_url: "https://github.com/BHDynamics/rfm_radio_dongle"
|
||||
board_image: "dynalora_usb.jpg"
|
||||
date_added:
|
||||
date_added: 2021-02-11
|
||||
family: atmel-samd
|
||||
features:
|
||||
- LoRa/Radio
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ name: "DynOSSAT-EDU EPS"
|
|||
manufacturer: "BH Dynamics"
|
||||
board_url: "https://bhdyn.com/newspace"
|
||||
board_image: "dynossat_edu_eps.jpg"
|
||||
date_added:
|
||||
date_added: 2020-10-16
|
||||
family: atmel-samd
|
||||
downloads_display: true
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ name: "DynOSSAT-EDU OBC"
|
|||
manufacturer: "BH Dynamics"
|
||||
board_url: "https://bhdyn.com/newspace"
|
||||
board_image: "dynossat_edu_obc.jpg"
|
||||
date_added:
|
||||
date_added: 2020-10-16
|
||||
family: atmel-samd
|
||||
downloads_display: true
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "ELECFREAKS"
|
|||
board_url: "https://www.elecfreaks.com/picoed.html"
|
||||
board_image: "elecfreaks_picoed.jpg"
|
||||
date_added: 2022-4-21
|
||||
family: raspberrypi
|
||||
features:
|
||||
- Speaker
|
||||
- Display
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ name: "TTGO T8 ESP32-S2"
|
|||
manufacturer: "LILYGO"
|
||||
board_url: "http://www.lilygo.cn/prod_view.aspx?TypeId=50033&Id=1321"
|
||||
board_image: "lilygo_ttgo_t8_s2.jpg"
|
||||
date_added:
|
||||
date_added: 2022-03-09
|
||||
family: esp32s2
|
||||
bootloader_id: lilygo_ttgo_t8_s2
|
||||
features:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ name: "TTGO T8 ESP32-S2 ST7789"
|
|||
manufacturer: "LILYGO"
|
||||
board_url: "http://www.lilygo.cn/prod_view.aspx?TypeId=50033&Id=1321"
|
||||
board_image: "lilygo_ttgo_t8_s2_st7789.jpg"
|
||||
date_added:
|
||||
date_added: 2021-02-14
|
||||
family: esp32s2
|
||||
bootloader_id: lilygo_ttgo_t8_s2_st7789
|
||||
features:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "Mixly"
|
|||
board_url: "https://mixly.org/"
|
||||
board_image: "mixgo_ce_serial.jpg"
|
||||
date_added: 2022-5-22
|
||||
family: esp32s2
|
||||
features:
|
||||
- Display
|
||||
- Wi-Fi
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "Mixly"
|
|||
board_url: "https://mixly.org/"
|
||||
board_image: "mixgo_ce_udisk.jpg"
|
||||
date_added: 2022-5-1
|
||||
family: esp32s2
|
||||
features:
|
||||
- Display
|
||||
- Wi-Fi
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ manufacturer: "PyCubed.org"
|
|||
board_url: "https://pycubed.org/"
|
||||
board_image: "pycubed_v05.jpg"
|
||||
date_added: 2021-9-12
|
||||
family: atmel-samd
|
||||
features:
|
||||
|
||||
---
|
||||
|
||||
### ⭐ Double-check the your PyCubed board version before updating firmware.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ manufacturer: "PyCubed.org"
|
|||
board_url: "https://pycubed.org/"
|
||||
board_image: "pycubed_v05.jpg"
|
||||
date_added: 2021-9-12
|
||||
family: atmel-samd
|
||||
features:
|
||||
|
||||
---
|
||||
|
||||
### ⭐ Double-check the your PyCubed board version before updating firmware.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "Raspberry Pi"
|
|||
board_url: "https://www.raspberrypi.com/products/compute-module-4/"
|
||||
board_image: "raspberry_pi_cm4.jpg"
|
||||
date_added: 2022-1-4
|
||||
family: raspberrypi
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "Raspberry Pi"
|
|||
board_url: "https://www.raspberrypi.com/products/compute-module-4-io-board/"
|
||||
board_image: "raspberrypi_cm4io.jpg"
|
||||
date_added: 2021-11-29
|
||||
family: raspberrypi
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ manufacturer: "Raspberry Pi"
|
|||
board_url: "https://www.raspberrypi.com/products/raspberry-pi-4-model-b/"
|
||||
board_image: "raspberry_pi_4b.jpg"
|
||||
date_added: 2021-11-29
|
||||
family: raspberrypi
|
||||
|
||||
---
|
||||
|
||||
**NOTE**: Not all features are supported in CircuitPython.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ manufacturer: "Raspberry Pi"
|
|||
board_url: "https://www.raspberrypi.com/products/raspberry-pi-zero/"
|
||||
board_image: "raspberry_pi_zero.jpg"
|
||||
date_added: 2022-2-14
|
||||
family: raspberrypi
|
||||
features:
|
||||
|
||||
---
|
||||
|
||||
**NOTE**: Not all features are supported in CircuitPython.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ manufacturer: "Raspberry Pi"
|
|||
board_url: "https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/"
|
||||
board_image: "raspberry_pi_zero_2_w.jpg"
|
||||
date_added: 2021-11-29
|
||||
family: raspberrypi
|
||||
|
||||
---
|
||||
|
||||
**NOTE**: Not all features are supported in CircuitPython.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ manufacturer: "Raspberry Pi"
|
|||
board_url: "https://www.raspberrypi.com/products/raspberry-pi-zero-w/"
|
||||
board_image: "raspberry_pi_zero_w.jpg"
|
||||
date_added: 2022-01-07
|
||||
family: raspberrypi
|
||||
|
||||
---
|
||||
|
||||
**NOTE**: Not all features are supported in CircuitPython.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ manufacturer: "SEEED"
|
|||
board_url: "https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html"
|
||||
board_image: "seeeduino_xiao_rp2040.jpg"
|
||||
date_added: 2022-1-4
|
||||
|
||||
family: raspberrypi
|
||||
features:
|
||||
- Breadboard-Friendly
|
||||
- Robotics
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "Blues Wireless"
|
|||
board_url: "https://blues.io/products/swan"
|
||||
board_image: "swan_r5.jpg"
|
||||
date_added: 2021-9-29
|
||||
family: stm
|
||||
features:
|
||||
- Feather-Compatible
|
||||
- Battery Charging
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ manufacturer: "Waveshare"
|
|||
board_url: "https://www.waveshare.com/rp2040-zero.htm"
|
||||
board_image: "waveshare_rp2040_zero.jpg"
|
||||
date_added: "2022-1-12"
|
||||
family: raspberrypi
|
||||
features:
|
||||
- USB-C
|
||||
- Breadboard-Friendly
|
||||
|
||||
---
|
||||
|
||||
a Pico-like MCU board based on Raspberry Pi RP2040
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ manufacturer: "WIZnet"
|
|||
board_url: "https://www.wiznet.io/product-item/w5100s-evb-pico/"
|
||||
board_image: "w5100s-evb-pico.jpg"
|
||||
date_added: 2022-4-26
|
||||
family: raspberrypi
|
||||
features:
|
||||
- Breadboard-Friendly
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"bootloaders": {
|
||||
"nrf52840": {
|
||||
"version": "0.6.3"
|
||||
"version": "0.6.4"
|
||||
},
|
||||
"atmel-samd": {
|
||||
"version": "v3.14.0"
|
||||
|
|
@ -15,6 +15,8 @@
|
|||
"esp32c3": {},
|
||||
"stm": {},
|
||||
"cxd56": {},
|
||||
"mimxrt10xx": {}
|
||||
"mimxrt10xx": {},
|
||||
"raspberrypi": {},
|
||||
"litex": {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 190 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 286 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 308 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 318 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 210 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 212 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 1,014 KiB After Width: | Height: | Size: 1,014 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 1,007 KiB |
|
Before Width: | Height: | Size: 373 KiB After Width: | Height: | Size: 773 KiB |
|
Before Width: | Height: | Size: 423 KiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 215 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
BIN
assets/images/boards/original/makerdiary_nrf52840_m2_devkit.jpg
Normal file
|
After Width: | Height: | Size: 554 KiB |
|
Before Width: | Height: | Size: 336 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 262 KiB |
|
Before Width: | Height: | Size: 678 KiB After Width: | Height: | Size: 2.8 MiB |
|
Before Width: | Height: | Size: 717 KiB After Width: | Height: | Size: 2 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 6.8 MiB |
|
Before Width: | Height: | Size: 817 KiB After Width: | Height: | Size: 2.4 MiB |
BIN
assets/images/boards/original/pine64.png
Normal file
|
After Width: | Height: | Size: 716 KiB |
|
Before Width: | Height: | Size: 2 MiB After Width: | Height: | Size: 6.1 MiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 5.4 MiB |
|
Before Width: | Height: | Size: 239 KiB After Width: | Height: | Size: 821 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 402 KiB |
|
Before Width: | Height: | Size: 455 KiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 488 KiB After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 21 KiB |
127
check-boards.py
Executable file
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/python3
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
import frontmatter
|
||||
from dateutil.parser import parse
|
||||
|
||||
# Check CircuitPython Download Features
|
||||
with open('template.md', "rt") as f:
|
||||
metadata, content = frontmatter.parse(f.read())
|
||||
acceptable_features = set(metadata['features'])
|
||||
|
||||
def valid_date(date):
|
||||
date = str(date)
|
||||
if date:
|
||||
try:
|
||||
parse(date)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
return False
|
||||
|
||||
def verify_features(folder, valid_features):
|
||||
valid = True
|
||||
for filename in Path(folder).glob("*.md"):
|
||||
with open(filename, "rt") as f:
|
||||
metadata, _ = frontmatter.parse(f.read())
|
||||
downloads_display = metadata.get('downloads_display')
|
||||
if downloads_display is None or downloads_display:
|
||||
board_id = metadata.get('board_id')
|
||||
if board_id == "unknown":
|
||||
continue
|
||||
features = metadata.get('features') or ()
|
||||
for feature in sorted(set(features) - valid_features):
|
||||
print(f"{filename}:0: Non-standard feature: {feature}")
|
||||
valid = False
|
||||
return valid
|
||||
|
||||
def verify_family(folder):
|
||||
valid = True
|
||||
bl_file = open('./_data/bootloaders.json')
|
||||
bootloaders = json.load(bl_file)
|
||||
valid_bootloaders = bootloaders["bootloaders"].keys()
|
||||
for filename in Path(folder).glob("*.md"):
|
||||
with open(filename, "rt") as f:
|
||||
metadata, _ = frontmatter.parse(f.read())
|
||||
downloads_display = metadata.get('downloads_display')
|
||||
if downloads_display is None or downloads_display:
|
||||
board_id = metadata.get('board_id') or ()
|
||||
if board_id == "unknown":
|
||||
continue
|
||||
family = metadata.get('family')
|
||||
if family is None:
|
||||
print(f"Family field is missing for {board_id}")
|
||||
valid = False
|
||||
elif family not in valid_bootloaders:
|
||||
print(f"Family field value of {family} for {board_id} is invalid.")
|
||||
valid = False
|
||||
bl_file.close()
|
||||
return valid
|
||||
|
||||
def verify_date_added(folder):
|
||||
valid = True
|
||||
for filename in Path(folder).glob("*.md"):
|
||||
with open(filename, "rt") as f:
|
||||
metadata, _ = frontmatter.parse(f.read())
|
||||
downloads_display = metadata.get('downloads_display')
|
||||
if downloads_display is None or downloads_display:
|
||||
board_id = metadata.get('board_id') or ()
|
||||
if board_id == "unknown":
|
||||
continue
|
||||
date_added = metadata.get('date_added')
|
||||
if date_added is None:
|
||||
print(f"date_added field is missing for {board_id}")
|
||||
valid = False
|
||||
elif not valid_date(date_added):
|
||||
print(f"{date_added} is an invalid date for {board_id}")
|
||||
valid = False
|
||||
return valid
|
||||
|
||||
def verify_contribute_not_present(folder):
|
||||
valid = True
|
||||
contribute = re.compile(r".*\n## Contribute", re.MULTILINE | re.DOTALL)
|
||||
for filename in Path(folder).glob("*.md"):
|
||||
with open(filename, "rt") as f:
|
||||
metadata, content = frontmatter.parse(f.read())
|
||||
board_id = metadata.get('board_id') or ()
|
||||
result = contribute.match(content)
|
||||
if result is not None:
|
||||
print(f"Contribute Section found for {board_id} in {folder}")
|
||||
return valid
|
||||
|
||||
if not verify_features("_board", acceptable_features):
|
||||
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for acceptable features")
|
||||
raise SystemExit(True)
|
||||
|
||||
# Check Blinka Download Features
|
||||
blinka_features = {
|
||||
"Ethernet",
|
||||
"HDMI",
|
||||
"Wi-Fi",
|
||||
"40-pin GPIO",
|
||||
"GPS",
|
||||
"Feather-Compatible",
|
||||
"Bluetooth/BLE",
|
||||
"STEMMA QT/QWIIC",
|
||||
"USB 3.0",
|
||||
"Infrared Receiver",
|
||||
}
|
||||
|
||||
if not verify_features("_blinka", blinka_features):
|
||||
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-blinka for acceptable features")
|
||||
raise SystemExit(True)
|
||||
|
||||
if not verify_family("_board"):
|
||||
print("Family or not found or invalid value. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for details")
|
||||
raise SystemExit(True)
|
||||
|
||||
if not verify_date_added("_board") or not verify_date_added("blinka"):
|
||||
print("Date Added field not found or invalid value. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for details")
|
||||
raise SystemExit(True)
|
||||
|
||||
if not verify_contribute_not_present("_board") or not verify_contribute_not_present("blinka"):
|
||||
print("Contribute section found. This should not be there since it is automatically added.")
|
||||
raise SystemExit(True)
|
||||
|
||||
raise SystemExit(False)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
from pathlib import Path
|
||||
import frontmatter
|
||||
|
||||
# Check CircuitPython Download Features
|
||||
with open('template.md', "rt") as f:
|
||||
metadata, content = frontmatter.parse(f.read())
|
||||
acceptable_features = set(metadata['features'])
|
||||
|
||||
def verify_features(folder, valid_features):
|
||||
success = True
|
||||
for filename in Path(folder).glob("*.md"):
|
||||
with open(filename, "rt") as f:
|
||||
metadata, content = frontmatter.parse(f.read())
|
||||
features = metadata.get('features') or ()
|
||||
for feature in sorted(set(features) - valid_features):
|
||||
print(f"{filename}:0: Non-standard feature: {feature}")
|
||||
success = False
|
||||
return success
|
||||
|
||||
if not verify_features("_board", acceptable_features):
|
||||
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-downloads for acceptable features")
|
||||
raise SystemExit(True)
|
||||
|
||||
# Check Blinka Download Features
|
||||
blinka_features = {
|
||||
"Ethernet",
|
||||
"HDMI",
|
||||
"Wi-Fi",
|
||||
"40-pin GPIO",
|
||||
"GPS",
|
||||
"Feather-Compatible",
|
||||
"Bluetooth/BLE",
|
||||
"STEMMA QT/QWIIC",
|
||||
"USB 3.0",
|
||||
"Infrared Receiver",
|
||||
}
|
||||
|
||||
failed = not verify_features("_blinka", blinka_features)
|
||||
if failed:
|
||||
print("Non-standard features found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/adding-to-blinka for acceptable features")
|
||||
|
||||
raise SystemExit(failed)
|
||||
81
check-images.py
Executable file
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/python3
|
||||
import os
|
||||
from pathlib import Path
|
||||
import frontmatter
|
||||
from PIL import Image
|
||||
|
||||
MIN_ACCEPTABLE_RATIO = 0.75 # HEIGHT / WIDTH
|
||||
MAX_ACCEPTABLE_RATIO = 0.8
|
||||
SMALL_IMAGE_MIN_WIDTH = 292
|
||||
SMALL_IMAGE_MAX_WIDTH = 800
|
||||
LARGE_IMAGE_MIN_WIDTH = 590
|
||||
REQUIRE_ORIGINAL_IMAGE = True
|
||||
|
||||
BOARD_IMAGE_PATH = "./assets/images/boards/"
|
||||
SMALL_IMAGE_PATH = BOARD_IMAGE_PATH + "small/"
|
||||
LARGE_IMAGE_PATH = BOARD_IMAGE_PATH + "large/"
|
||||
ORIGINAL_IMAGE_PATH = BOARD_IMAGE_PATH + "original/"
|
||||
|
||||
def verify_images(folder):
|
||||
valid = True
|
||||
for filename in sorted(Path(folder).glob("*.md")):
|
||||
with open(filename, "rt") as f:
|
||||
metadata, _ = frontmatter.parse(f.read())
|
||||
downloads_display = metadata.get('downloads_display')
|
||||
if downloads_display is None or downloads_display:
|
||||
board_image = metadata.get('board_image') or ()
|
||||
board_id = metadata.get('board_id') or ()
|
||||
if board_id == "unknown":
|
||||
continue
|
||||
# Small Image
|
||||
small_image_found = os.path.exists(SMALL_IMAGE_PATH + board_image)
|
||||
if small_image_found:
|
||||
img = Image.open(SMALL_IMAGE_PATH + board_image)
|
||||
if not verify_image_size(SMALL_IMAGE_PATH + board_image, SMALL_IMAGE_MIN_WIDTH, SMALL_IMAGE_MAX_WIDTH):
|
||||
valid = False
|
||||
large_image_found = os.path.exists(LARGE_IMAGE_PATH + board_image)
|
||||
if large_image_found:
|
||||
if not verify_image_size(LARGE_IMAGE_PATH + board_image, LARGE_IMAGE_MIN_WIDTH):
|
||||
valid = False
|
||||
img.close()
|
||||
sized_images_missing = not small_image_found and not large_image_found
|
||||
if REQUIRE_ORIGINAL_IMAGE or sized_images_missing:
|
||||
if os.path.exists(ORIGINAL_IMAGE_PATH + board_image):
|
||||
img = Image.open(ORIGINAL_IMAGE_PATH + board_image)
|
||||
if not verify_image_size(ORIGINAL_IMAGE_PATH + board_image, LARGE_IMAGE_MIN_WIDTH, check_ratio=sized_images_missing):
|
||||
valid = False
|
||||
img.close()
|
||||
else:
|
||||
if sized_images_missing:
|
||||
print(f"No images found for {board_id}")
|
||||
else:
|
||||
print(f"Original image {ORIGINAL_IMAGE_PATH + board_image} not found for {board_id}.")
|
||||
valid = False
|
||||
return valid
|
||||
|
||||
def verify_image_size(image_path, min_width, max_width=None, check_ratio=True):
|
||||
valid = True
|
||||
img = Image.open(image_path)
|
||||
width, height = img.size
|
||||
min_height = int(min_width * MIN_ACCEPTABLE_RATIO)
|
||||
if width < min_width:
|
||||
print(f"Image file {image_path} is too narrow ({width} x {height}). It should be at least {min_width} x {min_height} pixels.")
|
||||
valid = False
|
||||
elif (max_width and width > max_width):
|
||||
max_height = int(max_width * MAX_ACCEPTABLE_RATIO)
|
||||
print(f"Image file {image_path} is too wide ({width} x {height}). It should be no larger than {max_width} x {max_height} pixels.")
|
||||
valid = False
|
||||
elif check_ratio and height / width < MIN_ACCEPTABLE_RATIO:
|
||||
print(f"Ratio for image file {image_path} is too wide ({width} x {height}). Try reducing width or increasing height.")
|
||||
valid = False
|
||||
elif check_ratio and height / width > MAX_ACCEPTABLE_RATIO:
|
||||
print(f"Ratio for image file {image_path} is too tall ({width} x {height}). Try reducing height or increasing width.")
|
||||
valid = False
|
||||
img.close()
|
||||
return valid
|
||||
|
||||
success = verify_images("_board") and verify_images("_blinka")
|
||||
if not success:
|
||||
print("Missing images or images that do not meet requirements found. See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website/preparing-the-images for images acceptable sizes.")
|
||||
|
||||
raise SystemExit(not success)
|
||||