Skip to content

Commit cf4ccd1

Browse files
committed
Merge branch 'main' into feature/phase-1-templates-feedback
2 parents 3cba50d + 3c80a20 commit cf4ccd1

File tree

20 files changed

+945
-13
lines changed

20 files changed

+945
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ PlanForge is a self-hosted project planning tool that uses AI to generate compre
1515
- **Tech Spec Generation** - Detailed technical specifications based on the PRD
1616
- **Task Generation** - Break down tech specs into actionable development tasks
1717
- **Version History** - Browse, preview, and restore previous document versions
18+
- **Markdown Preview** - Write/Preview/Split editor modes with syntax highlighting
1819
- **Kanban Board** - Drag-and-drop task management with Flowforge
1920
- **User Authentication** - Secure login with email/password
2021
- **Regeneration** - Regenerate individual documents or the entire pipeline
@@ -149,6 +150,7 @@ REDIS_HOST=127.0.0.1
149150
- [x] ~~User authentication~~ (v0.4.0)
150151
- [x] ~~Version history~~ (v0.5.0)
151152
- [x] ~~GitHub Issues integration~~ (v0.6.0)
153+
- [x] ~~Markdown preview with syntax highlighting~~ (v0.7.0)
152154
- [ ] Team collaboration
153155
- [ ] Project templates
154156
- [ ] Diff comparison for versions
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace App\Livewire\Concerns;
4+
5+
use App\Services\MarkdownService;
6+
use Livewire\Attributes\Computed;
7+
8+
trait HasMarkdownPreview
9+
{
10+
public string $editorMode = 'write';
11+
12+
public function setEditorMode(string $mode): void
13+
{
14+
if (! in_array($mode, ['write', 'preview', 'split'])) {
15+
return;
16+
}
17+
18+
$this->editorMode = $mode;
19+
unset($this->previewHtml);
20+
}
21+
22+
#[Computed]
23+
public function previewHtml(): string
24+
{
25+
return app(MarkdownService::class)->render($this->content);
26+
}
27+
28+
protected function clearPreviewCache(): void
29+
{
30+
unset($this->previewHtml);
31+
}
32+
}

app/Livewire/Projects/Tabs/Prd.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Livewire\Projects\Tabs;
44

55
use App\Enums\DocumentType;
6+
use App\Livewire\Concerns\HasMarkdownPreview;
67
use App\Livewire\Concerns\HasVersionHistory;
78
use App\Models\Document;
89
use App\Models\DocumentVersion;
@@ -15,6 +16,7 @@
1516
class Prd extends Component
1617
{
1718
use AuthorizesRequests;
19+
use HasMarkdownPreview;
1820
use HasVersionHistory;
1921

2022
public string $projectId;
@@ -52,6 +54,7 @@ public function loadContent(): void
5254
public function updatedContent(): void
5355
{
5456
$this->isDirty = true;
57+
$this->clearPreviewCache();
5558
}
5659

5760
public function save(): void

app/Livewire/Projects/Tabs/Tech.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Actions\GenerateTasksFromTechSpec;
66
use App\Enums\DocumentType;
77
use App\Enums\PlanRunStepStatus;
8+
use App\Livewire\Concerns\HasMarkdownPreview;
89
use App\Livewire\Concerns\HasVersionHistory;
910
use App\Models\Document;
1011
use App\Models\DocumentVersion;
@@ -18,6 +19,7 @@
1819
class Tech extends Component
1920
{
2021
use AuthorizesRequests;
22+
use HasMarkdownPreview;
2123
use HasVersionHistory;
2224

2325
public string $projectId;
@@ -55,6 +57,7 @@ public function loadContent(): void
5557
public function updatedContent(): void
5658
{
5759
$this->isDirty = true;
60+
$this->clearPreviewCache();
5861
}
5962

6063
public function save(): void

app/Providers/AppServiceProvider.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use App\Events\TasksChanged;
66
use App\Listeners\QueueGitHubSync;
7+
use App\Services\MarkdownService;
78
use Illuminate\Cache\RateLimiting\Limit;
89
use Illuminate\Support\Facades\Event;
910
use Illuminate\Support\Facades\RateLimiter;
@@ -16,7 +17,7 @@ class AppServiceProvider extends ServiceProvider
1617
*/
1718
public function register(): void
1819
{
19-
//
20+
$this->app->singleton(MarkdownService::class);
2021
}
2122

2223
/**

app/Services/MarkdownService.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace App\Services;
4+
5+
use League\CommonMark\Environment\Environment;
6+
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
7+
use League\CommonMark\Extension\DisallowedRawHtml\DisallowedRawHtmlExtension;
8+
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
9+
use League\CommonMark\MarkdownConverter;
10+
11+
class MarkdownService
12+
{
13+
private MarkdownConverter $converter;
14+
15+
public function __construct()
16+
{
17+
$environment = new Environment([
18+
'html_input' => 'strip',
19+
'allow_unsafe_links' => false,
20+
]);
21+
22+
$environment->addExtension(new CommonMarkCoreExtension);
23+
$environment->addExtension(new GithubFlavoredMarkdownExtension);
24+
$environment->addExtension(new DisallowedRawHtmlExtension);
25+
26+
$this->converter = new MarkdownConverter($environment);
27+
}
28+
29+
public function render(string $markdown): string
30+
{
31+
if (empty(trim($markdown))) {
32+
return '';
33+
}
34+
35+
return $this->converter->convert($markdown)->getContent();
36+
}
37+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"firebase/php-jwt": "^7.0",
1212
"laravel/framework": "^12.0",
1313
"laravel/tinker": "^2.10.1",
14+
"league/commonmark": "^2.8",
1415
"livewire/livewire": "^3.6.4",
1516
"livewire/volt": "^1.7.0",
1617
"prism-php/prism": "^0.99.7",

composer.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 54 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
},
1919
"dependencies": {
2020
"@tailwindcss/forms": "^0.5.11",
21+
"@tailwindcss/typography": "^0.5.19",
22+
"highlight.js": "^11.11.1",
2123
"sortablejs": "^1.15.6"
2224
}
2325
}

0 commit comments

Comments
 (0)