You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
13 KiB
337 lines
13 KiB
5 years ago
|
<?php if(!defined('__TYPECHO_ADMIN__')) exit; ?>
|
||
|
<?php $content = !empty($post) ? $post : $page; if ($options->markdown): ?>
|
||
|
<script src="<?php $options->adminStaticUrl('js', 'hyperdown.js?v=' . $suffixVersion); ?>"></script>
|
||
|
<script src="<?php $options->adminStaticUrl('js', 'pagedown.js?v=' . $suffixVersion); ?>"></script>
|
||
|
<script src="<?php $options->adminStaticUrl('js', 'pagedown-extra.js?v=' . $suffixVersion); ?>"></script>
|
||
|
<script src="<?php $options->adminStaticUrl('js', 'diff.js?v=' . $suffixVersion); ?>"></script>
|
||
|
<script>
|
||
|
$(document).ready(function () {
|
||
|
var textarea = $('#text'),
|
||
|
toolbar = $('<div class="editor" id="wmd-button-bar" />').insertBefore(textarea.parent()),
|
||
|
preview = $('<div id="wmd-preview" class="wmd-hidetab" />').insertAfter('.editor');
|
||
|
|
||
|
var options = {}, isMarkdown = <?php echo intval($content->isMarkdown || !$content->have()); ?>;
|
||
|
|
||
|
options.strings = {
|
||
|
bold: '<?php _e('加粗'); ?> <strong> Ctrl+B',
|
||
|
boldexample: '<?php _e('加粗文字'); ?>',
|
||
|
|
||
|
italic: '<?php _e('斜体'); ?> <em> Ctrl+I',
|
||
|
italicexample: '<?php _e('斜体文字'); ?>',
|
||
|
|
||
|
link: '<?php _e('链接'); ?> <a> Ctrl+L',
|
||
|
linkdescription: '<?php _e('请输入链接描述'); ?>',
|
||
|
|
||
|
quote: '<?php _e('引用'); ?> <blockquote> Ctrl+Q',
|
||
|
quoteexample: '<?php _e('引用文字'); ?>',
|
||
|
|
||
|
code: '<?php _e('代码'); ?> <pre><code> Ctrl+K',
|
||
|
codeexample: '<?php _e('请输入代码'); ?>',
|
||
|
|
||
|
image: '<?php _e('图片'); ?> <img> Ctrl+G',
|
||
|
imagedescription: '<?php _e('请输入图片描述'); ?>',
|
||
|
|
||
|
olist: '<?php _e('数字列表'); ?> <ol> Ctrl+O',
|
||
|
ulist: '<?php _e('普通列表'); ?> <ul> Ctrl+U',
|
||
|
litem: '<?php _e('列表项目'); ?>',
|
||
|
|
||
|
heading: '<?php _e('标题'); ?> <h1>/<h2> Ctrl+H',
|
||
|
headingexample: '<?php _e('标题文字'); ?>',
|
||
|
|
||
|
hr: '<?php _e('分割线'); ?> <hr> Ctrl+R',
|
||
|
more: '<?php _e('摘要分割线'); ?> <!--more--> Ctrl+M',
|
||
|
|
||
|
undo: '<?php _e('撤销'); ?> - Ctrl+Z',
|
||
|
redo: '<?php _e('重做'); ?> - Ctrl+Y',
|
||
|
redomac: '<?php _e('重做'); ?> - Ctrl+Shift+Z',
|
||
|
|
||
|
fullscreen: '<?php _e('全屏'); ?> - Ctrl+J',
|
||
|
exitFullscreen: '<?php _e('退出全屏'); ?> - Ctrl+E',
|
||
|
fullscreenUnsupport: '<?php _e('此浏览器不支持全屏操作'); ?>',
|
||
|
|
||
|
imagedialog: '<p><b><?php _e('插入图片'); ?></b></p><p><?php _e('请在下方的输入框内输入要插入的远程图片地址'); ?></p><p><?php _e('您也可以使用附件功能插入上传的本地图片'); ?></p>',
|
||
|
linkdialog: '<p><b><?php _e('插入链接'); ?></b></p><p><?php _e('请在下方的输入框内输入要插入的链接地址'); ?></p>',
|
||
|
|
||
|
ok: '<?php _e('确定'); ?>',
|
||
|
cancel: '<?php _e('取消'); ?>',
|
||
|
|
||
|
help: '<?php _e('Markdown语法帮助'); ?>'
|
||
|
};
|
||
|
|
||
|
var converter = new HyperDown(),
|
||
|
editor = new Markdown.Editor(converter, '', options),
|
||
|
diffMatch = new diff_match_patch(), last = '', preview = $('#wmd-preview'),
|
||
|
mark = '@mark' + Math.ceil(Math.random() * 100000000) + '@',
|
||
|
span = '<span class="diff" />',
|
||
|
cache = {};
|
||
|
|
||
|
// 修正白名单
|
||
|
converter.enableHtml(true);
|
||
|
converter.commonWhiteList += '|img|cite|embed|iframe';
|
||
|
converter.specialWhiteList = $.extend(converter.specialWhiteList, {
|
||
|
'ol' : 'ol|li',
|
||
|
'ul' : 'ul|li',
|
||
|
'blockquote' : 'blockquote',
|
||
|
'pre' : 'pre|code'
|
||
|
});
|
||
|
|
||
|
converter.hook('beforeParseInline', function (html) {
|
||
|
return html.replace(/^\s*<!\-\-\s*more\s*\-\->\s*$/, function () {
|
||
|
return converter.makeHolder('<!--more-->');
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// 自动跟随
|
||
|
converter.hook('makeHtml', function (html) {
|
||
|
html = html.replace('<p><!--more--></p>', '<!--more-->');
|
||
|
|
||
|
if (html.indexOf('<!--more-->') > 0) {
|
||
|
var parts = html.split(/\s*<\!\-\-more\-\->\s*/),
|
||
|
summary = parts.shift(),
|
||
|
details = parts.join('');
|
||
|
|
||
|
html = '<div class="summary">' + summary + '</div>'
|
||
|
+ '<div class="details">' + details + '</div>';
|
||
|
}
|
||
|
|
||
|
|
||
|
var diffs = diffMatch.diff_main(last, html);
|
||
|
last = html;
|
||
|
|
||
|
if (diffs.length > 0) {
|
||
|
var stack = [], markStr = mark;
|
||
|
|
||
|
for (var i = 0; i < diffs.length; i ++) {
|
||
|
var diff = diffs[i], op = diff[0], str = diff[1]
|
||
|
sp = str.lastIndexOf('<'), ep = str.lastIndexOf('>');
|
||
|
|
||
|
if (op != 0) {
|
||
|
if (sp >=0 && sp > ep) {
|
||
|
if (op > 0) {
|
||
|
stack.push(str.substring(0, sp) + markStr + str.substring(sp));
|
||
|
} else {
|
||
|
var lastStr = stack[stack.length - 1], lastSp = lastStr.lastIndexOf('<');
|
||
|
stack[stack.length - 1] = lastStr.substring(0, lastSp) + markStr + lastStr.substring(lastSp);
|
||
|
}
|
||
|
} else {
|
||
|
if (op > 0) {
|
||
|
stack.push(str + markStr);
|
||
|
} else {
|
||
|
stack.push(markStr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
markStr = '';
|
||
|
} else {
|
||
|
stack.push(str);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
html = stack.join('');
|
||
|
|
||
|
if (!markStr) {
|
||
|
var pos = html.indexOf(mark), prev = html.substring(0, pos),
|
||
|
next = html.substr(pos + mark.length),
|
||
|
sp = prev.lastIndexOf('<'), ep = prev.lastIndexOf('>');
|
||
|
|
||
|
if (sp >= 0 && sp > ep) {
|
||
|
html = prev.substring(0, sp) + span + prev.substring(sp) + next;
|
||
|
} else {
|
||
|
html = prev + span + next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 替换img
|
||
|
html = html.replace(/<(img)\s+([^>]*)\s*src="([^"]+)"([^>]*)>/ig, function (all, tag, prefix, src, suffix) {
|
||
|
if (!cache[src]) {
|
||
|
cache[src] = false;
|
||
|
} else {
|
||
|
return '<span class="cache" data-width="' + cache[src][0] + '" data-height="' + cache[src][1] + '" '
|
||
|
+ 'style="background:url(' + src + ') no-repeat left top; width:'
|
||
|
+ cache[src][0] + 'px; height:' + cache[src][1] + 'px; display: inline-block; max-width: 100%;'
|
||
|
+ '-webkit-background-size: contain;-moz-background-size: contain;-o-background-size: contain;background-size: contain;" />';
|
||
|
}
|
||
|
|
||
|
return all;
|
||
|
});
|
||
|
|
||
|
// 替换block
|
||
|
html = html.replace(/<(iframe|embed)\s+([^>]*)>/ig, function (all, tag, src) {
|
||
|
if (src[src.length - 1] == '/') {
|
||
|
src = src.substring(0, src.length - 1);
|
||
|
}
|
||
|
|
||
|
return '<div style="background: #ddd; height: 40px; overflow: hidden; line-height: 40px; text-align: center; font-size: 12px; color: #777">'
|
||
|
+ tag + ' : ' + $.trim(src) + '</div>';
|
||
|
});
|
||
|
|
||
|
return html;
|
||
|
});
|
||
|
|
||
|
function cacheResize() {
|
||
|
var t = $(this), w = parseInt(t.data('width')), h = parseInt(t.data('height')),
|
||
|
ow = t.width();
|
||
|
|
||
|
t.height(h * ow / w);
|
||
|
}
|
||
|
|
||
|
var to;
|
||
|
editor.hooks.chain('onPreviewRefresh', function () {
|
||
|
var diff = $('.diff', preview), scrolled = false;
|
||
|
|
||
|
if (to) {
|
||
|
clearTimeout(to);
|
||
|
}
|
||
|
|
||
|
$('img', preview).load(function () {
|
||
|
var t = $(this), src = t.attr('src');
|
||
|
|
||
|
if (scrolled) {
|
||
|
preview.scrollTo(diff, {
|
||
|
offset : - 50
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (!!src && !cache[src]) {
|
||
|
cache[src] = [this.width, this.height];
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$('.cache', preview).resize(cacheResize).each(cacheResize);
|
||
|
|
||
|
var changed = $('.diff', preview).parent();
|
||
|
if (!changed.is(preview)) {
|
||
|
changed.css('background-color', 'rgba(255,230,0,0.5)');
|
||
|
to = setTimeout(function () {
|
||
|
changed.css('background-color', 'transparent');
|
||
|
}, 4500);
|
||
|
}
|
||
|
|
||
|
if (diff.length > 0) {
|
||
|
var p = diff.position(), lh = diff.parent().css('line-height');
|
||
|
lh = !!lh ? parseInt(lh) : 0;
|
||
|
|
||
|
if (p.top < 0 || p.top > preview.height() - lh) {
|
||
|
preview.scrollTo(diff, {
|
||
|
offset : - 50
|
||
|
});
|
||
|
scrolled = true;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
<?php Typecho_Plugin::factory('admin/editor-js.php')->markdownEditor($content); ?>
|
||
|
|
||
|
var input = $('#text'), th = textarea.height(), ph = preview.height(),
|
||
|
uploadBtn = $('<button type="button" id="btn-fullscreen-upload" class="btn btn-link">'
|
||
|
+ '<i class="i-upload"><?php _e('附件'); ?></i></button>')
|
||
|
.prependTo('.submit .right')
|
||
|
.click(function() {
|
||
|
$('a', $('.typecho-option-tabs li').not('.active')).trigger('click');
|
||
|
return false;
|
||
|
});
|
||
|
|
||
|
$('.typecho-option-tabs li').click(function () {
|
||
|
uploadBtn.find('i').toggleClass('i-upload-active',
|
||
|
$('#tab-files-btn', this).length > 0);
|
||
|
});
|
||
|
|
||
|
editor.hooks.chain('enterFakeFullScreen', function () {
|
||
|
th = textarea.height();
|
||
|
ph = preview.height();
|
||
|
$(document.body).addClass('fullscreen');
|
||
|
var h = $(window).height() - toolbar.outerHeight();
|
||
|
|
||
|
textarea.css('height', h);
|
||
|
preview.css('height', h);
|
||
|
});
|
||
|
|
||
|
editor.hooks.chain('enterFullScreen', function () {
|
||
|
$(document.body).addClass('fullscreen');
|
||
|
|
||
|
var h = window.screen.height - toolbar.outerHeight();
|
||
|
textarea.css('height', h);
|
||
|
preview.css('height', h);
|
||
|
});
|
||
|
|
||
|
editor.hooks.chain('exitFullScreen', function () {
|
||
|
$(document.body).removeClass('fullscreen');
|
||
|
textarea.height(th);
|
||
|
preview.height(ph);
|
||
|
});
|
||
|
|
||
|
function initMarkdown() {
|
||
|
editor.run();
|
||
|
|
||
|
var imageButton = $('#wmd-image-button'),
|
||
|
linkButton = $('#wmd-link-button');
|
||
|
|
||
|
Typecho.insertFileToEditor = function (file, url, isImage) {
|
||
|
var button = isImage ? imageButton : linkButton;
|
||
|
|
||
|
options.strings[isImage ? 'imagename' : 'linkname'] = file;
|
||
|
button.trigger('click');
|
||
|
|
||
|
var checkDialog = setInterval(function () {
|
||
|
if ($('.wmd-prompt-dialog').length > 0) {
|
||
|
$('.wmd-prompt-dialog input').val(url).select();
|
||
|
clearInterval(checkDialog);
|
||
|
checkDialog = null;
|
||
|
}
|
||
|
}, 10);
|
||
|
};
|
||
|
|
||
|
Typecho.uploadComplete = function (file) {
|
||
|
Typecho.insertFileToEditor(file.title, file.url, file.isImage);
|
||
|
};
|
||
|
|
||
|
// 编辑预览切换
|
||
|
var edittab = $('.editor').prepend('<div class="wmd-edittab"><a href="#wmd-editarea" class="active"><?php _e('撰写'); ?></a><a href="#wmd-preview"><?php _e('预览'); ?></a></div>'),
|
||
|
editarea = $(textarea.parent()).attr("id", "wmd-editarea");
|
||
|
|
||
|
$(".wmd-edittab a").click(function() {
|
||
|
$(".wmd-edittab a").removeClass('active');
|
||
|
$(this).addClass("active");
|
||
|
$("#wmd-editarea, #wmd-preview").addClass("wmd-hidetab");
|
||
|
|
||
|
var selected_tab = $(this).attr("href"),
|
||
|
selected_el = $(selected_tab).removeClass("wmd-hidetab");
|
||
|
|
||
|
// 预览时隐藏编辑器按钮
|
||
|
if (selected_tab == "#wmd-preview") {
|
||
|
$("#wmd-button-row").addClass("wmd-visualhide");
|
||
|
} else {
|
||
|
$("#wmd-button-row").removeClass("wmd-visualhide");
|
||
|
}
|
||
|
|
||
|
// 预览和编辑窗口高度一致
|
||
|
$("#wmd-preview").outerHeight($("#wmd-editarea").innerHeight());
|
||
|
|
||
|
return false;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (isMarkdown) {
|
||
|
initMarkdown();
|
||
|
} else {
|
||
|
var notice = $('<div class="message notice"><?php _e('这篇文章不是由Markdown语法创建的, 继续使用Markdown编辑它吗?'); ?> '
|
||
|
+ '<button class="btn btn-xs primary yes"><?php _e('是'); ?></button> '
|
||
|
+ '<button class="btn btn-xs no"><?php _e('否'); ?></button></div>')
|
||
|
.hide().insertBefore(textarea).slideDown();
|
||
|
|
||
|
$('.yes', notice).click(function () {
|
||
|
notice.remove();
|
||
|
$('<input type="hidden" name="markdown" value="1" />').appendTo('.submit');
|
||
|
initMarkdown();
|
||
|
});
|
||
|
|
||
|
$('.no', notice).click(function () {
|
||
|
notice.remove();
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
</script>
|
||
|
<?php endif; ?>
|
||
|
|