# contract-document-rendering Specification

## Purpose
Defines how field values are substituted into contract and contract type templates so that values always render as literal text while the template's own HTML markup is preserved.
## Requirements
### Requirement: Field Values Render as Literal Text
When the system renders a contract or contract type template (stored preview, custom preview, preview PDF, signed contract PDF), every field value substituted for a `${code}` placeholder SHALL be HTML-escaped so that it is displayed exactly as stored, character for character, and is never interpreted as HTML markup. This SHALL apply regardless of the value's source: default fields, custom fields, and `overriding_fields` from the request.

#### Scenario: Value containing an HTML tag
- **WHEN** an employee's `contract_position` is `Trưởng nhóm R&D / Kỹ thuật (Cấp 2) – "A" <b>` and a contract whose template contains `${employee_position}` is previewed (e.g. `POST /admin/employees/{id}/contracts/{contractId}/preview` with a `template`)
- **THEN** the rendered PDF shows the text `Trưởng nhóm R&D / Kỹ thuật (Cấp 2) – "A" <b>` in full, including `<b>`
- **AND** the text following the placeholder is not rendered in bold

#### Scenario: Value containing special characters
- **WHEN** a substituted value contains `&`, `<`, `>`, `"` or `'`
- **THEN** the generated HTML contains the corresponding HTML entities (`&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#039;`) at that position
- **AND** the rendered document shows the original characters

#### Scenario: Value that looks like an HTML entity
- **WHEN** a substituted value contains the literal text `&amp;`
- **THEN** the rendered document shows `&amp;`, not `&`

#### Scenario: Overriding field value containing HTML
- **WHEN** a contract preview or update is requested with an `overriding_fields` item whose `value` is `<i>x</i>`
- **THEN** the rendered document shows the text `<i>x</i>` and nothing is italicized

#### Scenario: Stored preview of a contract
- **WHEN** a contract's stored `preview` is regenerated (contract update, refresh from contract type) and a field value contains `<b>`
- **THEN** the stored `preview` HTML contains `&lt;b&gt;` at that position

#### Scenario: Contract type preview
- **WHEN** a contract type template is previewed with fake contract data and a substituted value contains HTML-significant characters
- **THEN** those characters are escaped in the same way

#### Scenario: Empty or missing value
- **WHEN** a field value is `null` or empty
- **THEN** the placeholder is replaced with an empty string, as before

#### Scenario: Plain value is unchanged
- **WHEN** a substituted value contains no HTML-significant characters (e.g. a formatted date `16/10/2026` or number `15,000,000`)
- **THEN** the output is identical to the output before this change

### Requirement: Template Markup Is Preserved
Escaping SHALL apply only to substituted values. The template's own HTML (authored in the rich text editor, including formatting around placeholders) SHALL be rendered as HTML, unchanged.

#### Scenario: Placeholder wrapped in formatting
- **WHEN** a template contains `<strong>${employee_name}</strong>`
- **THEN** the employee's name is rendered in bold

#### Scenario: Salary information list
- **WHEN** a template contains `${salary_information}`
- **THEN** it renders as a `<ul>` list with one `<li>` per salary item, as before
- **AND** each payslip item name and value inside the list is escaped as literal text
