dbf0cf0eb8
For images that have greater height than width values, the image proportions for Yomichan were being calculated incorrectly. This can be observed for example in the SMK8 entry for くの字点 and the DAIJIRIN2 entry for 定積分.
152 lines
4.6 KiB
Python
152 lines
4.6 KiB
Python
import re
|
||
import os
|
||
from bs4 import BeautifulSoup
|
||
|
||
import bot.yomichan.glossary.icons as Icons
|
||
from bot.soup import delete_soup_nodes
|
||
from bot.data import load_yomichan_name_conversion
|
||
from bot.yomichan.glossary.gloss import make_gloss
|
||
from bot.name_conversion import convert_names
|
||
|
||
|
||
def make_glossary(entry, image_dir):
|
||
soup = entry.get_page_soup()
|
||
__fill_alts(soup)
|
||
__delete_unused_nodes(soup)
|
||
__clear_styles(soup)
|
||
__set_data_class(soup)
|
||
__convert_links(soup, entry)
|
||
__convert_priority_markers(soup)
|
||
__convert_gaiji(soup, image_dir)
|
||
__convert_rectangles(soup, image_dir)
|
||
|
||
name_conversion = load_yomichan_name_conversion(entry.target)
|
||
convert_names(soup, name_conversion)
|
||
|
||
gloss = make_gloss(soup.span)
|
||
glossary = [gloss]
|
||
return glossary
|
||
|
||
|
||
def __fill_alts(soup):
|
||
for name in ["親見出仮名", "親見出表記"]:
|
||
for el in soup.find_all(name):
|
||
el.name = "a"
|
||
alt = el.attrs["alt"]
|
||
el.string = alt
|
||
el.attrs["href"] = f"?query={alt}&wildcards=off"
|
||
del el.attrs["alt"]
|
||
|
||
|
||
def __delete_unused_nodes(soup):
|
||
for name in ["audio", "連濁"]:
|
||
delete_soup_nodes(soup, name)
|
||
|
||
|
||
def __clear_styles(soup):
|
||
for el in soup.select("[style]"):
|
||
del el.attrs["style"]
|
||
|
||
|
||
def __set_data_class(soup):
|
||
for el in soup.select("[class]"):
|
||
el.attrs["data-class"] = el.attrs["class"]
|
||
|
||
|
||
def __convert_links(soup, entry):
|
||
for el in soup.find_all("a"):
|
||
href = el.attrs["href"]
|
||
if href.startswith("$"):
|
||
el.unwrap()
|
||
elif re.match(r"^[0-9]+(?:-[0-9A-F]{4})?$", href):
|
||
ref_entry_id = entry.id_string_to_entry_id(href)
|
||
ref_entry = entry.ID_TO_ENTRY[ref_entry_id]
|
||
expression = ref_entry.get_first_expression()
|
||
el.attrs["href"] = f"?query={expression}&wildcards=off"
|
||
elif re.match(r"^(?:https?:|\?)[\w\W]*", href):
|
||
pass
|
||
else:
|
||
raise Exception(f"Invalid href format: {href}")
|
||
|
||
|
||
def __convert_priority_markers(soup):
|
||
style = "vertical-align: super; font-size: 0.6em"
|
||
for el in soup.find_all("img", attrs={"alt": "*"}):
|
||
el.name = "span"
|
||
el.string = "*"
|
||
el.attrs["style"] = style
|
||
for el in soup.find_all("img", attrs={"alt": "⁑"}):
|
||
el.name = "span"
|
||
el.string = "**"
|
||
el.attrs["style"] = style
|
||
|
||
|
||
def __convert_gaiji(soup, image_dir):
|
||
for el in soup.find_all("img"):
|
||
src = el.attrs["src"]
|
||
path = image_dir
|
||
for part in src.split("/"):
|
||
if part.strip() == "":
|
||
continue
|
||
path = os.path.join(path, part)
|
||
ratio = Icons.calculate_ratio(path)
|
||
img = BeautifulSoup("<img/>", "xml").img
|
||
img.attrs = {
|
||
"height": 1.0,
|
||
"width": ratio,
|
||
"sizeUnits": "em",
|
||
"collapsible": False,
|
||
"collapsed": False,
|
||
"background": False,
|
||
"appearance": "monochrome",
|
||
"title": el.attrs["alt"] if el.has_attr("alt") else "",
|
||
"path": f"{os.path.basename(image_dir)}/{src}",
|
||
"src": src,
|
||
}
|
||
el.name = "span"
|
||
el.clear()
|
||
el.append(img)
|
||
el.attrs["style"] = "vertical-align: text-bottom;"
|
||
|
||
|
||
def __convert_rectangles(soup, image_dir):
|
||
cls_to_appearance = {
|
||
"default": "monochrome",
|
||
"fill": "monochrome",
|
||
"red": "auto",
|
||
"redfill": "auto",
|
||
}
|
||
for el in soup.find_all("rect"):
|
||
cls = el.attrs["class"] if el.has_attr("class") else "default"
|
||
filename = f"{el.text}-{cls}.svg"
|
||
path = os.path.join(image_dir, filename)
|
||
__make_rectangle(path, el.text, cls)
|
||
ratio = Icons.calculate_ratio(path)
|
||
img = BeautifulSoup("<img/>", "xml").img
|
||
img.attrs = {
|
||
"height": 1.0,
|
||
"width": ratio,
|
||
"sizeUnits": "em",
|
||
"collapsible": False,
|
||
"collapsed": False,
|
||
"background": False,
|
||
"appearance": cls_to_appearance[cls],
|
||
"title": el.text,
|
||
"path": f"{os.path.basename(image_dir)}/{filename}",
|
||
}
|
||
el.name = "span"
|
||
el.clear()
|
||
el.append(img)
|
||
el.attrs["style"] = "vertical-align: text-bottom; margin-right: 0.25em"
|
||
|
||
|
||
def __make_rectangle(path, text, cls):
|
||
if cls == "fill":
|
||
Icons.make_monochrome_fill_rectangle(path, text)
|
||
elif cls == "red":
|
||
Icons.make_rectangle(path, text, "red", "white", "red")
|
||
elif cls == "redfill":
|
||
Icons.make_rectangle(path, text, "red", "red", "white")
|
||
else:
|
||
Icons.make_rectangle(path, text, "black", "transparent", "black")
|