@mostajs/markdown-html 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -12,7 +12,7 @@ const html = markdownPage(await readFile('README.md', 'utf8'), { title: 'Aide' }
12
12
 
13
13
  ## Périmètre (assumé)
14
14
 
15
- Titres (+ ancres, table des matières), paragraphes, **gras**/*italique*/`code`/~~barré~~, listes à puces, numérotées et **cases à cocher**, blocs de code, **tableaux** (avec défilement horizontal), citations, règles, liens. Pas un moteur CommonMark complet : un rendu de doc interne, pas un CMS.
15
+ Titres (+ ancres, table des matières ; depuis 0.2.0, les ancres gardent les écritures non latines — chinois, arabe, cyrillique — et un titre sans lettre reçoit `section-n` ; les ancres latines ne changent pas), paragraphes, **gras**/*italique*/`code`/~~barré~~, listes à puces, numérotées et **cases à cocher**, blocs de code, **tableaux** (avec défilement horizontal), citations, règles, liens. Pas un moteur CommonMark complet : un rendu de doc interne, pas un CMS.
16
16
 
17
17
  ## Sécurité
18
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mostajs/markdown-html",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Rendu Markdown → HTML zéro dépendance, sans build : titres, listes, tableaux, code, citations, liens, cases à cocher + table des matières. Tout est échappé (le HTML d'un .md n'est PAS interprété). Pour servir un README comme page d'aide.",
5
5
  "author": "Dr Hamid MADANI <drmdh@msn.com>",
6
6
  "license": "AGPL-3.0-or-later",
package/src/index.js CHANGED
@@ -24,13 +24,17 @@ export function inline(text = '') {
24
24
  return out;
25
25
  }
26
26
 
27
- const slug = (s) => s.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '')
28
- .replace(/[^a-z0-9\s-]/g, '').trim().replace(/\s+/g, '-');
27
+ // 0.2.0 : les lettres, chiffres et signes des écritures non latines (chinois, arabe, cyrillique…) sont gardés ; une
28
+ // lettre latine suit la règle de 0.1.x (accents retirés, le reste ôté) : aucune ancre latine ne change.
29
+ const gardee = (c) => /[a-z0-9\s-]/.test(c) || (/[\p{L}\p{N}\p{M}]/u.test(c) && !/\p{Script=Latin}/u.test(c));
30
+ const slug = (s) => [...s.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '')]
31
+ .filter(gardee).join('').normalize('NFC').trim().replace(/\s+/g, '-');
29
32
 
30
33
  /** Markdown → HTML. Retourne { html, toc } (la table des matières : les titres de niveau 2). */
31
34
  export function mdToHtml(md = '') {
32
35
  const lines = String(md).replace(/\r\n/g, '\n').split('\n');
33
36
  const out = []; const toc = [];
37
+ let sansNom = 0; // 0.2.0 : un titre sans lettre ni chiffre reçoit « section-n », jamais une ancre vide
34
38
  let i = 0;
35
39
  const closeList = (state) => { if (state.ul) { out.push('</ul>'); state.ul = false; } if (state.ol) { out.push('</ol>'); state.ol = false; } };
36
40
  const state = { ul: false, ol: false };
@@ -68,7 +72,7 @@ export function mdToHtml(md = '') {
68
72
  if (h) {
69
73
  closeList(state);
70
74
  const lvl = h[1].length; const txt = h[2].replace(/\s*#+\s*$/, '');
71
- const id = slug(txt);
75
+ const id = slug(txt) || `section-${++sansNom}`;
72
76
  if (lvl === 2) toc.push({ id, text: txt.replace(/[*`]/g, '') });
73
77
  out.push(`<h${lvl} id="${id}">${inline(txt)}</h${lvl}>`);
74
78
  i++; continue;
@@ -105,8 +109,10 @@ export function mdToHtml(md = '') {
105
109
  continue;
106
110
  }
107
111
 
108
- // Ligne vide → ferme les listes
109
- if (!line.trim()) { closeList(state); i++; continue; }
112
+ // Ligne vide → NE ferme PAS la liste (listes « lâches » : items séparés par une ligne vide =
113
+ // une seule liste, numérotation continue). La liste est fermée par le prochain bloc non-liste
114
+ // (titre, paragraphe, citation, tableau, code, hr) qui appelle closeList, ou en fin de document.
115
+ if (!line.trim()) { i++; continue; }
110
116
 
111
117
  // Paragraphe (les lignes suivantes sont recollées)
112
118
  closeList(state);
@@ -165,4 +171,4 @@ export function markdownPage(md = '', { title = 'Aide', head = '', toc = true, l
165
171
  + `${head}<style>${MD_CSS}</style></head><body><article class="md">${nav}${r.html}</article></body></html>`;
166
172
  }
167
173
 
168
- export const moduleInfo = { name: '@mostajs/markdown-html', version: '0.1.0' };
174
+ export const moduleInfo = { name: '@mostajs/markdown-html', version: '0.2.0' };