implemented preview of article markdown via AJAX
This commit is contained in:
+25
-23
@@ -2,56 +2,58 @@
|
|||||||
|
|
||||||
<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']);
|
||||||
|
|
||||||
foreach ($arr as $a) {
|
foreach ($arr as $a) {
|
||||||
$tmp = explode('=', $a);
|
$tmp = explode('=', $a);
|
||||||
$key = $tmp[0];
|
$key = $tmp[0];
|
||||||
$value = $tmp[1];
|
$value = $tmp[1];
|
||||||
|
|
||||||
$args[$key] = $value;
|
$args[$key] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
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'])) {
|
||||||
if ($args['action'] == 'signup') {
|
if ($args['action'] == 'signup') {
|
||||||
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>
|
||||||
';
|
';
|
||||||
$args = get_args_from_url();
|
$args = get_args_from_url();
|
||||||
|
|
||||||
if (isset($args['view'])) {
|
if (isset($args['view'])) {
|
||||||
if ($args['view'] == 'users') {
|
if ($args['view'] == 'users') {
|
||||||
echo '
|
echo '
|
||||||
<script src="js/upload.js"></script>
|
<script src="js/upload.js"></script>
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if ($_SERVER['SCRIPT_NAME'] == '/compose.php') {
|
||||||
?>
|
echo '
|
||||||
|
<script src="js/md_preview.js"></script>
|
||||||
|
';
|
||||||
|
}
|
||||||
|
?>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+60
-38
@@ -4,77 +4,87 @@ require_once 'functions/functions.php';
|
|||||||
include_once 'functions/article_functions.php';
|
include_once 'functions/article_functions.php';
|
||||||
|
|
||||||
if (!empty($_POST)) {
|
if (!empty($_POST)) {
|
||||||
if (isset($_POST['article_id'])) {
|
if (isset($_POST['article_id'])) {
|
||||||
$tags = [];
|
$tags = [];
|
||||||
for ($i = 0; $i < count($_POST['tags']); $i++)
|
for ($i = 0; $i < count($_POST['tags']); $i++)
|
||||||
$tags[] = $_POST['tags'][$i];
|
$tags[] = $_POST['tags'][$i];
|
||||||
|
|
||||||
update_article($_POST['article_id'], $_POST['title'], $_POST['excerpt'], $tags, $_POST['markdown']);
|
update_article($_POST['article_id'], $_POST['title'], $_POST['excerpt'], $tags, $_POST['markdown']);
|
||||||
header('Location: articles.php?article_id=' . $_POST['article_id']);
|
header('Location: articles.php?article_id=' . $_POST['article_id']);
|
||||||
} else {
|
} else {
|
||||||
$id = create_article($_COOKIE['user_id'], $_POST['title'], $_POST['excerpt'], (isset($_POST['tags']) ? $_POST['tags'] : []), $_POST['markdown']);
|
$id = create_article($_COOKIE['user_id'], $_POST['title'], $_POST['excerpt'], (isset($_POST['tags']) ? $_POST['tags'] : []), $_POST['markdown']);
|
||||||
header('Location: articles.php?article_id=' . $id);
|
header('Location: articles.php?article_id=' . $id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($_COOKIE['role_id']) || $_COOKIE['role_id'] == 4)
|
if (!isset($_COOKIE['role_id']) || $_COOKIE['role_id'] == 4)
|
||||||
header('Location: articles.php');
|
header('Location: articles.php');
|
||||||
|
|
||||||
include_once 'components/head.php';
|
include_once 'components/head.php';
|
||||||
|
|
||||||
if (isset($_GET['article_id'])) {
|
if (isset($_GET['article_id'])) {
|
||||||
$article_id = $_GET['article_id'];
|
$article_id = $_GET['article_id'];
|
||||||
|
|
||||||
$conn = get_connection();
|
$conn = get_connection();
|
||||||
$stmt = $conn->prepare('SELECT * FROM article WHERE article_id = ?');
|
$stmt = $conn->prepare('SELECT * FROM article WHERE article_id = ?');
|
||||||
$stmt->bind_param('i', $article_id);
|
$stmt->bind_param('i', $article_id);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$article = $stmt->get_result()->fetch_assoc();
|
$article = $stmt->get_result()->fetch_assoc();
|
||||||
|
|
||||||
$stmt = $conn->prepare('SELECT tag_id FROM article_tags WHERE article_id = ?');
|
$stmt = $conn->prepare('SELECT tag_id FROM article_tags WHERE article_id = ?');
|
||||||
$stmt->bind_param('i', $article_id);
|
$stmt->bind_param('i', $article_id);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$result = $stmt->get_result();
|
$result = $stmt->get_result();
|
||||||
$tags = [];
|
$tags = [];
|
||||||
while ($row = $result->fetch_assoc())
|
while ($row = $result->fetch_assoc())
|
||||||
$tags[] = $row['tag_id'];
|
$tags[] = $row['tag_id'];
|
||||||
|
|
||||||
$title = $article['title'];
|
$title = $article['title'];
|
||||||
$excerpt = $article['excerpt'];
|
$excerpt = $article['excerpt'];
|
||||||
$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)
|
||||||
{
|
{
|
||||||
$raw_tags = article_tags();
|
$raw_tags = article_tags();
|
||||||
$tags_boxes = '
|
$tags_boxes = '
|
||||||
<div class="checkboxes">
|
<div class="checkboxes">
|
||||||
<label>Tags</label>
|
<label>Tags</label>
|
||||||
';
|
';
|
||||||
|
|
||||||
foreach ($raw_tags as $row) {
|
foreach ($raw_tags as $row) {
|
||||||
$tags_boxes .= '
|
$tags_boxes .= '
|
||||||
<label class="form_checkbox_container">' . $row['tag'] . '
|
<label class="form_checkbox_container">' . $row['tag'] . '
|
||||||
<input name="tags[]" value="' . $row['tag_id'] . '" type="checkbox"' . (isset($tags) && in_array($row['tag_id'], $tags) ? ' checked' : '') . '>
|
<input name="tags[]" value="' . $row['tag_id'] . '" type="checkbox"' . (isset($tags) && in_array($row['tag_id'], $tags) ? ' checked' : '') . '>
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
|
|
||||||
$tags_boxes .= '
|
$tags_boxes .= '
|
||||||
</div>
|
</div>
|
||||||
';
|
';
|
||||||
|
|
||||||
$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,14 +110,9 @@ 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>
|
||||||
';
|
';
|
||||||
|
|
||||||
|
|||||||
@@ -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,18 +1,15 @@
|
|||||||
<?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';
|
||||||
|
|
||||||
function home_content()
|
function home_content()
|
||||||
{
|
{
|
||||||
$content = '
|
$content = '
|
||||||
<div class="article">
|
<div class="article">
|
||||||
<h1>Vintage Coding</h1>
|
<h1>Vintage Coding</h1>
|
||||||
<h3>Intentional Craftsmanship Over Ephemeral Trends</h3>
|
<h3>Intentional Craftsmanship Over Ephemeral Trends</h3>
|
||||||
@@ -34,5 +31,5 @@ function home_content()
|
|||||||
</div>
|
</div>
|
||||||
';
|
';
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|||||||
+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