aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blog/feed.py31
-rw-r--r--blog/views.py5
-rw-r--r--static/css/styles.css5
-rw-r--r--templates/blog/partials/base.html3
-rw-r--r--templates/blog/post.html2
-rw-r--r--templates/blog_admin/edit_post.html290
6 files changed, 175 insertions, 161 deletions
diff --git a/blog/feed.py b/blog/feed.py
index 93a8b060..67389a86 100644
--- a/blog/feed.py
+++ b/blog/feed.py
@@ -1,8 +1,6 @@
import re
import requests
-# from .context_processors import add_excerpt
-from bs4 import BeautifulSoup
from django.conf import settings
from django.contrib.syndication.views import Feed
from django.utils import feedgenerator
@@ -11,19 +9,6 @@ from django.utils.feedgenerator import Enclosure
from .models import Post
request_domain = settings.DEBUG and 'https://preview.thatcomputerscientist.com' or 'https://thatcomputerscientist.com'
-mathjax_path = f'{request_domain}/static/js/MathJax/MathJax.js?config=default'
-mathjax_config = '''
-<script type="text/x-mathjax-config">
- MathJax.Hub.Config({
- jax: ["input/TeX", "output/HTML-CSS"],
- tex2jax: {
- inlineMath: [['$','$'], ['\\(','\\)']],
- processEscapes: true
- },
- "HTML-CSS": { availableFonts: ["TeX"] },
- });
-</script>
-'''
class RSSFeed(Feed):
title = 'That Computer Scientist'
@@ -32,24 +17,14 @@ class RSSFeed(Feed):
feed_type = feedgenerator.Rss201rev2Feed
def items(self):
- return Post.objects.all().filter(is_public=True).order_by('-date')
+ return Post.objects.all().filter(is_public=True).order_by('-date')[:10]
def item_title(self, item):
return item.title
def item_description(self, item):
- r = requests.get(f'{request_domain}/weblog/{item.slug}')
- soup = BeautifulSoup(r.text, 'html.parser')
- article_body = soup.find(id='article-body')
- for img in article_body.find_all('img'):
- if not img.get('id'):
- img['style'] = 'float: left; margin: 5px 11px 5px 0px; max-width: 710px;' + img.get('style', '')
-
- article_body = str(article_body)
- article_body = re.sub(r"[\x00-\x08\x0B-\x1F\x7F-\x9F]", "", str(article_body))
- article_body += f'<script type="text/javascript" src="{mathjax_path}"></script>'
- article_body += mathjax_config
- return article_body
+ body = re.sub(r"[\x00-\x08\x0B-\x1F\x7F-\x9F]", "", str(item.body))
+ return body
def item_link(self, item):
return f'{request_domain}/weblog/{item.slug}'
diff --git a/blog/views.py b/blog/views.py
index f24ade8d..b253db6e 100644
--- a/blog/views.py
+++ b/blog/views.py
@@ -159,7 +159,10 @@ def post(request, slug):
soup = BeautifulSoup(post.body, 'html.parser')
code_blocks = soup.find_all('pre', class_='ql-syntax')
for code_block in code_blocks:
- code_block.replace_with(BeautifulSoup(highlight_code_blocks(code_block), 'html.parser'))
+ data_language = code_block.get('data-language')
+ if data_language == 'true':
+ data_language = None
+ code_block.replace_with(BeautifulSoup(highlight_code_blocks(code_block, language=data_language), 'html.parser'))
# float: right every other image
images = soup.find_all('img')
diff --git a/static/css/styles.css b/static/css/styles.css
index 526a4fc9..8639081b 100644
--- a/static/css/styles.css
+++ b/static/css/styles.css
@@ -387,14 +387,14 @@ blockquote {
#editor-container img {
float: left;
margin: 5px 11px 5px 0px;
- max-width: 710px;
}
#article-body img.block,
#editor-container img.block {
margin: 5px auto;
display: block;
- height: auto;
+ max-height: none;
+ max-width: 710px;
}
#article-body h2,
@@ -514,5 +514,6 @@ blockquote {
#article-body img,
#editor-container img {
max-height: 300px;
+ max-width: 300px;
}
} \ No newline at end of file
diff --git a/templates/blog/partials/base.html b/templates/blog/partials/base.html
index 12c4d6ea..b9c4b48d 100644
--- a/templates/blog/partials/base.html
+++ b/templates/blog/partials/base.html
@@ -155,7 +155,8 @@
<script src="{% static 'js/tl.js' %}"></script>
{% if request.COOKIES.summonOneko == 'true' %}
<script src="{% static 'js/oneko.js' %}"></script>
- {% endif %} {% block scripts %} {% endblock %}
+ {% endif %}
+ {% block scripts %} {% endblock %}
<!-- Google tag (gtag.js) -->
<script
async
diff --git a/templates/blog/post.html b/templates/blog/post.html
index 8ecb1a29..2a927c3d 100644
--- a/templates/blog/post.html
+++ b/templates/blog/post.html
@@ -49,7 +49,7 @@
<div id="article-body">
{{ post.first_paragraph | safe }}
- <img style="width: 100%; height: 473.3333px; max-height: 473.3333px; margin: 20px auto; display: block; border-radius: 8px;" src="{% url 'ignis:post_image' '710' post.id %}.gif" alt="Post Image for {{ post.title }}" id="arpi_">
+ <img style="border-radius: 8px;" src="{% url 'ignis:post_image' '710' post.id %}.gif" alt="Post Image for {{ post.title }}" id="arpi_" class="block">
<hr>
{{ post.body | safe }}
</div>
diff --git a/templates/blog_admin/edit_post.html b/templates/blog_admin/edit_post.html
index 452565ba..164bd1a1 100644
--- a/templates/blog_admin/edit_post.html
+++ b/templates/blog_admin/edit_post.html
@@ -1,144 +1,177 @@
-{% extends 'blog/partials/base.html' %} {% block content %}
-{% load static %}
-
+{% extends 'blog/partials/base.html' %} {% block content %} {% load static %}
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet" />
-<div class="main">
- <div style="position: relative;">
- <h2>Editing Post: {{ post.title }}</h2>
- <br>
- <div id="math-formula-block" style="
- position: absolute;
- top: 95px;
- left: 185px;
- width: 320px;
- background: #121212;
- padding: 10px 20px 15px 20px;
- z-index: 3;
- display: none;
- ">
- <textarea id="math_formula" placeholder="Type MathJax Formula to Insert..." style="width: 300px; display: block; margin: 0px 0px 20px 0px;" rows="5"></textarea>
- <input type="radio" name="math_formula_type" value="inline" checked /> <span style="margin-right: 10px; position: relative; top: -2.5px;">Inline</span>
- <input type="radio" name="math_formula_type" value="block" style="margin-left: 10px;"> <span style="margin-right: 10px; position: relative; top: -2.5px;">Block</span>
- <button id="math_formula_insert" style="float: right; margin-top: -5px;" class="button button-special">Insert</button>
- <button id="math_formula_cancel" style="float: right; margin-top: -5px; margin-right: 10px;" class="button">Cancel</button>
- </div>
- <form action="{% url 'blog-admin:edit-post' post.slug %}" method="post" enctype="multipart/form-data">
- {% csrf_token %}
-
- <div class="form-group">
- <div id="toolbar-container">
- <span class="ql-formats">
- <button class="ql-header" value="1"></button>
- <button class="ql-header" value="2"></button>
- </span>
- <span class="ql-formats">
- <button class="ql-bold"></button>
- <button class="ql-italic"></button>
- <button class="ql-underline"></button>
- <button class="ql-strike"></button>
- </span>
- <span class="ql-formats">
- <button class="ql-blockquote"></button>
- <button class="ql-code-block"></button>
- </span>
- <span class="ql-formats">
- <button class="ql-script" value="sub"></button>
- <button class="ql-script" value="super"></button>
- </span>
-
- <span class="ql-formats">
- <button class="ql-list" value="ordered"></button>
- <button class="ql-list" value="bullet"></button>
- </span>
- <span class="ql-formats">
- <select class="ql-align"></select>
- </span>
- <span class="ql-formats">
- <button class="ql-link"></button>
- <button class="ql-image"></button>
- <button class="ql-formula"></button>
- </span>
- <span class="ql-formats">
- <button class="ql-clean"></button>
- </span>
- </div>
- <div id="editor-container" style="width: 730px;"></div>
- </div>
- <div class="form-group" style="display: none;">
- <textarea name="body" id="body">{{ post.body }}</textarea>
- </div>
- <br>
- <div class="form-group">
- <button type="submit" class="button button-special">Save</button>
- </div>
- </form>
+<style>
+ button {
+ color: #444;
+ }
+ textarea#body {
+ margin: 10px 0 0 0;
+ width: 710px;
+ height: 400px;
+ }
+</style>
+<h1>Editing Post: {{ post.title }}</h1>
+<div style="max-width: 730px">
+ <div id="toolbar-container">
+ <span class="ql-formats">
+ <button class="ql-header" value="1"></button>
+ <button class="ql-header" value="2"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-bold"></button>
+ <button class="ql-italic"></button>
+ <button class="ql-underline"></button>
+ <button class="ql-strike"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-blockquote"></button>
+ <button class="ql-code-block"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-script" value="sub"></button>
+ <button class="ql-script" value="super"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-list" value="ordered"></button>
+ <button class="ql-list" value="bullet"></button>
+ </span>
+ <span class="ql-formats">
+ <select class="ql-align"></select>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-link"></button>
+ <button class="ql-image"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-clean"></button>
+ <button class="ql-html" onclick="toggleHTML()">HTML</button>
+ </span>
</div>
+ <div id="editor-container"></div>
+ <form action="{% url 'blog-admin:edit-post' post.slug %}" method="post">
+ {% csrf_token %}
+ <div style="display: none" id="HTMLContent">
+ <textarea name="body" id="body">{{ post.body }}</textarea>
+ </div>
+ <br />
+ <button type="submit" class="button button-special">Save</button>
+ </form>
</div>
+{% endblock %} {% block scripts %}
<script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>
<script>
const Delta = Quill.import("delta");
- function showFormulaInsert(quill) {
- var formulaInsert = document.getElementById("math_formula_insert");
- var formulaCancel = document.getElementById("math_formula_cancel");
- var formulaInput = document.getElementById("math_formula");
- var formulaContainer = document.getElementById("math-formula-block");
- formulaContainer.style.display = "block";
- formulaInsert.onclick = function () {
- var formula = formulaInput.value;
- var formulaType = document.querySelector('input[name="math_formula_type"]:checked').value;
- if (formulaType == "inline") {
- quill.insertText(quill.getSelection().index, " $" + formula + "$ ");
- } else {
- quill.insertText(quill.getSelection().index, " $$" + formula + "$$ ");
+ let BlockEmbed = Quill.import("blots/block/embed");
+
+ class ImageBlock extends BlockEmbed {
+ static create(value) {
+ let node = super.create();
+ node.setAttribute("src", value.url);
+
+ if (value.size == "block") {
+ node.classList.add("block");
}
- formulaContainer.style.display = "none";
+
+ return node;
+ }
+
+ static value(node) {
+ return {
+ url: node.getAttribute("src"),
+ };
+ }
+
+ html() {
+ const { url } = this.value();
+ return `<img src="${url}">`;
}
- formulaCancel.onclick = function () {
- formulaContainer.style.display = "none";
+
+ static blotName = "image";
+ static tagName = "img";
+ }
+
+ Quill.register(ImageBlock);
+
+ function imageUpload(formData, quill, range, size) {
+ const imageURL = "{% url 'ignis:upload_image' %}";
+ const headers = {
+ "X-CSRFToken": "{{ csrf_token }}",
+ };
+ $.ajax({
+ url: imageURL,
+ type: "POST",
+ headers: headers,
+ data: formData,
+ processData: false,
+ contentType: false,
+ success: function (data) {
+ const imageURL = data.url;
+ quill.updateContents(
+ new Delta()
+ .retain(range.index)
+ .delete(range.length)
+ .insert({ image: { url: imageURL, size: size } })
+ );
+ },
+ error: function (err) {
+ console.log(err);
+ },
+ });
+ }
+
+ class CodeBlock extends Quill.import("formats/code-block") {
+ static create(value) {
+ let domNode = super.create();
+ domNode.setAttribute("data-language", value);
+ return domNode;
}
}
- var quill = new Quill("#editor-container", {
+ CodeBlock.blotName = "code-block";
+ CodeBlock.tagName = "pre";
+ Quill.register(CodeBlock);
+
+ const quill = new Quill("#editor-container", {
modules: {
toolbar: {
container: "#toolbar-container",
handlers: {
- formula: function () {
- showFormulaInsert(quill);
+ "code-block": function() {
+ const language = prompt("Enter language", "text");
+ this.quill.format("code-block", language);
+
},
image: function () {
- // open image upload dialog
- let fileInput = this.container.querySelector('input.ql-image[type=file]');
+ var size = prompt(
+ "Set Image Size: 0 (default) for inline, 1 for block",
+ "0"
+ );
+ if (size == "0") {
+ size = "";
+ } else if (size == "1") {
+ size = "block";
+ } else {
+ size = "";
+ }
+ let fileInput = this.container.querySelector(
+ "input.ql-image[type=file]"
+ );
if (fileInput == null) {
- fileInput = document.createElement('input');
- fileInput.setAttribute('type', 'file');
- fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon');
- fileInput.classList.add('ql-image');
- fileInput.addEventListener('change', () => {
+ fileInput = document.createElement("input");
+ fileInput.setAttribute("type", "file");
+ fileInput.setAttribute(
+ "accept",
+ "image/png, image/gif, image/jpeg, image/bmp, image/x-icon"
+ );
+ fileInput.classList.add("ql-image");
+ fileInput.addEventListener("change", () => {
if (fileInput.files != null && fileInput.files[0] != null) {
let range = this.quill.getSelection(true);
- const url = "/ignis/upload";
const formData = new FormData();
formData.append("image", fileInput.files[0]);
- formData.append("id", {{ post.id }});
- // append csrf token in header
- const headers = new Headers();
- headers.append("X-CSRFToken", "{{ csrf_token }}");
-
- fetch(url, {
- method: "POST",
- headers: headers,
- body: formData,
- }).then((response) => response.json()).then((result) => {
- this.quill.updateContents(new Delta()
- .retain(range.index)
- .delete(range.length)
- .insert({ image: result.url })
- , Quill.sources.USER);
- fileInput.value = "";
- }).catch((error) => {
- console.error("Error:", error);
- });
+ formData.append("id", "{{ post.id }}");
+ const imageURL = imageUpload(formData, this.quill, range, size);
+ fileInput.value = "";
}
});
this.container.appendChild(fileInput);
@@ -152,18 +185,19 @@
theme: "snow",
});
- // update body on text change
+ var content = $("#body").val();
+ content = content.replace(/<p><br><\/p>/g, "");
+ console.log(content);
+ //quill.setContents(quill.clipboard.convert(content), "silent");
+ quill.clipboard.dangerouslyPasteHTML(0, content);
quill.on("text-change", function (delta, oldDelta, source) {
document.getElementById("body").value = quill.root.innerHTML;
});
- try {
- const value = document.getElementById("body").value;
- const newValue = value.replace(/<p><br><\/p>/g, "");
- const delta = quill.clipboard.convert(value);
- quill.setContents(delta, "silent");
- } catch (e) {
- console.log(e);
+ function toggleHTML() {
+ $("#HTMLContent").toggle();
}
+
+
</script>
-{% endblock %}
+{% endblock %} \ No newline at end of file