| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 | <template lang='pug'>  .editor-ckeditor    div(ref='toolbarContainer')    div.contents(ref='editor')    v-system-bar.editor-ckeditor-sysbar(dark, status, color='grey darken-3')      .caption.editor-ckeditor-sysbar-locale {{locale.toUpperCase()}}      .caption.px-3 /{{path}}      template(v-if='$vuetify.breakpoint.mdAndUp')        v-spacer        .caption Visual Editor        v-spacer        .caption {{$t('editor:ckeditor.stats', { chars: stats.characters, words: stats.words })}}    editor-conflict(v-model='isConflict', v-if='isConflict')    page-selector(mode='select', v-model='insertLinkDialog', :open-handler='insertLinkHandler', :path='path', :locale='locale')</template><script>import _ from 'lodash'import { get, sync } from 'vuex-pathify'import DecoupledEditor from '@requarks/ckeditor5'import EditorConflict from './ckeditor/conflict.vue'/* global siteLangs */export default {  components: {    EditorConflict  },  props: {    save: {      type: Function,      default: () => {}    }  },  data() {    return {      editor: null,      stats: {        characters: 0,        words: 0      },      content: '',      isConflict: false,      insertLinkDialog: false    }  },  computed: {    isMobile() {      return this.$vuetify.breakpoint.smAndDown    },    locale: get('page/locale'),    path: get('page/path'),    activeModal: sync('editor/activeModal')  },  methods: {    insertLink () {      this.insertLinkDialog = true    },    insertLinkHandler ({ locale, path }) {      this.editor.execute('link', siteLangs.length > 0 ? `/${locale}/${path})` : `/${path}`)    }  },  async mounted () {    this.$store.set('editor/editorKey', 'ckeditor')    this.editor = await DecoupledEditor.create(this.$refs.editor, {      placeholder: 'Type the page content here',      wordCount: {        onUpdate: stats => {          this.stats = {            characters: stats.characters,            words: stats.words          }        }      }    })    this.$refs.toolbarContainer.appendChild(this.editor.ui.view.toolbar.element)    if (this.mode !== 'create') {      this.editor.setData(this.$store.get('editor/content'))    }    this.editor.model.document.on('change:data', _.debounce(evt => {      this.$store.set('editor/content', this.editor.getData())    }, 300))    this.$root.$on('editorInsert', opts => {      switch (opts.kind) {        case 'IMAGE':          this.editor.execute('imageInsert', {            source: opts.path          })          break        case 'BINARY':          this.editor.execute('link', opts.path, {            linkIsDownloadable: true          })          break      }    })    this.$root.$on('editorLinkToPage', opts => {      this.insertLink()    })    // Handle save conflict    this.$root.$on('saveConflict', () => {      this.isConflict = true    })    this.$root.$on('overwriteEditorContent', () => {      this.editor.setData(this.$store.get('editor/content'))    })  },  beforeDestroy () {    if (this.editor) {      this.editor.destroy()      this.editor = null    }  }}</script><style lang="scss">$editor-height: calc(100vh - 64px - 24px);$editor-height-mobile: calc(100vh - 56px - 16px);.editor-ckeditor {  background-color: mc('grey', '200');  flex: 1 1 50%;  display: flex;  flex-flow: column nowrap;  height: $editor-height;  max-height: $editor-height;  position: relative;  @at-root .theme--dark & {    background-color: mc('grey', '900');  }  @include until($tablet) {    height: $editor-height-mobile;    max-height: $editor-height-mobile;  }  &-sysbar {    padding-left: 0;    &-locale {      background-color: rgba(255,255,255,.25);      display:inline-flex;      padding: 0 12px;      height: 24px;      width: 63px;      justify-content: center;      align-items: center;    }  }  .ck.ck-toolbar {    border: none;    justify-content: center;    background-color: mc('grey', '300');    color: #FFF;  }  > .ck-editor__editable {    background-color: mc('grey', '100');    overflow-y: auto;    overflow-x: hidden;    padding: 2rem;    box-shadow: 0 0 5px hsla(0, 0, 0, .1);    margin: 1rem auto 0;    width: calc(100vw - 256px - 16vw);    min-height: calc(100vh - 64px - 24px - 1rem - 40px);    border-radius: 5px;    @at-root .theme--dark & {      background-color: #303030;      color: #FFF;    }    @include until($widescreen) {      width: calc(100vw - 2rem);      margin: 1rem 1rem 0 1rem;      min-height: calc(100vh - 64px - 24px - 1rem - 40px);    }    @include until($tablet) {      width: 100%;      margin: 0;      min-height: calc(100vh - 56px - 24px - 76px);    }    &.ck.ck-editor__editable:not(.ck-editor__nested-editable).ck-focused {      border-color: #FFF;      box-shadow: 0 0 10px rgba(mc('blue', '700'), .25);      @at-root .theme--dark & {        border-color: #444;        border-bottom: none;        box-shadow: 0 0 10px rgba(#000, .25);      }    }    &.ck .ck-editor__nested-editable.ck-editor__nested-editable_focused,    &.ck .ck-editor__nested-editable:focus,    .ck-widget.table td.ck-editor__nested-editable.ck-editor__nested-editable_focused,    .ck-widget.table th.ck-editor__nested-editable.ck-editor__nested-editable_focused {      background-color: mc('grey', '100');      @at-root .theme--dark & {        background-color: mc('grey', '900');      }    }  }}</style>
 |