feat: 更新 MarkdownEditor 组件及其 editor.md 源码
This commit is contained in:
parent
a43f75db00
commit
a9678c0400
@ -295,6 +295,18 @@
|
|||||||
info : "fa-info-circle"
|
info : "fa-info-circle"
|
||||||
},
|
},
|
||||||
toolbarIconTexts : {},
|
toolbarIconTexts : {},
|
||||||
|
toolbarNoFocus : [
|
||||||
|
"link",
|
||||||
|
"reference-link",
|
||||||
|
"image",
|
||||||
|
"code-block",
|
||||||
|
"preformatted-text",
|
||||||
|
"watch",
|
||||||
|
"preview",
|
||||||
|
"search",
|
||||||
|
"fullscreen",
|
||||||
|
"info",
|
||||||
|
],
|
||||||
|
|
||||||
lang : {
|
lang : {
|
||||||
name : "zh-cn",
|
name : "zh-cn",
|
||||||
@ -437,6 +449,49 @@
|
|||||||
var classPrefix = this.classPrefix = editormd.classPrefix;
|
var classPrefix = this.classPrefix = editormd.classPrefix;
|
||||||
var settings = this.settings = $.extend(true, editormd.defaults, options);
|
var settings = this.settings = $.extend(true, editormd.defaults, options);
|
||||||
|
|
||||||
|
// 支持新增或覆盖原有 toolbar(要求 settings.toolbarIcons 非自定义模式)
|
||||||
|
if (settings.appendToolbar && typeof settings.toolbarIcons === "string" && settings.toolbarIcons in editormd.toolbarModes) {
|
||||||
|
settings.appendToolbar.forEach(toolbar => {
|
||||||
|
// 如果没有 name 字段,则忽略该 toolbar
|
||||||
|
if (!('name' in toolbar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果是 | 分隔符,则仅用于占位分隔
|
||||||
|
if (toolbar.name === "|") {
|
||||||
|
editormd.toolbarModes[settings.toolbarIcons].push("|");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果未定义该 toolbar,则执行 append;否则覆盖原有 toolbar
|
||||||
|
if (!editormd.toolbarModes[settings.toolbarIcons].includes(toolbar.name)) {
|
||||||
|
editormd.toolbarModes[settings.toolbarIcons].push(toolbar.name);
|
||||||
|
}
|
||||||
|
if ('icon' in toolbar) {
|
||||||
|
settings.toolbarIconsClass[toolbar.name] = toolbar.icon;
|
||||||
|
}
|
||||||
|
if ('title' in toolbar) {
|
||||||
|
settings.lang.toolbar[toolbar.name] = toolbar.title;
|
||||||
|
}
|
||||||
|
if ('handler' in toolbar) {
|
||||||
|
editormd.toolbarHandlers[toolbar.name] = toolbar.handler;
|
||||||
|
if ('shortcut' in toolbar) {
|
||||||
|
// 给新增的工具栏图标绑定快捷键
|
||||||
|
toolbar.shortcut.forEach(key => editormd.keyMaps[key] = toolbar.handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ('nofocus' in toolbar && toolbar.nofocus === true) {
|
||||||
|
if (!settings.toolbarNoFocus.includes[toolbar.name]) {
|
||||||
|
settings.toolbarNoFocus.push(toolbar.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.shortcutFunction) {
|
||||||
|
for (const key in settings.shortcutFunction) {
|
||||||
|
editormd.keyMaps[key] = settings.shortcutFunction[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
id = (typeof id === "object") ? settings.id : id;
|
id = (typeof id === "object") ? settings.id : id;
|
||||||
|
|
||||||
var editor = this.editor = $("#" + id);
|
var editor = this.editor = $("#" + id);
|
||||||
@ -1339,12 +1394,12 @@
|
|||||||
if (typeof settings.toolbarHandlers[name] !== "undefined")
|
if (typeof settings.toolbarHandlers[name] !== "undefined")
|
||||||
{
|
{
|
||||||
$.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection);
|
$.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection);
|
||||||
|
} else {
|
||||||
|
alert("This feature is not yet implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name !== "link" && name !== "reference-link" && name !== "image" && name !== "code-block" &&
|
if (!settings.toolbarNoFocus.includes(name)) {
|
||||||
name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "search" && name !== "fullscreen" && name !== "info")
|
|
||||||
{
|
|
||||||
cm.focus();
|
cm.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3901,8 +3956,8 @@
|
|||||||
|
|
||||||
if (typeof attrs !== "undefined")
|
if (typeof attrs !== "undefined")
|
||||||
{
|
{
|
||||||
// 将 html 标签的 attr value 中存在的 <> 进行转义
|
// 将 html 标签的 attr value 中可能存在的 <> 尖括号进行转义,避免后面的正则替换发生错误
|
||||||
// 示例 <a name="<p>code</p>"></a> 替换为 <a name="<p>code</p>"></a>
|
// 示例 <a name="<p>code</p>"></a> 转化为 <a name="<p>code</p>"></a>
|
||||||
html = html.replace(/(\w+)="([^"]*)"/g, (match, key, value) => {
|
html = html.replace(/(\w+)="([^"]*)"/g, (match, key, value) => {
|
||||||
const escapedValue = value.replace(/</g, '<').replace(/>/g, '>');
|
const escapedValue = value.replace(/</g, '<').replace(/>/g, '>');
|
||||||
return `${key}="${escapedValue}"`;
|
return `${key}="${escapedValue}"`;
|
||||||
|
|||||||
4
public/static/editor.md/editormd.amd.min.js
vendored
4
public/static/editor.md/editormd.amd.min.js
vendored
File diff suppressed because one or more lines are too long
@ -225,6 +225,18 @@
|
|||||||
info : "fa-info-circle"
|
info : "fa-info-circle"
|
||||||
},
|
},
|
||||||
toolbarIconTexts : {},
|
toolbarIconTexts : {},
|
||||||
|
toolbarNoFocus : [
|
||||||
|
"link",
|
||||||
|
"reference-link",
|
||||||
|
"image",
|
||||||
|
"code-block",
|
||||||
|
"preformatted-text",
|
||||||
|
"watch",
|
||||||
|
"preview",
|
||||||
|
"search",
|
||||||
|
"fullscreen",
|
||||||
|
"info",
|
||||||
|
],
|
||||||
|
|
||||||
lang : {
|
lang : {
|
||||||
name : "zh-cn",
|
name : "zh-cn",
|
||||||
@ -367,6 +379,49 @@
|
|||||||
var classPrefix = this.classPrefix = editormd.classPrefix;
|
var classPrefix = this.classPrefix = editormd.classPrefix;
|
||||||
var settings = this.settings = $.extend(true, {}, editormd.defaults, options);
|
var settings = this.settings = $.extend(true, {}, editormd.defaults, options);
|
||||||
|
|
||||||
|
// 支持新增或覆盖原有 toolbar(要求 settings.toolbarIcons 非自定义模式)
|
||||||
|
if (settings.appendToolbar && typeof settings.toolbarIcons === "string" && settings.toolbarIcons in editormd.toolbarModes) {
|
||||||
|
settings.appendToolbar.forEach(toolbar => {
|
||||||
|
// 如果没有 name 字段,则忽略该 toolbar
|
||||||
|
if (!('name' in toolbar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果是 | 分隔符,则仅用于占位分隔
|
||||||
|
if (toolbar.name === "|") {
|
||||||
|
editormd.toolbarModes[settings.toolbarIcons].push("|");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果未定义该 toolbar,则执行 append;否则覆盖原有 toolbar
|
||||||
|
if (!editormd.toolbarModes[settings.toolbarIcons].includes(toolbar.name)) {
|
||||||
|
editormd.toolbarModes[settings.toolbarIcons].push(toolbar.name);
|
||||||
|
}
|
||||||
|
if ('icon' in toolbar) {
|
||||||
|
settings.toolbarIconsClass[toolbar.name] = toolbar.icon;
|
||||||
|
}
|
||||||
|
if ('title' in toolbar) {
|
||||||
|
settings.lang.toolbar[toolbar.name] = toolbar.title;
|
||||||
|
}
|
||||||
|
if ('handler' in toolbar) {
|
||||||
|
editormd.toolbarHandlers[toolbar.name] = toolbar.handler;
|
||||||
|
if ('shortcut' in toolbar) {
|
||||||
|
// 给新增的工具栏图标绑定快捷键
|
||||||
|
toolbar.shortcut.forEach(key => editormd.keyMaps[key] = toolbar.handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ('nofocus' in toolbar && toolbar.nofocus === true) {
|
||||||
|
if (!settings.toolbarNoFocus.includes[toolbar.name]) {
|
||||||
|
settings.toolbarNoFocus.push(toolbar.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.shortcutFunction) {
|
||||||
|
for (const key in settings.shortcutFunction) {
|
||||||
|
editormd.keyMaps[key] = settings.shortcutFunction[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
id = (typeof id === "object") ? settings.id : id;
|
id = (typeof id === "object") ? settings.id : id;
|
||||||
|
|
||||||
var editor = this.editor = $("#" + id);
|
var editor = this.editor = $("#" + id);
|
||||||
@ -1269,12 +1324,12 @@
|
|||||||
if (typeof settings.toolbarHandlers[name] !== "undefined")
|
if (typeof settings.toolbarHandlers[name] !== "undefined")
|
||||||
{
|
{
|
||||||
$.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection);
|
$.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection);
|
||||||
|
} else {
|
||||||
|
alert("This feature is not yet implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name !== "link" && name !== "reference-link" && name !== "image" && name !== "code-block" &&
|
if (!settings.toolbarNoFocus.includes(name)) {
|
||||||
name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "search" && name !== "fullscreen" && name !== "info")
|
|
||||||
{
|
|
||||||
cm.focus();
|
cm.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3832,8 +3887,8 @@
|
|||||||
|
|
||||||
if (typeof attrs !== "undefined")
|
if (typeof attrs !== "undefined")
|
||||||
{
|
{
|
||||||
// 将 html 标签的 attr value 中存在的 <> 进行转义
|
// 将 html 标签的 attr value 中可能存在的 <> 尖括号进行转义,避免后面的正则替换发生错误
|
||||||
// 示例 <a name="<p>code</p>"></a> 替换为 <a name="<p>code</p>"></a>
|
// 示例 <a name="<p>code</p>"></a> 转化为 <a name="<p>code</p>"></a>
|
||||||
html = html.replace(/(\w+)="([^"]*)"/g, (match, key, value) => {
|
html = html.replace(/(\w+)="([^"]*)"/g, (match, key, value) => {
|
||||||
const escapedValue = value.replace(/</g, '<').replace(/>/g, '>');
|
const escapedValue = value.replace(/</g, '<').replace(/>/g, '>');
|
||||||
return `${key}="${escapedValue}"`;
|
return `${key}="${escapedValue}"`;
|
||||||
|
|||||||
3
public/static/editor.md/editormd.min.js
vendored
3
public/static/editor.md/editormd.min.js
vendored
File diff suppressed because one or more lines are too long
@ -46,7 +46,6 @@
|
|||||||
action += "&callback=" + settings.uploadCallbackURL + "&dialog_id=editormd-image-dialog-" + guid;
|
action += "&callback=" + settings.uploadCallbackURL + "&dialog_id=editormd-image-dialog-" + guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageFileName = classPrefix + "image-file";
|
|
||||||
// 将 action 置为 # 号。后面使用 ajax 重写图片上传请求
|
// 将 action 置为 # 号。后面使用 ajax 重写图片上传请求
|
||||||
var dialogContent = ( (settings.imageUpload) ? "<form action=\"#\" target=\"" + iframeName + "\" method=\"post\" enctype=\"multipart/form-data\" class=\"" + classPrefix + "form\">" : "<div class=\"" + classPrefix + "form\">" ) +
|
var dialogContent = ( (settings.imageUpload) ? "<form action=\"#\" target=\"" + iframeName + "\" method=\"post\" enctype=\"multipart/form-data\" class=\"" + classPrefix + "form\">" : "<div class=\"" + classPrefix + "form\">" ) +
|
||||||
( (settings.imageUpload) ? "<iframe name=\"" + iframeName + "\" id=\"" + iframeName + "\" guid=\"" + guid + "\"></iframe>" : "" ) +
|
( (settings.imageUpload) ? "<iframe name=\"" + iframeName + "\" id=\"" + iframeName + "\" guid=\"" + guid + "\"></iframe>" : "" ) +
|
||||||
@ -61,8 +60,8 @@
|
|||||||
"<label>" + imageLang.url + "</label>" +
|
"<label>" + imageLang.url + "</label>" +
|
||||||
"<input type=\"text\" data-url />" + (function(){
|
"<input type=\"text\" data-url />" + (function(){
|
||||||
return (settings.imageUpload) ? "<div class=\"" + classPrefix + "file-input\">" +
|
return (settings.imageUpload) ? "<div class=\"" + classPrefix + "file-input\">" +
|
||||||
// 这里增加 id = {imageFileName},方便后面拿到文件数据
|
// 这里增加 id 属性,方便后面拿到文件数据
|
||||||
"<input type=\"file\" name=\"" + imageFileName + "\" id=\"" + imageFileName + "\" accept=\"image/*\" />" +
|
"<input type=\"file\" id=\"" + classPrefix + "image-file\" name=\"" + classPrefix + "image-file\" accept=\"image/*\" />" +
|
||||||
"<input type=\"submit\" value=\"" + imageLang.uploadButton + "\" />" +
|
"<input type=\"submit\" value=\"" + imageLang.uploadButton + "\" />" +
|
||||||
"</div>" : "";
|
"</div>" : "";
|
||||||
})() +
|
})() +
|
||||||
@ -145,15 +144,17 @@
|
|||||||
// 给按钮绑定事件,支持手动更新 settings.imageUploadURL
|
// 给按钮绑定事件,支持手动更新 settings.imageUploadURL
|
||||||
$('#lock-or-unlock').on('click', function() {
|
$('#lock-or-unlock').on('click', function() {
|
||||||
let uploadURLInput = $('#upload-url-input')
|
let uploadURLInput = $('#upload-url-input')
|
||||||
if (uploadURLInput.attr('disabled') == undefined) {
|
if (uploadURLInput.attr('disabled') === undefined) {
|
||||||
// 如果输入框未被禁用,则禁用按钮
|
// 如果输入框未被禁用,则禁用按钮
|
||||||
$(this).text('Unlock');
|
$(this).text('Unlock');
|
||||||
uploadURLInput.attr('disabled', 'disabled');
|
uploadURLInput.attr('disabled', 'disabled');
|
||||||
// 用输入框内容更新 imageUploadURL
|
// 用输入框内容更新 imageUploadURL
|
||||||
if (uploadURLInput.val().trim().length > 0) {
|
if (uploadURLInput.val().trim().length > 0) {
|
||||||
settings.imageUploadURL = uploadURLInput.val().trim()
|
settings.imageUploadURL = uploadURLInput.val().trim()
|
||||||
// 触发回调事件,支持向上暴露
|
// 更新 imageUploadURL 触发回调事件
|
||||||
settings.imageUploadURLChange(settings.imageUploadURL)
|
if (typeof settings.imageUploadURLChange === 'function') {
|
||||||
|
settings.imageUploadURLChange(settings.imageUploadURL)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 如果输入框为禁用状态,则解锁输入框
|
// 如果输入框为禁用状态,则解锁输入框
|
||||||
@ -163,7 +164,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var fileInput = dialog.find("[name=\"" + imageFileName + "\"]");
|
var fileInput = dialog.find("[name=\"" + classPrefix + "image-file\"]");
|
||||||
|
|
||||||
fileInput.bind("change", function() {
|
fileInput.bind("change", function() {
|
||||||
var fileName = fileInput.val();
|
var fileName = fileInput.val();
|
||||||
@ -193,7 +194,7 @@
|
|||||||
|
|
||||||
loading(false);
|
loading(false);
|
||||||
|
|
||||||
// 注释掉官方写法,这里存在 iframe 跨域问题
|
// 注释掉原来的写法,这里存在 iframe 跨域问题
|
||||||
// var body = (uploadIframe.contentWindow ? uploadIframe.contentWindow : uploadIframe.contentDocument).document.body;
|
// var body = (uploadIframe.contentWindow ? uploadIframe.contentWindow : uploadIframe.contentDocument).document.body;
|
||||||
// var json = (body.innerText) ? body.innerText : ( (body.textContent) ? body.textContent : null);
|
// var json = (body.innerText) ? body.innerText : ( (body.textContent) ? body.textContent : null);
|
||||||
|
|
||||||
@ -211,10 +212,13 @@
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// 重写图片上传方法
|
// 重写图片上传方法,支持 token 鉴权
|
||||||
var formData = new FormData();
|
|
||||||
formData.append(imageFileName, $("#" + imageFileName)[0].files[0]);
|
|
||||||
var action = settings.imageUploadURL + (settings.imageUploadURL.indexOf("?") >= 0 ? "&" : "?") + "guid=" + guid;
|
var action = settings.imageUploadURL + (settings.imageUploadURL.indexOf("?") >= 0 ? "&" : "?") + "guid=" + guid;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append(classPrefix + "image-file", $("#" + classPrefix + "image-file")[0].files[0]);
|
||||||
|
if (settings.imageUploadToken !== undefined && settings.imageUploadToken.length > 0) {
|
||||||
|
formData.append("token", settings.imageUploadToken);
|
||||||
|
}
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: action,
|
url: action,
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|
|||||||
@ -213,6 +213,18 @@
|
|||||||
info : "fa-info-circle"
|
info : "fa-info-circle"
|
||||||
},
|
},
|
||||||
toolbarIconTexts : {},
|
toolbarIconTexts : {},
|
||||||
|
toolbarNoFocus : [
|
||||||
|
"link",
|
||||||
|
"reference-link",
|
||||||
|
"image",
|
||||||
|
"code-block",
|
||||||
|
"preformatted-text",
|
||||||
|
"watch",
|
||||||
|
"preview",
|
||||||
|
"search",
|
||||||
|
"fullscreen",
|
||||||
|
"info",
|
||||||
|
],
|
||||||
|
|
||||||
lang : {
|
lang : {
|
||||||
name : "zh-cn",
|
name : "zh-cn",
|
||||||
@ -355,6 +367,49 @@
|
|||||||
var classPrefix = this.classPrefix = editormd.classPrefix;
|
var classPrefix = this.classPrefix = editormd.classPrefix;
|
||||||
var settings = this.settings = $.extend(true, editormd.defaults, options);
|
var settings = this.settings = $.extend(true, editormd.defaults, options);
|
||||||
|
|
||||||
|
// 支持新增或覆盖原有 toolbar(要求 settings.toolbarIcons 非自定义模式)
|
||||||
|
if (settings.appendToolbar && typeof settings.toolbarIcons === "string" && settings.toolbarIcons in editormd.toolbarModes) {
|
||||||
|
settings.appendToolbar.forEach(toolbar => {
|
||||||
|
// 如果没有 name 字段,则忽略该 toolbar
|
||||||
|
if (!('name' in toolbar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果是 | 分隔符,则仅用于占位分隔
|
||||||
|
if (toolbar.name === "|") {
|
||||||
|
editormd.toolbarModes[settings.toolbarIcons].push("|");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果未定义该 toolbar,则执行 append;否则覆盖原有 toolbar
|
||||||
|
if (!editormd.toolbarModes[settings.toolbarIcons].includes(toolbar.name)) {
|
||||||
|
editormd.toolbarModes[settings.toolbarIcons].push(toolbar.name);
|
||||||
|
}
|
||||||
|
if ('icon' in toolbar) {
|
||||||
|
settings.toolbarIconsClass[toolbar.name] = toolbar.icon;
|
||||||
|
}
|
||||||
|
if ('title' in toolbar) {
|
||||||
|
settings.lang.toolbar[toolbar.name] = toolbar.title;
|
||||||
|
}
|
||||||
|
if ('handler' in toolbar) {
|
||||||
|
editormd.toolbarHandlers[toolbar.name] = toolbar.handler;
|
||||||
|
if ('shortcut' in toolbar) {
|
||||||
|
// 给新增的工具栏图标绑定快捷键
|
||||||
|
toolbar.shortcut.forEach(key => editormd.keyMaps[key] = toolbar.handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ('nofocus' in toolbar && toolbar.nofocus === true) {
|
||||||
|
if (!settings.toolbarNoFocus.includes[toolbar.name]) {
|
||||||
|
settings.toolbarNoFocus.push(toolbar.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.shortcutFunction) {
|
||||||
|
for (const key in settings.shortcutFunction) {
|
||||||
|
editormd.keyMaps[key] = settings.shortcutFunction[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
id = (typeof id === "object") ? settings.id : id;
|
id = (typeof id === "object") ? settings.id : id;
|
||||||
|
|
||||||
var editor = this.editor = $("#" + id);
|
var editor = this.editor = $("#" + id);
|
||||||
@ -1257,12 +1312,12 @@
|
|||||||
if (typeof settings.toolbarHandlers[name] !== "undefined")
|
if (typeof settings.toolbarHandlers[name] !== "undefined")
|
||||||
{
|
{
|
||||||
$.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection);
|
$.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection);
|
||||||
|
} else {
|
||||||
|
alert("This feature is not yet implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name !== "link" && name !== "reference-link" && name !== "image" && name !== "code-block" &&
|
if (!settings.toolbarNoFocus.includes(name)) {
|
||||||
name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "search" && name !== "fullscreen" && name !== "info")
|
|
||||||
{
|
|
||||||
cm.focus();
|
cm.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3822,8 +3877,8 @@
|
|||||||
|
|
||||||
if (typeof attrs !== "undefined")
|
if (typeof attrs !== "undefined")
|
||||||
{
|
{
|
||||||
// 将 html 标签的 attr value 中存在的 <> 进行转义
|
// 将 html 标签的 attr value 中可能存在的 <> 尖括号进行转义,避免后面的正则替换发生错误
|
||||||
// 示例 <a name="<p>code</p>"></a> 替换为 <a name="<p>code</p>"></a>
|
// 示例 <a name="<p>code</p>"></a> 转化为 <a name="<p>code</p>"></a>
|
||||||
html = html.replace(/(\w+)="([^"]*)"/g, (match, key, value) => {
|
html = html.replace(/(\w+)="([^"]*)"/g, (match, key, value) => {
|
||||||
const escapedValue = value.replace(/</g, '<').replace(/>/g, '>');
|
const escapedValue = value.replace(/</g, '<').replace(/>/g, '>');
|
||||||
return `${key}="${escapedValue}"`;
|
return `${key}="${escapedValue}"`;
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: '720px'
|
default: '720px'
|
||||||
},
|
},
|
||||||
// 默认不开启本地上传
|
// 是否支持图片本地上传
|
||||||
imageUpload: {
|
imageUpload: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@ -52,6 +52,12 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
// 图片上传时携带的 token
|
||||||
|
imageUploadToken: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
// 当 image-dialog 插件更新 imageUploadURL 时触发
|
// 当 image-dialog 插件更新 imageUploadURL 时触发
|
||||||
imageUploadURLChange: {
|
imageUploadURLChange: {
|
||||||
type: Function,
|
type: Function,
|
||||||
@ -60,6 +66,24 @@ export default {
|
|||||||
console.log("new imageUploadURL: " + newURL)
|
console.log("new imageUploadURL: " + newURL)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 新增或覆盖原有工具栏。相关属性如下:
|
||||||
|
// - name: 必须定义. 如果是 | 则仅做分隔符;如果和原有 toolbar name 冲突则覆盖原有 toolbar
|
||||||
|
// - icon: font-awesome icon. 需确保在 editormd.css 中已定义
|
||||||
|
// - title: 定义悬停该 toolbar 时浮现的文本
|
||||||
|
// - handler: 定义点击该 toolbar 后触发的操作
|
||||||
|
// - shortcut: 定义该 toolbar 绑定的快捷键
|
||||||
|
// - nofoucs: 默认为 false;如果为 true 则点击该 toolbar 后不会触发 cm.focus() 事件
|
||||||
|
appendToolbar: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
// 编辑器内绑定快捷键事件,会覆盖原有快捷键事件
|
||||||
|
shortcutFunction: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: {},
|
||||||
|
},
|
||||||
// 编辑器加载完成后,执行该函数
|
// 编辑器加载完成后,执行该函数
|
||||||
onload: {
|
onload: {
|
||||||
type: Function,
|
type: Function,
|
||||||
@ -67,13 +91,13 @@ export default {
|
|||||||
default: () => { }
|
default: () => { }
|
||||||
},
|
},
|
||||||
// 全屏编辑器时,执行该函数
|
// 全屏编辑器时,执行该函数
|
||||||
onfullscreen: {
|
onFullScreen: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: false,
|
required: false,
|
||||||
default: () => { }
|
default: () => { }
|
||||||
},
|
},
|
||||||
// 退出全屏时,执行该函数
|
// 退出全屏时,执行该函数
|
||||||
onfullscreenExit: {
|
onFullScreenExit: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: false,
|
required: false,
|
||||||
default: () => { }
|
default: () => { }
|
||||||
@ -87,16 +111,13 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
if (this.autoInit) {
|
if (this.autoInit) {
|
||||||
this.initEditor()
|
this.initEditor()
|
||||||
|
// 设置延迟初始化 markdown 编辑器。因为只会初始化一次,需要等待数据加载完成之后再初始化
|
||||||
|
// setTimeout(() => {
|
||||||
|
// this.initEditor()
|
||||||
|
// }, 300)
|
||||||
}
|
}
|
||||||
// 设置延迟初始化markdown编辑器,因为只会初始化一次,需要等待数据加载完成之后再初始化
|
|
||||||
// setTimeout(() => {
|
|
||||||
// this.initEditor()
|
|
||||||
// }, 300)
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isEditorLoadingCompleted() {
|
|
||||||
return editorClient != defaultEditorValue && this.loadingCompleted
|
|
||||||
},
|
|
||||||
fetchScript(url) {
|
fetchScript(url) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
scriptjs(url, () => {
|
scriptjs(url, () => {
|
||||||
@ -106,7 +127,7 @@ export default {
|
|||||||
},
|
},
|
||||||
initEditor() {
|
initEditor() {
|
||||||
(async () => {
|
(async () => {
|
||||||
await this.fetchScript('/static/jQuery/jquery.min.js')
|
await this.fetchScript('/static/jquery/jquery.min.js')
|
||||||
await this.fetchScript('/static/editor.md/editormd.js')
|
await this.fetchScript('/static/editor.md/editormd.js')
|
||||||
// await this.fetchScript('/static/editor.md/editorrmd.amd.js')
|
// await this.fetchScript('/static/editor.md/editorrmd.amd.js')
|
||||||
// 加载完成以上 JS 资源之后,再加载编辑器
|
// 加载完成以上 JS 资源之后,再加载编辑器
|
||||||
@ -132,27 +153,31 @@ export default {
|
|||||||
taskList: true,
|
taskList: true,
|
||||||
|
|
||||||
// 定义图片本地上传的功能
|
// 定义图片本地上传的功能
|
||||||
imageUpload: vm.imageUpload, // 支持图片本地上传。若不提供 imageUploadURL 则需要用户自行设定
|
imageUpload: vm.imageUpload, // 是否支持图片本地上传。若不提供 imageUploadURL 则需要用户自行设定
|
||||||
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "ico"],
|
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "ico"],
|
||||||
imageUploadURL: vm.imageUploadURL, // 可用于上传图片的服务端接口
|
imageUploadURL: vm.imageUploadURL, // 可用于上传图片的服务端接口
|
||||||
imageUploadURLChange: function (newURL) {
|
imageUploadToken: vm.imageUploadToken,
|
||||||
// 当 image-dialog 插件更新 imageUploadURL 时触发
|
imageUploadURLChange: vm.imageUploadURLChange,
|
||||||
vm.imageUploadURLChange(newURL)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 可分区域定制样式主题
|
// 可分区域定制样式主题
|
||||||
// theme: (localStorage.theme) ? localStorage.theme : "dark",
|
// theme: (localStorage.theme) ? localStorage.theme : "dark",
|
||||||
// editorTheme: (localStorage.editorTheme) ? localStorage.editorThheme : "3024-night",
|
// editorTheme: (localStorage.editorTheme) ? localStorage.editorThheme : "3024-night",
|
||||||
// previewTheme: (localStorage.previewTheme) ? localStorage.previewTheme : "default",
|
// previewTheme: (localStorage.previewTheme) ? localStorage.previewTheme : "default",
|
||||||
|
|
||||||
|
// 给工具栏补充工具事件
|
||||||
|
appendToolbar: vm.appendToolbar,
|
||||||
|
|
||||||
|
// 绑定快捷键。如果冲突,会覆盖其他相同快捷键事件
|
||||||
|
shortcutFunction: vm.shortcutFunction,
|
||||||
|
|
||||||
// 全屏
|
// 全屏
|
||||||
onfullscreen: function () {
|
onfullscreen: function () {
|
||||||
vm.onfullscreen()
|
vm.onFullScreen()
|
||||||
},
|
},
|
||||||
|
|
||||||
// 退出全屏
|
// 退出全屏
|
||||||
onfullscreenExit: function () {
|
onfullscreenExit: function () {
|
||||||
vm.onfullscreenExit()
|
vm.onFullScreenExit()
|
||||||
},
|
},
|
||||||
|
|
||||||
// 监听更新,更新父组件值
|
// 监听更新,更新父组件值
|
||||||
@ -181,6 +206,9 @@ export default {
|
|||||||
})
|
})
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
|
isEditorLoadingCompleted() {
|
||||||
|
return editorClient != defaultEditorValue && this.loadingCompleted
|
||||||
|
},
|
||||||
|
|
||||||
// 以下是 editor.md 对外暴露的 API
|
// 以下是 editor.md 对外暴露的 API
|
||||||
resetHeight(height) {
|
resetHeight(height) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user