editor-ckeditor.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template lang='pug'>
  2. .editor-ckeditor
  3. div(ref='toolbarContainer')
  4. div.contents(ref='editor')
  5. v-system-bar.editor-ckeditor-sysbar(dark, status, color='grey darken-3')
  6. .caption.editor-ckeditor-sysbar-locale {{locale.toUpperCase()}}
  7. .caption.px-3 /{{path}}
  8. template(v-if='$vuetify.breakpoint.mdAndUp')
  9. v-spacer
  10. .caption Visual Editor
  11. v-spacer
  12. .caption {{stats.characters}} Chars, {{stats.words}} Words
  13. </template>
  14. <script>
  15. import _ from 'lodash'
  16. import { get, sync } from 'vuex-pathify'
  17. import DecoupledEditor from '@requarks/ckeditor5'
  18. export default {
  19. props: {
  20. save: {
  21. type: Function,
  22. default: () => {}
  23. }
  24. },
  25. data() {
  26. return {
  27. editor: null,
  28. stats: {
  29. characters: 0,
  30. words: 0
  31. },
  32. content: ''
  33. }
  34. },
  35. computed: {
  36. isMobile() {
  37. return this.$vuetify.breakpoint.smAndDown
  38. },
  39. locale: get('page/locale'),
  40. path: get('page/path'),
  41. activeModal: sync('editor/activeModal')
  42. },
  43. methods: {
  44. },
  45. async mounted () {
  46. this.$store.set('editor/editorKey', 'ckeditor')
  47. this.editor = await DecoupledEditor.create(this.$refs.editor, {
  48. placeholder: 'Type the page content here',
  49. wordCount: {
  50. onUpdate: stats => {
  51. this.stats = {
  52. characters: stats.characters,
  53. words: stats.words
  54. }
  55. }
  56. }
  57. })
  58. this.$refs.toolbarContainer.appendChild(this.editor.ui.view.toolbar.element)
  59. if (this.mode !== 'create') {
  60. this.editor.setData(this.$store.get('editor/content'))
  61. }
  62. this.editor.model.document.on('change:data', _.debounce(evt => {
  63. this.$store.set('editor/content', this.editor.getData())
  64. }, 300))
  65. this.$root.$on('editorInsert', opts => {
  66. console.info(opts)
  67. switch (opts.kind) {
  68. case 'IMAGE':
  69. this.editor.execute('imageInsert', {
  70. source: opts.path
  71. })
  72. break
  73. case 'BINARY':
  74. this.insertAtCursor({
  75. content: `[${opts.text}](${opts.path})`
  76. })
  77. break
  78. }
  79. })
  80. },
  81. beforeDestroy () {
  82. if (this.editor) {
  83. this.editor.destroy()
  84. this.editor = null
  85. }
  86. }
  87. }
  88. </script>
  89. <style lang="scss">
  90. $editor-height: calc(100vh - 64px - 24px);
  91. $editor-height-mobile: calc(100vh - 56px - 16px);
  92. .editor-ckeditor {
  93. background-color: mc('grey', '200');
  94. flex: 1 1 50%;
  95. display: flex;
  96. flex-flow: column nowrap;
  97. height: $editor-height;
  98. max-height: $editor-height;
  99. position: relative;
  100. @at-root .theme--dark & {
  101. background-color: mc('grey', '900');
  102. }
  103. @include until($tablet) {
  104. height: $editor-height-mobile;
  105. max-height: $editor-height-mobile;
  106. }
  107. &-sysbar {
  108. padding-left: 0;
  109. &-locale {
  110. background-color: rgba(255,255,255,.25);
  111. display:inline-flex;
  112. padding: 0 12px;
  113. height: 24px;
  114. width: 63px;
  115. justify-content: center;
  116. align-items: center;
  117. }
  118. }
  119. .ck.ck-toolbar {
  120. border: none;
  121. justify-content: center;
  122. background-color: mc('grey', '300');
  123. color: #FFF;
  124. }
  125. > .ck-editor__editable {
  126. background-color: mc('grey', '100');
  127. overflow-y: auto;
  128. overflow-x: hidden;
  129. padding: 2rem;
  130. box-shadow: 0 0 5px hsla(0, 0, 0, .1);
  131. margin: 1rem auto 0;
  132. width: calc(100vw - 256px - 16vw);
  133. min-height: calc(100vh - 64px - 24px - 1rem - 40px);
  134. border-radius: 5px;
  135. @at-root .theme--dark & {
  136. background-color: #303030;
  137. color: #FFF;
  138. }
  139. @include until($widescreen) {
  140. width: calc(100vw - 2rem);
  141. margin: 1rem 1rem 0 1rem;
  142. min-height: calc(100vh - 64px - 24px - 1rem - 40px);
  143. }
  144. @include until($tablet) {
  145. width: 100%;
  146. margin: 0;
  147. min-height: calc(100vh - 56px - 24px - 76px);
  148. }
  149. &.ck.ck-editor__editable:not(.ck-editor__nested-editable).ck-focused {
  150. border-color: #FFF;
  151. box-shadow: 0 0 10px rgba(mc('blue', '700'), .25);
  152. @at-root .theme--dark & {
  153. border-color: #444;
  154. border-bottom: none;
  155. box-shadow: 0 0 10px rgba(#000, .25);
  156. }
  157. }
  158. &.ck .ck-editor__nested-editable.ck-editor__nested-editable_focused,
  159. &.ck .ck-editor__nested-editable:focus,
  160. .ck-widget.table td.ck-editor__nested-editable.ck-editor__nested-editable_focused,
  161. .ck-widget.table th.ck-editor__nested-editable.ck-editor__nested-editable_focused {
  162. background-color: mc('grey', '900');
  163. }
  164. }
  165. }
  166. </style>