Vai al contenuto

Markup testuale

Questo documento definisce la sintassi e la semantica del markup testuale in neumaRk: regole comuni di formattazione applicabili a tutti i container testuali del linguaggio (marker, end-decorator, comment-label, annotation note, label di sezione, prosa di forma).

L'obiettivo è fornire un sistema unificato e ortogonale in cui un primo asse decide la cornice grafica (container), un secondo asse decide lo stile di default (costrutto ospitante), e un terzo asse — opzionale — consente all'utente di applicare markup esplicito.


1. Tre assi ortogonali

Il rendering del testo in neumaRk è funzione di tre assi indipendenti:

  1. Container — il testo sta fra virgolette; la cornice attorno è facoltativa: "…" (nessuna), ["…"] (riquadro, abbreviabile in […]), ("…") (tonda). Vedi §2.1.
  2. Stile di default — determinato dal costrutto ospitante (marker, comment-label, annotation, prosa, ecc.).
  3. Markup utente — opzionale, definito tramite un sottoinsieme di Markdown applicato dentro il container.

Nessuno dei tre assi vincola gli altri. Lo stesso testo può essere espresso con qualunque cornice, qualunque default semantico, con o senza markup esplicito.

Eccezione: marker M). Nei marker della riga M) (sezioni e annotazioni, vedi neumaRk_markers.md §3.1) le quadre e le virgolette portano semantica strutturale, non una cornice: […] = sezione (target di PLAY/FORM, delimita scope collassabili), "…" = annotazione (testo descrittivo, non strutturale). Il modello a cornice di §2.1 non si applica in M). Una sezione scritta ["NOME"] vale [NOME]: le virgolette delimitano il nome e non ne fanno parte.


2. Container testuali

2.1 Forme: il modello a cornice

Un container testuale è un testo fra virgolette "…" con una cornice facoltativa attorno:

Forma Cornice Note
"testo" nessuna
["testo"] riquadro forma di riferimento
[testo] riquadro abbreviazione di ["testo"]: stesso risultato
("testo") tonda una coppia di parentesi attorno al testo

Le virgolette di ["…"] e ("…") delimitano il testo e non compaiono mai nella resa: ["testo"] e [testo] producono lo stesso riquadro.

Il modello vale per tutti i container di §2.2 che lo indicano: label d'accordo (di accordo, di gruppo, di riga), testi di A) (sulla nota, alla stanghetta, sopra C)), testi di D) (sulla nota, alla stanghetta), annotazioni di nota ed end-decorator testuali. Restano fuori, con la loro sintassi: sezione e annotazione di M) (vedi l'eccezione in §1), label di onda e di staffa d'analisi (~"…", {"…"), label dei box PLAY)/FORM).

Dentro la cornice il testo è un container normale: markup (§3), a-capo ; (§3bis, una sola cornice attorno all'intera pila), link (§3quater), escape \" (§4).

Riconoscimento della tonda. È una cornice solo la forma esatta ("…"): ( seguita subito da ", e la " di chiusura seguita subito da ). Ogni altra ( conserva il significato del suo contesto: legatura in A) (("dolce" … ) è una legatura che parte con un testo), gruppo di accordi opzionali o durata in C). In D) le parentesi non hanno altro significato: una ( o ) fuori da ("…") è ignorata e segnalata con W177.

2.2 Dove si applica il markup

Il markup definito in questo documento si applica a tutti i container testuali del linguaggio:

Costrutto Container ammessi Riferimento
Sezione M) […] (strutturale) neumaRk_markers.md §3.1
Annotazione M) "…" neumaRk_markers.md §3.1
End-decorator testuale modello a cornice neumaRk_flow_and_repeats.md §4.3
Comment-label chord / group / row modello a cornice neumaRk_chords.md §8
Annotation note modello a cornice neumaRk_notes_and_durations.md §8
Annotation dinamiche D) modello a cornice neumaRk_dynamics.md §3.4
Testo A) (nota, stanghetta, sopra C)) modello a cornice neumaRk_articulations.md §13.1
Label articolazione A) (onda, staffa) "…" neumaRk_articulations.md §10.2/§10.3
Top/bottom label box di sezione "…" neumaRk_play_and_form.md §3.3
Prosa libera in PLAY) / FORM) tutta la prosa neumaRk_play_and_form.md §5
Prosa libera in TEXT) tutta la prosa neumaRk_text_line.md §3

Il markup non si applica a:

  • valori dell'header (titolo, credits, year, style, key, meter, BPM), che sono renderizzati in modo autonomo dal sistema;
  • nomi tecnici dei marker quando referenziati in PLAY) / FORM), dove il matching è per text-equality (il markup, se presente, è applicato in display ma stripped per il matching);
  • volta begin (|[1.]), che è un container simil-box predeterminato e non ammette markup interno.

3. Sintassi del markup

Il markup neumaRk è un sottoinsieme di Markdown, scelto per essere deterministico e single-line.

3.1 Dimensione del testo

I 3 prefissi #/##/### selezionano una dimensione relativa che dipende dal ruolo size del costrutto (vedi §5):

  • role reduced (default per: comment-label chord/group/row, annotation note, annotation D), label PLAY/FORM, annotation marker "…"): il default è la dimensione media; ### scende al piccolo, # sale al grande.
  • role body (default per: marker M) [NAME], prosa PLAY/FORM): il default è la dimensione media; i prefissi scalano SOPRA e SOTTO.
Prefisso role reduced role body
# grande (1.33× default) grande (1.5× default)
## medio (= default, no prefix) medio (1.0× default = body)
### piccolo (0.67× default) piccolo (0.7× default)

Resa di riferimento (informativa): i fattori fra parentesi sono quelli dell'implementazione di riferimento. Normativi sono i tre gradi (grande, medio, piccolo) e il default medio.

Regole:

  • lo spazio dopo #/##/### è obbligatorio: #hashtag è letterale, # title apre lo span;
  • il prefisso compare solo all'inizio del testo del container o all'inizio di un run di prosa (in PLAY) / FORM), dopo un token strutturale o all'inizio del body);
  • lo span aperto da #/##/### si chiude al primo dei seguenti eventi: fine del container, prossimo token strutturale in PLAY) / FORM) ([…], &kw, $, @);
  • #### e oltre sono trattati come letterali;
  • ## è ammesso per esplicitare il livello size anche se ridondante col default (in entrambi i role il medio coincide col no-prefix).

3.2 Enfasi

Tre forme di emphasis, attivate da delimitatori in coppia:

Sintassi Effetto
*foo* italic
**foo** bold
***foo*** bold + italic

Regole:

  • gli span sono delimitatori chiusi: un * non chiuso è letterale (nessun render parziale);
  • l'asterisco chiudente deve essere preceduto da contenuto non vuoto;
  • gli span possono comparire in qualunque posizione del testo;
  • non è ammesso annidamento di emphasis (per esempio **foo *bar* baz** non è valido): la forma ***foo*** è atomica.

3.3 Underline

Sintassi attivata dal doppio underscore:

Sintassi Effetto
__foo__ underline

Regole:

  • come gli span di emphasis, lo span è delimitatore chiuso: un __ non chiuso è letterale;
  • il __ chiudente deve essere preceduto da contenuto non vuoto;
  • lo span può comparire in qualunque posizione del testo;
  • underscore singolo _ è letterale: _x_ non è italic alternativo (NRK non adotta la convenzione Markdown di _ come alias di *);
  • ___foo___ (tre o più underscore di apertura/chiusura) è trattato come letterale, analogamente a #### per i prefissi di dimensione.

Underline non è una forma di emphasis: è un asse ortogonale a bold/italic. La regola "non annidamento di emphasis" di §3.2 non si applica all'underline.

3.4 Combinazione

Più span di emphasis possono coesistere nello stesso testo, purché disgiunti:

*foo* and **bar**            ✓  italic + bold disgiunti
*foo and **bar***            ✗  annidamento non ammesso
***foo*** plain ***bar***    ✓  due span bold-italic disgiunti

L'underline è un asse ortogonale: può coesistere con bold e italic nello stesso span:

**__foo__**                  ✓  bold + underline
*__foo__*                    ✓  italic + underline
***__foo__***                ✓  bold + italic + underline
__**foo**__                  ✓  ordine delimitatori libero
__*foo* and **bar**__        ✓  underline su span con emphasis disgiunti interni

Uno span di emphasis o underline può coesistere con un prefisso di dimensione: il prefisso vale per l'intero span del testo, gli altri delimitatori modificano solo la porzione interna:

# Title with **bold** and __underline__ words

3bis. A-capo ; (testo multi-riga)

Dentro ogni container testuale (§2), in entrambe le forme "…" e […] e con qualunque cornice (["…"], ("…")), un ; non escapato è un a-capo: il contenuto si compone di più righe. Per un ; letterale si usa l'escape \; (§4).

c4"ten.;trp."          → 2 righe: "ten." / "trp."
c4("in 3\;4")          → 1 riga:  "in 3;4"  (';' letterale)
c4"r1;r2;r3"           → 3 righe
M) | "poco;a poco" |   → 2 righe: "poco" / "a poco"
C) | C7"alt;b9" |      → 2 righe: "alt" / "b9"

La regola vale allo stesso modo per "…" e per […]: le due forme differiscono solo per il riquadro (§2.1), quindi passare da C7"a;b" a C7[a;b] non cambia l'a-capo.

Perché ;. Un container occupa una sola riga del sorgente (§6.2): l'a-capo del file non è disponibile, e serve un separatore. Il ; è inerte dentro il container (il parser ne conserva l'intero contenuto), raro come carattere letterale in un'etichetta e senza significato altrove in neumaRk. Un ; dentro l'indirizzo di un link [testo=>url] è parte dell'indirizzo e non va a capo (§3quater).

Esclusioni. Non sono container d'a-capo, e il ; vi resta letterale:

  • il nome di sezione M) [NOME]: è il bersaglio di PLAY)/FORM) per uguaglianza di testo (stessa ragione per cui non ammette link);
  • l'etichetta di versione %%NAME "…": è il nome della variante;
  • l'etichetta di INFO): sta su una riga sola;
  • volta |[1.], valori d'header e sillabe L), che non portano markup.

Nella prosa di TEXT) e di INFO) il ; è un carattere come gli altri. La prosa di questi blocchi non è un container: occupa più righe del sorgente e va a capo sull'a-capo del sorgente, quindi non le serve un separatore. Due regole, ciascuna con la sua ragione: fra le righe del sorgente l'a-capo; dentro un container, che deve stare su una riga sola, il ;.

In PLAY)/FORM) il ; va a capo anche nella prosa. Lì l'a-capo del sorgente vale uno spazio (neumaRk_play_and_form.md §6), quindi l'unico modo di andare a capo in un punto preciso è il ;, come nei container: ogni ; non escapato chiude la riga di box e prosa (§6.3), e \; stampa un ;.

Resa multi-riga. Il primo segmento è sempre la riga in alto: si legge dall'alto in basso. La riga più vicina al rigo resta dove sarebbe la riga singola e la pila si allontana dal rigo: sopra il rigo (annotazioni di nota, di M) e di A), label della banda accordi, label di onda e staffa, end-decorator) cresce verso l'alto, e l'ultima riga resta ferma; sotto il rigo (annotazione D)) cresce verso il basso, e la prima riga resta ferma. Con una riga sola la resa non cambia. L'interlinea è la stessa ovunque (nella resa di riferimento 1,18 × la dimensione più grande fra le righe), e una riga vuota (a;;b) resta vuota. Il markup di §3 si applica per riga: ("**ten.**;trp."). Con una cornice, una sola cornice avvolge l'intera pila (non una per riga).

Ogni riga conserva l'allineamento del container: centrata dove il testo è centrato (comment-label d'accordo e di gruppo, annotazione A) su una sigla), a sinistra dove è ancorato a sinistra (annotazione M), annotazione A) sulla nota, label di riga, label a lato di C-7"…"-, label di onda e staffa {…}), a destra dove è appeso al bordo destro della misura (end-decorator, A) e D) alla stanghetta di fine misura). Un testo impilato sopra un altro (label di gruppo, annotazione A), label di riga) scavalca la pila intera di quello sotto, non solo la sua ultima riga. Una linea tratteggiata di prolungamento resta agganciata alla riga più vicina al rigo, per quota e per partenza.

Copertura della resa. Ogni container disegna il ; su più righe: annotazioni di nota e di M), D), A) (alla nota e alla stanghetta), comment-label d'accordo, di gruppo e di riga, testi sugli accordi, label di onda e staffa d'analisi, end-decorator testuali, label dei box PLAY)/FORM), voci di FOOT). Le label dei box PLAY)/FORM) vanno anche a capo per larghezza, riga per riga, e la label sotto il box cresce verso il basso (la sua riga più vicina al box è la prima).

Sorgente vs contenuto — la riga sorgente resta single-line (nessun carattere di nuova riga nel file: vedi §6.2); è il contenuto del container a essere multi-riga, diviso sui ;.


3ter. Richiamo footnote [^etichetta]

Il markup ammette il richiamo a nota a piè di pagina [^etichetta]: un piccolo segno reso in apice dentro il testo, che rimanda a una definizione del blocco globale FOOT). La grammatica completa (etichette, blocco FOOT), ripetizione multi-pagina, diagnostici W162–W166) è in neumaRk_footnotes.md. In sintesi:

  • [^*] [^†] [^1] = etichetta esplicita (segno = simbolo/numero); [^] = auto-numerato.
  • Riconosciuto come richiamo solo dentro "…" per i container note/accordi/ marker e i testi di A)/D) (dove [NAME] è strutturale), anche dentro una cornice (["…"], ("…")), non nell'abbreviazione […], dove la ] del richiamo chiuderebbe il container: c4[a[^1]] non è valido (E001), si scrive c4["a[^1]"]; nella prosa PLAY)/FORM)/TEXT) (non quotata) vale sull'intero testo. L'escape \[ resta parentesi letterale.
  • NON collide con il corsivo *…* (per questo si usa la cornice [^…]).
c4("piano[^*]")

Il markup ammette un link a materiale esterno: il video da cui è tratta una trascrizione, una voce d'enciclopedia, la pagina di un autore.

Forma Si vede Porta a
[testo=>url] testo url
[=>url] il dominio (it.wikipedia.org, senza www.) url
TEXT) Trascrizione dal [live a Montreux=>https://www.youtube.com/watch?v=abc123]
TEXT) Vedi [=>https://it.wikipedia.org/wiki/Bill_Evans]
C) | Cm7"cfr. [la fonte=>https://example.org/lp]" | F7 |

Regole:

  • il testo si separa dall'indirizzo al primo =>;
  • nel testo vale il markup di §3 ([*Montreux* **1978**=>…]); nell'indirizzo no: è letterale fino alla ]. _, __, *, #, ; e // nell'indirizzo sono caratteri dell'indirizzo — nessun sottolineato, nessun a-capo (§3bis), nessun commento;
  • una ] dentro l'indirizzo si scrive \]: è l'unico escape risolto nell'indirizzo;
  • schemi ammessi: solo http:// e https://, senza spazi (uno spazio si scrive %20). Un indirizzo con un altro schema (mailto:, ftp:…), relativo o con spazi non è un link: resta il testo, non attivabile (W175). Un link vuoto — [testo=>] o [=>] — lascia il testo, se c'è (W176);
  • \[testo=>url] è testo letterale, reso com'è scritto (§4): serve a mostrare la sintassi. Anche qui il // dell'indirizzo non apre un commento;
  • il dominio della forma breve è ricavato alla resa: il documento conserva l'indirizzo intero.

Dove vale. Stessa regola di riconoscimento del richiamo [^…] (§3ter): dentro "…" per note, accordi, testi di A)/D) e annotazioni di marker; sull'intero testo per la prosa di TEXT), PLAY) e FORM), per etichetta e corpo di INFO) e per le voci di FOOT). In PLAY)/FORM) un […] che contiene => è un link, mai un box di sezione. Il link non vale nei nomi di sezione M) [NOME], che sono il bersaglio di PLAY)/FORM) per uguaglianza di testo, né nelle sillabe L).

Resa. Il link è una proprietà del testo, non del contenuto musicale. A schermo il testo è reso come link — distinto dal sottolineato __…__ — e può essere attivato. In stampa e in PDF esce come testo normale, senza stile da link e senza collegamento.


4. Escape

Il carattere \ (backslash) precede un meta-carattere per renderlo letterale.

Token Forma escaped
* \*
_ \_
# \#
[ \[
] \]
" \"
; \;
\ \\

L'escape \_ serve quando si vuole inserire un __ letterale in un testo che dovrebbe esserne consumato dal markup (raro: i singoli _ sono già letterali by default).

Esempi:

M) | [The \*Real\* Book] |
c4"track \#3"

Un \ non seguito da un meta-carattere è letterale.

Gli escape valgono in qualunque testo che ammette markup: nei container e nella prosa. In particolare \; scrive un ; anche dove il ; è già letterale (prosa, nomi di sezione), così la stessa scrittura funziona ovunque. L'unica eccezione è l'indirizzo di un link, dove si risolve solo \] (§3quater).

Dentro un container "…" (con qualunque cornice) \" non chiude il testo:

c4"il \"Re\""          → il "Re"
C) | C("a \"tempo\"") |  → (a "tempo")

L'header (titolo, credits, style) non è testo con markup: lì " e \ sono letterali e non si escapano (neumaRk_header.md §5).


5. Stile di default per costrutto

La cornice (nessuna, riquadro, tonda) decide solo la grafica attorno al testo. Lo stile di default (size, weight, italic) è proprietà del costrutto ospitante.

Costrutto Default style
Marker M) [NAME] bold, size body (role body, vedi §3.1)
Annotation marker M) "…" plain, size media (role reduced)
End-decorator testuale plain, size body (role body)
Comment-label chord / group / row plain, size media (role reduced)
Annotation note plain, size media (role reduced)
Annotation dinamiche D) plain, size media (role reduced)
Top/bottom label box PLAY/FORM plain, size media (role reduced)
Prosa PLAY/FORM plain, size body (role body)
Prosa TEXT) plain, size body (role body)

Il role size decide come i prefissi #/##/### scalano attorno al default (vedi §3.1 tabella). In entrambi i role il default è la size media e ### scende SOTTO (piccolo); il role reduced differisce solo per quanto sale # (nella resa di riferimento 1.33× invece di 1.5×).

Il markup utente (§3) sovrascrive sempre il default. Per esempio un comment-label parte plain: chord"sub" è reso tondo, mentre chord"*sub*" accende l'italic via markup sopra quel default.


6. Regole di parsing

6.1 Disambiguazione […] e ( per ruolo

In neumaRk il delimitatore […] è condiviso fra più costrutti (polychord, volta, end-decorator, comment-label, annotation note, grace block, ecc.). La disambiguazione è posizionale e definita nelle spec dei singoli costrutti. Una volta che il parser ha identificato il ruolo del […], il contenuto è interpretato secondo le regole di questo documento.

La ( è cornice tonda solo nella forma esatta ("…") (§2.1); altrove mantiene il ruolo del suo costrutto (legatura, gruppo opzionale, durata, oggetto di contesto, play directive).

6.2 Single-line nel sorgente, multi-riga nel contenuto

I container "…", […], ["…"], ("…") occupano una sola riga sorgente: non ammettono caratteri di nuova riga nel file. Un container aperto e non chiuso nella sua misura (una ", [ o (" senza chiusura prima della stanghetta) legge come testo il resto della misura: nelle righe N), A), D) e M) il parser lo segnala con W133 (in N) le note che seguono nella misura si perdono: c4"abc d e f | conserva solo c4); nella riga accordi il token non è riconosciuto (E102).

Il contenuto però può essere multi-riga: l'a-capo si esprime col separatore ; (§3bis), non con un newline nel sorgente. Così una singola riga N) resta allineata a colonne con le altre righe del datapack anche quando l'annotazione si rende su più righe.

La prosa di PLAY) / FORM) ammette continuazione di riga (vedi documenti correlati).

6.3 Container vuoti

[] e "" sono letterali: non vengono interpretati come container.


7. Casi limite

7.1 Markup nei nomi di reference

Dentro [NAME] di reference in PLAY) / FORM), il NAME è interpretato come testo. Il markup interno è applicato in display ma rimosso prima del matching con i marker definiti:

PLAY) [**Solo**] [A]

[**Solo**] cerca un marker chiamato "Solo" e lo rende in bold se trovato. Se il NAME contiene markup non chiuso o malformato, il fallback è il matching letterale comprensivo dei caratteri di markup.

7.2 Spazi attorno ai delimitatori di emphasis e underline

A differenza di Markdown standard, neumaRk non richiede che i delimitatori (*, __) siano "tight" rispetto al contenuto: * foo * è equivalente a *foo*, __ foo __ è equivalente a __foo__. La scelta riduce errori comuni e mantiene il markup più tollerante.

7.3 Cornici diverse nello stesso documento

Nei costrutti col modello a cornice le forme si mescolano liberamente, anche sulla stessa riga. La scelta è guidata solo dalla grafica voluta.

C) | C"freely" | F[swing] | G["a tempo"] | C("rit.") |

8. Riassunto

Asse Valori Decide
Container "…" / ["…"] ([…]) / ("…") nessuna cornice / riquadro / tonda
Costrutto marker, label, annotation, … size + weight + italic di default
Markup utente *…*, **…**, __…__, # …, […=>url], ecc. override esplicito

I tre assi sono ortogonali. Nessuno dei tre vincola gli altri.


9. Diagnostici

Codice Condizione
E102 Container non chiuso su una riga accordi (§6.2)
W133 Container non chiuso nella misura su N), A), D), M): il resto della misura è testo (§6.2)
W175 Link con indirizzo non http/https o malformato: resta il testo (§3quater)
W176 Link vuoto [testo=>] / [=>] (§3quater)
W177 In D), parentesi fuori da una cornice ("…"): ignorate (§2.1)

I diagnostici dei richiami [^…] (W162–W166) sono in neumaRk_footnotes.md.


Questo documento definisce il sistema di formattazione testuale unificato di neumaRk, applicabile a tutti i container testuali del linguaggio.