Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat table support codeblock #198

Merged
merged 8 commits into from
Apr 21, 2022
56 changes: 53 additions & 3 deletions src/Cherry.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import getPosBydiffs from './utils/recount-pos';
import defaultConfig from './Cherry.config';
import './sass/cherry.scss';
import cloneDeep from 'lodash/cloneDeep';
import Event from './Event';

import { urlProcessorProxy } from './UrlCache';
import { CherryStatic } from './CherryStatic';
Expand Down Expand Up @@ -70,6 +71,13 @@ export default class Cherry extends CherryStatic {
this.options.editor.defaultModel = 'previewOnly';
}

/**
* @property
* @type {string} 实例ID
*/
this.instanceId = `cherry-${new Date().getTime()}${Math.random()}`;
this.options.instanceId = this.instanceId;

/**
* @private
* @type {Engine}
Expand All @@ -83,6 +91,11 @@ export default class Cherry extends CherryStatic {
* @private
*/
init() {
this.status = {
toolbar: 'show',
previewer: 'show',
editor: 'show',
};
let mountEl = document.getElementById(this.options.id);

if (!mountEl) {
Expand Down Expand Up @@ -147,6 +160,24 @@ export default class Cherry extends CherryStatic {
this.switchModel(this.options.editor.defaultModel);

this.cherryDomResize();
Event.on(this.instanceId, Event.Events.toolbarHide, () => {
this.status.toolbar = 'hide';
});
Event.on(this.instanceId, Event.Events.toolbarShow, () => {
this.status.toolbar = 'show';
});
Event.on(this.instanceId, Event.Events.previewerClose, () => {
this.status.previewer = 'hide';
});
Event.on(this.instanceId, Event.Events.previewerOpen, () => {
this.status.previewer = 'show';
});
Event.on(this.instanceId, Event.Events.editorClose, () => {
this.status.editor = 'hide';
});
Event.on(this.instanceId, Event.Events.editorOpen, () => {
this.status.editor = 'show';
});
}

/**
Expand All @@ -155,7 +186,7 @@ export default class Cherry extends CherryStatic {
*/
cherryDomResize() {
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
for (const {} of entries) {
setTimeout(() => this.editor.editor.refresh(), 10);
}
});
Expand Down Expand Up @@ -198,6 +229,23 @@ export default class Cherry extends CherryStatic {
}
}

/**
* 获取实例id
* @returns {string}
* @public
*/
getInstanceId() {
return this.instanceId;
}

/**
* 获取编辑器状态
* @returns {Object}
*/
getStatus() {
return this.status;
}

/**
* 获取编辑区内的markdown源码内容
* @returns markdown源码内容
Expand Down Expand Up @@ -420,6 +468,7 @@ export default class Cherry extends CherryStatic {
editor.appendChild(textArea);

this.editor = new Editor({
$cherry: this,
editorDom: editor,
wrapperDom: this.wrapperDom,
value: this.options.value,
Expand Down Expand Up @@ -456,6 +505,7 @@ export default class Cherry extends CherryStatic {
const previewerMask = createElement('div', 'cherry-previewer-mask');

this.previewer = new Previewer({
$cherry: this,
virtualDragLineDom: virtualDragLine,
editorMaskDom: editorMask,
previewerMaskDom: previewerMask,
Expand Down Expand Up @@ -487,10 +537,10 @@ export default class Cherry extends CherryStatic {

/**
* @private
* @param {Event} evt
* @param {Event} _evt
* @param {import('codemirror').Editor} codemirror
*/
editText(evt, codemirror) {
editText(_evt, codemirror) {
try {
if (this.timer) {
clearTimeout(this.timer);
Expand Down
2 changes: 2 additions & 0 deletions src/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ export default class Editor {
Object.assign(this.options.codemirror, codemirror);
}
Object.assign(this.options, restOptions);
this.$cherry = this.options.$cherry;
this.instanceId = this.$cherry.getInstanceId();
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Event.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export default new (class Event {
Events = {
previewerClose: 'previewer:close',
previewerOpen: 'previewer:open',
editorClose: 'editor:close',
editorOpen: 'editor:open',
toolbarHide: 'toolbar:hide',
toolbarShow: 'toolbar:show',
};
Expand Down
11 changes: 6 additions & 5 deletions src/Previewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ export default class Previewer {
* @param {Partial<import('~types/previewer').PreviewerOptions>} options 预览区域设置
*/
constructor(options) {
/**
* @property
* @type {string} 实例ID
*/
this.instanceId = `cherry-previewer-${new Date().getTime()}`;
/**
* @property
* @type {import('~types/previewer').PreviewerOptions}
Expand All @@ -88,6 +83,8 @@ export default class Previewer {
};

Object.assign(this.options, options);
this.$cherry = this.options.$cherry;
this.instanceId = this.$cherry.getInstanceId();
/**
* @property
* @private
Expand Down Expand Up @@ -642,12 +639,15 @@ export default class Previewer {
this.update(this.options.previewerCache.html);
}
this.cleanHtmlCache();
Event.emit(this.instanceId, Event.Events.previewerOpen);
Event.emit(this.instanceId, Event.Events.editorClose);
}

editOnly(dealToolbar = false) {
this.$dealEditAndPreviewOnly(true);
this.cleanHtmlCache();
Event.emit(this.instanceId, Event.Events.previewerClose);
Event.emit(this.instanceId, Event.Events.editorOpen);
}

recoverPreviewer(dealToolbar = false) {
Expand All @@ -665,6 +665,7 @@ export default class Previewer {
this.cleanHtmlCache();

Event.emit(this.instanceId, Event.Events.previewerOpen);
Event.emit(this.instanceId, Event.Events.editorOpen);

setTimeout(() => this.editor.editor.refresh(), 0);
}
Expand Down
5 changes: 4 additions & 1 deletion src/toolbars/PreviewerBubble.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export default class PreviewerBubble {
* @param {import('../Editor').default} editor
*/
constructor(previewer, editor) {
this.instanceId = `cherry-toolbar-${new Date().getTime()}`;
/**
* @property
* @type {import('../Previewer').default}
Expand Down Expand Up @@ -77,6 +76,10 @@ export default class PreviewerBubble {
}

$onClick(e) {
// 只有双栏编辑模式才出现该功能
if (this.previewer.$cherry.getStatus().editor === 'hide') {
return;
}
const { target } = e;
this.$removeAllPreviewerBubbles();
if (typeof target.tagName === 'undefined') {
Expand Down
20 changes: 13 additions & 7 deletions src/utils/tableContentHander.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,20 @@ const tableContentHander = {
*/
$collectTableCode() {
const tableCodes = [];
this.codeMirror.getValue().replace(this.tableReg, function (...args) {
const match = args[0].replace(/^\n*/, '');
const offsetBegin = args[args.length - 2] + args[0].match(/^\n*/)[0].length;
tableCodes.push({
code: match,
offset: offsetBegin,
this.codeMirror
.getValue()
.replace(this.codeBlockReg, (whole, ...args) => {
// 先把代码块里的表格语法关键字干掉
return whole.replace(/\|/g, '.');
})
.replace(this.tableReg, function (whole, ...args) {
const match = whole.replace(/^\n*/, '');
const offsetBegin = args[args.length - 2] + whole.match(/^\n*/)[0].length;
tableCodes.push({
code: match,
offset: offsetBegin,
});
});
});
this.tableEditor.tableCodes = tableCodes;
},

Expand Down
1 change: 1 addition & 0 deletions types/cherry.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface CherryOptions {
id: string;
/** 初始内容,引擎模式下不生效 */
value: string;
instanceId?: string;
}

export interface CherryExternalsOptions {
Expand Down
2 changes: 2 additions & 0 deletions types/editor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/
import CodeMirror from 'codemirror';
import Cherry from '../src/Cherry.js';

interface EditorEventMap {
onBlur: FocusEvent;
Expand Down Expand Up @@ -54,4 +55,5 @@ export type EditorConfiguration = {
/** 预览区域跟随编辑器光标自动滚动 */
autoScrollByCursor: boolean;
fileUpload?: (file: File, callback: (fileUrl: string) => void) => void;
$cherry?: Cherry;
};
2 changes: 2 additions & 0 deletions types/previewer.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Cherry from '../src/Cherry.js';
export type AfterUpdateCallbackFunc = () => void;

export interface PreviewerOptions {
Expand Down Expand Up @@ -25,4 +26,5 @@ export interface PreviewerOptions {
previewerMaskDom: HTMLDivElement;
/** 是否开启预览区域菜单 */
enablePreviewerBubble?: boolean;
$cherry?: Cherry;
}