CommonMark: una specifica formale per il ribasso

Pubblicato: 2022-03-10
Riepilogo rapido ↬ Markdown è un potente linguaggio di markup che consente la modifica e la formattazione in formato di testo normale che può quindi essere analizzato e visualizzato come HTML. Ha una sintassi dichiarativa che è potente e facile da imparare per persone tecniche e non. Tuttavia, a causa delle conseguenti ambiguità nella sua specifica originale, ci sono stati un certo numero di versioni distinte (o versioni personalizzate) che mirano a cancellare tali ambiguità e ad estendere il supporto della sintassi originale. Ciò ha portato a una forte divergenza da ciò che può essere analizzato e ciò che è reso. CommonMark mira a fornire una specifica standardizzata di Markdown che rifletta il suo utilizzo nel mondo reale.

CommonMark è una versione razionalizzata della sintassi Markdown con una specifica il cui obiettivo è rimuovere le ambiguità e l'incoerenza che circondano la specifica Markdown originale. Offre una specifica standardizzata che definisce la sintassi comune del linguaggio insieme a una suite di test completi per convalidare le implementazioni di Markdown rispetto a questa specifica.

GitHub utilizza Markdown come linguaggio di markup per i suoi contenuti utente.

"CommonMark è un progetto ambizioso per specificare formalmente la sintassi Markdown utilizzata da molti siti Web su Internet in un modo che rifletta il suo utilizzo nel mondo reale [...] Consente alle persone di continuare a utilizzare Markdown come hanno sempre fatto offrendo agli sviluppatori una specifica completa e implementazioni di riferimento per interoperare e visualizzare Markdown in modo coerente tra le piattaforme.

— "Una specifica formale per il markdown aromatizzato a GitHub", The GitHub Blog

Nel 2012, GitHub ha creato la propria versione di Markdown — GitHub Flavored Markdown (GFM) — per combattere la mancanza di standardizzazione Markdown ed estendere la sintassi alle sue esigenze. GFM è stato costruito su Sundown, un parser creato appositamente da GitHub per risolvere alcune delle carenze dei parser Markdown esistenti all'epoca. Cinque anni dopo, nel 2017, ha annunciato il ritiro di Sundown a favore della libreria di analisi e rendering CommonMark, cmark in A formal spec for GitHub Flavored Markdown.

Nella sezione Domande comuni di Markdown e Visual Studio Code, è documentato che Markdown in VSCode ha come target la specifica CommonMark Markdown usando la libreria markdown-it, che di per sé segue la specifica CommonMark.

CommonMark è stato ampiamente adottato e implementato (vedi l'elenco delle implementazioni CommonMark) per l'uso in diversi linguaggi come C (es. cmark), C# (es. CommonMark.NET), JavaScript (es. markdown-it) ecc. Questa è una buona notizia per gli sviluppatori e gli autori si stanno gradualmente spostando verso una nuova frontiera in cui sono stati in grado di utilizzare Markdown con una sintassi coerente e una specifica standardizzata.

Una breve nota sui parser di markdown

I parser Markdown sono al centro della conversione del testo Markdown in HTML, direttamente o indirettamente.

Parser come cmark e commonmark.js non convertono direttamente Markdown in HTML, ma lo convertono in un albero di sintassi astratto (AST) e quindi rendono l'AST come HTML, rendendo il processo più granulare e soggetto a manipolazioni. Tra l'analisi - in AST - e il rendering - in HTML, ad esempio, il testo Markdown potrebbe essere esteso.

Altro dopo il salto! Continua a leggere sotto ↓

Supporto per la sintassi Markdown di CommonMark

I progetti o le piattaforme che implementano già la specifica CommonMark come linea di base del loro aspetto specifico sono spesso superset del sottoinsieme rigoroso della specifica CommonMark Markdown. Per la maggior parte, CommonMark ha mitigato molte ambiguità costruendo una specifica su cui basarsi. GFM è un ottimo esempio, mentre supporta ogni sintassi CommonMark, lo estende anche per adattarlo al suo utilizzo.

Il supporto della sintassi di CommonMark può essere inizialmente limitato, ad esempio, non ha supporto per questa sintassi della tabella, ma è importante sapere che questo è in base alla progettazione poiché questo commento in questo thread di conversazione rivela: che la sintassi supportata è rigorosa e dice essere la sintassi principale del linguaggio stesso, la stessa specificata dal suo creatore, John Gruber in Markdown: Syntax.

Al momento della scrittura, ecco una serie di sintassi supportate:

  1. Paragrafi e interruzioni di riga,
  2. intestazioni,
  3. Enfasi e forte enfasi,
  4. Regole orizzontali,
  5. liste,
  6. Collegamenti,
  7. Immagini,
  8. citazioni in blocco,
  9. Codice,
  10. Blocchi di codice.

Per seguire gli esempi, si consiglia di utilizzare l'editor commonmark.js dingus per provare la sintassi e ottenere l'anteprima renderizzata, l'HTML generato e l'AST.

Paragrafi e interruzioni di riga

In Markdown, i paragrafi sono righe continue di testo separate da almeno una riga vuota.

Le seguenti regole definiscono un paragrafo:

  1. I paragrafi Markdown vengono visualizzati in HTML come l'elemento Paragraph, <p>.
  2. I diversi paragrafi sono separati da una o più righe vuote tra di loro.
  3. Per un'interruzione di riga, un paragrafo deve essere post-corretto con due spazi vuoti (o un equivalente di tabulazione) o una barra rovesciata ( \ ).
Sintassi HTML renderizzato
Questa è una riga di testo <p>Questa è una riga di testo</p>
Questa è una riga di testo
E un'altra riga di testo
E un altro ma il
stesso paragrafo
<p>Questa è una riga di testo
E un'altra riga di testo
E un altro ma il
stesso paragrafo</p>
Questo è un paragrafo

E un altro paragrafo

E un altro
<p>Questo è un paragrafo</p>
<p>E un altro paragrafo</p>
<p>E un altro</p>
Due spazi dopo una riga di testo
O una barra rovesciata post-fissata\
Entrambi significano un'interruzione di riga
<p>Due spazi dopo una riga di testo<br /><br>O una barra rovesciata post-fissata<br /><br>Entrambi significano un'interruzione di riga</p>
  • Tutorial interattivo per conoscere i paragrafi.
  • Dingus permalink controlla l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni sui paragrafi.

Intestazioni

Le intestazioni in Markdown rappresentano uno degli elementi di intestazione HTML. Esistono due modi per definire le intestazioni:

  1. Intestazione ATX.
  2. Intestazione del testo.

Le seguenti regole definiscono le intestazioni ATX:

  1. Sono supportati il ​​livello di intestazione 1 ( h1 ), fino al livello di intestazione 6, ( h6 ).
  2. Le intestazioni in stile Atx sono precedute dal simbolo hash ( # ).
  3. È necessario che ci sia almeno uno spazio vuoto che separi il testo e il simbolo hash ( # ).
  4. Il conteggio degli hash è equivalente al numero cardinale dell'intestazione. Un hash è h1 , due hash, h2 , 6 hash, h6 .
  5. È anche possibile aggiungere un numero arbitrario di simboli hash alle intestazioni, sebbene ciò non causi alcun effetto (ad esempio # Heading 1 # )
Sintassi HTML renderizzato
# Titolo 1 <h1>Titolo 1</h1>
## Titolo 2 <h2>Titolo 2</h2>
### Titolo 3 <h3>Titolo 3</h3>
#### Titolo 4 <h4>Titolo 4</h4>
##### Titolo 5 <h5>Titolo 5</h5>
###### Titolo 6 <h6>Titolo 6</h6>
## Intestazione 2 ## <h2>Titolo 2</h2>

Le seguenti regole definiscono le intestazioni Setext:

  1. Sono supportati solo il livello di intestazione 1 (h1) e il livello di intestazione 2 (h2).
  2. La definizione in stile Setext viene eseguita rispettivamente con i simboli di uguale (=) e trattino.
  3. Con Setext è richiesto almeno un simbolo uguale o trattino.
Sintassi HTML renderizzato
Titolo 1
=
<h1>Titolo 1</h1>
Titolo 2
-
<h2>Titolo 2</h2>
  • Tutorial interattivo per conoscere le intestazioni.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni sulle intestazioni ATX.
  • Ulteriori informazioni sulle intestazioni di Setext.

Enfasi e forte enfasi

L'enfasi in Markdown può essere in corsivo o in grassetto (enfasi forte).

Le seguenti regole definiscono l'enfasi:

  1. L'enfasi ordinaria e quella forte sono visualizzate in HTML rispettivamente come l'elemento Emphasis, <em> e Strong, <strong>.
  2. Un testo delimitato da un singolo asterisco ( * ) o da un trattino basso ( _ ) sarà un enfasi.
  3. Un testo delimitato da doppi asterischi o trattino basso sarà un forte enfasi.
  4. I simboli di delimitazione (asterischi o trattino basso) devono corrispondere.
  5. Non deve esserci spazio tra i simboli e il testo allegato.
Sintassi HTML renderizzato
_Italic_ <em>Corsivo</em>
*Italic* <em>Corsivo</em>
__Bold__ <strong>Grassetto</strong>
**Bold** <strong>Grassetto</strong>
  • Tutorial interattivo per conoscere l'enfasi.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni su Enfasi e forte enfasi.

Regola orizzontale

Una regola orizzontale, <hr/>, viene creata con tre o più asterischi ( * ), trattini ( - ) o trattini bassi ( _ ), su una nuova riga. I simboli sono separati da un numero qualsiasi di spazi, o per niente.

Sintassi HTML renderizzato
*** <h />
* * * <h />
--- <h />
- - - <h />
___ <h />
_ _ _ <h />
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Scopri di più sulle pause tematiche.

Elenchi

Gli elenchi in Markdown sono un elenco puntato (non ordinato) o un elenco ordinato.

Le seguenti regole definiscono un elenco:

  1. Gli elenchi puntati vengono visualizzati in HTML come elemento dell'elenco non ordinato, <ul>.
  2. Gli elenchi ordinati vengono visualizzati in HTML come elemento dell'elenco ordinato, <ol>.
  3. Gli elenchi puntati utilizzano asterischi, più e trattini come indicatori.
  4. Gli elenchi ordinati utilizzano numeri seguiti da punti o parentesi di chiusura.
  5. Gli indicatori devono essere coerenti (è necessario utilizzare solo l'indicatore con cui si inizia per il resto della definizione degli elementi dell'elenco).
Sintassi HTML renderizzato
* uno
* Due
* tre
<ul>
<li>uno</li>
<li>due</li>
<li>tre</li>
</ul>
+ uno
+ due
+ tre
<ul>
<li>uno</li>
<li>due</li>
<li>tre</li>
</ul>
- uno
- Due
- tre
<ul>
<li>uno</li>
<li>due</li>
<li>tre</li>
</ul>
- uno
- Due
+ tre
<ul>
<li>uno</li>
<li>due</li>
</ul>
<ul>
<li>tre</li>
</ul>
1 uno
2. due
3. tre
<ol>
<li>uno</li>
<li>due</li>
<li>tre</li>
</ol>
3. tre
4. quattro
5. cinque
<ol inizio="3">
<li>tre</li>
<li>quattro</li>
<li>cinque</li>
</ol>
1 uno
2. due
3. tre
<ol>
<li>uno</li>
<li>due</li>
<li>tre</li>
</ol>
  • Tutorial interattivo per conoscere gli elenchi.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni sugli elementi degli elenchi.

Collegamenti

I collegamenti sono supportati con il formato inline e di riferimento .

Le seguenti regole definiscono un collegamento:

  1. I collegamenti vengono visualizzati come elemento HTML Anchor, <a>.
  2. Il formato inline ha la sintassi: [value](URL "optional-title") senza spazio tra parentesi.
  3. Il formato di riferimento ha la sintassi: [value][id] per il riferimento e [id]: href "optional-title" per l'etichetta del collegamento ipertestuale, separati da almeno una riga.
  4. L' id è l' identificatore di definizione e può essere composto da lettere, numeri, spazi e segni di punteggiatura.
  5. Gli identificatori di definizione non fanno distinzione tra maiuscole e minuscole.
  6. È disponibile anche il supporto per i collegamenti automatici, in cui l'URL è delimitato dal simbolo minore di (<) e maggiore di (>) e visualizzato letteralmente.
 <!--Markdown--> [Google](https://google.com “Google”) <!--Rendered HTML--> <a href="https://google.com" title="Google">Google</a> <!--Markdown--> [Google](https://google.com) <!--Rendered HTML--> <a href="https://google.com">Google</a> <!--Markdown--> [Comparing Styling Methods in Next.js](/2020/09/comparing-styling-methods-next-js) <!--Rendered HTML--> <a href="/2020/09/comparing-styling-methods-next-js">Comparing Styling Methods In Next.js</a> <!--Markdown--> [Google][id] <!--At least a line must be in-between--> <!--Rendered HTML--> <a href="https://google.com" title="Google">Google</a> <!--Markdown--> <https://google.com> <!--Rendered HTML--> <a href="https://google.com">google.com</a> <!--Markdown--> <[email protected]> <!--Rendered HTML--> <a href="mailto:[email protected]">[email protected]</a>
  • Tutorial interattivo per conoscere i collegamenti.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni sui collegamenti.

immagini

Le immagini in Markdown seguono i formati inline e di riferimento per i collegamenti.

Le seguenti regole definiscono le immagini:

  1. Le immagini vengono visualizzate come elemento dell'immagine HTML, <img>.
  2. Il formato inline ha la sintassi: ![alt text](image-url "optional-title") .
  3. Il formato di riferimento ha la sintassi: ![alt text][id] per il riferimento e [id]: image-url "optional-title" per l'etichetta dell'immagine. Entrambi devono essere separati da almeno una riga vuota.
  4. Il titolo dell'immagine è facoltativo e l'URL dell'immagine può essere relativo.
 <!--Markdown--> ![alt text](image-url "optional-title") <!--Rendered HTML--> <img src="image-url" alt="alt text" title="optional-title" /> <!--Markdown--> ![alt text][id] <!--At least a line must be in-between--> <!--Markdown--> <!--Rendered HTML--> <img src="image-url" alt="alt text" title="optional-title" />
  • Tutorial interattivo per conoscere le immagini.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni sulle immagini.

Citazioni in blocco

L'elemento HTML Block Citazione, <blockquote>, può essere creato anteponendo a una nuova riga il simbolo maggiore di ( > ).

 <!--Markdown--> > This is a blockquote element > You can start every new line > with the greater than symbol. > That gives you greater control > over what will be rendered. <!--Rendered HTML--> <blockquote> <p>This is a blockquote element You can start every new line with the greater than symbol. That gives you greater control over what will be rendered.</p> </blockquote>

Le citazioni in blocco possono essere nidificate:

 <!--Markdown--> > Blockquote with a paragraph >> And another paragraph >>> And another <!--Rendered HTML--> <blockquote> <p>Blockquote with a paragraph</p> <blockquote> <p>And another paragraph</p> <blockquote> <p>And another</p> </blockquote> </blockquote> </blockquote>

Possono anche contenere altri elementi Markdown, come intestazioni, codice, voci di elenco e così via.

 <!--Markdown--> > Blockquote with a paragraph > # Heading 1 > Heading 2 > - > 1. One > 2. Two <!--Rendered HTML--> <blockquote> <p>Blockquote with a paragraph</p> <h1>Heading 1</h1> <h2>Heading 2</h2> <ol> <li>One</li> <li>Two</li> </ol> </blockquote>
  • Tutorial interattivo per conoscere le citazioni in blocco.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni su Blockquotes.

Codice

È supportato anche l'elemento HTML Inline Code, <code>. Per crearne uno, delimita il testo con segni di spunta inversa (`) o doppi segni di spunta indietro se è necessario che ci sia un segno di spunta indietro letterale nel testo che lo racchiude.

 <!--Markdown--> `inline code snippet` <!--Rendered HTML--> <code>inline code snippet</code> <!--Markdown--> `<button type='button'>Click Me</button>` <!--Rendered HTML--> <code><button type='button'>Click Me</button></code> <!--Markdown--> `` There's an inline back-tick (`). `` <!--Rendered HTML--> <code>There's an inline back-tick (`).</code>
  • Tutorial interattivo per conoscere il codice.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni sugli intervalli di codice.

Blocchi di codice

È supportato anche l'elemento di testo preformattato HTML, <pre>. Questo può essere fatto con almeno tre e un numero uguale di segni di spunta all'indietro ( ` ) o tilde ( ~ ) — normalmente indicati come code-fence, o una nuova riga che inizia un rientro di almeno 4 spazi.

 <!--Markdown--> ``` const dedupe = (array) => [...new Set(array)]; ``` <!--Rendered HTML--> <pre><code>const dedupe = (array) => [...new Set(array)];</code></pre> <!--Markdown--> const dedupe = (array) => [...new Set(array)]; <!--Rendered HTML--> <pre><code>const dedupe = (array) => [...new Set(array)];</code></pre>
  • Tutorial interattivo per conoscere il codice.
  • Link permanente Dingus per controllare l'esempio completo con Anteprima e AST.
  • Ulteriori informazioni sui blocchi di codice recintati e rientrati.

Utilizzo dell'HTML in linea

Secondo la nota specifica originale di John Grubers sull'HTML in linea, qualsiasi markup che non è coperto dalla sintassi di Markdown, usi semplicemente l'HTML stesso, con le uniche restrizioni che gli elementi HTML a livello di blocco, ad esempio <div> , <table> , <pre> , <p> , ecc. — devono essere separati dal contenuto circostante da righe vuote e i tag di inizio e fine del blocco non devono essere rientrati con tabulazioni o spazi.

Tuttavia, a meno che tu non sia probabilmente una delle persone dietro CommonMark stesso, o giù di lì, molto probabilmente scriverai Markdown con un aspetto che è già esteso per gestire un gran numero di sintassi non attualmente supportate da CommonMark.

Andando avanti

CommonMark è un lavoro in corso costante con le sue specifiche aggiornate per l'ultima volta il 6 aprile 2019. Esistono numerose applicazioni popolari che lo supportano nel pool di strumenti Markdown. Con la consapevolezza dello sforzo di CommonMark verso la standardizzazione, penso sia sufficiente concludere che, nella semplicità di Markdown, c'è molto lavoro dietro le quinte e che è una buona cosa per lo sforzo di CommonMark che la specifica formale di GitHub Flavored Markdown si basa sulla specifica.

Il passaggio allo sforzo di standardizzazione di CommonMark non impedisce la creazione di versioni per estendere la sua sintassi supportata e poiché CommonMark si prepara alla versione 1.0 con problemi che devono essere risolti, ci sono alcune risorse interessanti sullo sforzo continuo che puoi utilizzare per il tuo lettura.

Risorse

  • Presentazione di Markdown di John Gruber
  • Sito ufficiale di CommonMark
  • Spec. Markdown aromatizzata GitHub
  • cmark repository ufficiale
  • Il fork di cmark di GitHub
  • Ribasso su Wikipedia
  • Guida al ribasso