I definitely could use a markdown editor field type in my Laravel admin tool Laramanager. So I decided to add one to the core. In a previous version of Laramanager, there was one. However, this was bundled into UIKit 2. The latest verion of LaraManager uses UIKit 3 which did not carry over the HTML/Markdown editor. So, I took a look at a few options for a new editor and parser and didn't find anything I liked that worked "out of the box". So, I decided to build my own with some really great existing JS packages.
I decided to try out CodeMirror (codemirror.net) for the editor. To get started I'll start by installing the codemirror node package in Laramanager.
npm install codemirror --save
Now I want to load the modes/languages for this package. Just for now, I'm going to load the main modes I will use. Maybe in the future I'll build a few options for accomidating more. But for now I'm just going to load JS, PHP, XML/HTML and GFM (Github Flavored Markdown) modes.
assets/js/scripts.js
window.codemirror = require('codemirror');
require('codemirror/mode/markdown/markdown');
require('codemirror/mode/gfm/gfm');
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/php/php');
require('codemirror/mode/xml/xml');
Now I'm going to make a new field directory in the core fields in Laramanager.
src/views/fields/markdown
In this directory there are 4 files that are supported for any core field.
- display.blade.php (Required) This view renders the value in the field on the admin side.
- field.blade.php (Required) This view renders the form input(s) for the field.
- scripts.blade.php Scripts required by the field
- options.blade.php Generally fields are presented in this view when the field needs additional information.
I will need all but the options.blade.php
view and will start with the field.blade.php
view.
src/views/fields/markdown/field.blade.php
@include('laramanager::partials.elements.form.textarea', [
'field' => [
'name' => $field->slug,
'class' => 'field-markdown',
'value' => isset($entity) ? $entity->{$field->slug} : null
]
])
Notice that I am using a form helper built into the LaraManager core. Now I'll add it to the list of fields.
src/Philsquare/LaraManager/Http/Controllers/ResourceFieldController.php
class ResourceFieldController extends Controller {
protected $fields = [
'text' => 'Text',
'email' => 'Email',
'slug' => 'Slug',
'password' => 'Password',
'image' => 'Image',
'images' => 'Images',
'checkbox' => 'Checkbox',
'textarea' => 'Textarea',
'wysiwyg' => 'WYSIWYG',
'select' => 'Select',
'date' => 'Date',
'relational' => 'Relational',
'markdown' => 'Markdown'
// 'html' => 'HTML'
];
...
}
This controller will pass this list into the field create view which contains the field type dropdown list.
Ok, that is enough for me to start testing it out. But first, I need to create a new resource for testing this field in LaraManager. I'll do this by setting up a posts table with a text column called body, add a "Post" model and then add it as a resource (https://laramanager.philmareu.com/docs/resources).
The field shows up in the list, so that's great. Let's see if this field type will get added as a field.
Well, I was able to save the field to this resourse. Excellent. Now to try and use the editor when adding a new entry.
It looks like a plain textarea field. This makes sense, I haven't initiated the editor. I'll need to add the appropriate JS to the script.blade.php
view file to make this happen.
src/views/fields/markdown/scripts.blade.php
<script>
_.forEach(document.getElementsByClassName('field-markdown'), function(field) {
codemirror.fromTextArea(field, {
mode: 'gfm',
theme: "default",
extraKeys: {"Enter": "newlineAndIndentContinueMarkdownList"}
})
});
</script>
After refreshing the page the field seems to be working! Looks like it could use a border and some other style adjustments. But I won't worry about that now.
One more thing, I need the display.blade.php
view. This view is basically the preview of the content used by a few panels in the admin.
src/views/fields/markdown/display.blade.php
<div id="markdown-display-{{ $field->id }}">
{!! Parsedown::instance()->text($entity->{$field->slug}) !!}
</div>
Here I am using the PHP parser Laravel uses for parsing email templates. Super simple.
This is a good stopping point. In another post, I will add a full-screen mode and the ability to preview the markdown in rendered HTML.