Content Edit Plugin
Front end editing of the md contents (+
header.menu ) of web pages by authorised users.
The Content Edit Plugin is for Grav CMS. The plugin is designed for corporate websites where PR & marketing users want to update the visible parts of a site (the md contents and the
page.header.menu) without needing much technical training (a working knowledge of md is required, but is relatively simple). In addition, it is required that the users should NOT have any admin or supervisor permissions on the site. It is required only that they update existing md pages. Furthermore, it is required that different users can be given access to different pages. When multiple language files exist in a route, then all are made available for editing independent of the current active language.
Installing the Content Edit plugin can be done in one of two ways. The GPM (Grav Package Manager) installation method enables you to quickly and easily install the plugin with a simple terminal command, while the manual method enables you to do so via a zip file.
GPM Installation (Preferred)
The simplest way to install this plugin is via the Grav Package Manager (GPM) through your system's terminal (also called the command line). From the root of your Grav install type:
bin/gpm install content-edit
This will install the Content Edit plugin into your
/user/plugins directory within Grav. Its files can be found under
To install this plugin, just download the zip version of this repository and unzip it under
/your/site/grav/user/plugins. Then, rename the folder to
content-edit. You can find these files on GitHub or via GetGrav.org.
You should now have all the plugin files under
RECOMMENDATION: This plugin has been designed to be used in combination with the Admin and DataManager plugins.
If you use the admin plugin, you can install directly through the admin plugin by browsing the
Plugins tab and clicking on the
Before configuring this plugin, you should copy the
user/config/plugins/content-edit.yaml and only edit that copy.
Here is the default configuration and an explanation of available options:
enabled: true preview: enabled editReport: html_side_side
previewDisable to remove the preview window
editReportselects the renderer for differences between original and edited versions of pages. The four options are generated by the php-diff library.
All these options can be set in the Admin page.
Note that if you use the admin plugin, a file with your configuration, and named content-edit.yaml will be saved in the
user/config/plugins/ folder once the configuration is saved in the admin.
A special page is created to be rendered by the
content-edit template. Within the header of the page a page collection is created. The contents of this collection, or more precisely, the
routes to files with
.md content, is then displayed as a tree.
If there is only .md file with no language extension, then with a button for editing labeled 'Default' is shown.
If the route will generate html that can be previewed, then a label is shown, together with an anchor to open the page in another browser tab.
If there are language files with GRAV language extensions, then a selector button and anchor (if previewable) are shown for each language.
The screenshot shows the tree of pages, which pages can be edited, and which can be previewed (generate a valid page). Inclusion, Editing and Previewing can be turned off on a per route basis (see Granular Control).
Here some pages have two language files with extensions
Security is handled by the Login plugin. The page rendered with the
content-edit template to provide editing access SHOULD be protected by only granting access to users with specific permission. More about permissions can be found in the Login documentation.
Allowing for any frontend editing of content creates a vulnerability for hacking. This vulnerability is controlled through the Login plugin and setting access permissions on pages that expose content for editing.
A website developer should be aware that since arbitrary JS scripts can be included in md content, care must be taken to give editing permission to users.
For example, we specify one
group called editors and another called reviewers by creating
user/config/groups.yaml with the following content:
editors: groupname: 'editors' readableName: 'PR Staff' description: 'For managing corporate site' icon: 'pencil' access: site: login: 'true' edit: 'true' reviewers: groupname: 'reviewers' readableName: 'Oversight staff' description: 'review process for corporate site content' icon: eye access: site: login: 'true' review: 'true'
Note that we have not given
Next, we create the file
user/pages/site_editing/content-edit.md (for extra safety, remember that if the directory is not prefixed with a number, as per GRAV defaults, then it will not be visible in the menu, but can be navigated to in the browser URL bar; this means only users who know the route can find it):
--- title: Site edit content: items: '@root' access: site: edit ---
Now any user that belongs to the
editors group will be able to access
http://somecorporate.com/site_editing (assuming the GRAV starts in the www root).
For example, if we create a user called peter and under
email: firstname.lastname@example.org fullname: PP title: tester language: en groups: - editors hashed_password: qwertyuiop
The key item, of course, is groups. By being a member of the
editors group, the user gets
content-edit template will generate a page with a tree of pages and subpages, as described above. Each page is normally (see below for granular control) accompanied by an selector button, labeled either
Default for single language pages, or with the language extension for multi-language pages.
Once an edit button associated with a route is clicked, an instance of simpleMDE (generated by the simplemde Jquery plugin) is opened with the md content, eg.
When the content is edited, a Save button appears.
When the header of a page explicitly contains a menu item (in the example the source header contains
menu: 'British'), the text of the header is provided in a text box that can be edited. GRAV* provides a number of menu fall backs, but only
menu can be edited. If there is no
menu option, then the menu fallback is shown, but cannot be edited.
The language extension for the selected page is also shown with the editor.
In the example, a page is selected which cannot be previewed. When a previewable page is selected, a Preview button appears together with the Save button. Clicking on the Preview button will cause GRAV to generate the html for the route. The editor window is swapped for the preview window.
If the Preview option is disabled, the review button will not be visible.
Note that only changes that have been Saved will be visible in the Review section. Unsaved changes remain in the editor and are not transferred to the website source.
It is possible to link to a file and to insert an image. The file and image are uploaded and a shortcode link is inserted into the md code.
minus-square-o (in the image the cursor is hovering over the button) is provided to remove an image or link.
- To select the file to be deleted:
- Select the whole of the link text to be deleted, or
- Place the cursor inside the link text.
Then click the image delete button.
- The deletion can only be carried out if :
- the referenced file is in the same directory as the
*.mdfile (the developer can place images in other directories, but these are not exposed to a non-admin frontend user),
- the file can be deleted by the GRAV system (the correct ownership and permissions are set)
- the referenced file exists.
- the referenced file is in the same directory as the
- If a link is found for which no local file exists, the link text is deleted from the md file.
Page Collections and Different User Groups
All of the files in the
page.collection will be listed. More about collections can be found in Grav documentation.
If different groups of users are to be given access to different pages, then each page can be assigned some tag appropriate to the user group, and on the content-edit page for that group, the page collection can be created using the appropriate tag.
Currently, there has to be a separate content-edit page for each separate page collection because access is granted on a per page basis, not on a per collection basis.
Three options are provided on a per route basis. The following may appear in the header of the default language page:
contentEdit: noPreview: true noEdit: true dontInclude: false
Even though it is possible to fine-tune a page collection, there may be pages falling within the collection that should only be edited by a staff member with supervisor permissions.
dontInclude can be set to true if a page (and its children) should not be included at all in the route tree.
On each page that should not be edited, the option
contentEdit.noEdit should be enabled.
When a web page is created dynamically from a number of
*.md sources, then GRAV will probably generate an error if the browser is pointed to a sub-page. This is true for modular pages and for pages within a sequential-form.
content-edit plugin can detected a modular page, but cannot detect other forms of dynamic page. Consequently, the website developer needs to manually label such pages with
contentEdit.noPreview: true in the page header.
However, each of separate page within a modular page may contain md content that should be available for frontend editing. An selector button will be generated for each page in a modular page (provided that
contentEdit.noEdit: true is not present in that page's header).
All changes to pages are logged in a diff format in
user/data/content-edit/ in a file that has the month in the filename.
If Admin Plugin and DataManagerPlugin are installed, then
content-edit provides a template for viewing the editing by someone with
The php-diff library provides for two html and two text styles for rendering differences between edited and unedited files. These can be selected in the plugin options.
Note: the diff rendering is generated at the time edits are saved, not at the time edits are viewed. So if a change is made in diff renderer, old edits will be shown in the previous form.
Frontend monitoring can be provided by creating a route with a file
content-edit-review.md in it. (If the route is not prefixed with a digit, then GRAV will not show it in the navigation bar.)
Access to this page can also be controlled using group/users. For example, we create the file
review/content-edit-review.md with the content:
--- title: Edit Review access: site: review: true --- # Editing Applied to Site
Note that the access permission is the one granted in the
reviewers group above. For this example, we gave peter
review permission. The page generates the following
A month can be selected and the edits made in that month are shown. The detail of each edit (if appropriate) can be opened.
At present only one language is available. Most of the plugin can be translated, with the exception of text generated by the diff-library.
- GRAV, LOGIN, DataManager developers, of course.
- Credit is due to SimpleMDE for its embeddable md editor.
- A great deal of this plugin is inspired by, and chunks just copied from, the editable-simplemde plugin for GRAV. A very innovative plugin!
- For the php-diff library by Chris Boulton.
- For the simple Upload function by Michael Brook.
If a plugin other than
content-edit provides a custom template for DataManager, the one provided by
content-edit may not be used. In that case, the edits will show up as a standard yaml file. This issue does not affect the
- Provide a mechanism to sanitise tags that could generate active content in an md file.
- This will also require a mechanism to place into the page header such scripting / shortcode elements that the developer wants on the page.