# Components and blocks

Printexam has two levels:

- `components` build the document.
- `blocks` build the content inside an `exercise`.

A layout can contain components or blocks, but never both.

## Components

### Text

Use for titles, instructions, section headings, and other document-level content.

```json
{ "id": "title", "type": "text", "content": "<h1>Biology</h1>" }
```

### Student information

Creates labeled lines. Field length is `short`, `medium`, or `long`.

```json
{
  "id": "student-info",
  "type": "student-information",
  "options": {
    "fields": [
      { "id": "name", "label": "Name", "length": "long" },
      { "id": "class", "label": "Class", "length": "short" }
    ]
  }
}
```

### Divider

Style is `solid`, `dashed`, or `dotted`.

```json
{ "id": "divider-1", "type": "divider", "options": { "style": "solid" } }
```

### Exercise

Groups one or more question blocks. `options` is currently an empty object.

```json
{
  "id": "q1",
  "type": "exercise",
  "blocks": [
    { "id": "q1-prompt", "type": "text", "content": "<p>Write your answer.</p>" },
    { "id": "q1-answer", "type": "open-response", "options": { "lines": 4 } }
  ],
  "options": {}
}
```

### Component layout

Groups document components. See [Layouts](#layouts).

```json
{
  "id": "header-grid",
  "type": "layout",
  "components": [],
  "options": { "mode": "grid", "columns": 2 }
}
```

## Exercise blocks

### Text block

```json
{ "id": "q1-prompt", "type": "text", "content": "<p>Define photosynthesis.</p>" }
```

### Fill text

`content` must contain at least one blank marker. `wordBank` controls whether answers and distractors are printed above the text.

```json
{
  "id": "q2-fill",
  "type": "fill-text",
  "content": "<p>Plants absorb {{water}} through their roots.</p>",
  "wordBank": false,
  "distractorWords": []
}
```

### Math

`alignment` is `left`, `center`, or `right`.

```json
{
  "id": "q3-equation",
  "type": "math",
  "content": "x^2 + 5x + 6 = 0",
  "alignment": "center"
}
```

### Multiple choice

Use at least two choices. Choice text is plain text. `options` is currently an empty object.

```json
{
  "id": "q4-choices",
  "type": "multiple-choice",
  "choices": [
    { "id": "q4-a", "text": "Solid" },
    { "id": "q4-b", "text": "Liquid" }
  ],
  "options": {}
}
```

### Open response

`lines` is an integer from `1` to `100`.

```json
{ "id": "q5-answer", "type": "open-response", "options": { "lines": 6 } }
```

### Block layout

Groups exercise blocks. See [Layouts](#layouts).

```json
{
  "id": "q6-grid",
  "type": "layout",
  "blocks": [],
  "options": { "mode": "grid", "columns": 2 }
}
```

## Layouts

Both layout types use the same options:

```json
{ "mode": "vertical", "columns": 2 }
```

- `vertical`: stack children from top to bottom.
- `horizontal`: place children in one horizontal row.
- `grid`: place children in a grid using `columns`.
- `columns`: integer from `1` to `12`. Always include it, even when the mode is not `grid`.

Use layouts only when the prompt requires parallel or grouped content. A normal exam can use a flat component and block order.
