# AGENTS.md ## Purpose This project is a small Markdown-to-HTML utility used behind NGINX. When a `.md` file is requested, `src/md2html.php` loads the Markdown, converts it with Parsedown, and renders HTML styled by `src/markdown.css`. `src/toc.js` builds an interactive table of contents from the rendered headings. ## Key Files - `src/md2html.php`: entrypoint for conversion and HTML output. - `src/markdown.css`: visual styling for rendered Markdown (`.markdown-body`). - `src/toc.js`: vanilla JavaScript for the table of contents and per-document panel state. - `composer.json`: PHP dependency config (`erusev/parsedown`). - `tests/fixtures/toc.md`: Markdown regression fixture. - `tests/render.php`: checks PHP output and exports heading data for JS tests. - `tests/toc.test.cjs`: Node.js tests using DOM doubles, without a browser. - `tests/run.ps1`: PowerShell runner for PHP and JS integration checks. ## Environment Assumptions - Project root: `D:\www\md2html` - Markdown files are resolved from `D:\www\...` - CSS and JS are linked under `//localhost/md2html/src/` with `?h=`. - NGINX forwards Markdown requests to `$document_root/md2html/src/md2html.php`; see README.md. ## Change Priorities 1. Keep output readable on desktop and mobile. 2. Preserve Markdown semantics generated by Parsedown. 3. Keep JavaScript in `src/toc.js`, use vanilla JavaScript, and avoid unnecessary dependencies. 4. Keep the utility simple and fast. ## Styling Rules (`src/markdown.css`) - Style only inside `.markdown-body` unless there is a strong reason to change global page behavior. - Navigation is outside `.markdown-body`; scope its styles to `.md2html-toc*` and `.md2html-document` where possible. - At widths above 760px, the open panel must leave space for the document; at smaller widths, use a dismissible overlay. - Keep the toggle fixed and available, the panel independently scrollable, and reduced-motion preferences respected. - Must cover: headings, links, lists, blockquotes, inline code, code blocks, tables, images, hr. - Keep strong contrast and accessible font sizes. - Ensure long code lines and wide tables remain usable on small screens (`overflow-x`). - Prefer CSS variables for colors and spacing to simplify future theme changes. ## PHP Rules (`src/md2html.php`) - Keep dependency loading via the project root's `vendor/autoload.php`, resolved relative to the entrypoint directory. - Keep response minimal: ``, UTF-8 and viewport meta, stylesheet link, deferred script, navigation controls, and wrapped content. - Keep CSS and JS URLs versioned using `md5_file()` on paths relative to `__DIR__`. - Do not assign anonymous functions or closures to PHP variables; use named functions or class methods. - Output helpers should return rendered content for callers to consume. - Do not remove `.md` extension guard. - Any path-handling changes must remain compatible with Windows paths. ## Table of Contents Rules (`src/toc.js`) - Build navigation from rendered H1–H3 in `.markdown-body`, preserving order and indicating levels with indentation. Do not add a Markdown parser. - Keep existing unique IDs, generate collision-free IDs for other headings, and retain native anchor navigation. - Use DOM creation and `textContent` for heading labels; do not insert untrusted content through `innerHTML`. - Default to closed. Store panel state under `md2html:toc:` + pathname + query string, excluding the fragment. - Handle unavailable localStorage without disabling navigation. - Maintain ARIA state, keyboard access, Escape dismissal, mobile close controls, and readable output without JavaScript. ## Validation After Edits - Never use a browser or browser automation. Leave visual browser verification to Igor; use non-browser checks instead. - Run relevant checks from the project root: - `php -l src/md2html.php` - `php -l tests/render.php` when changing the PHP test helper. - `node --check src/toc.js` - `./tests/run.ps1` - `git diff --check` - Tests require PHP with DOM, Composer dependencies, and Node.js supporting `node:test` and `--test-isolation=none`. - Keep regression coverage for heading levels, formatting, code fences, duplicate and existing anchors, Unicode, empty and long contents, URL-specific state, blocked storage, mobile dismissal, asset hashes, and the `.md` guard. - DOM doubles do not verify actual layout or scrolling. Igor manually checks desktop/mobile layout, long-panel scrolling, anchor navigation, and readability of Markdown elements. ## Non-Goals - Building a full CMS. - Adding heavy frontend frameworks. - Replacing Parsedown unless explicitly requested.