mirror of
https://github.com/gabriele-cusato/HandTranscriptMd.git
synced 2026-07-22 06:14:06 +00:00
corretto parsing, ora funziona anche per le tabelle con il carattere // al posto di <>
This commit is contained in:
parent
e94264e3cf
commit
aa4e6d565b
5 changed files with 121 additions and 94 deletions
13
CLAUDE.md
13
CLAUDE.md
|
|
@ -223,6 +223,19 @@ cd C:\Projects\pluginObsidian\handWrittenMarkdownConverter\HandTranscriptMd; nod
|
|||
|
||||
### Task aperti
|
||||
|
||||
- **Bug `<TABLE>` multi-riga** — `src/md-parser.ts` → `expandKeywords`, case `TABLE`:
|
||||
- Le intestazioni vengono generate correttamente ma le righe dati vengono lasciate invariate
|
||||
- Esempio input:
|
||||
```
|
||||
<TABLE> Col1, Col2, Col3
|
||||
val1, val2, val3
|
||||
val4, val5, val6
|
||||
<TABLE>
|
||||
```
|
||||
- Output atteso: tabella completa con intestazioni + righe dati
|
||||
- Output attuale: intestazioni ok, poi le righe dati restano come testo grezzo (`val1,val2,val3`) seguite da `| |` e `|---|`
|
||||
- Probabile causa: il loop di raccolta righe in `case 'TABLE'` non legge correttamente le righe successive
|
||||
|
||||
- **Keyword personalizzate nelle impostazioni** — `src/settings.ts` + `src/md-parser.ts`:
|
||||
- Permettere all'utente di aggiungere keyword custom nella pagina impostazioni
|
||||
- Ogni keyword custom ha: nome (es. `FIRMA`), output markdown (es. `— Mario Rossi`)
|
||||
|
|
|
|||
|
|
@ -349,6 +349,8 @@ async function doConvertWiki(
|
|||
const rawText = await recognizer.recognize(base64);
|
||||
if (!rawText.trim()) throw new Error('Nessun testo riconosciuto');
|
||||
const markdown = parseMarkdown(rawText);
|
||||
// In modalità debug mostra il testo grezzo restituito da Gemini (prima del parsing)
|
||||
if (plugin.settings.debugMode) new Notice(`[DEBUG] Testo grezzo Gemini:\n${rawText}`, 30000);
|
||||
await archiveSvgByPath(svgPath, plugin);
|
||||
await replaceWikiEmbedWithMarkdown(svgPath, markdown, sourcePath, plugin);
|
||||
new Notice('Conversione completata!');
|
||||
|
|
@ -375,6 +377,8 @@ async function doConvert(
|
|||
if (!rawText.trim()) { new Notice('Nessun testo riconosciuto'); return; }
|
||||
|
||||
const markdown = parseMarkdown(rawText);
|
||||
// In modalità debug mostra il testo grezzo restituito da Gemini (prima del parsing)
|
||||
if (plugin.settings.debugMode) new Notice(`[DEBUG] Testo grezzo Gemini:\n${rawText}`, 30000);
|
||||
await archiveSvg(data, plugin);
|
||||
await replaceEmbedWithMarkdown(ctx, data, markdown, plugin);
|
||||
new Notice('Conversione completata!');
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ export function normalizeMarkdownSymbols(rawText: string): string {
|
|||
* Applica le correzioni su una singola riga (non dentro blocchi codice).
|
||||
*/
|
||||
function normalizeLine(line: string): string {
|
||||
// Righe keyword <KEYWORD> — non modificare, le gestisce expandKeywords
|
||||
if (/^<[A-Za-z0-9_]+/i.test(line.trim())) return line;
|
||||
// Righe keyword //KEYWORD — non modificare, le gestisce expandKeywords
|
||||
if (/^\/\/[A-Za-z0-9_]/i.test(line.trim())) return line;
|
||||
|
||||
// Rimuove spazi finali (non iniziali: servono per le liste annidate)
|
||||
line = line.trimEnd();
|
||||
|
|
@ -194,10 +194,10 @@ export function expandKeywords(text: string, fnStart = 1): string {
|
|||
const line = lines[i];
|
||||
const trimmed = line.trim();
|
||||
|
||||
// Pattern: <KEYWORD> contenuto oppure <KEYWORD extra> contenuto (es. <CODEBLOCK js>)
|
||||
// Il parametro extra (linguaggio per CODEBLOCK) è dentro le <>: <CODEBLOCK js>
|
||||
// Il contenuto segue > con opzionale : e/o spazio (es. <H1> CIAO, <H1>:CIAO)
|
||||
const kw = trimmed.match(/^<([A-Za-z0-9_]+)(?:\s+([^>]*?))?\s*>[\s:]*(.*)/i);
|
||||
// Pattern: //KEYWORD contenuto oppure //KEYWORD: contenuto (colon opzionale)
|
||||
// Es: //H1 CIAO, //LIST a, b, c, //CODEBLOCK js, //HR
|
||||
// Il contenuto segue il nome keyword separato da spazio e/o ':'
|
||||
const kw = trimmed.match(/^\/\/([A-Za-z0-9_]+)\s*:?\s*(.*)/i);
|
||||
|
||||
if (!kw) {
|
||||
out.push(line);
|
||||
|
|
@ -206,8 +206,7 @@ export function expandKeywords(text: string, fnStart = 1): string {
|
|||
}
|
||||
|
||||
const keyword = kw[1].toUpperCase(); // nome keyword normalizzato
|
||||
const extra = (kw[2] ?? '').trim(); // parametro aggiuntivo (es. linguaggio CODEBLOCK)
|
||||
const content = (kw[3] ?? '').trim(); // contenuto dopo ':'
|
||||
const content = (kw[2] ?? '').trim(); // contenuto dopo la keyword
|
||||
|
||||
switch (keyword) {
|
||||
|
||||
|
|
@ -287,9 +286,9 @@ export function expandKeywords(text: string, fnStart = 1): string {
|
|||
case 'INDENT': out.push(` ${content}`); break;
|
||||
|
||||
// --- CODEBLOCK multi-riga (termina con riga vuota) ---
|
||||
// Sintassi: _CODEBLOCK js: (linguaggio nel parametro opzionale prima di ':')
|
||||
// Sintassi: //CODEBLOCK js (linguaggio dopo il nome keyword)
|
||||
case 'CODEBLOCK': {
|
||||
const lang = extra; // es. "js", "python", ""
|
||||
const lang = content; // es. "js", "python", ""
|
||||
i++;
|
||||
const codeLines: string[] = [];
|
||||
// Raccoglie righe fino alla prima riga vuota o fine testo
|
||||
|
|
@ -314,9 +313,9 @@ export function expandKeywords(text: string, fnStart = 1): string {
|
|||
}
|
||||
|
||||
// --- TABLE multi-riga ---
|
||||
// Header: <TABLE> Col1, Col2, Col3
|
||||
// Header: //TABLE Col1, Col2, Col3
|
||||
// Righe: val1, val2, val3 (una per riga, virgola come separatore)
|
||||
// Fine: <TABLE> (tag di chiusura) oppure riga vuota / senza virgola
|
||||
// Fine: //TABLE (tag di chiusura) oppure riga vuota / senza virgola
|
||||
case 'TABLE': {
|
||||
const headers = content.split(',').map(h => h.trim());
|
||||
const rows: string[][] = [];
|
||||
|
|
@ -324,7 +323,7 @@ export function expandKeywords(text: string, fnStart = 1): string {
|
|||
while (i < lines.length) {
|
||||
const rowLine = lines[i].trim();
|
||||
// Tag di chiusura: "<TABLE>" senza contenuto
|
||||
if (/^<TABLE>\s*$/i.test(rowLine)) { i++; break; }
|
||||
if (/^\/\/TABLE\s*$/i.test(rowLine)) { i++; break; }
|
||||
// Fine implicita: riga vuota o riga senza virgola
|
||||
if (!rowLine || !rowLine.includes(',')) break;
|
||||
rows.push(rowLine.split(',').map(c => c.trim()));
|
||||
|
|
|
|||
|
|
@ -104,88 +104,93 @@ describe('normalizeMarkdownSymbols — blocchi codice protetti', () => {
|
|||
// =============================================================================
|
||||
|
||||
describe('expandKeywords — titoli', () => {
|
||||
expect(expand('<H1> Titolo')).toBe('# Titolo');
|
||||
expect(expand('<H2> Sezione')).toBe('## Sezione');
|
||||
expect(expand('<H3> Sub')).toBe('### Sub');
|
||||
expect(expand('<H4> Piccolo')).toBe('#### Piccolo');
|
||||
expect(expand('//H1 Titolo')).toBe('# Titolo');
|
||||
expect(expand('//H2 Sezione')).toBe('## Sezione');
|
||||
expect(expand('//H3 Sub')).toBe('### Sub');
|
||||
expect(expand('//H4 Piccolo')).toBe('#### Piccolo');
|
||||
});
|
||||
|
||||
describe('expandKeywords — inline style', () => {
|
||||
expect(expand('<B> parola')).toBe('**parola**');
|
||||
expect(expand('<I> corsivo')).toBe('*corsivo*');
|
||||
expect(expand('<BI> entrambi')).toBe('***entrambi***');
|
||||
expect(expand('<S> barrato')).toBe('~~barrato~~');
|
||||
expect(expand('<HL> evidenziato')).toBe('==evidenziato==');
|
||||
expect(expand('<CODE> var x')).toBe('`var x`');
|
||||
expect(expand('//B parola')).toBe('**parola**');
|
||||
expect(expand('//I corsivo')).toBe('*corsivo*');
|
||||
expect(expand('//BI entrambi')).toBe('***entrambi***');
|
||||
expect(expand('//S barrato')).toBe('~~barrato~~');
|
||||
expect(expand('//HL evidenziato')).toBe('==evidenziato==');
|
||||
expect(expand('//CODE var x')).toBe('`var x`');
|
||||
});
|
||||
|
||||
describe('expandKeywords — liste', () => {
|
||||
expect(expand('<LIST> a, b, c')).toBe('- a\n- b\n- c');
|
||||
expect(expand('<NUMLIST> a, b, c')).toBe('1. a\n2. b\n3. c');
|
||||
expect(expand('<CHECK> task1, task2')).toBe('- [ ] task1\n- [ ] task2');
|
||||
expect(expand('//LIST a, b, c')).toBe('- a\n- b\n- c');
|
||||
expect(expand('//NUMLIST a, b, c')).toBe('1. a\n2. b\n3. c');
|
||||
expect(expand('//CHECK task1, task2')).toBe('- [ ] task1\n- [ ] task2');
|
||||
});
|
||||
|
||||
describe('expandKeywords — tabella', () => {
|
||||
expect(expand('<TABLE> A, B, C')).toContain('| A | B | C |');
|
||||
expect(expand('<TABLE> A, B, C')).toContain('|---|---|---|');
|
||||
expect(expand('//TABLE A, B, C')).toContain('| A | B | C |');
|
||||
expect(expand('//TABLE A, B, C')).toContain('|---|---|---|');
|
||||
// Tabella con righe dati e tag di chiusura
|
||||
const tableInput = '//TABLE Col1, Col2, Col3\nval1, val2, val3\nval4, val5, val6\n//TABLE';
|
||||
const tableOut = expand(tableInput);
|
||||
expect(tableOut).toContain('| Col1 | Col2 | Col3 |');
|
||||
expect(tableOut).toContain('| val1 | val2 | val3 |');
|
||||
expect(tableOut).toContain('| val4 | val5 | val6 |');
|
||||
});
|
||||
|
||||
describe('expandKeywords — callout', () => {
|
||||
expect(expand('<NOTE> testo')).toBe('> [!NOTE]\n> testo');
|
||||
expect(expand('<WARN> testo')).toBe('> [!WARNING]\n> testo');
|
||||
expect(expand('<TIP> testo')).toBe('> [!TIP]\n> testo');
|
||||
expect(expand('<INFO> testo')).toBe('> [!INFO]\n> testo');
|
||||
expect(expand('<ERROR> testo')).toBe('> [!ERROR]\n> testo');
|
||||
expect(expand('<IMPORTANT> testo')).toBe('> [!IMPORTANT]\n> testo');
|
||||
expect(expand('<QUOTE> testo')).toBe('> testo');
|
||||
expect(expand('//NOTE testo')).toBe('> [!NOTE]\n> testo');
|
||||
expect(expand('//WARN testo')).toBe('> [!WARNING]\n> testo');
|
||||
expect(expand('//TIP testo')).toBe('> [!TIP]\n> testo');
|
||||
expect(expand('//INFO testo')).toBe('> [!INFO]\n> testo');
|
||||
expect(expand('//ERROR testo')).toBe('> [!ERROR]\n> testo');
|
||||
expect(expand('//IMPORTANT testo')).toBe('> [!IMPORTANT]\n> testo');
|
||||
expect(expand('//QUOTE testo')).toBe('> testo');
|
||||
});
|
||||
|
||||
describe('expandKeywords — link e immagini', () => {
|
||||
expect(expand('<LINK> Google, https://google.com')).toBe('[Google](https://google.com)');
|
||||
expect(expand('<IMG> logo, https://example.com/img.png')).toBe('');
|
||||
expect(expand('//LINK Google, https://google.com')).toBe('[Google](https://google.com)');
|
||||
expect(expand('//IMG logo, https://example.com/img.png')).toBe('');
|
||||
});
|
||||
|
||||
describe('expandKeywords — separatori', () => {
|
||||
expect(expand('<HR>')).toBe('---');
|
||||
expect(expand('<SEP>')).toBe('---');
|
||||
expect(expand('//HR')).toBe('---');
|
||||
expect(expand('//SEP')).toBe('---');
|
||||
});
|
||||
|
||||
describe('expandKeywords — footnote', () => {
|
||||
expect(expand('<FN> questa è una nota')).toBe('[^1]: questa è una nota');
|
||||
expect(expand('//FN questa è una nota')).toBe('[^1]: questa è una nota');
|
||||
// Due footnote consecutive: numeri 1 e 2
|
||||
expect(expand('<FN> prima\n<FN> seconda')).toBe('[^1]: prima\n[^2]: seconda');
|
||||
expect(expand('//FN prima\n//FN seconda')).toBe('[^1]: prima\n[^2]: seconda');
|
||||
// Partenza custom
|
||||
expect(expand('<FN> nota', 5)).toBe('[^5]: nota');
|
||||
expect(expand('//FN nota', 5)).toBe('[^5]: nota');
|
||||
});
|
||||
|
||||
describe('expandKeywords — math', () => {
|
||||
expect(expand('<MATH> E=mc^2')).toBe('$E=mc^2$');
|
||||
expect(expand('//MATH E=mc^2')).toBe('$E=mc^2$');
|
||||
});
|
||||
|
||||
describe('expandKeywords — tag e date/ora', () => {
|
||||
expect(expand('<TAG> progetto')).toBe('#progetto');
|
||||
expect(expand('<TAG> due parole')).toBe('#due_parole');
|
||||
// <DATE>, <TIME>, <DATETIME> usano la data corrente: verifichiamo solo il formato
|
||||
const dateOut = expand('<DATE>');
|
||||
expect(expand('//TAG progetto')).toBe('#progetto');
|
||||
expect(expand('//TAG due parole')).toBe('#due_parole');
|
||||
// //DATE, //TIME, //DATETIME usano la data corrente: verifichiamo solo il formato
|
||||
const dateOut = expand('//DATE');
|
||||
expect(typeof dateOut === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateOut) ? 'ok' : 'fail').toBe('ok');
|
||||
});
|
||||
|
||||
describe('expandKeywords — alias e case-insensitive', () => {
|
||||
expect(expand('<bold> testo')).toBe('**testo**'); // alias BOLD = B
|
||||
expect(expand('<BOLD> testo')).toBe('**testo**');
|
||||
expect(expand('<strike> testo')).toBe('~~testo~~'); // alias STRIKE = S
|
||||
expect(expand('<hr>')).toBe('---'); // lowercase
|
||||
expect(expand('<Table> A, B')).toContain('| A | B |'); // mixed case
|
||||
expect(expand('//bold testo')).toBe('**testo**'); // alias BOLD = B
|
||||
expect(expand('//BOLD testo')).toBe('**testo**');
|
||||
expect(expand('//strike testo')).toBe('~~testo~~'); // alias STRIKE = S
|
||||
expect(expand('//hr')).toBe('---'); // lowercase
|
||||
expect(expand('//Table A, B')).toContain('| A | B |'); // mixed case
|
||||
});
|
||||
|
||||
describe('expandKeywords — colon opzionale dopo >', () => {
|
||||
expect(expand('<B>testo')).toBe('**testo**'); // nessun separatore
|
||||
expect(expand('<H1>Titolo')).toBe('# Titolo'); // nessun separatore
|
||||
expect(expand('<B>: testo')).toBe('**testo**'); // con colon
|
||||
describe('expandKeywords — colon opzionale', () => {
|
||||
expect(expand('//B: testo')).toBe('**testo**'); // con colon
|
||||
expect(expand('//H1: Titolo')).toBe('# Titolo'); // con colon
|
||||
});
|
||||
|
||||
describe('expandKeywords — CODEBLOCK multi-riga', () => {
|
||||
const input = '<CODEBLOCK js>\nconsole.log(\'ciao\')\nconst x = 1\n';
|
||||
const input = '//CODEBLOCK js\nconsole.log(\'ciao\')\nconst x = 1\n';
|
||||
const out = expand(input);
|
||||
expect(out).toContain('```js');
|
||||
expect(out).toContain('console.log(\'ciao\')');
|
||||
|
|
@ -193,7 +198,7 @@ describe('expandKeywords — CODEBLOCK multi-riga', () => {
|
|||
});
|
||||
|
||||
describe('expandKeywords — indent', () => {
|
||||
expect(expand('<INDENT> testo')).toBe(' testo');
|
||||
expect(expand('//INDENT testo')).toBe(' testo');
|
||||
});
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -201,10 +206,16 @@ describe('expandKeywords — indent', () => {
|
|||
// =============================================================================
|
||||
|
||||
describe('pipeline completa', () => {
|
||||
expect(parse('#Ciao\n<LIST> a, b')).toBe('# Ciao\n- a\n- b');
|
||||
expect(parse('##sezione\n<B> parola chiave')).toBe('## Sezione\n**parola chiave**');
|
||||
expect(parse('#Ciao\n//LIST a, b')).toBe('# Ciao\n- a\n- b');
|
||||
expect(parse('##sezione\n//B parola chiave')).toBe('## Sezione\n**parola chiave**');
|
||||
// Il blocco codice non viene toccato dalla normalizzazione
|
||||
expect(parse('```\n#non toccare\n```')).toBe('```\n#non toccare\n```');
|
||||
// Tabella con righe dati attraverso la pipeline completa
|
||||
const tableInput = '//TABLE Col1, Col2, Col3\nval1, val2, val3\nval4, val5, val6\n//TABLE';
|
||||
const tableOut = parse(tableInput);
|
||||
expect(tableOut).toContain('| Col1 | Col2 | Col3 |');
|
||||
expect(tableOut).toContain('| val1 | val2 | val3 |');
|
||||
expect(tableOut).toContain('| val4 | val5 | val6 |');
|
||||
});
|
||||
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -216,45 +216,45 @@ export class HandwritingSettingTab extends PluginSettingTab {
|
|||
cls: 'hwm_keyword-summary',
|
||||
});
|
||||
details.createEl('p', {
|
||||
text: 'Scrivi queste keyword nel disegno per generare la struttura markdown corrispondente. Tutte sono case-insensitive (<h1> = <H1>). Il contenuto segue direttamente dopo >.',
|
||||
text: 'Scrivi queste keyword nel disegno per generare la struttura markdown corrispondente. Tutte sono case-insensitive (//h1 = //H1). Il contenuto segue dopo la keyword separato da uno spazio.',
|
||||
cls: 'setting-item-description',
|
||||
});
|
||||
|
||||
// Tabella keyword: [nome, sintassi, output]
|
||||
const KEYWORDS: [string, string, string][] = [
|
||||
['<H1>', '<H1> Titolo', '# Titolo'],
|
||||
['<H2>', '<H2> Titolo', '## Titolo'],
|
||||
['<H3>', '<H3> Titolo', '### Titolo'],
|
||||
['<H4>', '<H4> Titolo', '#### Titolo'],
|
||||
['<B> / <BOLD>', '<B> testo', '**testo**'],
|
||||
['<I>', '<I> testo', '*testo*'],
|
||||
['<BI>', '<BI> testo', '***testo***'],
|
||||
['<S> / <STRIKE>', '<S> testo', '~~testo~~'],
|
||||
['<HL>', '<HL> testo', '==testo=='],
|
||||
['<CODE>', '<CODE> testo', '`testo`'],
|
||||
['<CODEBLOCK>', '<CODEBLOCK js>', '```js\n...\n```'],
|
||||
['<LIST>', '<LIST> a, b, c', '- a\n- b\n- c'],
|
||||
['<NUMLIST>', '<NUMLIST> a, b, c', '1. a\n2. b\n3. c'],
|
||||
['<CHECK>', '<CHECK> a, b, c', '- [ ] a\n- [ ] b\n- [ ] c'],
|
||||
['<TABLE>', '<TABLE> Col1, Col2', '| Col1 | Col2 |\n|---|---|\n| ... |'],
|
||||
['<NOTE>', '<NOTE> testo', '> [!NOTE]\n> testo'],
|
||||
['<WARN>', '<WARN> testo', '> [!WARNING]\n> testo'],
|
||||
['<TIP>', '<TIP> testo', '> [!TIP]\n> testo'],
|
||||
['<INFO>', '<INFO> testo', '> [!INFO]\n> testo'],
|
||||
['<ERROR>', '<ERROR> testo', '> [!ERROR]\n> testo'],
|
||||
['<IMPORTANT>', '<IMPORTANT> testo', '> [!IMPORTANT]\n> testo'],
|
||||
['<QUOTE>', '<QUOTE> testo', '> testo'],
|
||||
['<LINK>', '<LINK> testo, url', '[testo](url)'],
|
||||
['<IMG>', '<IMG> alt, url', ''],
|
||||
['<HR> / <SEP>', '<HR>', '---'],
|
||||
['<FN>', '<FN> nota a piè pagina', '[^1]: nota a piè pagina'],
|
||||
['<MATH>', '<MATH> formula', '$formula$'],
|
||||
['<MATHBLOCK>', '<MATHBLOCK>', '$$\n...\n$$'],
|
||||
['<TAG>', '<TAG> parola', '#parola'],
|
||||
['<DATE>', '<DATE>', 'YYYY-MM-DD'],
|
||||
['<TIME>', '<TIME>', 'HH:mm'],
|
||||
['<DATETIME>', '<DATETIME>', 'YYYY-MM-DD HH:mm'],
|
||||
['<INDENT>', '<INDENT> testo', ' testo'],
|
||||
['//H1', '//H1 Titolo', '# Titolo'],
|
||||
['//H2', '//H2 Titolo', '## Titolo'],
|
||||
['//H3', '//H3 Titolo', '### Titolo'],
|
||||
['//H4', '//H4 Titolo', '#### Titolo'],
|
||||
['//B / //BOLD', '//B testo', '**testo**'],
|
||||
['//I', '//I testo', '*testo*'],
|
||||
['//BI', '//BI testo', '***testo***'],
|
||||
['//S / //STRIKE', '//S testo', '~~testo~~'],
|
||||
['//HL', '//HL testo', '==testo=='],
|
||||
['//CODE', '//CODE testo', '`testo`'],
|
||||
['//CODEBLOCK', '//CODEBLOCK js', '```js\n...\n```'],
|
||||
['//LIST', '//LIST a, b, c', '- a\n- b\n- c'],
|
||||
['//NUMLIST', '//NUMLIST a, b, c', '1. a\n2. b\n3. c'],
|
||||
['//CHECK', '//CHECK a, b, c', '- [ ] a\n- [ ] b\n- [ ] c'],
|
||||
['//TABLE', '//TABLE Col1, Col2', '| Col1 | Col2 |\n|---|---|\n| ... |'],
|
||||
['//NOTE', '//NOTE testo', '> [!NOTE]\n> testo'],
|
||||
['//WARN', '//WARN testo', '> [!WARNING]\n> testo'],
|
||||
['//TIP', '//TIP testo', '> [!TIP]\n> testo'],
|
||||
['//INFO', '//INFO testo', '> [!INFO]\n> testo'],
|
||||
['//ERROR', '//ERROR testo', '> [!ERROR]\n> testo'],
|
||||
['//IMPORTANT', '//IMPORTANT testo', '> [!IMPORTANT]\n> testo'],
|
||||
['//QUOTE', '//QUOTE testo', '> testo'],
|
||||
['//LINK', '//LINK testo, url', '[testo](url)'],
|
||||
['//IMG', '//IMG alt, url', ''],
|
||||
['//HR / //SEP', '//HR', '---'],
|
||||
['//FN', '//FN nota a piè pagina', '[^1]: nota a piè pagina'],
|
||||
['//MATH', '//MATH formula', '$formula$'],
|
||||
['//MATHBLOCK', '//MATHBLOCK', '$$\n...\n$$'],
|
||||
['//TAG', '//TAG parola', '#parola'],
|
||||
['//DATE', '//DATE', 'YYYY-MM-DD'],
|
||||
['//TIME', '//TIME', 'HH:mm'],
|
||||
['//DATETIME', '//DATETIME', 'YYYY-MM-DD HH:mm'],
|
||||
['//INDENT', '//INDENT testo', ' testo'],
|
||||
];
|
||||
|
||||
const table = details.createEl('table', { cls: 'hwm_keyword-table' });
|
||||
|
|
|
|||
Loading…
Reference in a new issue