implemented preview of article markdown via AJAX
This commit is contained in:
+13
-11
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<?php
|
<?php
|
||||||
function get_args_from_url()
|
function get_args_from_url()
|
||||||
{
|
{
|
||||||
$args = [];
|
$args = [];
|
||||||
$arr = explode('&', $_SERVER['QUERY_STRING']);
|
$arr = explode('&', $_SERVER['QUERY_STRING']);
|
||||||
|
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_SERVER['SCRIPT_NAME'] == '/user.php') {
|
if ($_SERVER['SCRIPT_NAME'] == '/user.php') {
|
||||||
$args = get_args_from_url();
|
$args = get_args_from_url();
|
||||||
|
|
||||||
if (isset($args['action'])) {
|
if (isset($args['action'])) {
|
||||||
@@ -26,18 +26,16 @@
|
|||||||
echo '
|
echo '
|
||||||
<script src="js/profile_picture_cropper_modal.js"></script>
|
<script src="js/profile_picture_cropper_modal.js"></script>
|
||||||
<script src="js/upload.js"></script>
|
<script src="js/upload.js"></script>
|
||||||
';
|
';
|
||||||
} else if ($args['action'] == 'view') {
|
} else if ($args['action'] == 'view') {
|
||||||
echo '
|
echo '
|
||||||
<script src="js/user_actions_modal.js"></script>
|
<script src="js/user_actions_modal.js"></script>
|
||||||
<script src="js/profile_picture_cropper_modal.js"></script>
|
<script src="js/profile_picture_cropper_modal.js"></script>
|
||||||
<script src="js/upload.js"></script>
|
<script src="js/upload.js"></script>
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if ($_SERVER['SCRIPT_NAME'] == '/admin.php') {
|
||||||
|
|
||||||
if ($_SERVER['SCRIPT_NAME'] == '/admin.php') {
|
|
||||||
echo '
|
echo '
|
||||||
<script src="js/clickable_rows.js"></script>
|
<script src="js/clickable_rows.js"></script>
|
||||||
';
|
';
|
||||||
@@ -50,8 +48,12 @@
|
|||||||
';
|
';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if ($_SERVER['SCRIPT_NAME'] == '/compose.php') {
|
||||||
?>
|
echo '
|
||||||
|
<script src="js/md_preview.js"></script>
|
||||||
|
';
|
||||||
|
}
|
||||||
|
?>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+24
-2
@@ -44,12 +44,21 @@ if (isset($_GET['article_id'])) {
|
|||||||
$existing_markdown = read_file_one_string($_ENV['ARTICLES_FQ_PATH'] . $article_id . '/article.md');
|
$existing_markdown = read_file_one_string($_ENV['ARTICLES_FQ_PATH'] . $article_id . '/article.md');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<div class="grid-2x1">
|
||||||
|
';
|
||||||
if (!empty($existing_markdown)) {
|
if (!empty($existing_markdown)) {
|
||||||
echo form($article_id, $title, $excerpt, $existing_markdown, $tags);
|
echo form($article_id, $title, $excerpt, $existing_markdown, $tags);
|
||||||
} else {
|
} else {
|
||||||
echo form();
|
echo form();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo preview();
|
||||||
|
|
||||||
|
echo '
|
||||||
|
</div>
|
||||||
|
';
|
||||||
|
|
||||||
include_once 'components/foot.php';
|
include_once 'components/foot.php';
|
||||||
|
|
||||||
function form($article_id = null, $title = null, $excerpt = null, $existing_markdown = null, $tags = null)
|
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 = '
|
$form = '
|
||||||
<div class="form_card">
|
<div class="full-height">
|
||||||
|
<div class="form_card" id="composer">
|
||||||
<form method="post">
|
<form method="post">
|
||||||
' . (isset($article_id) ? '<input type="hidden" name="article_id" value="' . $article_id . '">' : '') . '
|
' . (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') . '">
|
<input class="button" type="submit" value="' . (isset($article_id) ? 'Update Article' : 'Create Article') . '">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
';
|
';
|
||||||
|
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function preview()
|
||||||
|
{
|
||||||
|
$preview = '
|
||||||
|
<div class="full-height">
|
||||||
|
<div class="form_card" id="md_preview">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
';
|
||||||
|
|
||||||
|
return $preview;
|
||||||
|
}
|
||||||
|
|||||||
+58
-2
@@ -168,6 +168,7 @@ code {
|
|||||||
.view_card {
|
.view_card {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
|
margin-bottom: 50px;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
height: max-content;
|
height: max-content;
|
||||||
@@ -335,6 +336,7 @@ textarea {
|
|||||||
margin: 15px 15px 15px 0px;
|
margin: 15px 15px 15px 0px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition-duration: 500ms;
|
transition-duration: 500ms;
|
||||||
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:focus,
|
input:focus,
|
||||||
@@ -348,10 +350,12 @@ textarea:hover {
|
|||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
height: 500px;
|
height: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkboxes {}
|
.checkboxes {
|
||||||
|
height: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="radio"] {
|
input[type="radio"] {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -639,6 +643,58 @@ input[type="file"] {
|
|||||||
display: none;
|
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) {
|
@media screen and (max-width: 992px) {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 10vw;
|
font-size: 10vw;
|
||||||
|
|||||||
@@ -92,12 +92,6 @@ function article_page_from_markdown($article_id)
|
|||||||
$parsedown = new Parsedown();
|
$parsedown = new Parsedown();
|
||||||
$parsedown->setSafeMode(true);
|
$parsedown->setSafeMode(true);
|
||||||
$article_content = $parsedown->text($markdown);
|
$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 = '
|
$html = '
|
||||||
<div class="article">
|
<div class="article">
|
||||||
@@ -116,15 +110,10 @@ function article_page_from_markdown($article_id)
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="line" style="margin-bottom: 15px;"></div>
|
<div class="line" style="margin-bottom: 15px;"></div>
|
||||||
<div class="article_grid">
|
|
||||||
<div class="article_toc">
|
|
||||||
' . $article_toc . '
|
|
||||||
</div>
|
|
||||||
<div class="article_content">
|
<div class="article_content">
|
||||||
' . $article_content . '
|
' . $article_content . '
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
';
|
';
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once 'vendor/autoload.php';
|
require_once 'vendor/autoload.php';
|
||||||
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../');
|
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
|
||||||
$dotenv->safeLoad();
|
$dotenv->safeLoad();
|
||||||
|
|
||||||
// Use environment variables for the database password and IP address.
|
// Use environment variables for the database password and IP address.
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
// Initializes environment variables and other stuff.
|
|
||||||
// if (!isset($_SESSION['initialized']))
|
|
||||||
require_once 'functions/init.php';
|
require_once 'functions/init.php';
|
||||||
require_once 'functions/functions.php';
|
require_once 'functions/functions.php';
|
||||||
include_once 'components/head.php';
|
include_once 'components/head.php';
|
||||||
|
|
||||||
|
|
||||||
echo home_content();
|
echo home_content();
|
||||||
|
|
||||||
include_once 'components/foot.php';
|
include_once 'components/foot.php';
|
||||||
|
|||||||
+3
-4
@@ -1,9 +1,8 @@
|
|||||||
// Optional: Real-time preview using JavaScript
|
|
||||||
const textarea = document.querySelector('textarea');
|
const textarea = document.querySelector('textarea');
|
||||||
const preview = document.getElementById('preview');
|
const preview = document.getElementById('md_preview');
|
||||||
|
|
||||||
textarea.addEventListener('input', function() {
|
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',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
@@ -12,6 +11,6 @@ textarea.addEventListener('input', function() {
|
|||||||
})
|
})
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
preview.innerHTML = data;
|
preview.innerHTML = decodeURIComponent(data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user