Customize Kpimark
In order to customize course output you’re able to use Kpimark extensions API.
Basically, the only API for extending Kpimark are @register_renderer(renderer)
and @register_validator
decorators. Register renderer takes one argument, which is basically renderer
, which is going to be replaced during runtime Kpimark initialization in it4kt-builder.
Example
Kpimark gives you possibility to take control of markdown parsing process. While building a course you have option to provide init.py
file from root of your course directory.
Let’s say that we would like to add new block token for solution admonition. Generally, there are two main goals that needs to be done:
- Create a new token for document parsing
- Provide renderer method which translates token’s content to desired output.
Declare a new token
In order to achieve these goals you can start with following code inside init.py
:
from it4kt.kpimark.tokens.admonitions import AdmonitionBlock
class SolutionBlock(AdmonitionBlock):
ALERT_TYPES = ["solution", "riešenie"]
@classmethod
def start(cls, line):
return super().start(line, cls.ALERT_TYPES)
In this first step we are importing some basic stuff from it4kt-builder. We aim to provide new admonition so our token’s class shoudl extend AdmonitionBlock
. Then, we provide match keywords to ALERT_TYPES
static class variable, which our block is going to use during matching process.
Note
Every block token can implement start(cls, line)
to match beginning of the block from document lines and read(cls, lines)
method in order to declare way in which your token is parsing lines from document.
Declare renderer method
We have declared our new Token and first goal is achieved. Now, for the second goal we are going to implement a new HTML renderer, which is resposible for HTML output generation:
...
from it4kt.kpimark.extension import register_renderer
from it4kt.kpimark.renderers.html import KpimarkHTMLRenderer
...
@register_renderer(KpimarkHTMLRenderer)
class ExtendedRenderer(KpimarkHTMLRenderer):
TOKENS_EXTENDED = [SolutionBlock]
def render_solution_block(self, token):
return self.render_admonition(token, "solution", heading="Solution")
We’ve just created our custom HTML renderer, which is going to replace basic KpimarkHTMLRenderer during runtime. We implemented rendering method for SolutionBlock
, which we’ve defined earlier.
Warning
User can provide only one custom renderer for every output-related renderer. In any other case an exception is going to be raised.
As our goal was to implement admonition we are able to use base render_admonition()
method from KpimarkHTMLRenderer
.
Tip
User has also possibility to edit only rendering process of the token if he needs to. To achieve this behavior you only need to override already existing token’s rendering method.
Internationalization
If you would like to provide localized keyword you can use i18n
global instance.
...
from it4kt import i18n
...
@register_renderer(KpimarkHTMLRenderer)
class CustomHTMLRenderer(KpimarkHTMLRenderer):
TOKENS_EXTENDED = [SolutionBlock]
def render_solution_block(self, token):
if i18n.language == "sk":
heading = "Riešenie"
else:
heading = "Solution"
return self.render_admonition(token, "solution", heading=heading)
In example above we are setting admonition header by current translation language.
Note
Keep in mind that you can provide translation string for every language defined in your course configuration and supported by it4kt-builder. For more about localization check it’s recipe page.
Validate defined token
User is also able to define validation method for any of the tokens.
...
from it4kt.kpimark.extension import register_validator
from it4kt.kpimark.validation.validator import Validator
...
@register_validator
class ExtendedValidator(Validator):
TOKENS_EXTENDED = [SolutionBlock]
def validate_solution_block(self, token):
pass
Warning
User can provide only provide single validator class. In any other case an exception is going to be raised.
Code used in example
from it4kt.kpimark.tokens.admonitions import AdmonitionBlock
from it4kt.kpimark.extension import register_validator
from it4kt.kpimark.validation.validator import Validator
from it4kt import i18n
class SolutionBlock(AdmonitionBlock):
ALERT_TYPES = ["solution", "riešenie"]
@classmethod
def start(cls, line):
return super().start(line, cls.ALERT_TYPES)
@register_renderer(KpimarkHTMLRenderer)
class ExtendedRenderer(KpimarkHTMLRenderer):
TOKENS_EXTENDED = [SolutionBlock]
def render_solution_block(self, token):
if i18n.language == "sk":
heading = "Riešenie"
else:
heading = "Solution"
return self.render_admonition(token, "solution", heading=heading)
@register_validator
class ExtendedValidator(Validator):
TOKENS_EXTENDED = [SolutionBlock]
def validate_solution_block(self, token):
pass