- Tema: redes, teléfono, correo, ubicación, reloj, flecha, check y menú pasan a Doodle Icons (Khushmeen Sidhu, CC0), en assets/icons/ y leídos por ga_icon(); la huella y el logotipo no cambian. Sin máscara de recorte, en currentColor y a 20 px. Se «menean» al pasar el ratón. - design/doodle-icons/: los 451 SVG originales, catálogo con buscador, script to-theme.py para añadir iconos al tema y README con origen y licencia. Fuera de la imagen Docker (.dockerignore). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
60 lines
2.6 KiB
Python
60 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Copia un Doodle Icon al tema, listo para ga_icon().
|
|
|
|
python3 design/doodle-icons/to-theme.py interface/heart → assets/icons/heart.svg
|
|
python3 design/doodle-icons/to-theme.py interface/heart corazon → assets/icons/corazon.svg (ga_icon( 'corazon' ))
|
|
python3 design/doodle-icons/to-theme.py arrows/arrow-right arrow --size 18
|
|
|
|
Quita la máscara de recorte (cortaba los bordes de algunos iconos), pasa el color a currentColor
|
|
(el icono toma el color del texto) y redondea las coordenadas a un decimal (≈ la mitad de peso).
|
|
"""
|
|
import argparse
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
HERE = pathlib.Path(__file__).resolve().parent
|
|
THEME_ICONS = HERE.parent.parent / 'wp-content/themes/gure-ametsa/assets/icons'
|
|
|
|
|
|
def round_number(match):
|
|
return ('%.1f' % float(match.group(0))).rstrip('0').rstrip('.') or '0'
|
|
|
|
|
|
def to_theme_svg(source, size):
|
|
view_box = re.search(r'viewBox="([^"]+)"', source).group(1)
|
|
body = re.sub(r'<defs>.*?</defs>', '', source, flags=re.S)
|
|
paths = []
|
|
for tag in re.findall(r'<path\b[^>]*>', body):
|
|
d = re.search(r'\bd="([^"]+)"', tag).group(1)
|
|
d = re.sub(r'-?\d*\.\d+|-?\d+', round_number, d)
|
|
d = re.sub(r'\s+', ' ', d).replace(' -', '-')
|
|
rule = ' fill-rule="evenodd"' if 'fill-rule="evenodd"' in tag else ''
|
|
paths.append(f'<path{rule} d="{d}"/>')
|
|
return (f'<svg class="ga-icon" viewBox="{view_box}" width="{size}" height="{size}" fill="currentColor" '
|
|
f'aria-hidden="true" focusable="false">{"".join(paths)}</svg>\n')
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument('icon', help='categoría/nombre, p. ej. interface/heart (ver catalogo.html)')
|
|
parser.add_argument('name', nargs='?', help='nombre en el tema (por defecto, el del icono)')
|
|
parser.add_argument('--size', type=int, default=20, help='ancho y alto en px (por defecto 20)')
|
|
args = parser.parse_args()
|
|
|
|
source = HERE / 'svg' / f'{args.icon.removesuffix(".svg")}.svg'
|
|
if not source.is_file():
|
|
sys.exit(f'No existe {source.relative_to(HERE)}. Mira los nombres en catalogo.html.')
|
|
name = args.name or source.stem
|
|
if not re.fullmatch(r'[a-z0-9-]+', name):
|
|
sys.exit('El nombre en el tema solo puede llevar minúsculas, números y guiones (p. ej. tik-tok).')
|
|
|
|
target = THEME_ICONS / f'{name}.svg'
|
|
target.write_text(to_theme_svg(source.read_text(encoding='utf-8'), args.size), encoding='utf-8')
|
|
print(f'{target.relative_to(HERE.parent.parent)} → ga_icon( \'{name}\' )')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|