/** * @fileoverview article tool for every theme * * @author Liyuan Li * @version 0.3.0.0, Nov 1, 2018 */ import $ from 'jquery' import { Editor } from './lib/b3log/editor/index' import { LazyLoadCSSImage, LazyLoadImage, ParseMarkdown } from './common' import config from '../../pipe.json' /** * @description 初始化目录 * @param {string} tocId 目录 id * @param {string} articleId 目录对应正文 id */ export const InitToc = ( tocId, articleId, articleOffset = 0, activeClass = 'toc__item--active') => { const $toc = $(`#${tocId}`) const $articleTocs = $(`#${articleId} [id^=toc]`) let tocPositionArray = [] // 目录点击 $toc.find('li').click(function () { const $it = $(this) setTimeout(function () { $toc.find('li').removeClass(activeClass) $it.addClass(activeClass) }, 50) }) $(window).scroll(function (event) { // 界面各种图片加载会导致帖子目录定位 tocPositionArray = [] $articleTocs.each(function () { tocPositionArray.push({ id: this.id, offsetTop: this.offsetTop, }) }) // 当前目录样式 let scrollTop = $(window).scrollTop() for (let i = 0, iMax = tocPositionArray.length; i < iMax; i++) { if (scrollTop < tocPositionArray[i].offsetTop - articleOffset) { $toc.find('li').removeClass(activeClass) const index = i > 0 ? i - 1 : 0 $toc.find(`a[href="#${$articleTocs[index].id}"]`). parent(). addClass(activeClass) break } } if (scrollTop >= $articleTocs[$articleTocs.length - 1].offsetTop - articleOffset) { $toc.find('li').removeClass(activeClass) $toc.find('li:last').addClass(activeClass) } }) $(window).scroll() } export const InitHljs = () => { const $codes = $('pre code') if ($codes.length === 0) { return false } var parseHljs = function () { $codes.each(function (i, block) { var $it = $(this) if ($it.hasClass('language-flow')) { return } if ($it.parent().find('.pipe-code__copy').length > 0) { return } $it.css({'max-height': $(window).height() - 40}). parent(). prepend(`
`) hljs.highlightBlock(block) }) } if (typeof hljs === 'undefined') { $.ajax({ method: 'GET', url: (config.StaticServer || config.Server) + '/theme/js/lib/highlight.min.js', dataType: 'script', cache: true, }).done(function () { parseHljs() }) } else { parseHljs() } } /** * @description 展开编辑器 * @param {String} reply 回复对象的名称 * @param {String} id 文章 id * @param {String} commentId 回复 id * @private */ export const ShowEditor = (reply, id, commentId) => { const $editor = $('#pipeEditor') if ($editor.length === 0) { location.href = 'https://hacpai.com/login' return } if (commentId) { $editor.data('commentid', commentId) } else { $editor.removeData('commentid') } $editor.css({'bottom': '0', 'opacity': 1}).data('id', id) $('body').css('padding-bottom', $editor.outerHeight() + 'px') $('#pipeEditorReplyTarget').text(reply) $('#pipeEditorComment textarea').focus() } export const InitComment = () => { /** * @description 隐藏编辑器 * @private */ const _hideEditor = () => { const $editor = $('#pipeEditor') $editor.css({'bottom': `-${$editor.outerHeight()}px`, 'opacity': 0}) $('body').css('padding-bottom', 0) } // comment null reply $('.pipe-comment__null').click(function () { const $commentNull = $(this) ShowEditor($commentNull.data('title'), $commentNull.data('id')) }) // bottom reply $('#pipeCommentsWrap').on('click', '#pipeCommentBottomComment', function () { const $bottomComment = $(this) ShowEditor($bottomComment.data('text'), $bottomComment.data('id')) }) // comment show reply $('#pipeCommentsWrap').on('click', '#pipeComments .fn-pointer', function () { const $it = $(this) if ($it.hasClass('disabled')) { return } $it.addClass('disabled') const $svg = $it.find('svg') if ($svg.hasClass('pipe-comment__chevron-down')) { $svg.removeClass('pipe-comment__chevron-down') if ($it.next().find('.pipe-comment__item').length > 0) { $it.next().slideToggle({ queue: false, complete: () => { $it.removeClass('disabled') }, }) return } $.ajax({ url: `${$('#pipeEditorComment').data('blogurl')}/comments/${$it.data( 'id')}/replies`, type: 'GET', success: (result) => { if (result.code === 0) { let commentHTML = '' result.data.forEach((item) => { commentHTML += `
${item.Author.Name} • ${item.CreatedAt}
${item.Content}
` }) $it.next().html(commentHTML).slideToggle({ queue: false, complete: () => { $it.removeClass('disabled') }, }) LazyLoadImage() LazyLoadCSSImage() InitHljs() ParseMarkdown() } else { alert(result.msg) $it.removeClass('disabled') } }, }) } else { $svg.addClass('pipe-comment__chevron-down') $it.next().slideToggle({ queue: false, complete: () => { $it.removeClass('disabled') }, }) } }) // comment remove $('#pipeCommentsWrap'). on('click', '#pipeComments .pipe-comment__btn--danger', function () { const $it = $(this) if (confirm($it.data('label'))) { $.ajax({ url: `${$('#pipeEditorComment'). data('blogurl')}/comments/${$it.data('id')}`, type: 'DELETE', success: (result) => { if (result.code === 0) { const $commentsCnt = $('#pipeCommentsCnt') const $comments = $('#pipeComments') const $item = $(`#pipeComment${$it.data('id')}`) if ($('#pipeComments > div > section').length === 1) { $comments.addClass('pipe-comment__null').html(` ${$it.data('label2')}`).click(function () { ShowEditor($comments.data('title'), $comments.data('id')) }) } else { $item.remove() $commentsCnt.text(parseInt($commentsCnt.text()) - 1) } } else { alert(result.msg) } }, }) } }) // comment reply $('#pipeCommentsWrap'). on('click', '#pipeComments .pipe-comment__btn--reply', function () { const $it = $(this) ShowEditor($it.data('title'), $it.data('id'), $it.data('commentid')) }) if ($('#pipeEditorComment').length === 0) { return } // init Editor const label = $('#pipeEditorComment').data('label').split(',') const $b3logEditor = Editor({ id: 'pipeEditorComment', placeholder: $('#pipeEditorComment').data('placeholder'), tipClass: 'pipe-tooltipped pipe-tooltipped--e', emojiURL: 'https://www.webpagefx.com/tools/emoji-cheat-sheet/', label: { emoji: label[0] + ' ', bold: label[1] + ' ', italic: label[2] + ' ', quote: label[3] + ' ', link: label[4] + ' ', upload: label[5], unorderedList: label[6] + ' ', orderedList: label[7] + ' ', view: label[8] + ' ', question: label[9], fullscreen: label[10] + ' ', emojiTip: 'EMOJI CHEAT SHEET', }, height: 180, keyup: (event) => { localStorage.setItem('pipeEditorComment', event.target.value) }, esc: _hideEditor, ctrlEnter: () => { $('#pipeEditorAdd').click() }, hasView: false, uploadURL: `${$('#pipeEditorComment').data('blogurl')}/upload`, fetchUpload: (url, succCB) => { $.ajax({ url: `${$('#pipeEditorComment').data('blogurl')}/fetch-upload`, type: 'POST', data: JSON.stringify({ url, }), success: function (result) { succCB(result.data.originalURL, result.data.url) }, }) }, previewClass: 'pipe-content__reset', staticServePath: config.StaticServer || config.Server, change: (value, $preview) => { if ($.trim(value) === '' || !$preview) { $preview && $preview.html('') return } $.ajax({ url: `${config.Server}/api/console/markdown`, type: 'POST', data: JSON.stringify({ mdText: value, }), success: function (result) { $preview.html(result.data.html) LazyLoadImage() LazyLoadCSSImage() InitHljs() ParseMarkdown() }, }) }, }) $b3logEditor.val(localStorage.getItem('pipeEditorComment')) // editor cancel $('#pipeEditorCancel').click(function () { _hideEditor() }) // editor add $('#pipeEditorAdd').click(function () { const label = $(this).data('label') const label2 = $(this).data('label2') const $editor = $('#pipeEditor') const $editorAdd = $(this) const $commentContent = $('#pipeEditorComment') if ($editorAdd.hasClass('disabled')) { return } if ($.trim($b3logEditor.val()).length === 0) { alert(label2) return } let requestData = { 'articleID': $editor.data('id'), 'content': $b3logEditor.val(), } if ($editor.data('commentid')) { requestData.parentCommentID = $editor.data('commentid') } $editorAdd.addClass('pipe-btn--disabled') $.ajax({ url: `${$commentContent.data('blogurl')}/comments`, data: JSON.stringify(requestData), type: 'POST', success: (result) => { if (result.code === 0) { _hideEditor() const $commentsCnt = $('#pipeCommentsCnt') const $comments = $('#pipeComments') if ($commentsCnt.length === 0) { $comments.removeClass('pipe-comment__null'). unbind('click'). html( `
1${label}
${result.data}
`) } else { $commentsCnt.text(parseInt($commentsCnt.text()) + 1) $('#pipeComments > div > section').last().after(result.data) } if ($(this).data('editable')) { $('#pipeComments > div > section'). last(). find('.pipe-comment__btn--danger'). removeClass('pipe-comment__btn--none') } LazyLoadCSSImage() LazyLoadImage() ParseMarkdown() InitHljs() $b3logEditor.val('') localStorage.removeItem('pipeEditorComment') } else { alert(result.msg) } $editorAdd.removeClass('pipe-btn--disabled') }, }) }) }