UNPKG

@ckeditor/ckeditor5-vue

Version:

Official Vue.js 3+ component for CKEditor 5 – the best browser-based rich text editor.

214 lines (213 loc) 7.13 kB
import * as Vue from "vue"; import { version, defineComponent, mergeModels, useModel, ref, watch, onMounted, markRaw, onBeforeUnmount, openBlock, createBlock, resolveDynamicComponent, computed, watchEffect, shallowReadonly, toValue } from "vue"; import { debounce } from "lodash-es"; import { createIntegrationUsageDataPlugin, isCKEditorFreeLicense, appendExtraPluginsToEditorConfig, uid, loadCKEditorCloud } from "@ckeditor/ckeditor5-integrations-common"; import { loadCKEditorCloud as loadCKEditorCloud2 } from "@ckeditor/ckeditor5-integrations-common"; /** * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md. */ const VueIntegrationUsageDataPlugin = createIntegrationUsageDataPlugin( "vue", { version: "7.3.0", frameworkVersion: version } ); /** * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md. */ function appendAllIntegrationPluginsToConfig(editorConfig) { if (isCKEditorFreeLicense(editorConfig.licenseKey)) { return editorConfig; } return appendExtraPluginsToEditorConfig(editorConfig, [ /** * This part of the code is not executed in open-source implementations using a GPL key. * It only runs when a specific license key is provided. If you are uncertain whether * this applies to your installation, please contact our support team. */ VueIntegrationUsageDataPlugin ]); } const VUE_INTEGRATION_READ_ONLY_LOCK_ID = "Lock from Vue integration (@ckeditor/ckeditor5-vue)"; const INPUT_EVENT_DEBOUNCE_WAIT = 300; const _sfc_main = /* @__PURE__ */ defineComponent({ ...{ name: "CKEditor" }, __name: "ckeditor", props: /* @__PURE__ */ mergeModels({ editor: {}, config: { default: () => ({}) }, tagName: { default: "div" }, disabled: { type: Boolean, default: false }, disableTwoWayDataBinding: { type: Boolean, default: false } }, { "modelValue": { type: String, default: "" }, "modelModifiers": {} }), emits: /* @__PURE__ */ mergeModels(["ready", "destroy", "blur", "focus", "input", "update:modelValue"], ["update:modelValue"]), setup(__props, { expose: __expose, emit: __emit }) { const model = useModel(__props, "modelValue"); const props = __props; const emit = __emit; const element = ref(); const instance = ref(); const lastEditorData = ref(); __expose({ instance, lastEditorData }); watch(model, (newModel) => { if (instance.value && newModel !== lastEditorData.value) { instance.value.data.set(newModel); } }); watch(() => props.disabled, (readOnlyMode) => { if (readOnlyMode) { instance.value.enableReadOnlyMode(VUE_INTEGRATION_READ_ONLY_LOCK_ID); } else { instance.value.disableReadOnlyMode(VUE_INTEGRATION_READ_ONLY_LOCK_ID); } }); function checkVersion() { const version2 = window.CKEDITOR_VERSION; if (!version2) { return console.warn('Cannot find the "CKEDITOR_VERSION" in the "window" scope.'); } const [major] = version2.split(".").map(Number); if (major >= 42 || version2.startsWith("0.0.0")) { return; } console.warn("The <CKEditor> component requires using CKEditor 5 in version 42+ or nightly build."); } function setUpEditorEvents(editor) { const emitDebouncedInputEvent = debounce((evt) => { if (props.disableTwoWayDataBinding) { return; } const data = lastEditorData.value = editor.data.get(); emit("update:modelValue", data, evt, editor); emit("input", data, evt, editor); }, INPUT_EVENT_DEBOUNCE_WAIT, { leading: true }); editor.model.document.on("change:data", emitDebouncedInputEvent); editor.editing.view.document.on("focus", (evt) => { emit("focus", evt, editor); }); editor.editing.view.document.on("blur", (evt) => { emit("blur", evt, editor); }); } checkVersion(); onMounted(() => { const editorConfig = appendAllIntegrationPluginsToConfig( Object.assign({}, props.config) ); if (model.value) { editorConfig.initialData = model.value; } props.editor.create(element.value, editorConfig).then((editor) => { instance.value = markRaw(editor); setUpEditorEvents(editor); if (model.value !== editorConfig.initialData) { editor.data.set(model.value); } if (props.disabled) { editor.enableReadOnlyMode(VUE_INTEGRATION_READ_ONLY_LOCK_ID); } emit("ready", editor); }).catch((error) => { console.error(error); }); }); onBeforeUnmount(() => { if (instance.value) { instance.value.destroy(); instance.value = void 0; } emit("destroy"); }); return (_ctx, _cache) => { return openBlock(), createBlock(resolveDynamicComponent(_ctx.tagName), { ref_key: "element", ref: element }, null, 512); }; } }); /** * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md. */ const useAsync = (asyncFunc) => { const lastQueryUUID = ref(null); const error = ref(null); const data = ref(null); const loading = computed(() => lastQueryUUID.value !== null); watchEffect(async () => { const currentQueryUID = uid(); lastQueryUUID.value = currentQueryUID; data.value = null; error.value = null; const shouldDiscardQuery = () => lastQueryUUID.value !== currentQueryUID; try { const result = await asyncFunc(); if (!shouldDiscardQuery()) { data.value = result; } } catch (err) { if (!shouldDiscardQuery()) { error.value = err; } } finally { if (!shouldDiscardQuery()) { lastQueryUUID.value = null; } } }); return { loading: shallowReadonly(loading), data: shallowReadonly(data), error: shallowReadonly(error) }; }; /** * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md. */ function useCKEditorCloud(config) { return useAsync( () => loadCKEditorCloud( toValue(config) ) ); } /** * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md. */ /* istanbul ignore if -- @preserve */ if (!Vue.version || !Vue.version.startsWith("3.")) { throw new Error( "The CKEditor plugin works only with Vue 3+. For more information, please refer to https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/vuejs-v3.html" ); } const CkeditorPlugin = { /** * Installs the plugin, registering the `<ckeditor>` component. * * @param app The application instance. */ install(app) { app.component("Ckeditor", _sfc_main); } }; export { _sfc_main as Ckeditor, CkeditorPlugin, loadCKEditorCloud2 as loadCKEditorCloud, useCKEditorCloud }; //# sourceMappingURL=ckeditor.js.map