|
@@ -91,7 +91,7 @@ export default {
|
|
|
type: [String, Boolean],
|
|
type: [String, Boolean],
|
|
|
/* eslint-disable max-len */
|
|
/* eslint-disable max-len */
|
|
|
default:
|
|
default:
|
|
|
- 'fontselect fontsizeselect forecolor backcolor | lineheight underline | bold italic strikethrough alignleft aligncenter alignright | bullist numlist | image media | link blockquote hr mathjax',
|
|
|
|
|
|
|
+ 'fontselect fontsizeselect forecolor backcolor lineheight paragraphSpacing indent outdent underline bold italic strikethrough alignleft aligncenter alignright bullist numlist dotEmphasis image media link blockquote hr mathjax',
|
|
|
},
|
|
},
|
|
|
wordlimitNum: {
|
|
wordlimitNum: {
|
|
|
type: [Number, Boolean],
|
|
type: [Number, Boolean],
|
|
@@ -146,7 +146,26 @@ export default {
|
|
|
mjx-container, mjx-container * {
|
|
mjx-container, mjx-container * {
|
|
|
font-size: 16px !important; /* 强制固定字体 */
|
|
font-size: 16px !important; /* 强制固定字体 */
|
|
|
line-height: 1.2 !important; /* 避免行高影响 */
|
|
line-height: 1.2 !important; /* 避免行高影响 */
|
|
|
- }`, // 解决公式每点击一次字体就变大
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ .emphasis-dot {
|
|
|
|
|
+ border-bottom: none;
|
|
|
|
|
+ background-image: radial-gradient(
|
|
|
|
|
+ circle at center,
|
|
|
|
|
+ currentColor 0.15em, /* 圆点大小相对于字体 */
|
|
|
|
|
+ transparent 0.16em
|
|
|
|
|
+ );
|
|
|
|
|
+ background-size: 1em 0.3em; /* 间距相对于字体大小,高度相对字体 */
|
|
|
|
|
+ background-repeat: repeat-x;
|
|
|
|
|
+ background-position: 0 100%;
|
|
|
|
|
+ padding-bottom: 0.3em; /* 间距也相对于字体 */
|
|
|
|
|
+ display: inline;
|
|
|
|
|
+ }
|
|
|
|
|
+ p { margin: 0 0 1em 0; }
|
|
|
|
|
+ .paragraph-spacing-small { margin-bottom: 0.5em; }
|
|
|
|
|
+ .paragraph-spacing-medium { margin-bottom: 1em; }
|
|
|
|
|
+ .paragraph-spacing-large { margin-bottom: 2em; }
|
|
|
|
|
+ .paragraph-spacing-custom { margin-bottom: var(--custom-spacing); }
|
|
|
|
|
+ `, // 解决公式每点击一次字体就变大
|
|
|
valid_elements: '*[*]', // 允许所有标签和属性
|
|
valid_elements: '*[*]', // 允许所有标签和属性
|
|
|
valid_children: '+body[style]', // 允许 MathJax 的样式
|
|
valid_children: '+body[style]', // 允许 MathJax 的样式
|
|
|
extended_valid_elements: 'span[*],mjx-container[*],svg[*],path[*]', // 明确允许 MathJax 标签
|
|
extended_valid_elements: 'span[*],mjx-container[*],svg[*],path[*]', // 明确允许 MathJax 标签
|
|
@@ -164,6 +183,7 @@ export default {
|
|
|
plugins: 'link lists image hr media autoresize ax_wordlimit paste', // 移除 lineheight
|
|
plugins: 'link lists image hr media autoresize ax_wordlimit paste', // 移除 lineheight
|
|
|
toolbar: this.toolbar, // 工具栏
|
|
toolbar: this.toolbar, // 工具栏
|
|
|
lineheight_formats: '0.5 1.0 1.2 1.5 2.0 2.5 3.0', // 行高选项(倍数)
|
|
lineheight_formats: '0.5 1.0 1.2 1.5 2.0 2.5 3.0', // 行高选项(倍数)
|
|
|
|
|
+ paragraphheight_formats: [0.5, 1.0, 1.2, 1.5, 2.0, 2.5, 3.0], // 段落间距
|
|
|
contextmenu: false, // 右键菜单
|
|
contextmenu: false, // 右键菜单
|
|
|
menubar: false, // 菜单栏
|
|
menubar: false, // 菜单栏
|
|
|
branding: false, // 品牌
|
|
branding: false, // 品牌
|
|
@@ -180,6 +200,33 @@ export default {
|
|
|
editor.on('init', () => {
|
|
editor.on('init', () => {
|
|
|
editor.getBody().style.fontSize = this.init.font_size; // 设置默认字体大小
|
|
editor.getBody().style.fontSize = this.init.font_size; // 设置默认字体大小
|
|
|
editor.getBody().style.fontFamily = this.init.font_family; // 设置默认字体
|
|
editor.getBody().style.fontFamily = this.init.font_family; // 设置默认字体
|
|
|
|
|
+
|
|
|
|
|
+ this.init.paragraphheight_formats.forEach((config) => {
|
|
|
|
|
+ const formatName = `paragraphSpacing${config}_em`;
|
|
|
|
|
+ editor.formatter.register(formatName, {
|
|
|
|
|
+ selector: 'p',
|
|
|
|
|
+ styles: { 'margin-bottom': config + 'em' },
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (!editor.formatter.has('emphasisDot')) {
|
|
|
|
|
+ editor.formatter.register('emphasisDot', {
|
|
|
|
|
+ inline: 'span',
|
|
|
|
|
+ // classes: 'emphasis-dot',
|
|
|
|
|
+ styles: {
|
|
|
|
|
+ 'border-bottom': 'none',
|
|
|
|
|
+ 'background-image':
|
|
|
|
|
+ 'radial-gradient(circle at center, currentColor 0.15em, transparent 0.16em)' /* 圆点大小相对于字体 */,
|
|
|
|
|
+ 'background-size': '1em 0.3em' /* 间距相对于字体大小,高度相对字体 */,
|
|
|
|
|
+ 'background-repeat': 'repeat-x',
|
|
|
|
|
+ 'background-position': '0 100%',
|
|
|
|
|
+ 'padding-bottom': '0.3em' /* 间距也相对于字体 */,
|
|
|
|
|
+ display: 'inline',
|
|
|
|
|
+ },
|
|
|
|
|
+ wrapper: true,
|
|
|
|
|
+ remove_similar: true,
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 自定义行高下拉(因为没有内置 lineheight 插件)
|
|
// 自定义行高下拉(因为没有内置 lineheight 插件)
|
|
@@ -211,14 +258,65 @@ export default {
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- editor.on('click', () => {
|
|
|
|
|
- if (editor?.queryCommandState('ToggleToolbarDrawer')) {
|
|
|
|
|
- editor.execCommand('ToggleToolbarDrawer');
|
|
|
|
|
- }
|
|
|
|
|
- if (!isRendered && window.MathJax) {
|
|
|
|
|
- isRendered = true;
|
|
|
|
|
- window.MathJax.typesetPromise([editor.getBody()]);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 添加段落间距下拉菜单
|
|
|
|
|
+ editor.ui.registry.addMenuButton('paragraphSpacing', {
|
|
|
|
|
+ icon: 'paragraph',
|
|
|
|
|
+ //text: '段落间距',
|
|
|
|
|
+ tooltip: '段落间距',
|
|
|
|
|
+ fetch: (callback) => {
|
|
|
|
|
+ const items = [];
|
|
|
|
|
+
|
|
|
|
|
+ // 动态生成菜单项
|
|
|
|
|
+ this.init.paragraphheight_formats.forEach((config) => {
|
|
|
|
|
+ const formatName = `paragraphSpacing${config}_em`;
|
|
|
|
|
+ items.push({
|
|
|
|
|
+ type: 'menuitem',
|
|
|
|
|
+ text: `${config}`,
|
|
|
|
|
+ onAction: () => {
|
|
|
|
|
+ // 先清除其他间距格式
|
|
|
|
|
+ this.init.paragraphheight_formats.forEach((cfg) => {
|
|
|
|
|
+ const fmtName = `paragraphSpacing${cfg}_em`;
|
|
|
|
|
+ editor.formatter.remove(fmtName);
|
|
|
|
|
+ });
|
|
|
|
|
+ // 应用当前选择的间距
|
|
|
|
|
+ editor.formatter.apply(formatName);
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 添加清除间距选项
|
|
|
|
|
+ items.push({
|
|
|
|
|
+ type: 'separator', // 分隔线
|
|
|
|
|
+ });
|
|
|
|
|
+ items.push({
|
|
|
|
|
+ type: 'menuitem',
|
|
|
|
|
+ text: '清除间距',
|
|
|
|
|
+ onAction: () => {
|
|
|
|
|
+ // 清除所有间距格式
|
|
|
|
|
+ this.init.paragraphheight_formats.forEach((config) => {
|
|
|
|
|
+ const formatName = `paragraphSpacing${config}_em`;
|
|
|
|
|
+ editor.formatter.remove(formatName);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ callback(items);
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 添加 添加着重点 按钮
|
|
|
|
|
+ editor.ui.registry.addButton('dotEmphasis', {
|
|
|
|
|
+ text: '●',
|
|
|
|
|
+ tooltip: '着重点',
|
|
|
|
|
+ onAction: () => {
|
|
|
|
|
+ const editor = tinymce.activeEditor;
|
|
|
|
|
+
|
|
|
|
|
+ if (editor.formatter.match('emphasisDot')) {
|
|
|
|
|
+ editor.formatter.remove('emphasisDot');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ editor.formatter.apply('emphasisDot');
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 添加 MathJax 按钮
|
|
// 添加 MathJax 按钮
|
|
@@ -230,6 +328,16 @@ export default {
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ editor.on('click', () => {
|
|
|
|
|
+ if (editor?.queryCommandState('ToggleToolbarDrawer')) {
|
|
|
|
|
+ editor.execCommand('ToggleToolbarDrawer');
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!isRendered && window.MathJax) {
|
|
|
|
|
+ isRendered = true;
|
|
|
|
|
+ window.MathJax.typesetPromise([editor.getBody()]);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
// 内容变化时重新渲染公式
|
|
// 内容变化时重新渲染公式
|
|
|
editor.on('change', () => this.renderMath());
|
|
editor.on('change', () => this.renderMath());
|
|
|
|
|
|
|
@@ -817,7 +925,7 @@ export default {
|
|
|
if (eleMathArs.length === 0) return;
|
|
if (eleMathArs.length === 0) return;
|
|
|
await this.$nextTick();
|
|
await this.$nextTick();
|
|
|
window.MathJax.typesetPromise(eleMathArs).catch((err) =>
|
|
window.MathJax.typesetPromise(eleMathArs).catch((err) =>
|
|
|
- /* eslint-disable */ console.error(...oo_tx(`483836707_818_65_818_101_11`, 'MathJax error:', err)),
|
|
|
|
|
|
|
+ /* eslint-disable */ console.error(...oo_tx(`483836707_818_65_818_101_11`, 'MathJax error:', err))
|
|
|
);
|
|
);
|
|
|
this.mathEleIsInit = true;
|
|
this.mathEleIsInit = true;
|
|
|
}
|
|
}
|
|
@@ -968,7 +1076,7 @@ export default {
|
|
|
{
|
|
{
|
|
|
acceptNode: (node) => (node.textContent.trim() ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT),
|
|
acceptNode: (node) => (node.textContent.trim() ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT),
|
|
|
},
|
|
},
|
|
|
- false,
|
|
|
|
|
|
|
+ false
|
|
|
);
|
|
);
|
|
|
return walker.nextNode();
|
|
return walker.nextNode();
|
|
|
},
|
|
},
|