faim
Version:
Element Plus & Element UI isomorphic UI component library, more than Element.
215 lines (213 loc) • 8.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodashEs = require("lodash-es");
var _tinymce = _interopRequireDefault(require("tinymce/tinymce"));
var _uuid = require("uuid");
var _vueDemi = require("vue-demi");
var _vueGlobalConfig = require("vue-global-config");
require("tinymce/models/dom");
require("tinymce/plugins/accordion");
require("tinymce/plugins/advlist");
require("tinymce/plugins/anchor");
require("tinymce/plugins/autolink");
require("tinymce/plugins/autosave");
require("tinymce/plugins/charmap");
require("tinymce/plugins/directionality");
require("tinymce/plugins/emoticons");
require("tinymce/plugins/emoticons/js/emojis.min");
require("tinymce/plugins/fullscreen");
require("tinymce/plugins/help");
require("tinymce/plugins/image");
require("tinymce/plugins/importcss");
require("tinymce/plugins/insertdatetime");
require("tinymce/plugins/link");
require("tinymce/plugins/lists");
require("tinymce/plugins/media");
require("tinymce/plugins/nonbreaking");
require("tinymce/plugins/pagebreak");
require("tinymce/plugins/preview");
require("tinymce/plugins/quickbars");
require("tinymce/plugins/save");
require("tinymce/plugins/searchreplace");
require("tinymce/plugins/table");
require("tinymce/plugins/visualblocks");
require("tinymce/plugins/visualchars");
require("tinymce/plugins/wordcount");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const model = {
prop: _vueDemi.isVue3 ? "modelValue" : "value",
event: _vueDemi.isVue3 ? "update:modelValue" : "input"
};
const globalProps = {};
const globalAttrs = {};
const globalListeners = {};
const globalSlots = {};
module.exports = (0, _vueDemi.defineComponent)({
name: "FaRichText",
install(app, options = {}) {
const {
props,
attrs,
listeners,
slots
} = (0, _vueGlobalConfig.resolveConfig)(options, {
props: this.props,
camelizePropNames: true
});
Object.assign(globalProps, props);
Object.assign(globalAttrs, attrs);
Object.assign(globalListeners, listeners);
Object.assign(globalSlots, slots);
app.component(this.name, this);
},
props: {
[model.prop]: String,
disabled: {
type: Boolean,
default: void 0
},
outputFormat: {}
},
emits: [model.event, "init"],
setup(props, {
emit,
expose,
attrs
}) {
const id = (0, _vueDemi.ref)(`minimce-${(0, _uuid.v4)()}`);
const preventSettingContent = (0, _vueDemi.ref)(false);
const preventUpdatingModelValue = (0, _vueDemi.ref)(false);
const Disabled = (0, _vueDemi.computed)(() => (0, _vueGlobalConfig.conclude)([props.disabled, globalProps.disabled], {
type: Boolean
}));
const OutputFormat = (0, _vueDemi.computed)(() => (0, _vueGlobalConfig.conclude)([props.outputFormat, globalProps.outputFormat], {
type: String
}));
const Options = (0, _vueDemi.computed)(() => (0, _vueGlobalConfig.conclude)([attrs, globalAttrs, {
selector: `#${id.value}`,
/**
* 默认开启所有免费插件
* https://www.tiny.cloud/docs/tinymce/6/full-featured-open-source-demo/
*/
plugins: "preview importcss searchreplace autolink autosave save directionality visualblocks visualchars fullscreen image link media table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons accordion",
menubar: "file edit view insert format tools table help",
toolbar: "undo redo | accordion accordionremove | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor removeformat | pagebreak | charmap emoticons | fullscreen preview save print | insertfile image media template link anchor codesample | ltr rtl",
quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
contextmenu: "link image table",
branding: false,
promotion: false,
quickbars_insert_toolbar: false,
// 默认屏蔽 iframe 原因:
// - 允许用户引入未知的 iframe 存在执行未知脚本等安全隐患
// - 小程序侧不支持 iframe
// - 小程序侧 web-view 中使用 iframe 需要配置业务域名
// - 给微信公众号 H5 侧带来授权问题
invalid_elements: "iframe,frame",
// note that skin and content_css is disabled to avoid the normal
// loading process and is instead loaded as a string via content_style
skin: false,
content_css: false,
// skin: useDarkMode ? 'oxide-dark' : 'oxide',
// content_css: useDarkMode ? 'dark' : 'default',
autosave_ask_before_unload: false,
// 改动后刷新,不再弹 alert
autosave_interval: "30s",
autosave_prefix: "{path}{query}-{id}-",
autosave_restore_when_empty: false,
autosave_retention: "2m",
// importcss_append: true,
// height: 500,
relative_urls: false,
convert_urls: false,
image_advtab: true,
image_caption: true,
// 开启时,出现两个 bug:1. 部分菜单项失效;2. 拖拉拽调整视频大小会错位(该问题在 v6.0 仍在存在)
media_live_embeds: false,
toolbar_mode: "sliding",
// toolbar_sticky: true,
// toolbar_sticky_offset: isSmallScreen ? 102 : 108,
// extended_valid_elements: 'img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name|referrerpolicy=no-referrer]',
init_instance_callback: editor => {
(0, _vueDemi.watch)(Disabled, n => {
editor.mode.set(n ? "readonly" : "design");
}, {
immediate: true
});
const onContentChange = (0, _lodashEs.debounce)(() => {
if (preventUpdatingModelValue.value) {
preventUpdatingModelValue.value = false;
return;
}
const newContent = editor.getContent({
format: OutputFormat.value
});
if (newContent !== props[model.prop]) {
preventSettingContent.value = true;
emit(model.event, newContent);
}
}, 100);
editor.on("Change input Redo Undo SetContent", onContentChange);
(0, _vueDemi.watch)(() => props[model.prop], newModelValue => {
if (preventSettingContent.value) {
preventSettingContent.value = false;
return;
}
preventUpdatingModelValue.value = true;
editor.setContent(newModelValue || "");
});
setTimeout(() => {
editor.setContent(props[model.prop] || "");
});
const wordcountButton = editor.getContainer().querySelector("button.tox-statusbar__wordcount");
wordcountButton?.click();
}
}], {
mergeFunction: (previousValue, currentValue) => (...args) => {
previousValue(...args);
currentValue(...args);
},
type: Object
}));
(0, _vueDemi.onUnmounted)(() => {
_tinymce.default.get(id.value)?.destroy();
});
(0, _vueDemi.onMounted)(() => {
const el = document.querySelector(`#${id.value}`);
const intersectionObserver = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
intersectionObserver.unobserve(el);
_tinymce.default.init(Options.value);
} else {}
});
if (el) {
intersectionObserver.observe(el);
}
});
expose?.({
id
});
return {
id
// loading,
// height: (Options.value.height ?? '400') + 'px',
};
},
render() {
return _vueDemi.isVue3 ? (0, _vueDemi.h)("textarea", {
id: this.id,
class: "fa-rich-text"
}) : (0, _vueDemi.h)("textarea", {
attrs: {
id: (0, _vueDemi.unref)(this.id),
class: "fa-rich-text"
},
on: {
input: value => {
this.$emit(model.event, value);
}
}
});
}
});