小书匠编辑器使用手册
Posted sama
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小书匠编辑器使用手册相关的知识,希望对你有一定的参考价值。
小书匠编辑器使用手册
概要
小书匠编辑器是一款专为markdown写作而设计的编辑器。
主要功能
- 专为markdown写作设计的文档编辑器,让用户心无旁骛的进行创作。
- 多种编辑模式。单栏编辑,双栏编辑,三栏编辑,全屏写作,全屏阅读...想怎么切换,就怎么切换,就是这样随心所欲。
- 多种编辑器实现。codemirror编辑器(提供vim,emacs按键,行专注等),ace编辑器(提供vim,emacs按键绑定,显示行号),轻量编辑器,CJK竖排编辑器
- 多种主题选择。包括编辑器主题,预览区代码高亮主题,及预览区用户自定义css。
- 丰富的语法支持。不仅提供了常用的commanmarkdown语法,还提供了许多有用的扩展语法,比如Latex公式,表格, 目录, 脚注, 视频, 音频, 附件, checklist, 流程图等。更多语法可查看<小书匠语法使用手册>
- 代码块文字格式语法。语法可查看<小书匠语法使用手册>
- 第三方同步。浏览器存储, 本地文件系统存储, dropbox, evernote, 印象笔记,gitoschina, 为知笔记, github等多种存储方案,保证了用户数据的安全,也让用户在存储方案上有了更多的选择。
- 支持evernote,印象笔记。提供双向操作,可以将文章保存到evernote/印象笔记上,也可以从evernote/印象笔记上导入数据。同时提供标签,附件,图片,待办等相关处理。
- 强大的文件管理功能。文件信息,标签,附件,音频,视频,图片管理。
- 发布功能。 支持将文章发布到博客平台上。
- 邮件发送功能。
- sourceMap对照功能。方便在源markdown文件和生成的html文件上进行比较,特别适合markdown初学者使用,了解每一个markdown解析产生的结果,也适用于文章后期的校对上。
- ppt。
- ppt跨屏演示
- pdf预览
- typewriter scrolling
- autocomplete 和 snippets 功能
离线版下载地址
WEB版访问地址
http://markdown.xiaoshujiang.com
元数据使用说明
语法开关元数据项,可以到设置面板里的语法扩展标签页下查看对应的元数据标识.在元数据里true时,表示当前文档强制打开该语法,false时表示强制关闭该语法.如果没有对应的元数据,则使用全局设置里的语法开关.
preview_previewType
元数据,可用的值为normal
和presentation
.用于文章在打开时,控制是否需要系统切换对应的预览界面.如果文章里没有该项元数据,或者元数据值不正确,则系统默认使用normal
预览界面.该元数据仅控制文章打开时初始化的界面,用户依然可以通过按钮在不同预览界面间切换.
浏览器存储
系统对创建的文章,都会在浏览器存储上进行保存。包括像evernote/印象笔记/github/dropbox等导入的文章,也都会保存一份副本,并创建一个标识,表示跟哪些第三方存储关联。
标题,标签
文章标题的处理规则:如果文章内存在元数据title,则系统自动使用元数据内的title做为标题。如果文章未使用到元数据功能,用户可以通过维护文章信息按钮,修改标题。标签tags的规则也跟标题一样。
附件
文章使用./
做为附件的引用标识。对于图片
,音频
,视频
,附件
等链接的处理,系统只处理以./
开头的链接,并转换成附件真实的地址进行显示。用户可以通过工具栏的插入图片
,插入音频
,插入视频
,插入附件
等按钮上传附件。
evernote/印象笔记
小书匠编辑器提供对evernote/印象笔记的支持,下面的使用说明默认用户已经完成了evernote/印象笔记的绑定操作,并将当前的工作平台切换到evernote/印象笔记下。
新建
通过新建按钮后,创建的文章将自动关联到evernote/印象笔记上(注:这里仅仅是在文章上创建一个关联的标识,只有当用户保存后,才能在服务器上查看到新的笔记)
打开
点击笔记,系统将自动把笔记导入,并将当前文章切换为导入的笔记内容。导入的文章自动与evernote/印象笔记上的笔记关联,下次再点击该笔记时,将直接从浏览器存储上打开。用户可以通过切换存储平台浏览器存储
,来删除该缓存的文件。导入的笔记如果本地没有缓存,系统将对服务器上的笔记进行判断,如果笔记是通过小书匠编辑器进行保存,并且文章在保存后没有被操作过,则系统自动使用保存时附带的markdown附件做为文章内容,重新导入。如果笔记已经被修改,或者笔记不是通过小书匠编辑器进行保存的,系统将自动将文章转换成markdown格式。
保存
对于新创建的文章,用户可以直接保存ctrl+s
,系统将弹出一个选择笔记本的窗口,确认后,系统将保存当前文章到evernote/印象笔记上。(在弹出窗口上选择笔记本时,如果用户选择了笔记,系统将覆盖该笔记)
对于已经存在的文章,但还没有保存到evernote/印象笔记,用户可以通过另存为ctrl+shift+s
将当前文章保存到evernote/印象笔记上。
不管是保存,还是另存为,保存成功后,系统都将自动对当前文章与evernote/印象笔记上的笔记进行关联。下次保存时ctrl+s
系统将自动同步保存到evernote/印象笔记上。
删除
系统不提供删除操作,用户需要自己到evernote/印象笔记端删除,如果本地缓存了笔记,可以通过浏览器存储
删除缓存。
重命名
直接修改元数据title,如果文章内未使用元数据功能,可通过浏览器存储
里的修改文章信息进行修改
标签管理
系统自动通过每篇文章的元数据tags
提取为笔记的标签。
附件管理
打开时,系统自动将笔记上的附件导入到文章对应的附件管理器上。保存时,系统将根据文章内对附件的引用,将附件保存到服务器上。这里的引用包括音频
,视频
,附件
,图片
。如果文章内使用到了流程图
,序列图
,公式
,统计图
等,系统将会把这些内容转换成图片进行保存。由于evernote/印象笔记在部分终端不提供视频,音频的支持,查看保存的文章时,对应的音频,视频将以附件的形式存储。
待办事项
目前系统仅同步了待办事项。
github/dropbox
新建
参考evernote/印象笔记
的新建
打开
参考evernote/印象笔记
的打开
不同的是,github/dropbox只能打开扩展名为html
,markdown
,md
,mkd
以及无扩展名的文件。
保存
参考evernote/印象笔记
的保存
不同的是,github/dropbox保存时,仅保存了markdown文章本身,并不会将markdown转换成html进行保存,也不会处理附件相关的内容。
对于新文章的保存,github/dropbox存储需要用户指定文件名及存储的位置。
删除
系统不提供删除操作
重命名
系统不提供重命名操作,只能通过另存为ctrl+shift+s
,保存成新的文件。
本地文件系统存储
本地文件系统存储仅在离线版提供支持。
新建
参考evernote/印象笔记
的新建
打开
参考github/dropbox
的打开
不同的是,本地文件系统存储在打开文件时,将会自动关联文章内的附件引用标识./
,自动抓取同级目录下对应的附件资源。
保存
参考github/dropbox
的保存
不同的是,本地文件系统存储在保存时,不仅保存了markdown文章,还会处理附件相关的内容,将附件保存到同级目录下,请确保附件的名称不要重复,防止数据被覆盖丢失。
删除
右击相应的文章可进行删除操作
重命名
右击相应的文章可进行重命名操作
发布
小书匠编辑器离线版提供文章发布功能,用户可以将自己的文章发布到博客系统上。发布功能实现了博客的metaweblogAPI(newPost, editPost, newMediaObject)。使用该发布功能,需要博客系统提供对应的api接口,系统将转换成html的文章和图片自动提交到博客系统上。
配置发布示例:
博客链接地址:比如http://www.cnblogs.com/sama/
用户名:ly901107
密码:用户在该博客上的密码
测试通过的博客地址:
博客园:http://www.cnblogs.com/[用户名]/
开源中国:http://my.oschina.net/[用户名]/blog
邮件发送
小书匠编辑器提供邮件发送功能,系统将对当前文章转换成html格式后进行发送,并对图片,视频等文件以附件的形式进行发送。
导出
小书匠编辑器提供多种格式的导出文件功能。html,markdown,html(inlinestyle),word,zip,pdf。
zip导出: 该导出将导出文章的所有信息,包括markdown,html,markdown文章内引用的所有附件,公式,流程图等对应的图片文件,以及方便再次导入时需要的标识数据文件。
pdf导出:目前pdf导出只能在chrome版浏览器上使用。
导入
小书匠编辑器提供markdown, html, zip三种导入功能,并且实现了文本文件直接拖动导入功能。
zip导入:导入的zip文件必需是由小书匠编辑器导出的文件。
from django.shortcuts import render, redirect, HttpResponse
from app01 import models
from static.utils.Pager import PageInfo
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
import random, os
from static.utils.check_code_random import rd_check_code
from django.forms import Form
from django.forms import fields, widgets
from django.core.exceptions import ValidationError
from app01.forms import MyRegisterForm, MyLoginForm
def index(request, *args, **kwargs):
‘‘‘
主页
:param request:
:param args:
:param kwargs:
:return:
‘‘‘
result = request.session.get(‘username‘)
if result:
# 分页
# 获取当前URL request.path_info
current_page = request.GET.get(‘page‘)
base_url = request.path_info
# 标签分类
# 基本方式一
# type_id = int(kwargs.get(‘type_id‘)) if kwargs.get(‘type_id‘) else None
# if type_id:
# article_list = models.Article.objects.filter(article_type_id=type_id)
# else:
# article_list = models.Article.objects.all()
# 方式二
content = {}
type_id = int(kwargs.get(‘type_id‘)) if kwargs.get(‘type_id‘) else None
if type_id:
content[‘article_type_id‘] = type_id
# 注意此处 filter条件为空字典的时候获取全部数据
# ******分页
all_count = models.Article.objects.filter(**content).count()
page_info = PageInfo(current_page, all_count, 10, base_url, 11)
# ******分页
article_list = models.Article.objects.filter(**content)[page_info.start():page_info.end()]
type_choice = models.Article.type_choice
login_flag = True
return render(request, ‘index.html‘, {
‘type_choice‘: type_choice,
‘article_list‘: article_list,
‘type_id‘: type_id,
‘page_info‘: page_info,
‘login_flag‘: login_flag
})
else:
return redirect(‘/login/‘)
def login(request):
‘‘‘
登陆界面
:param request:
:return:
‘‘‘
if request.method == ‘GET‘:
my_login_form = MyLoginForm()
return render(request, ‘login.html‘, {‘my_login_form‘: my_login_form})
else:
input_code = request.POST.get(‘code‘)
session_code = request.session.get(‘code‘)
my_login_form = MyLoginForm(request.POST)
# form表单验证
if my_login_form.is_valid():
# 验证码验证
if input_code.upper() == session_code.upper():
# 账号密码验证
input_username = request.POST.get(‘username‘)
input_password = request.POST.get(‘password‘)
result = models.UserInfo.objects.filter(username=input_username, password=input_password).first()
if result:
request.session[‘username‘] = result.username
return redirect(‘/idnex/‘)
else:
return render(request, ‘login.html‘, {‘my_login_form‘: my_login_form, ‘user_error‘: ‘账号或密码错误‘})
else:
return render(request, ‘login.html‘, {‘my_login_form‘: my_login_form, ‘code_error‘: ‘验证码错误‘})
else:
return render(request, ‘login.html‘, {‘my_login_form‘: my_login_form})
def check_code(request):
img, code = rd_check_code()
stream = BytesIO()
img.save(stream, ‘png‘)
data = stream.getvalue()
request.session[‘code‘] = code
return HttpResponse(data)
def register(request):
if request.method == ‘GET‘:
my_register_form = MyRegisterForm(request)
return render(request, ‘register.html‘, {‘my_register_form‘: my_register_form})
else:
# *****重点****
# 发送文件时需要将files传入
my_register_form = MyRegisterForm(request, request.POST, files=request.FILES)
if my_register_form.is_valid():
my_register_form.cleaned_data.pop(‘password2‘)
my_register_form.cleaned_data.pop(‘code‘)
# 获取文件存储
file_obj = request.FILES.get(‘avatar‘)
file_obj = request.FILES.get(‘avatar‘)
file_path = os.path.join(‘static‘, ‘avatar‘, file_obj.name)
my_register_form.cleaned_data[‘avatar‘] = ‘/‘ + file_path
print(my_register_form.cleaned_data)
# 写入头像信息
with open(file_path, ‘wb‘) as f:
# chunks() 括号一定要加
for chunk in file_obj.chunks():
f.write(chunk)
# 写入数据库
models.UserInfo.objects.create(**my_register_form.cleaned_data)
return redirect(‘/login/‘)
else:
return render(request, ‘register.html‘, {‘my_register_form‘: my_register_form})
def upload_avatar(request):
file_obj = request.FILES.get(‘avatar‘)
file_path = os.path.join(‘static‘, ‘avatar‘, file_obj.name)
with open(file_path, ‘wb‘) as f:
for chunk in file_obj.chunks():
f.write(chunk)
return HttpResponse(file_path)
def foo():
models
其他
web版实现了图片直接粘贴功能,用户不仅可以拖动图片上传,还可以直接复制粘贴图片。
以上是关于小书匠编辑器使用手册的主要内容,如果未能解决你的问题,请参考以下文章