From df315cfc8fb5479aeceff7764cd3f66585b95a2d Mon Sep 17 00:00:00 2001 From: Rossi-Luciano Date: Thu, 15 Jan 2026 17:21:17 -0300 Subject: [PATCH 1/8] =?UTF-8?q?feat(validation):=20adiciona=204=20valida?= =?UTF-8?q?=C3=A7=C3=B5es=20SPS=201.10=20para=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adiciona validação de restrição de mídia (video/mp4 ou audio/mp3) - Adiciona detecção de duplicação de label/caption - Adiciona validação de ocorrência única (0 ou 1 por elemento) - Adiciona verificação de incompatibilidade com alt-text='null' - Implementa suporte completo a i18n (msg_text, adv_text, adv_params) - Atinge 100% de conformidade SPS 1.10 para --- .../sps/validation/accessibility_data.py | 272 +++++++++++++++++- 1 file changed, 269 insertions(+), 3 deletions(-) diff --git a/packtools/sps/validation/accessibility_data.py b/packtools/sps/validation/accessibility_data.py index 55bcdefc8..9f0068af2 100644 --- a/packtools/sps/validation/accessibility_data.py +++ b/packtools/sps/validation/accessibility_data.py @@ -26,10 +26,14 @@ def validate(self): Executes all defined validations. """ yield from self.validate_alt_text() - yield from self.validate_alt_text_media_restriction() # NOVA - yield from self.validate_alt_text_not_duplicate_label_caption() # NOVA - yield from self.validate_decorative_figure_alt_text() # NOVA + yield from self.validate_alt_text_media_restriction() + yield from self.validate_alt_text_not_duplicate_label_caption() + yield from self.validate_decorative_figure_alt_text() yield from self.validate_long_desc() + yield from self.validate_long_desc_media_restriction() # NOVA + yield from self.validate_long_desc_not_duplicate_label_caption() # NOVA + yield from self.validate_long_desc_occurrence() # NOVA + yield from self.validate_long_desc_incompatible_with_null_alt() # NOVA yield self.validate_transcript() yield self.validate_speaker_and_speech() yield self.validate_accessibility_data_structure() @@ -420,6 +424,268 @@ def validate_long_desc(self): advice_params=advice_params, ) + def validate_long_desc_media_restriction(self): + """ + NOVA VALIDAÇÃO: Valida que em e só ocorre para vídeo/áudio. + + Regra SPS 1.10: + "Em e o elemento só deverá ocorrer quando + o formato do objeto for vídeo ou áudio, tendo os seguintes atributos para + @mime-type e @mime-subtype: video/mp4, audio/mp3" + """ + tag = self.data.get("tag") + + # Só valida para elementos e + if tag not in ("media", "inline-media"): + return + + long_desc = self.data.get("long_desc") + mimetype = self.data.get("mimetype") + mime_subtype = self.data.get("mime_subtype") + + # Se não há long-desc, não precisa validar esta regra + if not long_desc: + return + + # long-desc só deve estar presente para video/mp4 ou audio/mp3 + valid_combinations = [ + ("video", "mp4"), + ("audio", "mp3"), + ] + + current = (mimetype, mime_subtype) + valid = current in valid_combinations + + # Só retorna resultado quando há erro (validação inválida) + if not valid: + advice = ( + f"In <{tag}>, should only be used for video (mp4) or audio (mp3) files. " + f"Current mime-type is '{mimetype}' with mime-subtype '{mime_subtype}'. " + f"For other file types (PDF, ZIP, XLSX), remove or consider using different accessibility elements. " + f"Refer to SPS 1.10 documentation for details." + ) + advice_text = _( + "In <{tag}>, should only be used for video (mp4) or audio (mp3) files. " + "Current mime-type is {mimetype} with mime-subtype {mime_subtype}. " + "For other file types (PDF, ZIP, XLSX), remove or consider using different accessibility elements. " + "Refer to SPS 1.10 documentation for details." + ) + advice_params = { + "tag": tag, + "mimetype": mimetype or "undefined", + "mime_subtype": mime_subtype or "undefined" + } + + yield build_response( + title=" restriction for media", + parent=self.data, + item="long-desc", + sub_item="media restriction", + is_valid=False, + validation_type="value in list", + expected=f"mime-type/mime-subtype combinations: {valid_combinations}", + obtained=f"{mimetype}/{mime_subtype}", + advice=advice, + error_level=self.params.get("long_desc_media_restriction_error_level", "ERROR"), + data=self.data, + advice_text=advice_text, + advice_params=advice_params, + ) + + def validate_long_desc_not_duplicate_label_caption(self): + """ + NOVA VALIDAÇÃO: Valida que não copia o conteúdo de