2015-08-18 11 views
11

Vorrei creare un sommario di Markdown.
Per esempio in stackedit.iohttps://stackedit.io/editor#table-of-contents quando si inserisce:Genera il sommario da Markdown in php

[TOC] 

Esiste un modo per generare questo fuori di Markdown?

E.g. se si dispone di:

## header 1 
## header 2 

ToC dovrebbe essere:

<ol> 
    <li><a href="#header1">Header 1</a></li> 
    <li><a href="#header2">Header 2</a></li> 
</ol> 

Devo creare il mio mark-down parser solo per ottenere il ToC?

+2

Perché reinventare la ruota? http://parsedown.org/ – BenM

+1

Sto usando parsedown ma non crea un sommario automaticamente –

+0

'[TOC]' non è un markdown di azioni. – BenM

risposta

6

Di seguito è riportata una funzione che svolge il lavoro essenziale: restituisce un elenco JSON di titoli trovati, ciascuno con il relativo livello e testo.
Questo elemento JSON può inoltre essere utilizzato per generare la struttura HTML necessaria o qualsiasi altra cosa.

Schematicamente funziona in questo modo:

  1. ottenere il file Markdown come una stringa, e normalizzare line-breaks a solo \n (questo è importante per il passo # 3 di seguito)
  2. Applicare una semplice espressione regolare /^(?:=|-|#).*$/m con PREG_OFFSET_CAPTURE: così partite tutte le linee che sia:
    • sono i "underliners" di <h1> (quando "=") o <h2> (quando "-") titoli
    • sono titoli da soli (che inizia con "#")
  3. Iterate le righe abbinate:
    • per "underliners", guarda il file di origine per la linea precedente, che si trova come la stringa tra la offset della linea corrente e interruzione di riga precedente; quindi ottenere livello dal tipo underliner e il testo dalla riga precedente
    • altrimenti si procurano livello e testo dalla riga corrente stessa

Ecco la funzione:

function markdown_toc($file_path) { 
    $file = file_get_contents($file_path); 

    // ensure using only "\n" as line-break 
    $source = str_replace(["\r\n", "\r"], "\n", $file); 

    // look for markdown TOC items 
    preg_match_all(
    '/^(?:=|-|#).*$/m', 
    $source, 
    $matches, 
    PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE 
); 

    // preprocess: iterate matched lines to create an array of items 
    // where each item is an array(level, text) 
    $file_size = strlen($source); 
    foreach ($matches[0] as $item) { 
    $found_mark = substr($item[0], 0, 1); 
    if ($found_mark == '#') { 
     // text is the found item 
     $item_text = $item[0]; 
     $item_level = strrpos($item_text, '#') + 1; 
     $item_text = substr($item_text, $item_level); 
    } else { 
     // text is the previous line (empty if <hr>) 
     $item_offset = $item[1]; 
     $prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2)); 
     $item_text = 
     substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1); 
     $item_text = trim($item_text); 
     $item_level = $found_mark == '=' ? 1 : 2; 
    } 
    if (!trim($item_text) OR strpos($item_text, '|') !== FALSE) { 
     // item is an horizontal separator or a table header, don't mind 
     continue; 
    } 
    $raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)]; 
    } 

    // create a JSON list (the easiest way to generate HTML structure is using JS) 
    return json_encode($raw_toc); 
} 

qui è il risultato che restituisce dal home page of the link you provided:

[ 
    {"level":1,"text":"Welcome to StackEdit!"}, 
    {"level":2,"text":"Documents"}, 
    {"level":4,"text":"<\/i> Create a document"}, 
    {"level":4,"text":"<\/i> Switch to another document"}, 
    {"level":4,"text":"<\/i> Rename a document"}, 
    {"level":4,"text":"<\/i> Delete a document"}, 
    {"level":4,"text":"<\/i> Export a document"}, 
    {"level":2,"text":"Synchronization"}, 
    {"level":4,"text":"<\/i> Open a document"}, 
    {"level":4,"text":"<\/i> Save a document"}, 
    {"level":4,"text":"<\/i> Synchronize a document"}, 
    {"level":4,"text":"<\/i> Manage document synchronization"}, 
    {"level":2,"text":"Publication"}, 
    {"level":4,"text":"<\/i> Publish a document"}, 
    {"level":2,"text":"- Markdown, to publish the Markdown text on a website that can interpret it (**GitHub** for instance),"}, 
    {"level":2,"text":"- HTML, to publish the document converted into HTML (on a blog for example),"}, 
    {"level":4,"text":"<\/i> Update a publication"}, 
    {"level":4,"text":"<\/i> Manage document publication"}, 
    {"level":2,"text":"Markdown Extra"}, 
    {"level":3,"text":"Tables"}, 
    {"level":3,"text":"Definition Lists"}, 
    {"level":3,"text":"Fenced code blocks"}, 
    {"level":3,"text":"Footnotes"}, 
    {"level":3,"text":"SmartyPants"}, 
    {"level":3,"text":"Table of contents"}, 
    {"level":3,"text":"MathJax"}, 
    {"level":3,"text":"UML diagrams"}, 
    {"level":3,"text":"Support StackEdit"} 
] 
0

L'aggiunta del sommario non fa parte della normale sintassi del markdown, o è disponibile (ancora) in molti dei parser di markdown più grandi.

ho però aggiunto creazione automatica di Table of Contents nel mio mark-down parser: https://github.com/PeterWaher/IoTGateway/tree/master/Content/Waher.Content.Markdown

Funziona attraverso un'interfaccia plug per includere multimediali che utilizzano la stessa sintassi quando si inseriscono le immagini. Il modulo multimediale è selezionato in base alla valutazione calcolata dall'URL fornito. Questo ti consente di includere video, audio, clip YouTube, ecc.Consente inoltre di inserire un sommario. Devi solo scrivere ![Table of Contents](ToC).