diff --git a/DjangoBlog/tests.py b/DjangoBlog/tests.py index 8dff824..47fda83 100644 --- a/DjangoBlog/tests.py +++ b/DjangoBlog/tests.py @@ -13,12 +13,8 @@ @time: 2017/10/25 下午10:16 """ -from django.test import Client, RequestFactory, TestCase -from blog.models import Article, Category, Tag -from django.contrib.auth import get_user_model -from DjangoBlog.utils import get_current_site -from django.urls import reverse -import datetime +from django.test import TestCase + from DjangoBlog.utils import * @@ -49,8 +45,3 @@ class DjangoBlogTest(TestCase): } data = parse_dict_to_url(d) self.assertIsNotNone(data) - render = BlogMarkDownRenderer() - s = render.autolink('http://www.baidu.com') - self.assertTrue(s.find('nofollow') > 0) - s = render.link('http://www.baidu.com', 'test', 'test') - self.assertTrue(s.find('nofollow') > 0) diff --git a/DjangoBlog/utils.py b/DjangoBlog/utils.py index 6afd817..8cdbbfa 100644 --- a/DjangoBlog/utils.py +++ b/DjangoBlog/utils.py @@ -9,14 +9,9 @@ import string import uuid from hashlib import sha256 -import mistune import requests from django.contrib.sites.models import Site from django.core.cache import cache -from mistune import escape, escape_link -from pygments import highlight -from pygments.formatters import html -from pygments.lexers import get_lexer_by_name logger = logging.getLogger(__name__) @@ -93,82 +88,37 @@ def expire_view_cache(path, servername, serverport, key_prefix=None): return False -def block_code(text, lang, inlinestyles=False, linenos=False): - ''' - markdown代码高亮 - :param text: - :param lang: - :param inlinestyles: - :param linenos: - :return: - ''' - if not lang: - text = text.strip() - return u'
%s\n' % mistune.escape(text)
-
- try:
- lexer = get_lexer_by_name(lang, stripall=True)
- formatter = html.HtmlFormatter(
- noclasses=inlinestyles, linenos=linenos
- )
- code = highlight(text, lexer, formatter)
- if linenos:
- return '%s\n' % (
- lang, mistune.escape(text)
- )
-
-
@cache_decorator()
def get_current_site():
site = Site.objects.get_current()
return site
-class BlogMarkDownRenderer(mistune.Renderer):
- '''
- markdown渲染
- '''
+class CommonMarkdown:
+ @staticmethod
+ def _convert_markdown(value):
+ import markdown
+ md = markdown.Markdown(
+ extensions=[
+ 'extra',
+ 'codehilite',
+ 'toc',
+ 'tables',
+ ]
+ )
+ body = md.convert(value)
+ toc = md.toc
+ return body, toc
- def block_code(self, text, lang=None):
- # renderer has an options
- inlinestyles = self.options.get('inlinestyles')
- linenos = self.options.get('linenos')
- return block_code(text, lang, inlinestyles, linenos)
-
- def autolink(self, link, is_email=False):
- text = link = escape(link)
-
- if is_email:
- link = 'mailto:%s' % link
- if not link:
- link = "#"
- site = get_current_site()
- nofollow = "" if link.find(site.domain) > 0 else "rel='nofollow'"
- return '%s' % (link, nofollow, text)
-
- def link(self, link, title, text):
- link = escape_link(link)
- site = get_current_site()
- nofollow = "" if link.find(site.domain) > 0 else "rel='nofollow'"
- if not link:
- link = "#"
- if not title:
- return '%s' % (link, nofollow, text)
- title = escape(title, quote=True)
- return '%s' % (
- link, title, nofollow, text)
-
-
-class CommonMarkdown():
@staticmethod
- def get_markdown(value):
- renderer = BlogMarkDownRenderer(inlinestyles=False)
+ def get_markdown_with_toc(value):
+ body, toc = CommonMarkdown._convert_markdown(value)
+ return body, toc
- mdp = mistune.Markdown(escape=True, renderer=renderer)
- return mdp(value)
+ @staticmethod
+ def get_markdown(value):
+ body, toc = CommonMarkdown._convert_markdown(value)
+ return body
def send_email(emailto, title, content):
diff --git a/blog/models.py b/blog/models.py
index 067de72..c04a4cd 100644
--- a/blog/models.py
+++ b/blog/models.py
@@ -1,16 +1,17 @@
import logging
-from abc import ABCMeta, abstractmethod, abstractproperty
+from abc import abstractmethod
-from django.db import models
-from django.urls import reverse
from django.conf import settings
-from uuslug import slugify
from django.core.exceptions import ValidationError
-from django.utils.translation import gettext_lazy as _
-from DjangoBlog.utils import get_current_site
-from DjangoBlog.utils import cache_decorator, cache
+from django.db import models
+from django.urls import reverse
from django.utils.timezone import now
+from django.utils.translation import gettext_lazy as _
from mdeditor.fields import MDTextField
+from uuslug import slugify
+
+from DjangoBlog.utils import cache_decorator, cache
+from DjangoBlog.utils import get_current_site
logger = logging.getLogger(__name__)
@@ -94,6 +95,7 @@ class Article(BaseModel):
on_delete=models.CASCADE)
article_order = models.IntegerField(
'排序,数字越大越靠前', blank=False, null=False, default=0)
+ show_toc = models.BooleanField("是否显示toc目录", blank=False, null=False, default=False)
category = models.ForeignKey(
'Category',
verbose_name='分类',
diff --git a/blog/static/blog/css/style.css b/blog/static/blog/css/style.css
index 0cc1df1..d43f7f3 100644
--- a/blog/static/blog/css/style.css
+++ b/blog/static/blog/css/style.css
@@ -2479,17 +2479,26 @@ li #reply-title {
}
.breadcrumb {
- margin-bottom: 20px;
- list-style: none;
- border-radius: 4px;
+ margin-bottom: 20px;
+ list-style: none;
+ border-radius: 4px;
}
+
.breadcrumb > li {
- display: inline-block;
+ display: inline-block;
}
+
.breadcrumb > li + li:before {
- color: #ccc;
- content: "/\00a0";
+ color: #ccc;
+ content: "/\00a0";
}
+
.breadcrumb > .active {
- color: #777;
+ color: #777;
+}
+
+.break_line {
+ height: 1px;
+ border: none;
+ /*border-top: 1px dashed #f5d6d6;*/
}
\ No newline at end of file
diff --git a/blog/static/pygments/default.css b/blog/static/pygments/default.css
index 0f81fc8..73e6e49 100755
--- a/blog/static/pygments/default.css
+++ b/blog/static/pygments/default.css
@@ -1,59 +1,293 @@
-.highlight .hll { background-color: #ffffcc }
-.highlight { background: #ffffff; }
-.highlight .c { color: #177500 } /* Comment */
-.highlight .err { color: #000000 } /* Error */
-.highlight .k { color: #A90D91 } /* Keyword */
-.highlight .l { color: #1C01CE } /* Literal */
-.highlight .n { color: #000000 } /* Name */
-.highlight .o { color: #000000 } /* Operator */
-.highlight .ch { color: #177500 } /* Comment.Hashbang */
-.highlight .cm { color: #177500 } /* Comment.Multiline */
-.highlight .cp { color: #633820 } /* Comment.Preproc */
-.highlight .cpf { color: #177500 } /* Comment.PreprocFile */
-.highlight .c1 { color: #177500 } /* Comment.Single */
-.highlight .cs { color: #177500 } /* Comment.Special */
-.highlight .kc { color: #A90D91 } /* Keyword.Constant */
-.highlight .kd { color: #A90D91 } /* Keyword.Declaration */
-.highlight .kn { color: #A90D91 } /* Keyword.Namespace */
-.highlight .kp { color: #A90D91 } /* Keyword.Pseudo */
-.highlight .kr { color: #A90D91 } /* Keyword.Reserved */
-.highlight .kt { color: #A90D91 } /* Keyword.Type */
-.highlight .ld { color: #1C01CE } /* Literal.Date */
-.highlight .m { color: #1C01CE } /* Literal.Number */
-.highlight .s { color: #C41A16 } /* Literal.String */
-.highlight .na { color: #836C28 } /* Name.Attribute */
-.highlight .nb { color: #A90D91 } /* Name.Builtin */
-.highlight .nc { color: #3F6E75 } /* Name.Class */
-.highlight .no { color: #000000 } /* Name.Constant */
-.highlight .nd { color: #000000 } /* Name.Decorator */
-.highlight .ni { color: #000000 } /* Name.Entity */
-.highlight .ne { color: #000000 } /* Name.Exception */
-.highlight .nf { color: #000000 } /* Name.Function */
-.highlight .nl { color: #000000 } /* Name.Label */
-.highlight .nn { color: #000000 } /* Name.Namespace */
-.highlight .nx { color: #000000 } /* Name.Other */
-.highlight .py { color: #000000 } /* Name.Property */
-.highlight .nt { color: #000000 } /* Name.Tag */
-.highlight .nv { color: #000000 } /* Name.Variable */
-.highlight .ow { color: #000000 } /* Operator.Word */
-.highlight .mb { color: #1C01CE } /* Literal.Number.Bin */
-.highlight .mf { color: #1C01CE } /* Literal.Number.Float */
-.highlight .mh { color: #1C01CE } /* Literal.Number.Hex */
-.highlight .mi { color: #1C01CE } /* Literal.Number.Integer */
-.highlight .mo { color: #1C01CE } /* Literal.Number.Oct */
-.highlight .sb { color: #C41A16 } /* Literal.String.Backtick */
-.highlight .sc { color: #2300CE } /* Literal.String.Char */
-.highlight .sd { color: #C41A16 } /* Literal.String.Doc */
-.highlight .s2 { color: #C41A16 } /* Literal.String.Double */
-.highlight .se { color: #C41A16 } /* Literal.String.Escape */
-.highlight .sh { color: #C41A16 } /* Literal.String.Heredoc */
-.highlight .si { color: #C41A16 } /* Literal.String.Interpol */
-.highlight .sx { color: #C41A16 } /* Literal.String.Other */
-.highlight .sr { color: #C41A16 } /* Literal.String.Regex */
-.highlight .s1 { color: #C41A16 } /* Literal.String.Single */
-.highlight .ss { color: #C41A16 } /* Literal.String.Symbol */
-.highlight .bp { color: #5B269A } /* Name.Builtin.Pseudo */
-.highlight .vc { color: #000000 } /* Name.Variable.Class */
-.highlight .vg { color: #000000 } /* Name.Variable.Global */
-.highlight .vi { color: #000000 } /* Name.Variable.Instance */
-.highlight .il { color: #1C01CE } /* Literal.Number.Integer.Long */
\ No newline at end of file
+.codehilite .hll {
+ background-color: #ffffcc
+}
+
+.codehilite {
+ background: #ffffff;
+}
+
+.codehilite .c {
+ color: #177500
+}
+
+/* Comment */
+.codehilite .err {
+ color: #000000
+}
+
+/* Error */
+.codehilite .k {
+ color: #A90D91
+}
+
+/* Keyword */
+.codehilite .l {
+ color: #1C01CE
+}
+
+/* Literal */
+.codehilite .n {
+ color: #000000
+}
+
+/* Name */
+.codehilite .o {
+ color: #000000
+}
+
+/* Operator */
+.codehilite .ch {
+ color: #177500
+}
+
+/* Comment.Hashbang */
+.codehilite .cm {
+ color: #177500
+}
+
+/* Comment.Multiline */
+.codehilite .cp {
+ color: #633820
+}
+
+/* Comment.Preproc */
+.codehilite .cpf {
+ color: #177500
+}
+
+/* Comment.PreprocFile */
+.codehilite .c1 {
+ color: #177500
+}
+
+/* Comment.Single */
+.codehilite .cs {
+ color: #177500
+}
+
+/* Comment.Special */
+.codehilite .kc {
+ color: #A90D91
+}
+
+/* Keyword.Constant */
+.codehilite .kd {
+ color: #A90D91
+}
+
+/* Keyword.Declaration */
+.codehilite .kn {
+ color: #A90D91
+}
+
+/* Keyword.Namespace */
+.codehilite .kp {
+ color: #A90D91
+}
+
+/* Keyword.Pseudo */
+.codehilite .kr {
+ color: #A90D91
+}
+
+/* Keyword.Reserved */
+.codehilite .kt {
+ color: #A90D91
+}
+
+/* Keyword.Type */
+.codehilite .ld {
+ color: #1C01CE
+}
+
+/* Literal.Date */
+.codehilite .m {
+ color: #1C01CE
+}
+
+/* Literal.Number */
+.codehilite .s {
+ color: #C41A16
+}
+
+/* Literal.String */
+.codehilite .na {
+ color: #836C28
+}
+
+/* Name.Attribute */
+.codehilite .nb {
+ color: #A90D91
+}
+
+/* Name.Builtin */
+.codehilite .nc {
+ color: #3F6E75
+}
+
+/* Name.Class */
+.codehilite .no {
+ color: #000000
+}
+
+/* Name.Constant */
+.codehilite .nd {
+ color: #000000
+}
+
+/* Name.Decorator */
+.codehilite .ni {
+ color: #000000
+}
+
+/* Name.Entity */
+.codehilite .ne {
+ color: #000000
+}
+
+/* Name.Exception */
+.codehilite .nf {
+ color: #000000
+}
+
+/* Name.Function */
+.codehilite .nl {
+ color: #000000
+}
+
+/* Name.Label */
+.codehilite .nn {
+ color: #000000
+}
+
+/* Name.Namespace */
+.codehilite .nx {
+ color: #000000
+}
+
+/* Name.Other */
+.codehilite .py {
+ color: #000000
+}
+
+/* Name.Property */
+.codehilite .nt {
+ color: #000000
+}
+
+/* Name.Tag */
+.codehilite .nv {
+ color: #000000
+}
+
+/* Name.Variable */
+.codehilite .ow {
+ color: #000000
+}
+
+/* Operator.Word */
+.codehilite .mb {
+ color: #1C01CE
+}
+
+/* Literal.Number.Bin */
+.codehilite .mf {
+ color: #1C01CE
+}
+
+/* Literal.Number.Float */
+.codehilite .mh {
+ color: #1C01CE
+}
+
+/* Literal.Number.Hex */
+.codehilite .mi {
+ color: #1C01CE
+}
+
+/* Literal.Number.Integer */
+.codehilite .mo {
+ color: #1C01CE
+}
+
+/* Literal.Number.Oct */
+.codehilite .sb {
+ color: #C41A16
+}
+
+/* Literal.String.Backtick */
+.codehilite .sc {
+ color: #2300CE
+}
+
+/* Literal.String.Char */
+.codehilite .sd {
+ color: #C41A16
+}
+
+/* Literal.String.Doc */
+.codehilite .s2 {
+ color: #C41A16
+}
+
+/* Literal.String.Double */
+.codehilite .se {
+ color: #C41A16
+}
+
+/* Literal.String.Escape */
+.codehilite .sh {
+ color: #C41A16
+}
+
+/* Literal.String.Heredoc */
+.codehilite .si {
+ color: #C41A16
+}
+
+/* Literal.String.Interpol */
+.codehilite .sx {
+ color: #C41A16
+}
+
+/* Literal.String.Other */
+.codehilite .sr {
+ color: #C41A16
+}
+
+/* Literal.String.Regex */
+.codehilite .s1 {
+ color: #C41A16
+}
+
+/* Literal.String.Single */
+.codehilite .ss {
+ color: #C41A16
+}
+
+/* Literal.String.Symbol */
+.codehilite .bp {
+ color: #5B269A
+}
+
+/* Name.Builtin.Pseudo */
+.codehilite .vc {
+ color: #000000
+}
+
+/* Name.Variable.Class */
+.codehilite .vg {
+ color: #000000
+}
+
+/* Name.Variable.Global */
+.codehilite .vi {
+ color: #000000
+}
+
+/* Name.Variable.Instance */
+.codehilite .il {
+ color: #1C01CE
+}
+
+/* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/blog/templatetags/blog_tags.py b/blog/templatetags/blog_tags.py
index 73df621..c899099 100644
--- a/blog/templatetags/blog_tags.py
+++ b/blog/templatetags/blog_tags.py
@@ -13,24 +13,24 @@
@time: 2016/11/2 下午11:10
"""
+import hashlib
+import logging
+import random
+import urllib
+
from django import template
-from django.db.models import Q
from django.conf import settings
+from django.db.models import Q
+from django.shortcuts import get_object_or_404
from django.template.defaultfilters import stringfilter
-from django.utils.safestring import mark_safe
-import random
from django.urls import reverse
+from django.utils.safestring import mark_safe
+
+from DjangoBlog.utils import cache
+from DjangoBlog.utils import get_current_site
from blog.models import Article, Category, Tag, Links, SideBar, LinkShowType
-from django.utils.encoding import force_text
-from django.shortcuts import get_object_or_404
-import hashlib
-import urllib
from comments.models import Comment
-from DjangoBlog.utils import cache_decorator, cache
-from django.contrib.auth import get_user_model
from oauth.models import OAuthUser
-from DjangoBlog.utils import get_current_site
-import logging
logger = logging.getLogger(__name__)
@@ -64,6 +64,13 @@ def custom_markdown(content):
return mark_safe(CommonMarkdown.get_markdown(content))
+@register.simple_tag
+def get_markdown_toc(content):
+ from DjangoBlog.utils import CommonMarkdown
+ body, toc = CommonMarkdown.get_markdown_with_toc(content)
+ return mark_safe(toc), mark_safe(body)
+
+
@register.filter(is_safe=True)
@stringfilter
def truncatechars_content(content):
diff --git a/blog/tests.py b/blog/tests.py
index 6c90727..acf6ad8 100644
--- a/blog/tests.py
+++ b/blog/tests.py
@@ -1,17 +1,18 @@
+import os
+
+from django.conf import settings
+from django.core.files.uploadedfile import SimpleUploadedFile
+from django.core.management import call_command
+from django.core.paginator import Paginator
from django.test import Client, RequestFactory, TestCase
-from blog.models import Article, Category, Tag, SideBar, Links
-from django.contrib.auth import get_user_model
+from django.urls import reverse
+from django.utils import timezone
+
from DjangoBlog.utils import get_current_site, get_sha256
+from accounts.models import BlogUser
from blog.forms import BlogSearchForm
-from django.core.paginator import Paginator
+from blog.models import Article, Category, Tag, SideBar, Links
from blog.templatetags.blog_tags import load_pagination_info, load_articletags
-from accounts.models import BlogUser
-from django.core.files.uploadedfile import SimpleUploadedFile
-from django.conf import settings
-from django.urls import reverse
-from django.utils import timezone
-import os
-from django.core.management import call_command
# Create your tests here.
@@ -147,8 +148,7 @@ class ArticleTest(TestCase):
response = self.client.get('/sitemap.xml')
self.assertEqual(response.status_code, 200)
- from DjangoBlog.utils import block_code
- block = block_code("`python`", 'python')
+
self.client.get("/admin/blog/article/1/delete/")
self.client.get('/admin/servermanager/emailsendlog/')
self.client.get('admin/admin/logentry/')
diff --git a/requirements.txt b/requirements.txt
index d1f77d7..675479f 100644
Binary files a/requirements.txt and b/requirements.txt differ
diff --git a/templates/blog/tags/article_info.html b/templates/blog/tags/article_info.html
index db44157..25058af 100644
--- a/templates/blog/tags/article_info.html
+++ b/templates/blog/tags/article_info.html
@@ -51,7 +51,17 @@
{% else %}
- {{ article.body|custom_markdown }}
+ {% get_markdown_toc article.body as markdown %}
+ {% if article.show_toc %}
+
+ 目录:
+ {{ markdown.0|safe }}
+
+