How to embed <bottom-editor>, <bottom-exercise>, and <kara-editor>
inside common authoring platforms.
The bottomeditor DokuWiki plugin passes <bottom-editor>,
<bottom-exercise>, and <kara-editor> elements straight through the
renderer and injects the required JavaScript on any page that contains them.
No shortcode or special syntax is needed — authors write the elements directly
in the page source using DokuWiki's HTML mode.
The easiest way is the DokuWiki plugin manager:
Alternatively, download bottomeditor.zip and extract it
into lib/plugins/ so the result is lib/plugins/bottomeditor/plugin.info.txt.
Go to Admin → Configuration Settings → bottomeditor. The only setting is
base_url, which defaults to https://bottom.ch/editor/stable. Change it to
https://bottom.ch/editor/latest to track the latest build, or to a self-hosted URL.
Open a page in DokuWiki's source editor (not the WYSIWYG toolbar) and write elements directly:
<bottom-editor>
print("Hello from DokuWiki!")
</bottom-editor>
<bottom-exercise>
Write a function sum_to(n).
<script type="text/x-starter">
def sum_to(n):
pass
</script>
<script type="text/x-test">
assert sum_to(5) == 15
</script>
</bottom-exercise>
Note: Use the
<script type="text/x-starter">/<script type="text/x-test">syntax for exercise code blocks rather than<template>elements, as DokuWiki's HTML renderer may reformat<template>content.
An H5P content type is available for embedding exercises inside any H5P-enabled
platform (Moodle, DokuWiki with H5P plugin, standalone H5P.org, etc.). It wraps
<bottom-exercise> as a self-contained H5P activity that can be reused across
your content library.
H5P.BottomExercise-1.0.h5p.Once installed, add an H5P activity to your course or page, choose Bottom Exercise as the content type, then fill in the prompt, starter code, test code, and solution directly in the form — no HTML required.
Note: The H5P Hub (the public content type registry) is not currently supported. The content type must be installed by uploading the
.h5pfile directly, as described above.
Two complementary Moodle plugins are available.
mod_bottomeditorAdds a Python Exercise activity to the course activity chooser. Each instance is a single graded exercise on its own page. Student submissions are recorded in the Moodle gradebook.
mod_bottomeditor.zip.mod/ directory of your Moodle installation.In a course, Add activity → Python Exercise. Fill in the prompt, starter
code, test code, optional solution, and grading settings. The exercise is
rendered using the component loaded from the configured base URL
(https://bottom.ch/editor/stable by default — change it in the plugin
settings).
filter_bottomeditorEnables embedding exercises directly inside Page resources, Book chapters,
Labels, course descriptions, and any other place Moodle renders HTML.
Authors write <bottom-editor>, <bottom-exercise>, or <kara-editor> elements
directly in the HTML source; the filter injects the required scripts automatically.
filter_bottomeditor.zip.filter/ so the result is filter/bottomeditor/filter.php
(the Moodle web interface may not have write access to this directory;
use SSH/SFTP if needed).Moodle's HTML Purifier strips unknown custom elements when content is saved.
To preserve <bottom-exercise> etc., the author must have the
Trusted content capability (moodle/site:trustcontent):
moodle/site:trustcontent to the roles held by content authors
(e.g. Teacher, Manager).Without
trust:content, the custom element tags are stripped on save and the filter has nothing to work with. The filter only handles script injection; it does not bypass the save-time HTML Purifier.
Inside a Page resource or Book chapter, switch to the HTML source view and write elements directly:
<bottom-editor id="hello">
print("Hello from Moodle!")
</bottom-editor>
<bottom-exercise id="ex1">
Write a function sum_to(n).
<script type="text/x-starter">
def sum_to(n):
pass
</script>
<script type="text/x-test">
assert sum_to(5) == 15
</script>
</bottom-exercise>
The filter detects the elements and injects bottom-exercise.js and
kara-editor-page.js from the configured base URL once per page load.
If the same page already has an explicit <script> tag loading the component
(e.g. a different version), the filter's injection is suppressed to avoid a
double-registration error.