markdown2html.py est un script Python qui converti un fichier Markdown en HTML.
- il transforme les balises
<h3>
en balises<a href>
en créant des sections avec des identifiants uniques et ajoute ces ancres dans un fichier sections.html . Dans ce fichier index on peut ajouter des liens vers des fichiers en insérant le signe '-' devant le nom du fichier :
Exemples :[-mon PDF](document.pdf), [-mon html](fichier.html), [-mon texte](document.txt), [-mon code](code.py)
- il identifie des blocs de code spéciaux délimités par
<!--program>
et<program -->
Ces blocs définissent une zone d'affichage de code avec des attributs et les met en valeurs avec pygmentize un outil de coloration syntaxique du code.- il crée le fichier HTML en y intégrant les fichiers markdown2html.css et markdown.css
- markdown2html.css définit le style de la page HTML
- markdown.css définit des styles pour le fichier markdown
Créer un répertoire avec les fichiers markdown2html.py, markdown2html.css, markdown.css
Exécuter le fichier Python avec votre fichier Markdown :
python3 markdown2html.py mon_fichier.md
Un répertoire mon_fichier est créé, avec 3 fichiers à l'intèrieur :
article.html : le fichier HTML principal.
article.md : une copie du fichier Markdown.
sections.html : un index des liens créés avec les tags### et [-...]()
.
Vous pouvez éventuellement modifier les fichiers CSS.
Pygments :
Téléchargement et installation
ou avecpip install Pygments
(Exemple d'utilisation : pygmentize -S paraiso-dark -f html -a .codehilite)
markdown2html.py : converti le fichier Markdown en HTML
markdown2html.css : définit le style de la page HTML
markdown.css : définit des styles pour le fichier markdown
(Code thème : Dracula)
Les attributs doivent êtres placés entre 2 balises
<!-- program> ... <program -->
La première série d'attributs number-... personnalise les numéros de lignes.
Le série box-... la boite et le code.
les derniers attributs de la liste langage et theme correspondent aux options
de pygmentize , languages et styles .
Dans la section<!-- Program>
, lorsque vous spécifiez l’attribut code , vous pouvez
soit fournir le nom d’un fichier existant, soit écrire directement le code.
Par exemple, code: code_example_1.py suppose que code_example_1.py est un
fichier existant dans le même répertoire.
Exemple :
En ligne :
<!-- program>
...
language: python
theme: fruity
code:
print("Hello")
print("World!")
<program -->
Avec le fichier :
<!-- program>
...
language: js
theme: github-dark
code: script.js
<program -->
Dans la section "Exemples", de nombreux attributs sont répertoriés sans valeurs.
Ces attributs sont facultatifs et servent à personnaliser l'apparence du bloc de code.
Si un attribut n'est pas spécifié, le programme utilisera des valeurs par défaut.
Vous pouvez expérimenter avec différentes valeurs pour obtenir l'apparence souhaitée
pour votre bloc de code.
Quelques exemples
● )
...
box-shadow: inset 10px 10px 10px rgba(0,0,0,.7);
box-font-size: 10px
box-font-family: Source Code Pro
theme: fruity
...
number: 0
number-color:
number-background-color:
number-border:
number-border-radius:
number-padding-left-right:
number-margin-left:
number-margin-right:
number-font-weight:
box-background: #171932;
box-border:
box-border-radius: 10px
box-shadow: inset 10px 10px 10px rgba(0,0,0,.7);
box-font-size: 10px
box-font-family: Source Code Pro
box-line-height: 120%
box-width: 80%
box-height: 300px
box-margin-top: 10px
box-margin-bottom: 10px
box-margin-left: 10px
box-margin-right: 10px
language: python
theme: fruity
code: code_exemple_1.py
def find_programs_format_html_code(program_param, html_code):
div_highlight_style =\
"overflow: auto;"+\
f"height: {program_param['box-height:']};"+\
f"border-radius: {program_param['box-border-radius:']};"+\
f"width: {program_param['box-width:']};"+\
"margin: auto;"+\
f"border: {program_param['box-border:']};"+\
f"background: {program_param['box-background:']};"+\
f"box-shadow: {program_param['box-shadow:']};"
td_linenos_style = "td.linenos .normal-69f0d588-af6f-441f-bf73-62886affb2dc {"+\
f"color: {program_param['number-color:']};"+\
f"background-color: {program_param['number-background-color:']};"+\
f"border: {program_param['number-border:']};"+\
f"border-radius: {program_param['number-border-radius:']};"+\
f"padding-left: {program_param['number-padding-left-right:']};"+\
f"padding-right: {program_param['number-padding-left-right:']};"+\
f"margin-left: {program_param['number-margin-left:']};"+\
f"margin-right: {program_param['number-margin-right:']};"+\
f"font-weight: {program_param['number-font-weight:']};"+\
"}"
html_lignes = html_code.splitlines()
for i, ligne in enumerate(html_lignes):
if ligne.startswith('pre {'):
del html_lignes[:i]
break
# html_lignes[0] = "<style id='css-style'>"
html_lignes[0] = "<style>"
html_lignes[1] = td_linenos_style
html_code = "\n".join(html_lignes)
soup = BeautifulSoup(html_code, 'html.parser')
highlight_div = soup.find('div', attrs={'class': 'highlight'})
if highlight_div:
highlight_div['style'] = div_highlight_style
html_code = soup.prettify()
soup = BeautifulSoup(html_code, 'html.parser')
balises_pre = soup.find_all('pre')
for balise in balises_pre:
balise['style'] = f"line-height: {program_param['box-line-height:']};"+\
f"margin-top: {program_param['box-margin-top:']};"+\
f"margin-bottom: {program_param['box-margin-bottom:']};"+\
f"margin-left: {program_param['box-margin-left:']};"+\
f"margin-right: {program_param['box-margin-right:']};"+\
f"font-family: {program_param['box-font-family:']};"+\
f"font-size: {program_param['box-font-size:']};"+\
"padding: 0;"
if program_param['number:'] == '1':
balise['style'] += "width: max-content;"
html_code = soup.prettify()
return(html_code)
● )
...
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
box-font-size: 10px
box-font-family: Source Code Pro
theme: nord-darker
...
number: 1
number-color:
number-background-color:
number-border:
number-border-radius:
number-padding-left-right:
number-margin-left:
number-margin-right:
number-font-weight:
box-background:
box-border:
box-border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
box-font-size: 10px
box-font-family: Source Code Pro
box-line-height: 120%
box-width: 80%
box-height: 300px
box-margin-top: 10px
box-margin-bottom: 10px
box-margin-left: 10px
box-margin-right: 10px
language: python
theme: nord-darker
code: code_exemple_1.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
def find_programs_format_html_code(program_param, html_code): div_highlight_style =\ "overflow: auto;"+\ f"height: {program_param['box-height:']};"+\ f"border-radius: {program_param['box-border-radius:']};"+\ f"width: {program_param['box-width:']};"+\ "margin: auto;"+\ f"border: {program_param['box-border:']};"+\ f"background: {program_param['box-background:']};"+\ f"box-shadow: {program_param['box-shadow:']};" td_linenos_style = "td.linenos .normal-3e194fa7-eaab-4824-a857-9ac05a763b6f {"+\ f"color: {program_param['number-color:']};"+\ f"background-color: {program_param['number-background-color:']};"+\ f"border: {program_param['number-border:']};"+\ f"border-radius: {program_param['number-border-radius:']};"+\ f"padding-left: {program_param['number-padding-left-right:']};"+\ f"padding-right: {program_param['number-padding-left-right:']};"+\ f"margin-left: {program_param['number-margin-left:']};"+\ f"margin-right: {program_param['number-margin-right:']};"+\ f"font-weight: {program_param['number-font-weight:']};"+\ "}" html_lignes = html_code.splitlines() for i, ligne in enumerate(html_lignes): if ligne.startswith('pre {'): del html_lignes[:i] break # html_lignes[0] = "<style id='css-style'>" html_lignes[0] = "<style>" html_lignes[1] = td_linenos_style html_code = "\n".join(html_lignes) soup = BeautifulSoup(html_code, 'html.parser') highlight_div = soup.find('div', attrs={'class': 'highlight'}) if highlight_div: highlight_div['style'] = div_highlight_style html_code = soup.prettify() soup = BeautifulSoup(html_code, 'html.parser') balises_pre = soup.find_all('pre') for balise in balises_pre: balise['style'] = f"line-height: {program_param['box-line-height:']};"+\ f"margin-top: {program_param['box-margin-top:']};"+\ f"margin-bottom: {program_param['box-margin-bottom:']};"+\ f"margin-left: {program_param['box-margin-left:']};"+\ f"margin-right: {program_param['box-margin-right:']};"+\ f"font-family: {program_param['box-font-family:']};"+\ f"font-size: {program_param['box-font-size:']};"+\ "padding: 0;" if program_param['number:'] == '1': balise['style'] += "width: max-content;" html_code = soup.prettify() return(html_code) |
● )
...
box-shadow: rgba(6, 24, 44, 0.4) 0px 0px 0px 2px, rgba(6, 24, 44, 0.65) 0px 4px 6px -1px, rgba(255, 255, 255, 0.08) 0px 1px 0px inset;
box-font-size: 11px
box-font-family: Play
theme: vim
...
number: 0
number-color:
number-background-color:
number-border:
number-border-radius:
number-padding-left-right:
number-margin-left:
number-margin-right:
number-font-weight:
box-background: #0002A8
box-border:
box-border-radius:
box-shadow: rgba(6, 24, 44, 0.4) 0px 0px 0px 2px, rgba(6, 24, 44, 0.65) 0px 4px 6px -1px, rgba(255, 255, 255, 0.08) 0px 1px 0px inset;
box-font-size: 11px
box-font-family: Play
box-line-height: 120%
box-width: 80%
box-height: 300px
box-margin-top: 10px
box-margin-bottom: 10px
box-margin-left: 10px
box-margin-right: 10px
language: python
theme: vim
code: code_exemple_1.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
def find_programs_format_html_code(program_param, html_code): div_highlight_style =\ "overflow: auto;"+\ f"height: {program_param['box-height:']};"+\ f"border-radius: {program_param['box-border-radius:']};"+\ f"width: {program_param['box-width:']};"+\ "margin: auto;"+\ f"border: {program_param['box-border:']};"+\ f"background: {program_param['box-background:']};"+\ f"box-shadow: {program_param['box-shadow:']};" td_linenos_style = "td.linenos .normal-0be16b10-6228-4b1a-8815-7e3960baed19 {"+\ f"color: {program_param['number-color:']};"+\ f"background-color: {program_param['number-background-color:']};"+\ f"border: {program_param['number-border:']};"+\ f"border-radius: {program_param['number-border-radius:']};"+\ f"padding-left: {program_param['number-padding-left-right:']};"+\ f"padding-right: {program_param['number-padding-left-right:']};"+\ f"margin-left: {program_param['number-margin-left:']};"+\ f"margin-right: {program_param['number-margin-right:']};"+\ f"font-weight: {program_param['number-font-weight:']};"+\ "}" html_lignes = html_code.splitlines() for i, ligne in enumerate(html_lignes): if ligne.startswith('pre {'): del html_lignes[:i] break # html_lignes[0] = "<style id='css-style'>" html_lignes[0] = "<style>" html_lignes[1] = td_linenos_style html_code = "\n".join(html_lignes) soup = BeautifulSoup(html_code, 'html.parser') highlight_div = soup.find('div', attrs={'class': 'highlight'}) if highlight_div: highlight_div['style'] = div_highlight_style html_code = soup.prettify() soup = BeautifulSoup(html_code, 'html.parser') balises_pre = soup.find_all('pre') for balise in balises_pre: balise['style'] = f"line-height: {program_param['box-line-height:']};"+\ f"margin-top: {program_param['box-margin-top:']};"+\ f"margin-bottom: {program_param['box-margin-bottom:']};"+\ f"margin-left: {program_param['box-margin-left:']};"+\ f"margin-right: {program_param['box-margin-right:']};"+\ f"font-family: {program_param['box-font-family:']};"+\ f"font-size: {program_param['box-font-size:']};"+\ "padding: 0;" if program_param['number:'] == '1': balise['style'] += "width: max-content;" html_code = soup.prettify() return(html_code) |
● )
...
box-shadow: rgba(0, 0, 0, 0.0) 0px 2px 1px, rgba(0, 0, 0, 0.09) 0px 4px 2px, rgba(0, 0, 0, 0.09) 0px 8px 4px, rgba(0, 0, 0, 0.09) 0px 16px 8px, rgba(0, 0, 0, 0.09) 0px 32px 16px;
box-font-size: 12px
box-font-family: Ubuntu Mono
theme: fruity
...
number: 0
number-color:
number-background-color:
number-border:
number-border-radius:
number-padding-left-right:
number-margin-left:
number-margin-right:
number-font-weight:
box-background: #1B1E3B;
box-border:
box-border-radius: 10px
box-shadow: rgba(0, 0, 0, 0.0) 0px 2px 1px, rgba(0, 0, 0, 0.09) 0px 4px 2px, rgba(0, 0, 0, 0.09) 0px 8px 4px, rgba(0, 0, 0, 0.09) 0px 16px 8px, rgba(0, 0, 0, 0.09) 0px 32px 16px;
box-font-size: 12px
box-font-family: Ubuntu Mono
box-line-height: 120%
box-width: 60%
box-height: 297px
box-margin-top: 10px
box-margin-bottom: 10px
box-margin-left: 10px
box-margin-right: 10px
language: python
theme: fruity
code: code_exemple_1.py
def find_programs_format_html_code(program_param, html_code):
div_highlight_style =\
"overflow: auto;"+\
f"height: {program_param['box-height:']};"+\
f"border-radius: {program_param['box-border-radius:']};"+\
f"width: {program_param['box-width:']};"+\
"margin: auto;"+\
f"border: {program_param['box-border:']};"+\
f"background: {program_param['box-background:']};"+\
f"box-shadow: {program_param['box-shadow:']};"
td_linenos_style = "td.linenos .normal-8e3078eb-67c4-4376-82c1-2fbc78b17d0f {"+\
f"color: {program_param['number-color:']};"+\
f"background-color: {program_param['number-background-color:']};"+\
f"border: {program_param['number-border:']};"+\
f"border-radius: {program_param['number-border-radius:']};"+\
f"padding-left: {program_param['number-padding-left-right:']};"+\
f"padding-right: {program_param['number-padding-left-right:']};"+\
f"margin-left: {program_param['number-margin-left:']};"+\
f"margin-right: {program_param['number-margin-right:']};"+\
f"font-weight: {program_param['number-font-weight:']};"+\
"}"
html_lignes = html_code.splitlines()
for i, ligne in enumerate(html_lignes):
if ligne.startswith('pre {'):
del html_lignes[:i]
break
# html_lignes[0] = "<style id='css-style'>"
html_lignes[0] = "<style>"
html_lignes[1] = td_linenos_style
html_code = "\n".join(html_lignes)
soup = BeautifulSoup(html_code, 'html.parser')
highlight_div = soup.find('div', attrs={'class': 'highlight'})
if highlight_div:
highlight_div['style'] = div_highlight_style
html_code = soup.prettify()
soup = BeautifulSoup(html_code, 'html.parser')
balises_pre = soup.find_all('pre')
for balise in balises_pre:
balise['style'] = f"line-height: {program_param['box-line-height:']};"+\
f"margin-top: {program_param['box-margin-top:']};"+\
f"margin-bottom: {program_param['box-margin-bottom:']};"+\
f"margin-left: {program_param['box-margin-left:']};"+\
f"margin-right: {program_param['box-margin-right:']};"+\
f"font-family: {program_param['box-font-family:']};"+\
f"font-size: {program_param['box-font-size:']};"+\
"padding: 0;"
if program_param['number:'] == '1':
balise['style'] += "width: max-content;"
html_code = soup.prettify()
return(html_code)
● )
...
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
box-font-size: 14px
box-font-family: Outfit
box-height: auto
theme: nord
...
number: 0
number-color:
number-background-color:
number-border:
number-border-radius:
number-padding-left-right:
number-margin-left:
number-margin-right:
number-font-weight:
box-background:
box-border:
box-border-radius: 25px
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
box-font-size: 14px
box-font-family: Outfit
box-line-height: 110%
box-width: 70%
box-height: auto
box-margin-top: 10px
box-margin-bottom: 10px
box-margin-left: 10px
box-margin-right: 10px
language: python
theme: nord
code: code_exemple_1.py
def find_programs_format_html_code(program_param, html_code):
div_highlight_style =\
"overflow: auto;"+\
f"height: {program_param['box-height:']};"+\
f"border-radius: {program_param['box-border-radius:']};"+\
f"width: {program_param['box-width:']};"+\
"margin: auto;"+\
f"border: {program_param['box-border:']};"+\
f"background: {program_param['box-background:']};"+\
f"box-shadow: {program_param['box-shadow:']};"
td_linenos_style = "td.linenos .normal-79cd8648-6162-4cb3-b33e-baad72158800 {"+\
f"color: {program_param['number-color:']};"+\
f"background-color: {program_param['number-background-color:']};"+\
f"border: {program_param['number-border:']};"+\
f"border-radius: {program_param['number-border-radius:']};"+\
f"padding-left: {program_param['number-padding-left-right:']};"+\
f"padding-right: {program_param['number-padding-left-right:']};"+\
f"margin-left: {program_param['number-margin-left:']};"+\
f"margin-right: {program_param['number-margin-right:']};"+\
f"font-weight: {program_param['number-font-weight:']};"+\
"}"
html_lignes = html_code.splitlines()
for i, ligne in enumerate(html_lignes):
if ligne.startswith('pre {'):
del html_lignes[:i]
break
# html_lignes[0] = "<style id='css-style'>"
html_lignes[0] = "<style>"
html_lignes[1] = td_linenos_style
html_code = "\n".join(html_lignes)
soup = BeautifulSoup(html_code, 'html.parser')
highlight_div = soup.find('div', attrs={'class': 'highlight'})
if highlight_div:
highlight_div['style'] = div_highlight_style
html_code = soup.prettify()
soup = BeautifulSoup(html_code, 'html.parser')
balises_pre = soup.find_all('pre')
for balise in balises_pre:
balise['style'] = f"line-height: {program_param['box-line-height:']};"+\
f"margin-top: {program_param['box-margin-top:']};"+\
f"margin-bottom: {program_param['box-margin-bottom:']};"+\
f"margin-left: {program_param['box-margin-left:']};"+\
f"margin-right: {program_param['box-margin-right:']};"+\
f"font-family: {program_param['box-font-family:']};"+\
f"font-size: {program_param['box-font-size:']};"+\
"padding: 0;"
if program_param['number:'] == '1':
balise['style'] += "width: max-content;"
html_code = soup.prettify()
return(html_code)