{"id":3629,"date":"2020-05-26T15:54:56","date_gmt":"2020-05-26T21:54:56","guid":{"rendered":"http:\/\/bililite.com\/blog\/?p=3629"},"modified":"2022-07-11T11:04:49","modified_gmt":"2022-07-11T17:04:49","slug":"extending-parsedown-block-elements","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2020\/05\/26\/extending-parsedown-block-elements\/","title":{"rendered":"Extending Parsedown: Block elements"},"content":{"rendered":"<p>Continuing work on extending <a href=\"http:\/\/bililite.com\/blog\/2020\/05\/22\/extending-parsedown\/\">Parsedown<\/a>.<\/p>\n<p><a href=https:\/\/github.com\/dwachss\/kavanotparsedown>See the actual code<\/a>.<\/p>\n<p>Adding block-level elements is not much different <a href=\"http:\/\/bililite.com\/blog\/2020\/05\/26\/extending-parsedown-inline-elements\/\">from adding inline elements<\/a>. <a href=\"http:\/\/kavanot.name\">Kavanot.name<\/a> originally used <code class=\"language-html\" >&lt;footer&gt;<\/code> elements to indicate the source of a block quote:<\/p>\n<pre><code class=\"language-html\" >&lt;blockquote&gt;\r\n    Do or do not. There is no try.\r\n  &lt;\/blockquote&gt;\r\n  &lt;footer&gt;Yoda&lt;\/footer&gt;\r\n&lt;\/blockquote&gt;\r\n<\/code><\/pre>\n<p><a href=\"http:\/\/html5doctor.com\/cite-and-blockquote-reloaded\/\">While marking blockquotes this way is now acceptable<\/a>, for a long time it wasn't, and <a href=\"https:\/\/html.spec.whatwg.org\/multipage\/grouping-content.html#the-blockquote-element:the-blockquote-element-4\">the recommended way<\/a> was with <code class=\"language-html\" >&lt;figure&gt; and &lt;figcaption&gt;<\/code>. KavanotParsedown uses the latter model:<\/p>\n<pre><code class=\"language-html\" >&lt;figure&gt;\r\n  &lt;blockquote&gt;\r\n    Do or do not. There is no try.\r\n  &lt;figcaption&gt;Yoda&lt;\/figcaption&gt;\r\n&lt;figure&gt;\r\n<\/code><\/pre>\n<p>But I start with creating a <code class=\"language-html\" >&lt;footer&gt;<\/code> and then modifying the DOM. So I want to have a block element that I will indicate with <code class=\"language-php\" >\"--\"<\/code> at the start of the line.<\/p>\n<pre><code class=\"language-php\" >function __construct(){\r\n  $this->BlockTypes['-'][] = 'Source'; \/\/ only line needed to indicate a block level element\r\n  \/\/ ... rest of the constructor\r\n}\r\n\r\nprotected function blockSource($Line, $Block = null){\r\n  if (preg_match('\/^--[ ]*(.+)\/', $Line['text'], $matches)) {\r\n    return array(\r\n      'element' => array(\r\n        'name' => 'footer',\r\n        'handler' => array(\r\n          'function' => 'lineElements',\r\n          'argument' => $matches[1],\r\n          'destination' => 'elements'\r\n        ),\r\n        'attributes' => array('class' => 'source') \/\/ for styling, add a class automatically\r\n      )\r\n    );\r\n  }\r\n}\r\n\r\n<\/code><\/pre>\n<p>so <\/p>\n<pre><code class=\"language-markdown\" >&gt;Do or do not. There is no try.\r\n--Yoda<\/code><\/pre>\n<p>becomes<\/p>\n<pre><code class=\"language-html\" >&lt;blockquote&gt;\r\n    Do or do not. There is no try.\r\n  &lt;footer class=\"source\" &gt;Yoda&lt;\/footer&gt;\r\n&lt;\/blockquote&gt;<\/code><\/pre>\n<p>I realized that I might want to add an attribution to an image as well, without it being in a <code class=\"language-html\" >&lt;blockquote&gt;<\/code>, as <\/p>\n<pre><code class=\"language-markdown\" >&lt;p&gt;\r\n  &lt;img src=\/blog\/blogfiles\/pdf\/smiley.png alt=\"Smile!\"\/&gt;\r\n  &lt;footer class=\"source\" &gt;Some file I found on the web&lt;\/footer&gt;\r\n&lt;\/p&gt;\r\n<\/code><\/pre>\n<p>But as it stands, <\/p>\n<pre><code class=\"language-markdown\" >[Smile!](\/blog\/blogfiles\/pdf\/smiley.png)\r\n--Some file I found on the web<\/code><\/pre>\n<p>doesn't work; the <code class=\"language-html\" >&lt;p&gt;<\/code> ends before the <code class=\"language-html\" >&lt;footer&gt;<\/code> starts:<\/p>\n<pre><code class=\"language-markdown\" >&lt;p&gt;\r\n  &lt;img src=\/blog\/blogfiles\/pdf\/smiley.png alt=\"Smile!\"\/&gt;\r\n&lt;\/p&gt;\r\n&lt;footer class=\"source\" &gt;Some file I found on the web&lt;\/footer&gt;\r\n<\/code><\/pre>\n<p>so we need to check that the previous block wasn't a paragraph. If it was, then parse this line and add it to the paragraph as an internal element:<\/p>\n<pre><code class=\"language-php\" >protected function blockSource($Line, $Block = null){\r\n  if (preg_match('\/^--[ ]*(.+)\/', $Line['text'], $matches)) {\r\n    if ($Block && $Block['type'] === 'Paragraph'){\r\n      $Block['element']['handler']['argument'] .= \"\\n\".$this->element($this->blockSource($Line)['element']);\r\n      return $Block;\r\n    }\r\n    return array(\r\n      'element' => array(\r\n        'name' => 'footer',\r\n        'handler' => array(\r\n          'function' => 'lineElements',\r\n          'argument' => $matches[1],\r\n          'destination' => 'elements'\r\n        ),\r\n        'attributes' => array('class' => 'source') \/\/ for styling, add a class automatically\r\n      )\r\n    );\r\n  }\r\n}<\/code><\/pre>\n<p>and now it works, except that the footer is a child of the <code class=\"language-html\" >&lt;p&gt;<\/code> instead of the <code class=\"language-html\" >&lt;blockquote&gt;<\/code>. We'll have to fix that.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuing work on extending Parsedown. See the actual code. Adding block-level elements is not much different from adding inline elements. Kavanot.name originally used &lt;footer&gt; elements to indicate the source of a block quote: &lt;blockquote&gt; Do or do not. There is no try. &lt;\/blockquote&gt; &lt;footer&gt;Yoda&lt;\/footer&gt; &lt;\/blockquote&gt; While marking blockquotes this way is now acceptable, for a [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,9],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/3629"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=3629"}],"version-history":[{"count":8,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/3629\/revisions"}],"predecessor-version":[{"id":3638,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/3629\/revisions\/3638"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=3629"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=3629"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=3629"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}