<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/tinkr-editing-markdown-documents-using-xml-tools/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://ropensci.org/technotes/2018/10/01/tinkr/"> rOpenSci - open tools for open science</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Remember our recent post showing that <a rel="nofollow" href="https://ropensci.org/technotes/2018/09/05/commonmark/" target="_blank">one can wrangle Markdown files<br>
programmatically without regex</a>? That<br>
tech note showed how to convert Markdown bodies to XML in order to<br>
extract information from them. Now, this post goes one step further and<br>
presents <a rel="nofollow" href="https://github.com/ropenscilabs/tinkr" target="_blank"><code>tinkr</code></a>, a package for<br>
converting .md and .Rmd files to XML, editing them, and… <strong>writing them<br>
back as Markdown</strong>!</p>
<h2>General <code>tinkr</code> workflow</h2>
<p>The goal of <code>tinkr</code> is to convert Markdown files to XML and back to<br>
allow their editing with <code>xml2</code> (XPath!) instead of numerous complicated<br>
regular expressions. The XML represents the full Markdown <a rel="nofollow" href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_blank">syntax tree<br>
(or AST)</a>. <a rel="nofollow" href="https://www.w3schools.com/xml/xpath_intro.asp" target="_blank">If new<br>
to XPath refer to this great<br>
intro</a>. The package<br>
offers two functions, <code>to_xml</code> and <code>to_md</code>.</p>
<p>The current workflow for editing .md and .Rmd with <code>tinkr</code> is</p>
<ol>
<li>
<p>use <code>to_xml</code> to obtain XML from Markdown (<em>based on<br>
<code>commonmark::markdown_xml</code> and <code>blogdown:::split_yaml_body</code></em>).</p>
</li>
<li>
<p>edit the XML using <code>xml2</code>.</p>
</li>
<li>
<p>use <code>to_md</code> to save back the resulting Markdown (<em>this uses a XSLT<br>
stylesheet, and <a rel="nofollow" href="https://github.com/ropensci/xslt" target="_blank">the <code>xslt</code><br>
package</a></em>).</p>
</li>
</ol>
<p>Maybe there could be shortcuts functions for some operations in 2, maybe<br>
not.</p>
<p>The md to XML to md loop on which <code>tinkr</code> is based is slightly lossy<br>
because of Markdown syntax redundancy. For instance</p>
<ul>
<li>
<p>lists can be created with either “+”, “-” or “*“. When using<br>
<code>tinkr</code>, the md after editing will only use”-” for lists.</p>
</li>
<li>
<p>Links built like <code>[word][smallref]</code> and bottom <code>[smallref]: URL</code><br>
become <code>[word](URL)</code>.</p>
</li>
<li>
<p>Characters are escaped (e.g. “[” when not for a link).</p>
</li>
<li>
<p>Block quotes lines all get “>” whereas in the input only the<br>
first could have a “>” at the beginning of the first line.</p>
</li>
<li>
<p>Tables are no longer pretty, i.e. each header is followed by three<br>
dashes no matter the length of the longest string in the column. See<br>
<a rel="nofollow" href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#tables" target="_blank">this<br>
cheatsheet</a>.</p>
</li>
</ul>
<p>Such losses make your Markdown file different, and the git diff a bit<br>
harder to parse, but should <em>not</em> change the documents your .md or .Rmd<br>
is rendered to. If it does, report a bug in the <a rel="nofollow" href="https://github.com/ropenscilabs/tinkr/issues" target="_blank">issue<br>
tracker</a>! And in any case,<br>
as mentioned in the docs of the <a rel="nofollow" href="https://github.com/lockedata/namer" target="_blank"><code>namer</code><br>
package</a>, such programmatic Markdown<br>
editing is best paired with <a rel="nofollow" href="http://happygitwithr.com/" target="_blank">version<br>
control</a>.</p>
<p>A solution to not loose your Markdown style, e.g. your preferring “*“<br>
over “-” for lists is to tweak <a rel="nofollow" href="https://ropensci.org/technotes/2018/10/01/tinkr/inst/extdata/xml2md_gfm.xsl" target="_blank">our XSL<br>
stylesheet</a> and provide its filepath as<br>
<code>stylesheet_path</code> argument to <code>to_md</code>.</p>
<p>If you want to read more technical details, head over to <a rel="nofollow" href="https://ropensci.org/technotes/2018/10/01/tinkr/#tinkr-under-the-hood" target="_blank">that<br>
section</a>. But we’ll show examples first!</p>
<h2>A few <code>tinkr</code> examples</h2>
<p>Since <code>tinkr</code> is still a toddler package, it’s available <a rel="nofollow" href="https://github.com/ropenscilabs/tinkr" target="_blank">from GitHub<br>
only</a>.</p>
<pre><code>remotes::install_github(&quot;ropenscilabs/tinkr&quot;)
</code></pre>
<h3>Use <code>tinkr</code> to change header level</h3>
<p>We read “example1.md”, change all headers 3 to headers 1, and save it<br>
back to md.</p>
<pre><code># From Markdown to XML
path &lt;- system.file(&quot;extdata&quot;, &quot;example1.md&quot;, package = &quot;tinkr&quot;)
(yaml_xml_list &lt;- tinkr::to_xml(path))
</code></pre>
<pre><code>## $yaml
##  [1] &quot;---&quot;                                                                                                                                                                                                                                                                             
##  [2] &quot;title: \&quot;What have these birds been studied for? Querying science outputs with R\&quot;&quot;                                                                                                                                                                                              
##  [3] &quot;slug: birds-science&quot;                                                                                                                                                                                                                                                             
##  [4] &quot;authors:&quot;                                                                                                                                                                                                                                                                        
##  [5] &quot;  - name: Maëlle Salmon&quot;                                                                                                                                                                                                                                                         
##  [6] &quot;    url: https://masalmon.eu/&quot;                                                                                                                                                                                                                                                   
##  [7] &quot;date: 2018-09-11&quot;                                                                                                                                                                                                                                                                
##  [8] &quot;topicid: 1347&quot;                                                                                                                                                                                                                                                                   
##  [9] &quot;preface: The blog post series corresponds to the material for a talk Maëlle will give at the [Animal Movement Analysis summer school in Radolfzell, Germany on September the 12th](http://animove.org/animove-2019-evening-keynotes/), in a Max Planck Institute of Ornithology.&quot;
## [10] &quot;tags:&quot;                                                                                                                                                                                                                                                                           
## [11] &quot;- rebird&quot;                                                                                                                                                                                                                                                                        
## [12] &quot;- birder&quot;                                                                                                                                                                                                                                                                        
## [13] &quot;- fulltext&quot;                                                                                                                                                                                                                                                                      
## [14] &quot;- dataone&quot;                                                                                                                                                                                                                                                                       
## [15] &quot;- EML&quot;                                                                                                                                                                                                                                                                           
## [16] &quot;- literature&quot;                                                                                                                                                                                                                                                                    
## [17] &quot;output:&quot;                                                                                                                                                                                                                                                                         
## [18] &quot;  md_document:&quot;                                                                                                                                                                                                                                                                  
## [19] &quot;    variant: markdown_github&quot;                                                                                                                                                                                                                                                    
## [20] &quot;    preserve_yaml: true&quot;                                                                                                                                                                                                                                                         
## [21] &quot;---&quot;                                                                                                                                                                                                                                                                             
## 
## $body
## {xml_document}
## </code></pre>