@aksp/opencrew 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,6 +12,8 @@ const MARCADORES = new Set(['prefira', 'preferir', 'use', 'usar', 'utilize', 'ut
12
12
  const NEGACOES = new Set('nao nunca nem jamais sem evite evitar proibido proibida proibidos proibidas vetado vetada parar pare deixar deixe'.split(' '));
13
13
  // Com estas expressões a linha está escrita ao contrário: todos os termos continuam proibidos.
14
14
  const SEM_TROCA = /(?<![\p{L}\p{N}])(?:em vez de|ao inves de|no lugar de)(?![\p{L}\p{N}])/u;
15
+ // Começo de um item de lista: `-`, `*`, `+` ou numerado.
16
+ const MARCA_DE_ITEM = /^\s*(?:[-*+]|\d{1,3}[.)])\s+/;
15
17
 
16
18
  /** Fichas da linha, na ordem: termos entre aspas, e palavras e setas de fora das aspas. */
17
19
  function fichas(linha) {
@@ -74,9 +76,32 @@ function itensDaSecao(texto) {
74
76
  const inicio = titulos.findIndex((t) => t && semAcento(t[2]).replace(/^[^\p{L}\p{N}]+/u, '').startsWith('proibicoes explicitas'));
75
77
  if (inicio < 0) return [];
76
78
  const acima = new RegExp(`^#{1,${titulos[inicio][1].length}}\\s`);
77
- const resto = linhas.slice(inicio + 1);
78
- const fim = resto.findIndex((l) => acima.test(l) || l.trim() === '---');
79
- return resto.slice(0, fim < 0 ? resto.length : fim).filter((l) => /^\s*(?:[-*+]|\d{1,3}[.)])\s+/.test(l));
79
+ const fim = linhas.findIndex((l, i) => i > inicio && (acima.test(l) || l.trim() === '---'));
80
+ const daSecao = linhas.map((texto, indice) => ({ texto, indice })).slice(inicio + 1, fim < 0 ? linhas.length : fim);
81
+ return daSecao.filter((l) => MARCA_DE_ITEM.test(l.texto));
82
+ }
83
+
84
+ /**
85
+ * Item que o usuário deixou para o revisor: termina em "(revisão humana)" ou começa por "Sem trava
86
+ * automática". Não é trava de texto nem pendência. Spec: fase-u4a-conserto-de-crews.md, regra 8.
87
+ */
88
+ export function ehRevisaoHumana(linha) {
89
+ const item = semAcento(linha.replace(MARCA_DE_ITEM, '')).trim();
90
+ return item.endsWith('(revisao humana)') || item.startsWith('sem trava automatica');
91
+ }
92
+
93
+ /**
94
+ * Os itens da seção de proibições, numerados a partir de 1 na ordem do arquivo.
95
+ * @returns {Array<{ n: number, indice: number, texto: string, pendente: boolean }>} `indice`: a
96
+ * linha no arquivo · `texto`: o item sem a marca de lista · `pendente`: sem termo entre aspas e
97
+ * sem a marca de revisão humana
98
+ */
99
+ export function itensDeProibicao(texto) {
100
+ return itensDaSecao(texto).map((l, i) => {
101
+ const { proibidos, preferidos } = lerLinha(l.texto);
102
+ const pendente = !proibidos.length && !preferidos.length && !ehRevisaoHumana(l.texto);
103
+ return { n: i + 1, indice: l.indice, texto: l.texto.replace(MARCA_DE_ITEM, '').trim(), pendente };
104
+ });
80
105
  }
81
106
 
82
107
  /**
@@ -88,9 +113,9 @@ export async function lerProibicoes(raiz, crew) {
88
113
  const arquivo = path.resolve(raiz, crew, '_memory', 'memories.md');
89
114
  const r = { existe: existsSync(arquivo), termos: [], preferidos: [], semAspas: 0 };
90
115
  if (!r.existe) return r;
91
- for (const linha of itensDaSecao(await lerTexto(arquivo))) {
116
+ for (const { texto: linha } of itensDaSecao(await lerTexto(arquivo))) {
92
117
  const { proibidos, preferidos } = lerLinha(linha);
93
- if (!proibidos.length && !preferidos.length) r.semAspas += 1;
118
+ if (!proibidos.length && !preferidos.length && !ehRevisaoHumana(linha)) r.semAspas += 1;
94
119
  r.termos.push(...proibidos);
95
120
  r.preferidos.push(...preferidos);
96
121
  }