diff --git a/aplus_setup.py b/aplus_setup.py index 00347ac..3053931 100644 --- a/aplus_setup.py +++ b/aplus_setup.py @@ -36,6 +36,7 @@ def setup(app): app.add_config_value('append_content', [], 'html') app.add_config_value('override', {}, 'html') app.add_config_value('category_names', {}, 'html') + app.add_config_value('categories', {}, 'html') app.add_config_value('static_host', None, 'html') app.add_config_value('ae_default_submissions', 0, 'html') app.add_config_value('skip_language_inconsistencies', False, 'html') diff --git a/directives/ae_output.py b/directives/ae_output.py index 1d68ddd..d495211 100644 --- a/directives/ae_output.py +++ b/directives/ae_output.py @@ -3,6 +3,8 @@ Directive that places active element output divs. ''' import os.path +from typing import Any, Dict + from docutils.parsers.rst import directives from docutils import nodes from sphinx.errors import SphinxError @@ -84,6 +86,7 @@ def run(self): key_title = "{} {}".format(translations.get(env, 'exercise'), key) # Load or create exercise configuration. + data: Dict[str, Any] if 'config' in self.options: path = os.path.join(env.app.srcdir, self.options['config']) if not os.path.exists(path): @@ -106,9 +109,18 @@ def run(self): 'title': env.config.submit_title.format( key_title=key_title, config_title=config_title ), - 'category': 'active elements', 'max_submissions': self.options.get('submissions', data.get('max_submissions', env.config.ae_default_submissions)), }) + + if "category" in self.options: + data["category"] = self.options["category"] + elif "category" not in data: + data["category"] = ( + "active elements" + if data["max_submissions"] == 0 else + "active elements with max submissions" + ) + data.setdefault('status', self.options.get('status', 'unlisted')) self.apply_override(data, category) diff --git a/toc_config.py b/toc_config.py index 93ca103..dbc5bed 100644 --- a/toc_config.py +++ b/toc_config.py @@ -395,15 +395,31 @@ def parse_chapter(docname, doc, parent, module_meta): # Create categories. category_names = app.config.category_names + for key, name in category_names.items(): + category = app.config.categories.get(key, {"name": name}) + if name != category.get("name", name): + raise SphinxError(f"Name mismatch between config options 'category_names' and 'categories' for key '{key}': '{name}' vs '{category['name']}'") + categories = { key: { 'name': category_names.get(key, key), } for key in category_keys } + + for key, category in app.config.categories.items(): + if key not in categories: + raise SphinxError(f"Category with key '{key}' was configured but not used in the material") + + categories[key].update(category) + for key in ['chapter', 'feedback']: if key in categories: - categories[key]['status'] = 'nototal' + categories[key].setdefault('status', 'nototal') + + if "active elements" in categories: + categories["active elements"].setdefault("accept_unofficial_submits", True) + # Set unprotected paths unprotected_paths = course_meta.get('unprotected-paths', app.config.unprotected_paths) if isinstance(unprotected_paths, str): unprotected_paths = shlex.split(unprotected_paths)