123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- <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 DecoupledEditor from '../../../../wiki-ckeditor5/build/ckeditor'
- import EditorConflict from './ckeditor/conflict.vue'
- import { html as beautify } from 'js-beautify/js/lib/beautifier.min.js'
- /* 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, {
- language: this.locale,
- placeholder: 'Type the page content here',
- disableNativeSpellChecker: false,
- // TODO: Mention autocomplete
- //
- // mention: {
- // feeds: [
- // {
- // marker: '@',
- // feed: [ '@Barney', '@Lily', '@Marshall', '@Robin', '@Ted' ],
- // minimumCharacters: 1
- // }
- // ]
- // },
- 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', beautify(this.editor.getData(), { indent_size: 2, end_with_newline: true }))
- }, 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
- case 'DIAGRAM':
- this.editor.execute('imageInsert', {
- source: `data:image/svg+xml;base64,${opts.text}`
- })
- 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;
- }
- }
- .contents {
- table {
- margin: inherit;
- }
- pre > code {
- background-color: unset;
- color: unset;
- padding: .15em;
- }
- }
- .ck.ck-toolbar {
- border: none;
- justify-content: center;
- background-color: mc('grey', '300');
- color: #FFF;
- }
- .ck.ck-toolbar__items {
- justify-content: center;
- }
- > .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>
|