OverviewFilesCommitsIssuesDocsReleasesPeers

folio commits / 439db65

Add PHP markdown parser with tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
439db65533acd103828ec7a71b722c80965db22e
by plankatron <fleeky@gmail.com> · 2026-03-17T16:42:31.000Z

Changed files (2) +60 -0

lib/markdown.php +27 -0
……@@ -0,0 +1,27 @@
1<?php
2// lib/markdown.php — Minimal markdown-to-HTML parser
3
4function parse_markdown($md) {
5 $html = $md;
6
7 // Headings (must be processed before paragraphs)
8 $html = preg_replace('/^### (.+)$/m', '<h3>$1</h3>', $html);
9 $html = preg_replace('/^## (.+)$/m', '<h2>$1</h2>', $html);
10 $html = preg_replace('/^# (.+)$/m', '<h1>$1</h1>', $html);
11
12 // Inline formatting
13 $html = preg_replace('/\*\*(.+?)\*\*/', '<strong>$1</strong>', $html);
14 $html = preg_replace('/\*(.+?)\*/', '<em>$1</em>', $html);
15 $html = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $html);
16
17 // Paragraphs: split on double newlines
18 $html = preg_replace('/\n\n+/', '</p><p>', $html);
19 $html = '<p>' . $html . '</p>';
20
21 // Clean up headings wrapped in <p> tags
22 $html = preg_replace('/<p>(<h[123]>)/', '$1', $html);
23 $html = preg_replace('/(<\/h[123]>)<\/p>/', '$1', $html);
24 $html = str_replace('<p></p>', '', $html);
25
26 return $html;
27}
test_markdown.php +33 -0
……@@ -0,0 +1,33 @@
1<?php
2// test_markdown.php — run: php test_markdown.php
3require_once __DIR__ . '/lib/markdown.php';
4
5function assert_eq($label, $got, $expected) {
6 if ($got !== $expected) {
7 echo "FAIL: $label\n Expected: $expected\n Got: $got\n";
8 exit(1);
9 }
10 echo "PASS: $label\n";
11}
12
13// Headings
14assert_eq('h1', parse_markdown("# Title"), '<h1>Title</h1>');
15assert_eq('h2', parse_markdown("## Subtitle"), '<h2>Subtitle</h2>');
16assert_eq('h3', parse_markdown("### Sub-sub"), '<h3>Sub-sub</h3>');
17
18// Inline formatting
19assert_eq('bold', parse_markdown("**bold**"), '<p><strong>bold</strong></p>');
20assert_eq('italic', parse_markdown("*italic*"), '<p><em>italic</em></p>');
21assert_eq('link', parse_markdown("[text](url)"), '<p><a href="url">text</a></p>');
22
23// Paragraphs
24assert_eq('two paragraphs', parse_markdown("First\n\nSecond"), '<p>First</p><p>Second</p>');
25
26// Mixed
27assert_eq('heading then paragraph', parse_markdown("# Title\n\nSome text"), '<h1>Title</h1><p>Some text</p>');
28
29// Complex
30assert_eq('bold in paragraph', parse_markdown("This is **important** text"), '<p>This is <strong>important</strong> text</p>');
31assert_eq('link in paragraph', parse_markdown("Visit [my site](https://example.com) today"), '<p>Visit <a href="https://example.com">my site</a> today</p>');
32
33echo "\nAll markdown tests passed.\n";