Updated images code to pull from product URLs
This commit is contained in:
parent
d72370763c
commit
bee55221c4
6 changed files with 1562 additions and 1384 deletions
4
.github/workflows/daily-update.yml
vendored
4
.github/workflows/daily-update.yml
vendored
|
|
@ -42,7 +42,9 @@ jobs:
|
||||||
git submodule update --remote --recursive
|
git submodule update --remote --recursive
|
||||||
|
|
||||||
- name: Run conversion script
|
- name: Run conversion script
|
||||||
run: python convert_all_wippersnapper_definitions.py
|
run: |
|
||||||
|
pip install requests beautifulsoup4
|
||||||
|
python convert_all_wippersnapper_definitions.py
|
||||||
|
|
||||||
- name: Commit changes if any
|
- name: Commit changes if any
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,49 @@
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import glob
|
import glob
|
||||||
|
import re
|
||||||
|
import requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
# Base directory for the components
|
# Base directory for the components
|
||||||
COMPONENTS_DIR = r"./Wippersnapper_Components/components"
|
COMPONENTS_DIR = r"./Wippersnapper_Components/components"
|
||||||
OUTPUT_FILE = r"./wippersnapper_components.json"
|
OUTPUT_FILE = r"./wippersnapper_components.json"
|
||||||
|
|
||||||
|
def get_image_from_adafruit_product_url(product_url):
|
||||||
|
"""
|
||||||
|
Fetch the product image URL from an Adafruit product page by extracting
|
||||||
|
the og:image meta tag from the HTML.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product_url (str): URL to an Adafruit product page
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str or None: URL to the product image, or None if not found
|
||||||
|
"""
|
||||||
|
if not product_url or not re.match(r'https?://(?:www\.)?adafruit\.com/product/\d+', product_url):
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(product_url, timeout=10)
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Failed to fetch product page: {product_url}, status code: {response.status_code}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
og_image = soup.find('meta', property='og:image')
|
||||||
|
|
||||||
|
if og_image and 'content' in og_image.attrs:
|
||||||
|
image_url = og_image['content']
|
||||||
|
print(f"Found image URL from product page: {image_url}")
|
||||||
|
return image_url
|
||||||
|
else:
|
||||||
|
print(f"No og:image meta tag found for: {product_url}")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error fetching image from product URL {product_url}: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
def convert_components_to_json():
|
def convert_components_to_json():
|
||||||
"""
|
"""
|
||||||
Convert all component definition.json files into a single JSON file
|
Convert all component definition.json files into a single JSON file
|
||||||
|
|
@ -48,6 +85,10 @@ def convert_components_to_json():
|
||||||
"image": None
|
"image": None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Store product URL if available
|
||||||
|
if "productURL" in component_data:
|
||||||
|
component_info["productUrl"] = component_data["productURL"]
|
||||||
|
|
||||||
# Extract data types if available
|
# Extract data types if available
|
||||||
if "subcomponents" in component_data:
|
if "subcomponents" in component_data:
|
||||||
for meas_type in component_data["subcomponents"]:
|
for meas_type in component_data["subcomponents"]:
|
||||||
|
|
@ -80,13 +121,23 @@ def convert_components_to_json():
|
||||||
|
|
||||||
# Look for an image file
|
# Look for an image file
|
||||||
image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg']
|
image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg']
|
||||||
|
image_found = False
|
||||||
for ext in image_extensions:
|
for ext in image_extensions:
|
||||||
image_file = os.path.join(component_path, f"image{ext}")
|
image_file = os.path.join(component_path, f"image{ext}")
|
||||||
if os.path.exists(image_file):
|
if os.path.exists(image_file):
|
||||||
# Store relative path to image
|
# Store relative path to image
|
||||||
component_info["image"] = f"components/{category}/{component_dir}/image{ext}"
|
component_info["image"] = f"components/{category}/{component_dir}/image{ext}"
|
||||||
|
image_found = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# If no local image found and we have a product URL from Adafruit, try to fetch the image
|
||||||
|
if not image_found and "productUrl" in component_info:
|
||||||
|
product_url = component_info["productUrl"]
|
||||||
|
image_url = get_image_from_adafruit_product_url(product_url)
|
||||||
|
if image_url:
|
||||||
|
component_info["image"] = image_url
|
||||||
|
print(f"Using Adafruit product image for {category}/{component_dir}: {image_url}")
|
||||||
|
|
||||||
# Add to category components
|
# Add to category components
|
||||||
category_components.append(component_info)
|
category_components.append(component_info)
|
||||||
print(f"Processed {category}/{component_dir}")
|
print(f"Processed {category}/{component_dir}")
|
||||||
|
|
|
||||||
19
index.html
19
index.html
|
|
@ -540,13 +540,30 @@
|
||||||
|
|
||||||
// Show the current tab, and add an "active" class to the button that opened the tab
|
// Show the current tab, and add an "active" class to the button that opened the tab
|
||||||
document.getElementById(tabName).style.display = "block";
|
document.getElementById(tabName).style.display = "block";
|
||||||
evt.currentTarget.className += " active";
|
if (evt) {
|
||||||
|
evt.currentTarget.className += " active";
|
||||||
|
} else {
|
||||||
|
// If called programmatically, find and activate the correct tab
|
||||||
|
for (i = 0; i < tablinks.length; i++) {
|
||||||
|
if (tablinks[i].textContent.includes(tabName.replace('-components', ''))) {
|
||||||
|
tablinks[i].className += " active";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the application with data loading
|
// Initialize the application with data loading
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// This is handled by the load-wippersnapper-data.js script
|
// This is handled by the load-wippersnapper-data.js script
|
||||||
// It will call loadWippersnapperData() and initialize everything
|
// It will call loadWippersnapperData() and initialize everything
|
||||||
|
|
||||||
|
// Make sure only All Components tab is visible initially
|
||||||
|
const tabcontents = document.getElementsByClassName("component-tabcontent");
|
||||||
|
for (let i = 0; i < tabcontents.length; i++) {
|
||||||
|
if (tabcontents[i].id !== "all-components") {
|
||||||
|
tabcontents[i].style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Component search functionality
|
// Component search functionality
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,11 @@ function attachEventListeners() {
|
||||||
const boardImageElem = document.getElementById('board-image');
|
const boardImageElem = document.getElementById('board-image');
|
||||||
if (boardImageElem) {
|
if (boardImageElem) {
|
||||||
if (boardConfig.image) {
|
if (boardConfig.image) {
|
||||||
boardImageElem.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Boards/refs/heads/main/" + boardConfig.image;
|
if (!boardConfig.image.startsWith('http')) {
|
||||||
|
boardImageElem.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Boards/refs/heads/main/" + boardConfig.image;
|
||||||
|
} else {
|
||||||
|
boardImageElem.src = boardConfig.image;
|
||||||
|
}
|
||||||
boardImageElem.classList.remove('hidden');
|
boardImageElem.classList.remove('hidden');
|
||||||
} else {
|
} else {
|
||||||
boardImageElem.classList.add('hidden');
|
boardImageElem.classList.add('hidden');
|
||||||
|
|
|
||||||
|
|
@ -669,7 +669,11 @@ function createComponentCard(component, type) {
|
||||||
// Add image if available
|
// Add image if available
|
||||||
if (component.image) {
|
if (component.image) {
|
||||||
const img = document.createElement('img');
|
const img = document.createElement('img');
|
||||||
img.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Components/refs/heads/main/" + component.image;
|
if (!component.image.startsWith('http')) {
|
||||||
|
img.src = "https://raw.githubusercontent.com/adafruit/Wippersnapper_Components/refs/heads/main/" + component.image;
|
||||||
|
} else {
|
||||||
|
img.src = component.image;
|
||||||
|
}
|
||||||
img.alt = component.name;
|
img.alt = component.name;
|
||||||
card.appendChild(img);
|
card.appendChild(img);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue