Changing the Pandoc monospace font size or style in DOCX output - docx

When using markdown code blocks the resulting monospace font size is too large in DOCX documents.
I can adjust the font size of paragraphs by specifying a custom template.docx file, but for some reason the generated code blocks do not use a paragraph style, as opposed to most other generated output.
Is there any way to:
Make code blocks use a specific style so that I can override the style in the template.docx
Override the monospace font used in the DOCX representation of code blocks?
Updated to clarify:
I am using an external reference.docx based on a previously generated docx as described in the comments. By modifying the styles for heading1 etc I have reasonable control over the output. The problem is that generated monospace text does not use a named style, it is just "normal" with some changes. So I have no way to change it in the template unless I also change the size of all "normal" text.

Using Pandoc 1.17.2 and Word 2013 I have finally found a solution, it seems later versions of Pandoc uses a linked style that is by default hidden in Word.
Step 1: Generate a custom template file using
pandoc -o template_1.17.2.docx test.md
Where test.md includes source code and all other styles you may want to modify. For example:
~~~~
this is preformatted source using style "Source Code"
~~~~
~~~ xml
<this> is preformatted source using "KeyworkTok" and "NormalTok"</this>
~~~
Open template_1.17.2.docx in Word. The preformatted source is now formatted using the hidden linked style "Source Code". This style is NOT displayed in the styles preview pane by default, you can add it by configuring the styles preview pane by clicking the tiny square-with-arrow in the bottom right of the styles preview panel.
Modify this style as you wish and save the template. Then generate your document based on this template:
pandoc --reference-docx=template_1.17.2.docx -o mydoc.docx mydoc.md
You should now see the source properly formatted in mydoc.
#LinusR suggests that different source styles uses different Layout styles. I have added XML as an example. The formatted XML will use "KeywordTok" and "NormalTok".

Pandoc, when creating DOCX (MS Word) documents uses a reference.docx file. This has to be given on the Pandoc command line. Pandoc will then extract all default styles and formatting settings (unless they use custom names) from this reference DOCX and apply them on the generated DOCX:
pandoc -t docx -o out.docx in-markdown.txt --reference-docx=my.docx
The best way to arrive at a Pandoc-usable reference DOCX is to generate a first simple DOCX with the help of Pandoc, then take it to a Word installation, open it and change the styles to be used by you to your liking. Then save it, take it back to Pandoc and use it as a reference.
For ODT (LibreOffice/OpenOffice/OpenDocument) in addition to the reference.odt (which you can use with the --reference-odt flag), there's also a template. You can print the default template with pandoc -D odt, then modify it and use it with pandoc -o out.odt --template=modifiedTemplate.odt
Last advice: use the latest Pandoc version! (Current is 1.13.2.1. For end of this month a 1.14 is expected.) Its DOCX support improved considerably in recent releases.

Related

VScode markdown preview image size control - pandoc compatible?

Is there some VScode extension that allows image size control in this form?
![caption](image.png){ width=whatever }
That is the form that is used to get Pandoc to control image size in its output. In this case I'd like to use VSCode - one of my favorite tools - to compose markdown destined for docx output. I've got the Pandoc part working, I'd just like be able to get the previewing to work better in VScode. There might be an extension that does this, but there are zillions of markdown extension for VSCode so who knows.
An alternative would be if there custom css code that would do this, but my css knowledge is not sufficient to know if this is even possible.

Post-processing R Markdown-generated html files

Is there a way to automatically apply some post-processing to html files generated from R Markdown?
For example, if we use MathJax to render LaTeX code (primarily in RStudio), the resulting html file includes src= links to load MathJax from a CDN. The problem is, we also need to be able to display these files on internal network without internet access, and those links need to be replaced to point to a local copy of MathJax.
It would be convenient if there was some hook that I could use to do that after the html file is generated, but I haven't been able to find any.
If your post processing is specifically about MathJax, you might consider setting your output yaml to the following which will download local copies of libraries such as MathJax and link to them.
output:
html_document:
self_contained: FALSE
mathjax: local

embedding image into jupyter notebook and exporting to HTML

I am running Python 3.7 on Windows using pycharm. I have a jupyter notebook and I would like to embed an image into the notebook. I know all the ways of doing standard embedding with markdown language, BUT ideally what I want is:
a. Embed the image via markdown language, i.e. the notebook cell is in 'markdown' state, not 'Code' state, AND ALSO
b. Have it able to export to HTML and retain that image in the HTML file. i.e. on the notebook. I want to click File -> Download as -> HTML (.html), save the notebook file in .html format, and then when I send it to my buddy, the image that I attached is in the notebook, and he sees it.
I know i could do this in a cell ('code'):
from IPython.display import Image
Image(filename="myfile.jpg")
but I do not want to use 'Code', since when I send to my buddy, he will see the In [] code statement and the Out [] of the image in the notebook html file.
Note: This would be an image that was on my laptop that I would want in the html formatted exported notebook. It is NOT on the web where he could refer to it with a www type statement. Unless I'm crazy, there is no way to do this with markdown command in a cell, the only way to do it (with the image embedded 'permanently' into the .html format of the notebook), would be via a cell that was in 'Code' celltype.
When you use a code cell to show an image and then export the notebook to an HTML file, the image is converted to Base64 and the code directly used in the src attribute of the <img> tag. You can apply the same procedure with images included in markdown cells.
First, encode your image as Base64, e.g. by using one of the online enocders.
Create a markdown cell and include an <img> tag which uses your Base64 code, e.g.:
<img src="data:image/png;base64,CODE_FOLLOWS_HERE" />
Evaluate the cell and you should already see your image.
If you now export your notebook to HTML, the image should be included in the file the same way as images from code cells.
The only disadvantage with this approach is that your markdown cell gets cluttered with the (probably long) Base64 code. However, this is manageable by e.g. using a markdown cell dedicated solely to the image without other content.
You can install the Unofficial Jupyter Notebook Extensions.
It has some interesting extensions (e.g. spell checker, collapsible headings, ...). One of the extensions is Export HTML With Embedded Images which exactly does what you want.
To install Nbextensions using pip do the following:
$ pip install jupyter_contrib_nbextensions
$ pip install jupyter_nbextensions_configurator
$ jupyter contrib nbextension install --user
$ jupyter nbextensions_configurator enable --user
Then you will see in your Jupyter homepage a new tab (Nbextensions), where you can enable and configure different extension.
After enabling the "Export HTML With Embedded Images", you will see the corresponding option in the "File-Download as" menu.
My complete solution is based on Milania and
encoding-an-image-file-with-base64
how-to-base64-encode-an-image-using-python
BytesIO.getvalue
the code
import base64, io, IPython
from PIL import Image as PILImage
image = PILImage.open(image_path)
output = io.BytesIO()
image.save(output, format='PNG')
encoded_string = base64.b64encode(output.getvalue()).decode()
html = '<img src="data:image/png;base64,{}"/>'.format(encoded_string)
IPython.display.HTML(html)
For me, on Visual Studio Code, something like this did the trick (in a markdown cell, as you requested, and a image that you want to embed in your notebook and further be exported to the html output):
<figure>
<img src="./notebook_img/diptera_taxat_yes_no.jpg" width="200"/>
<figcaption>Limit the search on Diptera</figcaption>
</figure>
Where the image is located in "./notebook_img" relative to the location of the notebook (in this sense, the notebook is located in .)
Your buddy will not see the code from above when reading the HTML exported file, so that should satisfy the requested need as far as I understand. He will also not need the folder "notebook_img".

Embedding image in ipython notebook for distribution

I have an ipython notebook with an embedded image from my local drive. I was expecting it to be embedded in the JSON along with the output of code cells, but when I distributed the notebook, the image did not appear to users. What is the recommended way (or ways) to embed an image in a Notebook, so that it doesn't disappear if users rerun code cells, clear cell output, etc.?
The notebook system caches images included with ![label](image.png), but they last only until the python "kernel" serving the notebook is restarted. If I rename the image file on disk, I can close and reopen the notebook and it still shows the image; but it disappears when I restart the kernel.
Edit: If I generate an image as code cell output and then export the notebook to html, the image is embedded in the html as encoded data. Surely there must be a way to hook into this functionality and load the output into a markdown (or better yet "raw nbconvert") cell?
from IPython.display import Image
Image(filename='imagename.png')
will be exported (with ipython nbconvert) to html that contains the following:
<div class="output_png output_subarea output_execute_result">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnAAAAFgCAYAAAA...
</div>
However, even when I manually embedded this snippet into a markdown cell, I couldn't get the image to display. What am I doing wrong?
Update (2020)
Apparently, the problem has (finally!) been addressed in the newer notebook / Jupyter versions: as of 2018 (thanks for the link #Wayne), the html sanitizer will accept an embedded html image, as in <img src="data:image/png;base64,iV...> . Markdown image syntax also accepts images as embedded data, so there are two ways to do this. Details in these helpful answers:
markdown image syntax (answer by #id01)
html element syntax (in answer by #tel -- note that it works now!)
Are you happy to use an extra code cell to display the image? If so, use this:
from IPython.display import Image
Image(filename="example.png")
The output cell will have the raw image data embedded in the .ipynb file so you can share it and the image will be retained.
Note that the Image class also has a url keyword, but this will only link to the image unless you also specify embed=True (see the documentation for details). So it's safer to use the filename keyword unless you are referring to an image on a remote server.
I'm not sure if there is an easy solution if you require the image to be included in a Markdown cell, i.e. without a separate code cell to generate the embedded image data. You may be able to use the python markdown extension which allows dynamically displaying the contents of Python variables in markdown cells. However, the extension generates the markdown cells dynamically, so in order to retain the output when sharing the notebook you will need to run ipython nbconvert --to notebook original_notebook.ipynb --output preprocessed_notebook using the preprocessor pymdpreprocessor.py as mentioned in the section "Installation". The generated notebook then has the data embedded in the markdown cell as an HTML tag of the form <img src="data:image/png;base64,..."> so you can delete the corresponding code cell from preprocessed_notebook.ipynb. Unfortunately, when I tried this the contents of the <img> tag weren't actually displayed in the browser, so not sure if this is a viable solution. :-/
A different option would be to use the Image class in a code cell to generate the image as above, and then use nbconvert with a custom template to remove code input cells from the notebook. See this thread for details. However, this will strip all code cells from the converted notebook, so it may not be what you want.
The reason why the
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnAAAAFgCAYAAAA...
tag doesn't do anything when you put it in a markdown cell is because IPython uses an HTML sanitizer (something called Google Caja) that screens out this type of tag (and many others) before it can be rendered.
The HTML sanitizer in IPython can be completely disabled by adding the following line to your custom.js file (usually located at ~/.ipython/profile_default/static/custom/custom.js):
iPython.security.sanitize_html = function (html) { return html; };
It's not a great solution though, as it does create a security risk, and it doesn't really help that much with distribution.
Postscript:
The ability to render base64 encoded strings as images != obvious security concern, so there should be a way for the Caja people to eventually allow this sort of thing through (although the related feature request ticket was first opened back in 2012, so don't hold your breath).
I figured out that replacing the image URL in the ![name](image) with a base64 URL, similar to the ones found above, can embed an image in a markdown container.
Example markdown:
![smile](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAD9JREFUGJW1jzEOADAIAqHx/1+mE4ltNXEpI3eJQknCIGsiHSLJB+aO/06PxOo/x2wBgKR2jCeEy0rOO6MDdzYQJRcVkl1NggAAAABJRU5ErkJggg==)
If using the IPython HTML() function to output raw HTML, you can embed a linked image in base64 inside an <img> tag using the following method:
import base64
import requests
from IPython.core.display import HTML
def embedded_image(url):
response = requests.get(url)
uri = ("data:" +
response.headers['Content-Type'] + ";" +
"base64," + str(base64.b64encode(response.content).decode('utf-8')))
return uri
# Here is a small example. When you export the notebook as HTML,
# the image will be embedded in the HTML file
html = f'<img src="{embedded_image("https://upload.wikimedia.org/wikipedia/commons/5/56/Kosaciec_szczecinkowaty_Iris_setosa.jpg")}" />'
HTML(html)
UPDATE: As pointed out by #alexis, this doesn't actually answer the question correctly, this will not allow users to re-run cells and have images persist (this solution only allows one to embed the images into exports).
As of Jupyter Notebook 5, you can attach image data to cells, and refer to them from the cell via attachment:<image-file-name>. See the menu Edit > Insert Image, or use drag and drop.
Unfortunately, when converting notebooks with attached (embedded) images to HTML, those images will not show up.
To get them into the HTML code, you can use (for instance) nbtoolbelt.
It will replace those attachment: references by data: with the image data embedded in the img tag.

Using CSS when converting Markdown to PDF with Pandoc

I'm trying out Pandoc on OS X, and results thus far are impressive. One blocking problem, however, is getting CSS styles to work on inline code samples. I'm converting from Markdown to PDF.
I have this string in my source:
* Create a simple HTML document (<span class="filename">simple.html</span>) and load it into the browser via the file system
I've also tried this:
* Create a simple HTML document (`simple.html`{.filename}) and load it into the browser via the file system
I'd like to apply the class "filename" to the enclosed text in each case, but it doesn't seem to do anything to the output. However the manual says:
Some output formats can use this information to do syntax highlighting. Currently, the only output formats that uses this information are HTML and LaTeX.
Here's my command:
pandoc \
--output ./output.pdf \
--css source/styles.css \
source/en/docs/input.md
I'm converting to PDF, which is written by LaTeX by Pandoc internally. Can I get this to work? Or, can I use a style defined using a LaTeX command? - it doesn't have to be CSS. However, it must be a style system - it's not workable to change italic/font/colour attributes on each occasion.
I've tried sending output temporarily to HTML, and in that situation the styles are imported directly from the specific style asset. So, my stylesheet specification and span markup is correct, at least for one output format.
Addenda
A couple of afterthoughts:
The solution does not have to be Pandoc or Markdown. However, it does need to be a trivial text-based markup language that can convert reliably to PDF, as I want to store the document files on Git for easy forking and merging. I'm not keen on HTML as it is verbose, and engines to convert it aren't that great (though, admittedly, my formatting requirements are modest).
The HTML output from Pandoc is fine, so if I can find something that converts the (simple) HTML/CSS to PDF reliably, I'll be fine. Of course, Pandoc should be able to do this, but inline styles (for the background colour on code fragments) aren't rendered. This might be a faff, as I'll have to reintroduce things like page-breaks, which can be non-trivial in HTML-to-PDF converters.
"I'd like to apply the class "filename" to the enclosed text in each case, but it doesn't seem to do anything to the output."
It works for HTML. Running Pandoc interactively, ^D to see the resulting code:
$> pandoc -f markdown -t html
* Create a simple HTML document (`simple.html`{.filename}) and load it.
^D
<ul>
<li>Create a simple HTML document (<code class="filename">simple.html</code>) and load it.</li>
</ul>
It doesn't work for LaTeX if you use the .filename class. You need to use one of the known classnames:
$> pandoc -f markdown -t latex
* Create a simple HTML document (`simple.html`{.filename}) and load it.
^D
\begin{itemize}
\tightlist
\item
Create a simple HTML document (\texttt{simple.html}) and load it.
\end{itemize}
Now using one of the known classnames, like .bash, .postscript, .php, ...:
$> pandoc -f markdown -t latex
* Create a simple HTML document (`simple.html`{.bash}) and load it.
^D
\begin{itemize}
\tightlist
\item
Create a simple HTML document (\VERB|\KeywordTok{simple.html}| and
load it.
\end{itemize}
To convert HTML + CSS into PDF, you can also look into PrinceXML, which is free for non-commercial use.
I don't know LaTeX at all, but have hacked this solution using this helpful manual. First, create a style:
\definecolor{silver}{RGB}{230,230,230}
\newcommand{\inlinecodeblock}[1]{
\colorbox{silver}{
\texttt{#1}
}
}
And here's how to use it:
Some \inlinecodeblock{inline code}, and some widgets, go here
This creates a style with a background colour and a monospaced font. The margin and padding are a bit large for my preferences, but it's a very useable start. Here's what it looks like:
The disadvantage is that if I wish to output to a format that supports styles proper (such as HTML) then these are lost. Also, my solution only works with LaTeX/PDF. Thus, if you can fix these issues, please add a better answer!
Addendum: I have a better approach, which is thus:
\newcommand{\inlinecodeblock}[1]{
\fboxsep 1pt
\fboxrule 0pt
\colorbox{silver}{\strut{\texttt{#1}}}
}
This avoids the problem of excess horizontal padding - I think it was the line break in the colorbox parameter that did it. I've added in strut, which keeps highlights the same height regardless of whether the text has descenders.
It's not perfect though - there's still too much horizontal margin outside the box, and a comma after a box will still orphan onto the next line. I may give up with LaTeX, and render to HTML from Pandoc, and then use wkhtmltopdf to render the final document.

Resources