Skip to content

Criar validações para o elemento <table-wrap> #1112

@Rossi-Luciano

Description

@Rossi-Luciano

Objetivo

Implementar validações para o elemento <table-wrap> conforme a especificação SPS 1.10 e modelo NISO JATS, aumentando a conformidade de X% para 70% (7 de 10 regras).

Nota: Algumas validações para <table-wrap> podem já estar parcialmente implementadas no repositório. Este Issue visa reavaliar, complementar e garantir cobertura completa das regras SPS 1.10 e NISO JATS table model.


Contexto

O elemento <table-wrap> especifica todas as partes de uma única tabela. Tabelas devem seguir o modelo NISO JATS com regras específicas sobre estrutura (sem <tr> no primeiro nível, <th> apenas em <thead>, <td> apenas em <tbody>). Validações corretas garantem presença de elementos obrigatórios, estrutura adequada segundo NISO JATS, e conformidade com requisitos SPS.

Conformidade atual: X de 10 regras implementadas (X%)
Meta após implementação: 7 de 10 regras (70%)


Documentação SPS

Referência oficial: https://docs.google.com/document/d/1GTv4Inc2LS_AXY-ToHT3HmO66UT0VAHWJNOIqzBNSgA/edit?tab=t.0#heading=h.tablewrap

Regras principais conforme SPS 1.10 e NISO JATS:

  1. Ocorrência:

    • <table-wrap> pode aparecer zero ou mais vezes em: <app>, <body>, <p>, <sec>, <glossary>
  2. Atributo obrigatório:

    • @id (obrigatório)
  3. Elementos de identificação obrigatórios:

    • Tabelas obrigatoriamente devem ter pelo menos <label> OU <caption> + <title>
    • Na ausência de ambos os dados na tabela original, usar: <caption><title/></caption>
  4. Modelo NISO JATS table model:

    • Codificação baseada em NISO JATS table model e Table Formatting
    • Regras adicionais obrigatórias:
      • O primeiro nível da estrutura não pode conter <tr> (ex.: //table/tr é proibido)
      • Elemento <th> apenas como descendente de <thead>
      • Elemento <td> apenas como descendente de <tbody>
  5. Posicionamento:

    • Tabelas devem aparecer no XML logo abaixo da primeira chamada do texto
    • Exceção: apenas quando identificadas fora de <app-group> e <supplementary-material>
  6. Estrutura esperada:

    • <table-wrap> contém:
      • @id (obrigatório)
      • <label> ou <caption> + <title> (obrigatório)
      • <table> (obrigatório)
      • <table-wrap-foot> (opcional)
  7. Elementos dentro de <table>:

    • <colgroup> e <col> - Agrupamento de colunas (opcional)
    • <thead> - Cabeçalho (opcional)
    • <tbody> - Corpo (obrigatório)
    • <th> - Célula de cabeçalho (apenas em <thead>)
    • <td> - Célula de dados (apenas em <tbody>)

Regras a Implementar

P0 – Críticas (implementar obrigatoriamente)

# Regra Nível Descrição
1 Validar presença de @id CRITICAL O atributo @id é obrigatório em <table-wrap>
2 Validar presença de <label> ou <caption> CRITICAL Tabela deve ter pelo menos <label> OU <caption> com <title>
3 Validar ausência de <tr> no primeiro nível ERROR O primeiro nível de <table> não pode conter <tr> diretamente (//table/tr é proibido)
4 Validar <th> apenas em <thead> ERROR Elemento <th> deve aparecer apenas como descendente de <thead>
5 Validar <td> apenas em <tbody> ERROR Elemento <td> deve aparecer apenas como descendente de <tbody>

P1 – Importantes (implementar se possível)

# Regra Nível Descrição
6 Validar presença de <table> CRITICAL O elemento <table> é obrigatório em <table-wrap>
7 Validar presença de <tbody> WARNING Elemento <tbody> é esperado em <table> (corpo da tabela)

P2 – Futuras (fora do escopo deste Issue)

# Regra Motivo de exclusão
8 Validar posicionamento após primeira chamada Alta complexidade - requer análise de xref e ordem de elementos
9 Validar estrutura completa de linhas e células Média complexidade - validação já é parcialmente feita pelo schema
10 Validar que não está em app-group ou supplementary-material quando validar posicionamento Média complexidade - requer análise de contexto ancestral

Arquivos a Criar/Modificar

Avaliar existentes (podem ter validações parciais):

  • packtools/sps/models/table_wrap.py ou similar – Verificar se modelo existe
  • packtools/sps/validation/table_wrap.py – Verificar validações existentes
  • packtools/sps/validation/rules/table_wrap_rules.json ou similar – Verificar configuração

Criar (se não existirem):

  • packtools/sps/models/table_wrap.py – Modelo de extração de dados
  • packtools/sps/validation/table_wrap.py – Validações
  • packtools/sps/validation/rules/table_wrap_rules.json – Configuração de níveis de erro
  • tests/sps/validation/test_table_wrap.py – Testes unitários

Referenciar (implementações similares):

  • packtools/sps/validation/fig.py – Validação de figuras (estrutura similar)
  • packtools/sps/validation/utils.py – Funções auxiliares (build_response)

Exemplos de XML

XML Válido (deve passar sem erros):

<!-- Exemplo 1: Tabela simples com label e caption -->
<body>
    <sec>
        <p>See <xref ref-type="table" rid="t1">Table 1</xref>.</p>
        <table-wrap id="t1">
            <label>TABLE I</label>
            <caption>
                <title>Domains and signaling questions used to analyze the risk of bias</title>
            </caption>
            <table>
                <colgroup>
                    <col/>
                    <col/>
                </colgroup>
                <tbody>
                    <tr>
                        <td align="center">Domain</td>
                        <td align="center">Sample quality</td>
                    </tr>
                    <tr>
                        <td align="center">Description</td>
                        <td align="center">The methodology used</td>
                    </tr>
                </tbody>
            </table>
        </table-wrap>
    </sec>
</body>

<!-- Exemplo 2: Tabela apenas com label -->
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <tbody>
                <tr>
                    <td>Data 1</td>
                    <td>Data 2</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

<!-- Exemplo 3: Tabela apenas com caption e title -->
<body>
    <table-wrap id="t1">
        <caption>
            <title>Risk factors for segmental resection</title>
        </caption>
        <table>
            <tbody>
                <tr>
                    <td>Data 1</td>
                    <td>Data 2</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

<!-- Exemplo 4: Tabela sem label nem title (usar title vazio) -->
<body>
    <table-wrap id="t1">
        <caption>
            <title/>
        </caption>
        <table>
            <tbody>
                <tr>
                    <td>Data 1</td>
                    <td>Data 2</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

<!-- Exemplo 5: Tabela com thead e tbody -->
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <caption>
            <title>Sample data</title>
        </caption>
        <table>
            <thead>
                <tr>
                    <th>Header 1</th>
                    <th>Header 2</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Data 1</td>
                    <td>Data 2</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

<!-- Exemplo 6: Tabela com table-wrap-foot -->
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <caption>
            <title>Results</title>
        </caption>
        <table>
            <tbody>
                <tr>
                    <td>Value 1</td>
                    <td>Value 2</td>
                </tr>
            </tbody>
        </table>
        <table-wrap-foot>
            <fn>
                <p>Data are expressed as means ± standard error.</p>
            </fn>
        </table-wrap-foot>
    </table-wrap>
</body>

<!-- Exemplo 7: Tabela com fonte (attrib) -->
<body>
    <table-wrap id="t1">
        <label>Tabela 1</label>
        <caption>
            <title>Perfil das mulheres vítimas de violência</title>
        </caption>
        <table>
            <tbody>
                <tr>
                    <td>2018</td>
                    <td>71,66</td>
                </tr>
            </tbody>
        </table>
        <table-wrap-foot>
            <attrib>Fonte: Adaptado de Instituto de Segurança Pública do Rio de Janeiro (2022).</attrib>
        </table-wrap-foot>
    </table-wrap>
</body>

<!-- Exemplo 8: Tabela com colgroup -->
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <caption>
            <title>Data summary</title>
        </caption>
        <table>
            <colgroup>
                <col width="50%"/>
                <col width="50%"/>
            </colgroup>
            <tbody>
                <tr>
                    <td>Column 1</td>
                    <td>Column 2</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

<!-- Exemplo 9: Tabela com células mescladas (rowspan/colspan) -->
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <caption>
            <title>Merged cells example</title>
        </caption>
        <table>
            <thead>
                <tr>
                    <th rowspan="2">Category</th>
                    <th colspan="2">Values</th>
                </tr>
                <tr>
                    <th>Value 1</th>
                    <th>Value 2</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Data A</td>
                    <td>10</td>
                    <td>20</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

<!-- Exemplo 10: Tabela com estilo (colorida) -->
<body>
    <table-wrap id="t1">
        <label>Tabela 1</label>
        <caption>
            <title>Dados coloridos</title>
        </caption>
        <table frame="hsides" rules="all">
            <tbody>
                <tr style="background-color:#E2EFD9">
                    <td>Header</td>
                    <td>Value</td>
                </tr>
                <tr style="background-color:#E7E6E6">
                    <td>Data</td>
                    <td>100</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

XML Inválido – Caso 1: Sem @id (CRITICAL)

<body>
    <table-wrap>
        <label>Table 1</label>
        <table>
            <tbody>
                <tr>
                    <td>Data</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Atributo @id é obrigatório em <table-wrap>

XML Inválido – Caso 2: Sem nem (CRITICAL)

<body>
    <table-wrap id="t1">
        <table>
            <tbody>
                <tr>
                    <td>Data</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Tabela deve ter pelo menos <label> OU <caption> com <title>. Na ausência de ambos, use <caption><title/></caption>

XML Inválido – Caso 3: no primeiro nível (ERROR)

<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <tr>
                <td>Data</td>
            </tr>
        </table>
    </table-wrap>
</body>

Erro esperado: O primeiro nível de <table> não pode conter <tr> diretamente. Use <tbody> para envolver as linhas (<tr>)

XML Inválido – Caso 4: fora de (ERROR)

<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <tbody>
                <tr>
                    <th>Header</th>
                    <td>Data</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Elemento <th> deve aparecer apenas como descendente de <thead>, não em <tbody>

XML Inválido – Caso 5: fora de (ERROR)

<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <thead>
                <tr>
                    <td>Data in header</td>
                </tr>
            </thead>
        </table>
    </table-wrap>
</body>

Erro esperado: Elemento <td> deve aparecer apenas como descendente de <tbody>, não em <thead>

XML Inválido – Caso 6: Sem (CRITICAL)
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <caption>
            <title>Table title</title>
        </caption>
    </table-wrap>
</body>

Erro esperado: Elemento <table> é obrigatório em <table-wrap>

XML Inválido – Caso 7: @id vazio (CRITICAL)

<body>
    <table-wrap id="">
        <label>Table 1</label>
        <table>
            <tbody>
                <tr>
                    <td>Data</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Atributo @id não pode estar vazio

XML Inválido – Caso 8:

(WARNING)
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <thead>
                <tr>
                    <th>Header</th>
                </tr>
            </thead>
        </table>
    </table-wrap>
</body>

Erro esperado: (WARNING) Elemento <tbody> é esperado em <table> (corpo da tabela com dados)

XML Inválido – Caso 10:

sem <title> (CRITICAL)
<body>
    <table-wrap id="t1">
        <caption>
            <p>Some description</p>
        </caption>
        <table>
            <tbody>
                <tr>
                    <td>Data</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Quando há <caption>, deve conter <title>. Se não há título, use <label> ou <caption><title/></caption>

XML Inválido – Caso 9: Sem

diretamente em (ERROR)
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <tbody>
                <th>Header wrongly placed</th>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Elemento <th> deve aparecer apenas como descendente de <thead>, dentro de <tr>

XML Inválido – Caso 11: e

no primeiro nível (ERROR)
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <tr>
                <td>Row 1</td>
            </tr>
            <tr>
                <td>Row 2</td>
            </tr>
        </table>
    </table-wrap>
</body>

Erro esperado: O primeiro nível de <table> não pode conter <tr> diretamente (encontrados 2 elementos <tr>)

XML Inválido – Caso 13:

ambos vazios (CRITICAL)
<body>
    <table-wrap id="t1">
        <label></label>
        <caption>
            <title></title>
        </caption>
        <table>
            <tbody>
                <tr>
                    <td>Data</td>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: <label> e <title> não podem estar ambos vazios

XML Inválido – Caso 12: Múltiplos

em múltiplos lugares errados (ERROR)
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <tbody>
                <tr>
                    <th>Header 1</th>
                </tr>
                <tr>
                    <th>Header 2</th>
                </tr>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Elementos <th> devem aparecer apenas como descendentes de <thead> (encontrados 2 em <tbody>)

XML Inválido – Caso 14: vazio (CRITICAL)
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
        </table>
    </table-wrap>
</body>

Erro esperado: Elemento <table> está vazio. Deve conter pelo menos <tbody> com linhas

XML Inválido – Caso 15:

diretamente em (ERROR)
<body>
    <table-wrap id="t1">
        <label>Table 1</label>
        <table>
            <tbody>
                <td>Data wrongly placed</td>
            </tbody>
        </table>
    </table-wrap>
</body>

Erro esperado: Elemento <td> deve aparecer dentro de <tr> em <tbody>


Padrão de Implementação

Diretrizes Gerais:

  1. Seguir padrões existentes no repositório:

    • Consultar implementações similares como fig.py (estrutura similar de wrap)
    • Usar estrutura de classes já estabelecida no packtools
    • IMPORTANTE: Verificar se já existem validações parciais para <table-wrap> e integrá-las ou complementá-las
  2. Internacionalização (i18n):

    • OBRIGATÓRIO: Todas as mensagens devem suportar internacionalização
    • Usar advice_text e advice_params em build_response()
    • Consultar conversas anteriores sobre implementação de i18n no packtools
    • Referência: validações em article_contribs.py que já implementam i18n completo
  3. Validações condicionais:

    • Validações que dependem de contexto devem retornar None quando não aplicável
    • Exemplo: validação de <caption> com <title> só se aplica se houver <caption>
    • Exemplo: validação de <tbody> é WARNING, não CRITICAL
    • Usar filter_results() nos testes para remover None
  4. Uso de build_response():

    • Sempre usar parent=self.data (dict completo, nunca string)
    • Campo response deve conter: "OK", "WARNING", "ERROR", "CRITICAL"
    • Sempre fornecer advice_text e advice_params para i18n
  5. Modelo de dados:

    • Criar propriedade que retorna lista de dicionários (um para cada <table-wrap>)
    • Cada dict deve conter: id, has_label, label_text, has_caption, has_title, title_text, has_table, has_tbody, has_thead, tr_in_first_level, th_outside_thead, td_outside_tbody, parent, parent_id, parent_lang
  6. Validação de label ou caption:

    • Verificar presença de <label> OU (<caption> E <title>)
    • Se nenhum: ERROR
    • Se ambos vazios: ERROR
  7. Validação de primeiro nível:

    • Usar XPath: table/tr para detectar <tr> direto em <table>
    • Contar ocorrências e reportar se > 0
  8. Validação de <th> e <td>:

    • <th>: verificar se todos estão dentro de <thead> usando XPath: //th[not(ancestor::thead)]
    • <td>: verificar se todos estão dentro de <tbody> usando XPath: //td[not(ancestor::tbody)]
    • Contar violações e reportar
  9. Validação de estrutura:

    • Verificar presença de <table> usando .find()
    • Verificar presença de <tbody> (WARNING se ausente)
    • Verificar se <table> não está vazio
  10. Validação de texto vazio:

    • Usar .strip() para verificar se <label> e <title> têm conteúdo real
    • Considerar caso onde ambos estão presentes mas ambos vazios

Testes Esperados

Casos de teste obrigatórios:

Atributo @id:

  • <table-wrap> com @id (OK)
  • Sem @id (CRITICAL)
  • @id vazio (CRITICAL)
  • @id apenas espaços (CRITICAL)

Elementos de identificação:

  • Com <label> apenas (OK)
  • Com <caption> + <title> apenas (OK)
  • Com ambos <label> e <caption> + <title> (OK)
  • Com <caption> + <title/> vazio (OK - permitido)
  • Sem <label> nem <caption> (CRITICAL)
  • Com <caption> mas sem <title> (CRITICAL)
  • <label> vazio e sem <caption> (CRITICAL)
  • <label> e <title> ambos vazios (CRITICAL)

Elemento

:
  • Com <table> (OK)
  • Sem <table> (CRITICAL)
  • <table> vazio (CRITICAL)

Regra: tr no primeiro nível:

  • Sem <tr> no primeiro nível (OK)
  • Um <tr> no primeiro nível (ERROR)
  • Múltiplos <tr> no primeiro nível (ERROR)
  • <tr> dentro de <tbody> (OK)
  • <tr> dentro de <thead> (OK)

Regra: th apenas em thead:

  • <th> em <thead> (OK)
  • <th> em <tbody> (ERROR)
  • Múltiplos <th> em <tbody> (ERROR - reportar todos)
  • <th> diretamente em <table> (ERROR)
  • Sem <th> (OK - opcional)

Regra: td apenas em tbody:

  • <td> em <tbody> (OK)
  • <td> em <thead> (ERROR)
  • Múltiplos <td> em <thead> (ERROR - reportar todos)
  • <td> diretamente em <table> (ERROR)

Elemento

:
  • Com <tbody> (OK)
  • Sem <tbody> mas com <thead> (WARNING)
  • Sem <tbody> e sem <thead> (WARNING)

Estrutura completa:

  • Tabela com <thead> e <tbody> (OK)
  • Tabela apenas com <tbody> (OK)
  • Tabela com <colgroup> (OK)
  • Tabela com <table-wrap-foot> (OK)

Células mescladas:

  • Com rowspan (OK)
  • Com colspan (OK)
  • Com ambos (OK)

Estilos:

  • Com atributos frame, rules (OK)
  • Com style em células (OK)
  • Com background-color (OK)

Múltiplas tabelas:

  • Documento sem <table-wrap> (OK - zero ou mais)
  • Documento com uma <table-wrap> (OK)
  • Documento com múltiplas <table-wrap> (OK)

Casos de borda:

  • <table-wrap> completamente vazio (CRITICAL)
  • <label> com formatação (OK)
  • <title> com formatação (OK)
  • Tabela aninhada (verificar schema JATS)
  • <table> com múltiplos <tbody> (OK - permitido)

Total esperado: ~55 testes unitários

Estrutura de testes:

  • Usar filter_results() para remover None dos resultados
  • Asserções devem usar campo response (não is_valid)
  • Testes devem ser autocontidos e descritivos
  • Agrupar testes por categoria (id, identificação, table, primeiro nível, th, td, tbody)

Critérios de Aceite

O PR será aceito quando:

  • Verificação de validações existentes: Código existente para <table-wrap> foi analisado e integrado ou substituído adequadamente
  • Todas as regras P0 implementadas (5 validações CRITICAL/ERROR)
  • Todas as regras P1 implementadas (2 validações CRITICAL/WARNING)
  • Testes unitários passando com cobertura mínima de ~55 casos
  • Nenhum teste existente quebrado
  • Arquivo table_wrap_rules.json criado com todos os níveis de erro
  • Internacionalização completa em todas as mensagens (i18n obrigatório)
  • Código seguindo padrões do packtools (build_response, filter_results, validações condicionais)
  • Modelo de dados criado com extração adequada de todos os elementos
  • Validação de @id obrigatório funcionando
  • Validação de label ou caption+title funcionando
  • Validação de ausência de <tr> no primeiro nível funcionando
  • Validação de <th> apenas em <thead> funcionando
  • Validação de <td> apenas em <tbody> funcionando
  • Validação de presença de <table> funcionando
  • Validação de presença de <tbody> funcionando (WARNING)
  • Documentação inline clara (docstrings)

Referências

Documentação SPS:

Padrões JATS:

Referências internas packtools:

  • Internacionalização: Consultar conversas anteriores sobre implementação de i18n
  • Implementações similares: fig.py (estrutura de wrap similar)
  • Funções auxiliares: utils.py (build_response)

Labels Sugeridas

enhancement validation SPS-1.10 NISO-JATS good-first-issue


Impacto Esperado

Antes:

  • Conformidade SPS 1.10 e NISO JATS para <table-wrap>: X% (verificar validações existentes)
  • Atributo @id pode estar ausente
  • Tabelas podem estar sem identificação (label/caption)
  • <tr> pode aparecer no primeiro nível (violação NISO JATS)
  • <th> pode aparecer fora de <thead> (violação NISO JATS)
  • <td> pode aparecer fora de <tbody> (violação NISO JATS)
  • Elemento <table> pode estar ausente
  • Estrutura pode não ter <tbody>

Depois:

  • Conformidade SPS 1.10 e NISO JATS para <table-wrap>: 70% (7 de 10 regras)
  • Validação CRITICAL de @id obrigatório
  • Validação CRITICAL de identificação (label ou caption+title)
  • Validação ERROR de estrutura NISO JATS (sem tr no primeiro nível)
  • Validação ERROR de <th> apenas em <thead>
  • Validação ERROR de <td> apenas em <tbody>
  • Validação CRITICAL de presença de <table>
  • Validação WARNING de presença de <tbody>
  • ~55 testes unitários garantindo qualidade
  • Internacionalização completa (PT/EN/ES)

Benefícios:

  • Garante conformidade com modelo NISO JATS table
  • Detecta estruturas incorretas de tabelas antes da publicação
  • Assegura identificação adequada de tabelas (id, label/caption)
  • Previne violações do modelo JATS (th/td em locais errados)
  • Melhora processamento automatizado de tabelas
  • Facilita renderização correta em diferentes plataformas
  • Garante acessibilidade de tabelas (estrutura semântica)
  • Previne problemas de conversão de formatos
  • Melhora qualidade geral dos XMLs SciELO
  • Facilita manutenção e depuração de XMLs

Observações importantes:

  • Implementar internacionalização ajustando as respostas das validações ao formato da função build_response em packtools/sps/validation/utils.py;
  • Verificar e adicionar as validações no orquestrador: packtools/sps/validation/xml_validations.py e packtools/sps/validation/xml_validator.py
  • Verificar a corretude dos testes exsitentes para a validação e complementar caso necessário;
  • Realizar ajustes, caso necessário, nos modelos que são utilizados pelas validações, garantindo que o ajuste não interfira em possíveis usos atuais desses modelos.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions