Markdown view in a project

Hi people,

I will start to develop a site and one of the features I want to add is to render markdown documents of some entities.
What would you say is the best CakePHP 3 approach to do it?
Do you know any plugin or standard way so solve it?

There’s a plugin for it but it hasn’t been updated in years (so might need some updates):

Hi,
Thanks for your answer. I’ll take a look at it.

Pick the PHP markdown parser library that suits your needs. Wrap it into in a light Helper as the plugin @FinlayDaG33k mentioned 1 does. Personally I prefer CommonMarkdown, so I use:

<?php

// ...

use Cake\View\Helper;
use League\CommonMark\CommonMarkConverter;
class CommonmarkHelper extends Helper
{
    protected $_converter;
    /**
     * Parse text as CommonMark
     *
     * @param string $text text to parse
     *
     * @return string
     */
    public function parse($text)
    {
        return $this->_getParser()->convertToHtml($text);
    }
    /**
     * Get parser
     *
     * @return CommonMarkConverter
     */
    protected function _getParser()
    {
        if ($this->_converter !== null) {
            return $this->_converter;
        }
        $this->_converter = new CommonMarkConverter();
        return $this->_converter;
    }
}

And then in the template:

echo $Commonmark->parse($markdownContent);

Hi Schlaefer, your answer is great and I think it applies the same logic exposed in the plugin that Finlay recommends.
I think I expressed my motivation very poorly in the first post. I don’t want to render Markdown documents. What I want to do is to generate Markdown code based on the data of an entity.
That means something like this https://github.com/FriendsOfCake/cakephp-csvview but for .md output instead of .csv
In fact, I think I have to do exactly what that plugin does.

Understood. In that case a custom view class is probably the right solution. The setup the csview plugin uses is mentioned in the docs here [1]. Then bring your own code to build the representation - in your case the markdown - from the entity.

[1] https://book.cakephp.org/3.0/en/views.html#creating-your-own-view-classes

Thanks Schlaefer. I’ll work it this way and post the results when it’s done!

Finally I implemented this view class:

<?php

namespace App\View;

use Cake\View\View;
use Cake\Datasource\EntityInterface;

class MarkdownView extends View
{



public function loadHelpers()
{
    if (isset($this->viewVars['_serialize'])) {
        return;
    }
    parent::loadHelpers();
}

public function render($view = null, $layout = null)
{
    if (isset($this->viewVars['_serialize'])) {
        return $this->_serialize();
    }
    if ($view !== false && $this->_getViewFileName($view)) {
        return parent::render($view, false);
    }
}

protected function _serialize()
{
    $content = "";
    if (isset($this->viewVars['_header'])) {
        $content = $this->_renderHeader($this->viewVars['_header']);
    }
    $vars = $this->_dataToSerialize($this->viewVars['_serialize']);
    $content = $content.$this->_renderContent($vars);
    return $content;
}

protected function _renderHeader(array $header) {
    $retval = "---\n\n";
    foreach ($header as $key => $value) {
        $retval = $retval.$key.": ".$value."\n";
    }
    $retval = $retval."\n\n---\n\n";
    return($retval);
}

protected function _renderContent(array $vars, $level = 0) {
    $retval = "";
    foreach ($vars as $key => $value) {
        if (!(strpos($key, "_") === 0) && !(strpos($key, "[") === 0) && !(strpos($key, "*") === 0))
        {
            if (is_array($value)) {
                $retval = $retval.str_repeat("#", $level + 1)." ".$key."\n\n";
                $retval = $retval.$this->_renderContent($value, $level + 1);
            } else if (is_object($value) && method_exists($value, "toArray")) {                    
                $var = $value->toArray();
                $retval = $retval.str_repeat("#", $level + 1)." ".$key."\n\n";
                $retval = $retval.$this->_renderContent($var, $level + 1);
            } else {
                $retval = $retval.str_repeat("#", $level + 1)." ".$key."\n\n";
                $retval = $retval."".$value."\n\n";
            }                
        }            
    }
    return($retval);
}

protected function _dataToSerialize($serialize = true)
{
    if ($serialize === true) {
        $data = array_diff_key(
            $this->viewVars,
            array_flip($this->_specialVars)
            );
        
        if (empty($data)) {
            return null;
        }
        
        return $data;
    }
    
    if (is_array($serialize)) {
        $data = [];
        foreach ($serialize as $alias => $key) {
            if (is_numeric($alias)) {
                $alias = $key;
            }
            if (array_key_exists($key, $this->viewVars)) {
                $data[$alias] = $this->viewVars[$key];
            }
        }
        
        return !empty($data) ? $data : null;
    }
    
    return isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
}
}

I didn’t make it very configurable and made a lot of assumptions. It works… but it’s main result is that I’m approaching this the wrong way. After doing this, I realize that this is not really a case of serialization, but a case of custom template for each entity. That will give me a lot of options to customize each markdown document.

I appreciate all of your points of view.