Skip to content

Instantly share code, notes, and snippets.

@rossant
Last active March 25, 2024 12:03
Show Gist options
  • Save rossant/99a2316465c84192b630 to your computer and use it in GitHub Desktop.
Save rossant/99a2316465c84192b630 to your computer and use it in GitHub Desktop.
Convert from Markdown to OpenOffice for Linux Magazine
"""Convert from Markdown to OpenOffice for Linux Magazine.
Requirements:
* Python 3+ (doesn't seem to work on Python 2 because of odfpy)
* Latest IPython and Jupyter
Installation:
pip install ipymd
pip install odfpy
git clone https://gist.github.com/99a2316465c84192b630.git md2glmf
cd md2glmf
Usage:
python markdow_to_glmf.py somedocument.md
This generates `somedocument.odt`.
Note: the conversion code lives in the ipymd repo at https://github.com/rossant/ipymd
"""
import os
import os.path as op
import re
import sys
from ipymd import convert
from ipymd.core.prompt import SimplePromptManager, PythonPromptManager
from ipymd.lib.opendocument import ODFDocument, ODFRenderer, load_styles
from ipymd.formats.opendocument import ODFWriter, load_odf
SCRIPTDIR = op.dirname(op.realpath(__file__))
_PUNCTUATION_REGEX = r'[^\w\- ]'
def glmf_styles(path):
styles = load_styles(path)
return {name: style for name, style in styles.items()
}
mapping = {'normal-paragraph': 'Normal',
'heading-1': 'Heading',
'heading-2': 'Heading 1',
'heading-3': 'Heading 2',
'heading-4': 'Heading 3',
'heading-5': 'Heading 4',
'code': 'code',
'italic': 'italic',
'bold': 'gras',
'url': 'url',
'inline-code': 'code_par',
}
def _read_md(path):
with open(path, 'r') as f:
return f.read()
class GLMFODFRenderer(ODFRenderer):
def paragraph(self, text):
lines = text.splitlines()
head, tail = lines[:1], lines[1:]
if head[0] == 'chapeau':
style = 'chapeau'
elif head[0] == 'signature':
style = 'Signature'
elif head[0] == 'pragma':
style = 'pragma'
elif head[0] == 'legende':
style = 'legende'
else:
style = None
tail = lines
text = '\n'.join(tail)
with self._doc.paragraph(style):
self.text(text)
def list_start(self, ordered=False):
if self._doc.is_in_paragraph():
self._doc.end_paragraph()
# if ordered:
# self._doc.start_numbered_list()
# else:
# self._doc.start_list()
def list_end(self):
# self._doc.end_list()
pass
def list_item_start(self):
# self._doc.start_list_item()
self._doc.start_paragraph()
self._doc.text('- ')
def list_item_end(self):
if self._doc.is_in_paragraph():
self._doc.end_paragraph()
# self._doc.end_list_item()
def gen_odt(filename):
print("Converting {0}...".format(filename), end=' ')
template_path = '_template.ott'
# Create the ODF document.
styles = glmf_styles(template_path)
# from pprint import pprint
# pprint(styles)
odf_doc = ODFDocument(styles=styles,
style_mapping=mapping)
# Create the ODF writer.
prompt = PythonPromptManager()
writer = ODFWriter(odf_doc=odf_doc, prompt=prompt,
odf_renderer=GLMFODFRenderer
)
# Read Markdown file.
md = _read_md(filename)
# Convert the Markdown file to the ODF file.
convert(md, from_='markdown', to='opendocument', writer=writer)
# Save the ODF chapter.
writer.contents.save(op.join(op.splitext(filename)[0] + '.odt'))
print("done.")
if __name__ == '__main__':
import sys
gen_odt(sys.argv[1])
@Grahack
Copy link

Grahack commented May 22, 2016

Hi,

  1. Is there a sample kitchen-sink markdown file to document every other construction that is allowed for articles ?
  2. How can I insert an image ?
  3. Markdown normally allows one to go to a new line without the output doing so, but this tool doesn't allow this. Is it intented ?
    Thanks.

PS: Aussi, est-ce que ça ne vaudrait pas le coup de faire de ce gist un dépôt ?

@Martoni
Copy link

Martoni commented Jan 30, 2021

I'm also interested by a example :)

@Pierstoval
Copy link

When using this gist, I had to do run pip install traitlets jupyter_client nbformat notebook because they seemed to be necessary

@Pierstoval
Copy link

Also, it seems that this script is incompatible with unicode, therefore I had to make two changes:

  • First, remove all \r characters in my markdown file
  • Second, modify the script to apply unicode reading:
    diff --git a/markdown_to_glmf.py b/markdown_to_glmf.py
    index 0b26def..92119bd 100644
    --- a/markdown_to_glmf.py
    +++ b/markdown_to_glmf.py
    @@ -26,6 +26,7 @@ import os
     import os.path as op
     import re
     import sys
    +import codecs
     
     from ipymd import convert
     from ipymd.core.prompt import SimplePromptManager, PythonPromptManager
    @@ -60,7 +61,7 @@ mapping = {'normal-paragraph': 'Normal',
     
     
     def _read_md(path):
    -    with open(path, 'r') as f:
    +    with codecs.open(path, 'r', encoding='utf-8') as f:
             return f.read()

@Pierstoval
Copy link

I made several updates and added an example on my fork of this gist: https://gist.github.com/Pierstoval/7fe41732e22810e422388010ac2c0c91/revisions

Maybe this should become a single repository, to accept PRs 😉

@Martoni
Copy link

Martoni commented Dec 1, 2021

Could be added in repository «outils auteurs».

@rossant
Copy link
Author

rossant commented Dec 5, 2021

@Pierstoval Done! https://github.com/rossant/odt-linux-mag
Please feel free to propose PRs.
I should point out that I no longer support this code but I'll happily merge pull requests on the GitHub repository.
Thanks for your contributions!

@Pierstoval
Copy link

@rossant Here it is: rossant/odt-linux-mag#1

Thanks for your work

😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment