execonvert 0.5.5 → 0.5.7

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/CHANGELOG.md CHANGED
@@ -9,6 +9,32 @@ Categorías usadas: **Añadido**, **Cambiado**, **Corregido**, **Eliminado**.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.5.7] - 2026-09-13
13
+
14
+ ### Corregido
15
+ - Al importar un `.md`, las fórmulas escritas con `\(...\)` y `\[...\]` se
16
+ perdían: Markdown lee `\(`, `\)`, `\[` y `\]` como signos escapados y quita
17
+ la barra, así que llegaban al `.elpx` como texto entre paréntesis o
18
+ corchetes. Ahora se reconocen igual que `$...$` y `$$...$$`, tanto en su
19
+ propia línea como en mitad de un párrafo.
20
+ - Una fórmula en bloque escrita en mitad de un párrafo (`$$...$$` o
21
+ `\[...\]`) hacía desaparecer el texto que la seguía en ese párrafo.
22
+
23
+ ## [0.5.6] - 2026-09-05
24
+
25
+ ### Corregido
26
+ - La prima de las derivadas se anidaba un nivel en cada conversión de ida y
27
+ vuelta: `f^{'}` se convertía en `f^{^{'}}`, y repitiendo el ciclo seguía
28
+ acumulando capas. La causa es que temml escribe la prima como un superíndice
29
+ sobre una base vacía, que al volver de MathML se traducía literalmente. Solo
30
+ se colapsa esa forma: un superíndice doble real, que sí tiene base, no se
31
+ toca.
32
+ - Las dependencias del repositorio estaban ancladas a versiones anteriores a
33
+ las que instalaba cualquier usuario del paquete (`mathml-to-latex` 1.5.0
34
+ frente a 1.8.0), de modo que las pruebas no ejercitaban el mismo código que
35
+ se ejecuta al usarlo. Con ambas al día, un proyecto con 22 fórmulas
36
+ sobrevive tres ciclos `.elpx → .docx → .elpx` sin una sola diferencia.
37
+
12
38
  ## [0.5.5] - 2026-09-05
13
39
 
14
40
  ### Añadido
@@ -11,9 +11,9 @@ import { convertMarkdownToElpx } from '../src/markdown-import.js';
11
11
  import { installCliRuntime } from './runtime.js';
12
12
  import { EXE_RUNTIME_VERSION, isNewerThanRuntime } from '../src/exe-runtime.js';
13
13
  import { automaticCheck, autoCheckAllowed, runUpdate, updateText } from './updates.js';
14
- const CLI_VERSION = '0.5.5'.startsWith('__')
14
+ const CLI_VERSION = '0.5.7'.startsWith('__')
15
15
  ? String(JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8')).version)
16
- : '0.5.5';
16
+ : '0.5.7';
17
17
  const cliMessages = {
18
18
  es: {
19
19
  'help.title': 'CLI de eXeConvert',
@@ -1016,6 +1016,10 @@ function stripHtmlFromMath(value) {
1016
1016
  const document = new DOMParser().parseFromString(`<!doctype html><html><body>${withLineBreaks}</body></html>`, 'text/html');
1017
1017
  return document.body.textContent || '';
1018
1018
  }
1019
+ /** Exposed for tests: the LaTeX normalisation applied to every converted formula. */
1020
+ export function normalizeLatexForTests(value) {
1021
+ return normalizeLatexValue(value);
1022
+ }
1019
1023
  function normalizeLatexValue(value) {
1020
1024
  let output = value.normalize('NFC').replace(/\u00a0/g, ' ').replace(/\r/g, '');
1021
1025
  output = output.replace(/[\uFFFD\uFEFF\u00AD\u2066-\u2069\u200B-\u200F\u202A-\u202E\uFFF9-\uFFFB]/g, '');
@@ -1028,6 +1032,11 @@ function normalizeLatexValue(value) {
1028
1032
  output = output.replace(/(^|[^\\])\.{2}\s+\\\\/g, '$1\\ldots ');
1029
1033
  output = output.replace(/\\\\backslash\b/g, '\\\\');
1030
1034
  output = output.replace(/\\backslash\b/g, '\\\\');
1035
+ // temml writes a prime as a superscript with an empty base, so a round trip
1036
+ // through MathML turns f^{'} into f^{^{'}} and nests one level deeper every
1037
+ // time. Only the empty-base form is collapsed: a real double superscript
1038
+ // carries a base and is left alone.
1039
+ output = output.replace(/\^\{\s*\^\{\s*([\u2032\u2033\u2034'`]+)\s*\}\s*\}/g, "^{$1}");
1031
1040
  output = output.replace(/[ \t]+/g, ' ');
1032
1041
  output = output.replace(/ ?\n ?/g, '\n');
1033
1042
  output = output.trim();
@@ -15,8 +15,26 @@ markdown.use(texmath, {
15
15
  return options?.displayMode ? `\\[${trimmed}\\]` : `\\(${trimmed}\\)`;
16
16
  },
17
17
  },
18
- delimiters: ['dollars', 'beg_end'],
18
+ delimiters: ['dollars', 'brackets', 'beg_end'],
19
19
  });
20
+ // texmath only accepts \[...\] as a block of its own, while $$...$$ also works
21
+ // inside a paragraph. Without this rule markdown-it reads \[ and \] as escaped
22
+ // brackets and drops the backslashes, so the formula ends up as plain text.
23
+ const bracketDisplayRule = {
24
+ name: 'math_inline_bracket_display',
25
+ rex: /\\\[([\s\S]+?)\\\]/gy,
26
+ tag: '\\[',
27
+ };
28
+ markdown.inline.ruler.before('escape', bracketDisplayRule.name, texmath.inline(bracketDisplayRule));
29
+ // texmath wraps display math found inside a paragraph in <section>, which the
30
+ // HTML parser cannot nest in <p>: it closes the paragraph there and the text
31
+ // after the formula is lost. Keep the formula inline in the paragraph instead.
32
+ for (const name of ['math_inline_double', bracketDisplayRule.name]) {
33
+ markdown.renderer.rules[name] = (tokens, idx) => `<eqn>${texmath.render(tokens[idx].content, true, {})}</eqn>`;
34
+ }
35
+ export function renderMarkdownForTests(source) {
36
+ return markdown.render(source);
37
+ }
20
38
  export async function convertMarkdownToElpx(file, options, onProgress) {
21
39
  onProgress?.({ phase: 'read', message: 'Leyendo el archivo Markdown...', messageKey: 'progress.readMarkdown' });
22
40
  const source = await file.text();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "execonvert",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -41,7 +41,9 @@
41
41
  "test:cli": "node --test tests/cli-update.test.mjs",
42
42
  "test:docx": "node --test tests/docx-omml.test.mjs",
43
43
  "test:args": "node --test tests/cli-args.test.mjs",
44
- "test:version": "node --import tsx --test tests/runtime-version.test.mjs"
44
+ "test:version": "node --import tsx --test tests/runtime-version.test.mjs",
45
+ "test:primes": "node --import tsx --test tests/latex-primes.test.mjs",
46
+ "test:markdown": "node --import tsx --test tests/markdown-math.test.mjs"
45
47
  },
46
48
  "dependencies": {
47
49
  "@resvg/resvg-js": "^2.6.2",