implemented preview of article markdown via AJAX

This commit is contained in:
2025-04-12 11:00:44 -06:00
parent 4f0262aa89
commit fb35e93226
8 changed files with 161 additions and 84 deletions
+5 -3
View File
@@ -35,9 +35,7 @@
';
}
}
}
if ($_SERVER['SCRIPT_NAME'] == '/admin.php') {
} else if ($_SERVER['SCRIPT_NAME'] == '/admin.php') {
echo '
<script src="js/clickable_rows.js"></script>
';
@@ -50,6 +48,10 @@
';
}
}
} else if ($_SERVER['SCRIPT_NAME'] == '/compose.php') {
echo '
<script src="js/md_preview.js"></script>
';
}
?>
</footer>
+24 -2
View File
@@ -44,12 +44,21 @@ if (isset($_GET['article_id'])) {
$existing_markdown = read_file_one_string($_ENV['ARTICLES_FQ_PATH'] . $article_id . '/article.md');
}
echo '
<div class="grid-2x1">
';
if (!empty($existing_markdown)) {
echo form($article_id, $title, $excerpt, $existing_markdown, $tags);
} else {
echo form();
}
echo preview();
echo '
</div>
';
include_once 'components/foot.php';
function form($article_id = null, $title = null, $excerpt = null, $existing_markdown = null, $tags = null)
@@ -74,7 +83,8 @@ function form($article_id = null, $title = null, $excerpt = null, $existing_mark
';
$form = '
<div class="form_card">
<div class="full-height">
<div class="form_card" id="composer">
<form method="post">
' . (isset($article_id) ? '<input type="hidden" name="article_id" value="' . $article_id . '">' : '') . '
@@ -90,8 +100,20 @@ function form($article_id = null, $title = null, $excerpt = null, $existing_mark
<input class="button" type="submit" value="' . (isset($article_id) ? 'Update Article' : 'Create Article') . '">
</form>
</div>
</div>
';
return $form;
}
function preview()
{
$preview = '
<div class="full-height">
<div class="form_card" id="md_preview">
</div>
</div>
';
return $preview;
}
+58 -2
View File
@@ -168,6 +168,7 @@ code {
.view_card {
margin: 0 auto;
margin-top: 50px;
margin-bottom: 50px;
width: 70%;
padding: 18px;
height: max-content;
@@ -335,6 +336,7 @@ textarea {
margin: 15px 15px 15px 0px;
box-sizing: border-box;
transition-duration: 500ms;
resize: none;
}
input:focus,
@@ -348,10 +350,12 @@ textarea:hover {
textarea {
border-radius: 18px;
height: 500px;
height: 70%;
}
.checkboxes {}
.checkboxes {
height: max-content;
}
input[type="radio"] {
display: none;
@@ -639,6 +643,58 @@ input[type="file"] {
display: none;
}
::selection {
color: black;
background: orange;
}
.grid-2x1 {
margin: 0 auto;
width: 90%;
display: grid;
grid-template-columns: 50% 50%;
}
.grid-2x1 .form_card,
.grid-2x1 #md_preview {
width: 80%;
height: 90%;
overflow-y: scroll;
box-sizing: border-box;
}
.grid-2x1 #composer {
padding-top: 150px;
}
#md_preview {
border: none;
display: block;
}
.full-height {
height: 700px;
}
::-webkit-scrollbar {
background-color: black;
border-radius: 18px;
}
::-webkit-scrollbar-button {
display: none;
}
::-webkit-scrollbar-track {
display: none;
}
::-webkit-scrollbar-thumb {
background-color: orange;
border-radius: 9px;
}
@media screen and (max-width: 992px) {
h1 {
font-size: 10vw;
-11
View File
@@ -92,12 +92,6 @@ function article_page_from_markdown($article_id)
$parsedown = new Parsedown();
$parsedown->setSafeMode(true);
$article_content = $parsedown->text($markdown);
$article_toc = '';
$lines = preg_split("/\r\n|\n|\r/", $article_content);
foreach ($lines as $line)
if (str_contains($line, '<h4>'))
$article_toc .= '<p>' . extract_content_from_tag($line, '<h4>', '</h4>') . '</p><br>';
$html = '
<div class="article">
@@ -116,15 +110,10 @@ function article_page_from_markdown($article_id)
</div>
</div>
<div class="line" style="margin-bottom: 15px;"></div>
<div class="article_grid">
<div class="article_toc">
' . $article_toc . '
</div>
<div class="article_content">
' . $article_content . '
</div>
</div>
</div>
';
return $html;
+1 -1
View File
@@ -1,7 +1,7 @@
<?php
require_once 'vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../');
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->safeLoad();
// Use environment variables for the database password and IP address.
+12
View File
@@ -0,0 +1,12 @@
<?php
session_start();
header("Content-Security-Policy: default-src 'self'; font-src 'self' https://www.nerdfonts.com/assets/fonts/Symbols-2048-em%20Nerd%20Font%20Complete.woff2; style-src 'self' 'unsafe-inline' https://nerdfonts.com/assets/css/webfont.css https://www.nerdfonts.com/assets/css/webfont.css; script-src 'self'; img-src 'self';");
require_once '../vendor/autoload.php';
$markdown = urldecode($_POST['markdown']);
$parsedown = new Parsedown();
$parsedown->setSafeMode(true);
$article_content = $parsedown->text($markdown);
echo $article_content;
-3
View File
@@ -1,11 +1,8 @@
<?php
// Initializes environment variables and other stuff.
// if (!isset($_SESSION['initialized']))
require_once 'functions/init.php';
require_once 'functions/functions.php';
include_once 'components/head.php';
echo home_content();
include_once 'components/foot.php';
+3 -4
View File
@@ -1,9 +1,8 @@
// Optional: Real-time preview using JavaScript
const textarea = document.querySelector('textarea');
const preview = document.getElementById('preview');
const preview = document.getElementById('md_preview');
textarea.addEventListener('input', function() {
fetch('preview.php', { // Create a separate preview.php file for real-time updates
fetch('functions/preview.php', { // Create a separate preview.php file for real-time updates
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
@@ -12,6 +11,6 @@ textarea.addEventListener('input', function() {
})
.then(response => response.text())
.then(data => {
preview.innerHTML = data;
preview.innerHTML = decodeURIComponent(data);
});
});