# Developer Guide

This document explains how to work with the source files, run tests, and build
the final `README.md` that is consumed by LiaScript.

---

## Table of Contents

1. [Prerequisites](#prerequisites)
2. [Project structure](#project-structure)
3. [Building README.md](#building-readmemd)
4. [Running the tests](#running-the-tests)
5. [How the build works](#how-the-build-works)
6. [Adding or modifying a macro](#adding-or-modifying-a-macro)
7. [Editing the quiz logic](#editing-the-quiz-logic)
8. [Updating the LiaScript header](#updating-the-liascript-header)
9. [Updating the documentation body](#updating-the-documentation-body)
10. [CI pipeline](#ci-pipeline)

---

## Prerequisites

- [Node.js](https://nodejs.org/) ≥ 18  
- npm (bundled with Node.js)

```bash
# Install all development dependencies (Jest)
npm install
```

---

## Project structure

```
.
├── docs/
│   └── development.md          ← this file
├── scripts/
│   └── build.js                ← assembles README.md from source parts
├── src/
│   ├── header.yml              ← LiaScript YAML front-matter
│   ├── body.md                 ← user-facing documentation body
│   ├── js/
│   │   └── quiz-logic.js       ← pure JS logic functions (testable)
│   └── macros/
│       ├── dragdroporder.md    ← @dragdroporder macro template
│       ├── dragdropmultiple.md ← @dragdropmultiple macro template
│       ├── dragdropmultipleimages.md  ← @dragdropmultipleimages (deprecated)
│       └── dragdropsort.md     ← @dragdropsort macro template
├── tests/
│   ├── quiz-logic.test.js      ← unit tests for pure logic functions
│   └── build.test.js           ← integration tests for build output
├── .github/
│   └── workflows/
│       └── ci.yml              ← CI: test → build → commit README.md
├── package.json
└── README.md                   ← ⚠ auto-generated — do not edit directly
```

> **Important:** `README.md` is auto-generated by the build script.  
> Always edit the files inside `src/` and then run `npm run build`.

---

## Building README.md

```bash
npm run build
```

This runs `scripts/build.js`, which:

1. Reads the YAML front-matter from `src/header.yml`.
2. Reads each macro template from `src/macros/<name>.md` and replaces the
   `{{QUIZ_LOGIC}}` placeholder with the contents of `src/js/quiz-logic.js`
   (the CommonJS export block is stripped so the result is browser-compatible).
3. Reads the documentation body from `src/body.md`.
4. Writes everything into a single `README.md` at the repository root.

---

## Running the tests

```bash
npm test
```

Jest runs two test suites:

| Suite | What it tests |
|-------|--------------|
| `tests/quiz-logic.test.js` | Pure correctness functions (`isOrderCorrect`, `isMultipleChoiceCorrect`, `isSortCorrect`, `isValidHttpUrl`) |
| `tests/build.test.js` | The assembled `README.md` has the expected structure (header, macros, body, docs link) |

Add new unit tests to `tests/quiz-logic.test.js` whenever you add or change a
function in `src/js/quiz-logic.js`.  
Add new build assertions to `tests/build.test.js` whenever you add new
structural requirements to the generated `README.md`.

---

## How the build works

```
src/header.yml          ──┐
src/macros/*.md  ──┐      │
src/js/quiz-logic.js ──┘  │  scripts/build.js  ──▶  README.md
src/body.md         ──────┘
```

### The `{{QUIZ_LOGIC}}` placeholder

Each macro template that contains JavaScript can include the token
`{{QUIZ_LOGIC}}` inside its `<script>` block.  The build script replaces it
with all of the functions from `src/js/quiz-logic.js` at build time, so:

- The browser bundle remains self-contained (no extra `<script src>` needed).
- The same functions are covered by Jest unit tests.

Example location inside a macro template:

```html
<script>
  {{QUIZ_LOGIC}}

  const quizData = { … }
  …
</script>
```

---

## Adding or modifying a macro

1. **Create** (or edit) `src/macros/<your-macro-name>.md`.  
   - Put the HTML markup and `<script>` block directly in the file.
   - If your script uses `isOrderCorrect`, `isMultipleChoiceCorrect`,
     `isSortCorrect`, or `isValidHttpUrl`, add `{{QUIZ_LOGIC}}` at the top of
     the `<script>` block.
2. **Register** the macro name in the `MACRO_ORDER` array inside
   `scripts/build.js` (macros are written to `README.md` in this order).
3. **Build**: run `npm run build`.
4. **Test**: add assertions in `tests/build.test.js` to verify the new macro
   appears in `README.md`, then run `npm test`.
5. **Document**: add usage examples to `src/body.md`.

---

## Editing the quiz logic

`src/js/quiz-logic.js` contains the shared, pure correctness functions.  They
are inlined into every macro at build time.

When editing this file:

1. Update the corresponding unit tests in `tests/quiz-logic.test.js`.
2. Run `npm test` to confirm nothing is broken.
3. Run `npm run build` to regenerate `README.md` with the updated logic.

---

## Updating the LiaScript header

Edit `src/header.yml` to change metadata (author, version, imports, …).  
Run `npm run build` afterwards to regenerate `README.md`.

---

## Updating the documentation body

Edit `src/body.md` to update the user-facing sections of `README.md`
(quiz examples, how-to explanations, links, …).  
Run `npm run build` afterwards to regenerate `README.md`.

---

## CI pipeline

The workflow at `.github/workflows/ci.yml` runs on every push:

1. **Install** — `npm ci`
2. **Test** — `npm test` (build fails here if tests are red)
3. **Build** — `npm run build`
4. **Commit** — if `README.md` changed, the bot commits it back to the branch
   with the message `chore: regenerate README.md from sources [skip ci]`.

The commit step uses the `ACTIONS_PAT` secret (a Personal Access Token with
`repo` scope) when available, and falls back to `GITHUB_TOKEN` otherwise.  
If you need the bot to push to a protected branch, configure `ACTIONS_PAT` in
*Settings → Secrets and variables → Actions*.
