feat: integrated lesson markup

- added PageExtension plugin to inject custom styles scripts in a page
- removed the livecode integration and enabled PageExtension plugins for
  learn page
- also merged the profile_tab.py with plugins.py
- added a utility to find the macros from given text
- updated the before_save of lesson to find exercises using the macros
  and update the exercises as before

Issue #115
This commit is contained in:
Anand Chitipothu
2021-06-09 23:49:18 +05:30
parent 5363fb7eb3
commit d9185c0b6b
7 changed files with 145 additions and 93 deletions

View File

@@ -6,28 +6,28 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from ...section_parser import SectionParser
from ...md import markdown_to_html, find_macros
class Lesson(Document):
def before_save(self):
sections = SectionParser().parse(self.body or "")
self.sections = [self.make_lms_section(i, s) for i, s in enumerate(sections)]
macros = find_macros(self.body)
exercises = [value for name, value in macros if name == "Exercise"]
index = 1
for s in self.sections:
if s.type == "exercise":
e = s.get_exercise()
e.lesson = self.name
e.index_ = index
e.save()
index += 1
self.update_orphan_exercises()
for name in exercises:
e = frappe.get_doc("Exercise", name)
e.lesson = self.name
e.index_ = index
e.save()
index += 1
self.update_orphan_exercises(exercises)
def update_orphan_exercises(self):
def update_orphan_exercises(self, active_exercises):
"""Updates the exercises that were previously part of this lesson,
but not any more.
"""
linked_exercises = {row['name'] for row in frappe.get_all('Exercise', {"lesson": self.name})}
active_exercises = {s.id for s in self.get("sections") if s.type=="exercise"}
active_exercises = set(active_exercises)
orphan_exercises = linked_exercises - active_exercises
for name in orphan_exercises:
ex = frappe.get_doc("Exercise", name)
@@ -36,11 +36,19 @@ class Lesson(Document):
ex.index_label = ""
ex.save()
def render_html(self):
return markdown_to_html(self.body)
def get_sections(self):
return sorted(self.get('sections'), key=lambda s: s.index)
def get_exercises(self):
return [frappe.get_doc("Exercise", s.id) for s in self.get("sections") if s.type=="exercise"]
if not self.body:
return []
macros = find_macros(self.body)
exercises = [value for name, value in macros if name == "Exercise"]
return [frappe.get_doc("Exercise", name) for name in exercises]
def make_lms_section(self, index, section):
s = frappe.new_doc('LMS Section', parent_doc=self, parentfield='sections')

View File

@@ -26,13 +26,42 @@ def markdown_to_html(text):
"""
return markdown.markdown(text, extensions=['fenced_code', MacroExtension()])
def find_macros(text):
"""Returns all macros in the given text.
>>> find_macros(text)
[
('YouTubeVideo': 'abcd1234')
('Exercise', 'two-circles'),
('Exercise', 'four-circles')
]
"""
macros = re.findall(MACRO_RE, text)
# remove the quotes around the argument
return [(name, _remove_quotes(arg)) for name, arg in macros]
def _remove_quotes(value):
"""Removes quotes around a value.
Also strips the whitespace.
>>> _remove_quotes('"hello"')
'hello'
>>> _remove_quotes("'hello'")
'hello'
>>> _remove_quotes("hello")
'hello'
"""
return value.strip(" '\"")
def get_macro_registry():
d = frappe.get_hooks("community_markdown_macro_renderers") or {}
return {name: frappe.get_attr(klass[0]) for name, klass in d.items()}
def render_macro(macro_name, macro_argument):
# stripping the quotes on either side of the argument
macro_argument = macro_argument.strip(" '\"")
macro_argument = _remove_quotes(macro_argument)
registry = get_macro_registry()
if macro_name in registry:
@@ -40,13 +69,13 @@ def render_macro(macro_name, macro_argument):
else:
return f"<p>Unknown macro: {macro_name}</p>"
MACRO_RE = r'{{ *(\w+)\(([^{}]*)\) *}}'
class MacroExtension(Extension):
"""MacroExtension is a markdown extension to support macro syntax.
"""
def extendMarkdown(self, md):
self.md = md
MACRO_RE = r'{{ *(\w+)\(([^{}]*)\) *}}'
pattern = MacroInlineProcessor(MACRO_RE)
pattern.md = md
md.inlinePatterns.register(pattern, 'macro', 75)