Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 224 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,228 @@
*.egg-info
# ** .gitignore for mu **

TODO
/dist

/examples/olx.tar.gz
/examples_output
muenv
.DS_Store

# ** .gitignore for python **

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py.cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
# Pipfile.lock

# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# uv.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
# poetry.lock
# poetry.toml

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
# pdm.lock
# pdm.toml
.pdm-python
.pdm-build/

# pixi
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
# pixi.lock
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
# in the .venv directory. It is recommended not to include this directory in version control.
.pixi

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# Redis
*.rdb
*.aof
*.pid

# RabbitMQ
mnesia/
rabbitmq/
rabbitmq-data/

# ActiveMQ
activemq-data/

# SageMath parsed files
*.sage.py

# Environments
.env
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
# .idea/

# Abstra
# Abstra is an AI-powered process automation framework.
# Ignore directories containing user credentials, local state, and settings.
# Learn more at https://abstra.io/docs
.abstra/

# Visual Studio Code
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
# and can be added to the global gitignore or merged into this file. However, if you prefer,
# you could uncomment the following to ignore the entire vscode folder
# .vscode/

# Ruff stuff:
.ruff_cache/

# PyPI configuration file
.pypirc

# Marimo
marimo/_static/
marimo/_lsp/
__marimo__/

# Streamlit
.streamlit/secrets.toml
105 changes: 103 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,45 @@ Mu is for authors of online courses. It allows you to cross-compile courses from

Supported formats:

- [Markdown](https://daringfireball.net/projects/markdown/): with [Pandoc-flavoured](https://garrettgman.github.io/rmarkdown/authoring_pandoc_markdown.html) header attributes.
- [Markdown](https://daringfireball.net/projects/markdown/): single file with [Pandoc-flavoured](https://garrettgman.github.io/rmarkdown/authoring_pandoc_markdown.html) header attributes.
- [Folder Markdown](#folder-markdown): organized folder structure with multiple Markdown files.
- HTML 5
- Open Learning XML ([OLX](https://docs.openedx.org/en/latest/educators/navigation/olx.html)) from [Open edX](https://openedx.org).

Check out the [course.md](https://github.com/overhangio/mu/blob/main/examples/course.md) file to see what an actual course in Markdown format looks like.
Check out the [course.md](https://github.com/overhangio/mu/blob/main/examples/course.md) file to see what an actual course in single-file Markdown format looks like.

## Installation

### Using PyPI (latest stable release)

pip install mu-courses

### Using the development version from source

Since the PyPI version may not include the latest features and fixes, you can install directly from the repository:

1. Clone the repository:
```bash
git clone https://github.com/overhangio/mu.git
cd mu
```

2. Create a virtual environment:
```bash
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```

3. Install in editable mode with development dependencies:
```bash
pip install -e .
```

Alternatively, if you only want the latest features without development tools:
```bash
pip install -e .
```

Conversion from and to Markdown is handled with the help of [Pandoc](https://pandoc.org/). Thus, a recent version of Pandoc is required when working with Markdown documents. See the corresponding [installation instructions](https://pandoc.org/installing.html).

## Usage
Expand All @@ -28,6 +57,78 @@ Conversion from and to Markdown is handled with the help of [Pandoc](https://pan

When writing Markdown files, the generated documents will include non-standard (but widely recognized) [header identifiers](https://garrettgman.github.io/rmarkdown/authoring_pandoc_markdown.html#header-identifiers) to store the course unit attributes.

### Folder Markdown

For large courses, you can organize your content across multiple Markdown files in a folder structure instead of a single file. This is useful for team collaboration and better file organization.

**Folder structure:**

```
course_folder/
├── index.md # Course metadata and description
├── chapter1/
│ ├── index.md # Chapter metadata
│ ├── sequential1/
│ │ ├── index.md # Sequential metadata
│ │ ├── unit1.md # Content units
│ │ └── unit2.md
│ └── sequential2/
│ └── ...
└── chapter2/
└── ...
```

**File format:** Each Markdown file can include optional YAML frontmatter for metadata:

```yaml
---
title: My Unit Title
order: 1
hidden: false
---


```

**Metadata fields:**
- `title`: Display name (uses filename if not specified)
- `order`: Numeric ordering (default: 9999, sorted ascending)
- `hidden` or `draft`: Set to `true` to exclude from compilation
- `org`, `course`, `url_name`: Available at course level for OLX metadata

**Important:** Course, chapter, and sequential `index.md` files should contain only frontmatter. Any text in the body of these files will be ignored with a warning. If you need to add notes or comments for organization, use HTML comments:

```markdown
---
title: Chapter 1
order: 1
---

<!-- This is an internal note and will be ignored -->
```

Only unit files (non-index markdown files within sequentials) should contain actual content in their body.

**Usage:**

```bash
# Compile folder markdown to single markdown
mu /path/to/course_folder /path/to/compiled.md

# Or directly to OLX
mu /path/to/course_folder /path/to/olx/
```

**Debug mode:**

To debug the folder markdown compilation process, set the `MU_DEBUG_FOLDER_MD` environment variable:

```bash
MU_DEBUG_FOLDER_MD=1 mu /path/to/course_folder /path/to/olx/
```

This will keep the temporary merged markdown file and print its location to the console, allowing you to inspect the intermediate merged markdown before it's converted to the target format.

## Examples

Example courses are provided in the [examples](./examples) directory.
Expand Down
Binary file added examples/course_folder/chapter_1/.DS_Store
Binary file not shown.
6 changes: 6 additions & 0 deletions examples/course_folder/chapter_1/Sequential_1_1/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Sequential 1_1
order: 1
---

<!-- In this sequential, you will see the syllabus and solve some problems. -->
32 changes: 32 additions & 0 deletions examples/course_folder/chapter_1/Sequential_1_1/problems.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: Problems
order: 3
---


::: {mu-type=mcq}

#### Multiple choice question

What is the answer to Life, the Universe, and Everything?

* ✅ 6 x 7
* ❌ 666
* ❌ 0
* ✅ 42

:::

::: {mu-type=ftq}

#### Free text question

How many legs does a healthy snake have?

<!-- All accepted answers are listed below -->

* None
* Zero
* 0

:::
Loading