Skip to content

Commit dad1a60

Browse files
Merge pull request #126 from robertatakenaka/corrige_xref_reftype_and_element_name
Melhora identificação de ref-type e nome de elemento relacionado com xref
2 parents 13443a6 + f7a54ea commit dad1a60

5 files changed

Lines changed: 2537 additions & 354 deletions

File tree

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
"""
2+
Módulo para navegação recursiva de HTMLs locais com correção de âncoras e hrefs.
3+
Foco: processar HTMLs locais, corrigir âncoras/hrefs e retornar conteúdo para embedding.
4+
"""
5+
6+
import os
7+
import re
8+
import logging
9+
from typing import Optional
10+
from scielo_classic_website.htmlbody.html_body import HTMLContent
11+
12+
13+
class HTMLEmbedder:
14+
"""Navegador recursivo para HTMLs locais com correção de âncoras e hrefs.
15+
16+
Função principal: Navegar entre HTMLs locais, corrigir âncoras e hrefs
17+
adicionando prefixos baseados no nome do arquivo, e retornar o conteúdo
18+
corrigido para embedding no HTML principal.
19+
20+
A identificação de assets (PDF, etc.) ocorrerá depois, no HTML principal
21+
com todo o conteúdo já embedado.
22+
"""
23+
24+
def __init__(self, journal_acron_folder, file_reader, processed):
25+
"""
26+
Inicializa o navegador.
27+
28+
Args:
29+
file_reader: callable para ler arquivos HTML
30+
journal_acron_folder: Acrônimo da revista para identificar arquivos locais
31+
"""
32+
self.journal_acron_folder = journal_acron_folder
33+
self.file_reader = file_reader or None
34+
self.process_filenames = processed
35+
36+
def _is_local_html_file(self, href: str) -> bool:
37+
"""
38+
Determina se um arquivo HTML é local baseado na presença de acrônimo entre barras.
39+
40+
Args:
41+
href: Caminho para o arquivo HTML
42+
43+
Returns:
44+
True se for arquivo local (contém /acrônimo/), False caso contrário
45+
"""
46+
# Normaliza barras
47+
normalized_href = href.replace("\\", "/")
48+
49+
if self.journal_acron_folder not in normalized_href:
50+
return False
51+
52+
# URLs absolutas não são locais
53+
if normalized_href.startswith("http://") or normalized_href.startswith(
54+
"https://"
55+
):
56+
return False
57+
58+
# Verifica padrão /acrônimo/ no caminho
59+
pattern = r".*/([a-zA-Z]+)/[^/]*\.html?(?:#.*)?$"
60+
return bool(re.search(pattern, normalized_href))
61+
62+
def get_html_to_embed(self, href: str, raw_data=None) -> Optional[str]:
63+
"""
64+
Processa um HTML local navegando recursivamente e corrigindo âncoras/hrefs.
65+
66+
Args:
67+
href: Caminho para o arquivo HTML local
68+
raw_data: Dados brutos para acessar arquivos (opcional)
69+
70+
Returns:
71+
Node
72+
"""
73+
if not self._is_local_html_file(href):
74+
logging.info(f"Arquivo {href} não é local - não será processado")
75+
return None
76+
77+
anchor_prefix, ext = os.path.splitext(os.path.basename(href))
78+
79+
# Evita loops recursivos
80+
if anchor_prefix in self.process_filenames:
81+
logging.warning(f"Arquivo {href} já processado - evitando loop")
82+
return f"<!-- LOOP DETECTADO: {href} -->"
83+
84+
try:
85+
# Lê o conteúdo HTML
86+
html_content = self._read_html_file(href, raw_data)
87+
if not html_content:
88+
return None
89+
except Exception as e:
90+
logging.exception(e)
91+
return None
92+
93+
try:
94+
html_body = HTMLContent(html_content)
95+
body_node = html_body.tree.find("body")
96+
if body_node is None:
97+
logging.warning(f"Nenhum corpo encontrado em {href}")
98+
return None
99+
except Exception as e:
100+
logging.exception(e)
101+
return None
102+
103+
body_node.tag = "embedded-html"
104+
body_node.set("path", href)
105+
106+
self.add_anchor_prefix(body_node, href, anchor_prefix)
107+
self.process_filenames.add(anchor_prefix)
108+
109+
self.process_html_file(body_node)
110+
return body_node
111+
112+
def add_anchor_prefix(self, body_node, href, anchor_prefix):
113+
for node in body_node.xpath(".//a[@name]"):
114+
name = node.get("name")
115+
new_name = anchor_prefix + name
116+
node.set("name", new_name)
117+
for a_href in body_node.xpath(f'.//a[@href="{href}"]'):
118+
a_href.set("href", f"#{anchor_prefix}")
119+
a_href.set("original-href", href)
120+
121+
def process_html_file(self, body_node):
122+
for node in body_node.xpath(".//img[@src]|.//a[@src]"):
123+
node.set("href", node.get("src"))
124+
125+
for a_href in body_node.xpath(".//a[@href]"):
126+
href = (a_href.get("href") or "").strip()
127+
if not self._is_local_html_file(href):
128+
continue
129+
parts = href.split("#")
130+
path = parts[0]
131+
anchor = ""
132+
if len(parts) > 1:
133+
anchor = parts[-1]
134+
new_anchor_prefix, ext = os.path.splitext(os.path.basename(path))
135+
new_name = f"{new_anchor_prefix}{anchor}"
136+
new_anchor = f"#{new_name}"
137+
138+
if new_anchor_prefix in self.process_filenames:
139+
a_href.set("href", new_anchor)
140+
a_href.set("original-href", href)
141+
logging.info(f"HTML local já processado: {href}")
142+
continue
143+
try:
144+
# Navega e processa o HTML local recursivamente
145+
corrected_html = self.get_html_to_embed(path)
146+
except Exception as e:
147+
logging.exception(e)
148+
corrected_html = None
149+
if not corrected_html:
150+
logging.warning(f"Não foi possível processar HTML: {path}")
151+
continue
152+
# Cria elemento para o conteúdo embedado
153+
parent = a_href.getparent()
154+
if parent is None:
155+
continue
156+
# Cria wrapper com conteúdo corrigido
157+
parent.addnext(corrected_html)
158+
a_href.set("href", new_anchor)
159+
a_href.set("original-href", href)
160+
self.process_filenames.add(new_name)
161+
162+
def _read_html_file(self, href: str, raw_data=None) -> Optional[str]:
163+
"""
164+
Lê o conteúdo do arquivo HTML.
165+
166+
Args:
167+
href: Caminho para o arquivo HTML
168+
raw_data: Dados brutos para acessar arquivos (opcional)
169+
170+
Returns:
171+
Conteúdo do arquivo HTML ou None se erro
172+
"""
173+
try:
174+
if not self.file_reader:
175+
return None
176+
177+
return self.file_reader(href, self.journal_acron_folder)
178+
179+
except Exception as e:
180+
logging.error(f"Erro ao ler arquivo HTML {href}: {e}")
181+
return None
182+
183+
184+
def get_html_to_embed(href, journal_acron_folder, file_reader, processed):
185+
""" """
186+
try:
187+
html_embedder = HTMLEmbedder(journal_acron_folder, file_reader, processed)
188+
return html_embedder.get_html_to_embed(href)
189+
except Exception as e:
190+
logging.exception(e)

0 commit comments

Comments
 (0)