feat: editor preview scroll sync + preview styling fixes
This commit is contained in:
		| @@ -14,6 +14,7 @@ import { createApolloFetch } from 'apollo-fetch' | ||||
| import { BatchHttpLink } from 'apollo-link-batch-http' | ||||
| import { InMemoryCache } from 'apollo-cache-inmemory' | ||||
| import Vuetify from 'vuetify' | ||||
| import Velocity from 'velocity-animate' | ||||
| import Hammer from 'hammerjs' | ||||
| import store from './store' | ||||
|  | ||||
| @@ -95,6 +96,8 @@ Vue.use(VeeValidate, { | ||||
| }) | ||||
| Vue.use(Vuetify) | ||||
|  | ||||
| Vue.prototype.Velocity = Velocity | ||||
|  | ||||
| // ==================================== | ||||
| // Register Vue Components | ||||
| // ==================================== | ||||
|   | ||||
| @@ -141,6 +141,21 @@ const md = new MarkdownIt({ | ||||
|   .use(mdMark) | ||||
|   .use(mdImsize) | ||||
|  | ||||
| // Inject line numbers for preview scroll sync | ||||
| let linesMap = [] | ||||
| function injectLineNumbers (tokens, idx, options, env, slf) { | ||||
|   let line | ||||
|   if (tokens[idx].map && tokens[idx].level === 0) { | ||||
|     line = tokens[idx].map[0] | ||||
|     tokens[idx].attrJoin('class', 'line') | ||||
|     tokens[idx].attrSet('data-line', String(line)) | ||||
|     linesMap.push(line) | ||||
|   } | ||||
|   return slf.renderToken(tokens, idx, options, env, slf) | ||||
| } | ||||
| md.renderer.rules.paragraph_open = injectLineNumbers | ||||
| md.renderer.rules.heading_open = injectLineNumbers | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     codemirror | ||||
| @@ -192,13 +207,34 @@ export default { | ||||
|           self.$parent.save() | ||||
|         } | ||||
|       }) | ||||
|       cm.on('cursorActivity', this.scrollSync) | ||||
|       this.onCmInput(this.code) | ||||
|     }, | ||||
|     onCmInput: _.debounce(function (newContent) { | ||||
|       linesMap = [] | ||||
|       this.previewHTML = md.render(newContent) | ||||
|       this.$nextTick(function() { | ||||
|       this.$nextTick(() => { | ||||
|         Prism.highlightAllUnder(this.$refs.editorPreview) | ||||
|         this.scrollSync(this.cm) | ||||
|       }) | ||||
|     }, 500), | ||||
|     /** | ||||
|      * Update scroll sync | ||||
|      */ | ||||
|     scrollSync: _.debounce(function (cm) { | ||||
|       if (cm.somethingSelected()) { return } | ||||
|       let currentLine = cm.getCursor().line | ||||
|       if (currentLine < 3) { | ||||
|         this.Velocity(this.$refs.editorPreview, 'stop', true) | ||||
|         this.Velocity(this.$refs.editorPreview.firstChild, 'scroll', { offset: '-50', duration: 1000, container: this.$refs.editorPreview }) | ||||
|       } else { | ||||
|         let closestLine = _.findLast(linesMap, n => n <= currentLine) | ||||
|         let destElm = this.$refs.editorPreview.querySelector(`[data-line='${closestLine}']`) | ||||
|         if (destElm) { | ||||
|           this.Velocity(this.$refs.editorPreview, 'stop', true) | ||||
|           this.Velocity(destElm, 'scroll', { offset: '-100', duration: 1000, container: this.$refs.editorPreview }) | ||||
|         } | ||||
|       } | ||||
|     }, 500) | ||||
|   } | ||||
| } | ||||
| @@ -212,9 +248,10 @@ export default { | ||||
|   } | ||||
|  | ||||
|   &-editor { | ||||
|     background-color: darken(mc('grey', '900'), 4.5%); | ||||
|     flex: 1 1 50%; | ||||
|     display: block; | ||||
|     min-height: calc(100vh - 100px); | ||||
|     height: calc(100vh - 100px); | ||||
|     position: relative; | ||||
|  | ||||
|     &-title { | ||||
| @@ -229,7 +266,7 @@ export default { | ||||
|       position: absolute; | ||||
|       top: 0; | ||||
|       right: 0; | ||||
|       z-index: 2; | ||||
|       z-index: 7; | ||||
|       text-transform: uppercase; | ||||
|       font-size: .7rem; | ||||
|  | ||||
| @@ -243,14 +280,28 @@ export default { | ||||
|     flex: 1 1 50%; | ||||
|     background-color: mc('grey', '100'); | ||||
|     position: relative; | ||||
|     padding: 30px 1rem 1rem 1rem; | ||||
|     height: calc(100vh - 100px); | ||||
|     overflow: hidden; | ||||
|  | ||||
|     @include until($tablet) { | ||||
|       display: none; | ||||
|     } | ||||
|  | ||||
|     &-content { | ||||
|       height: calc(100vh - 100px); | ||||
|       overflow-y: scroll; | ||||
|       padding: 30px 1rem 1rem 1rem; | ||||
|       width: calc(100% + 1rem + 17px) | ||||
|       // -ms-overflow-style: none; | ||||
|  | ||||
|       // &::-webkit-scrollbar { | ||||
|       //   width: 0px; | ||||
|       //   background: transparent; | ||||
|       // } | ||||
|     } | ||||
|  | ||||
|     &-title { | ||||
|       background-color: mc('blue', '100'); | ||||
|       background-color: rgba(mc('blue', '100'), .75); | ||||
|       border-bottom-right-radius: 5px; | ||||
|       display: inline-flex; | ||||
|       height: 30px; | ||||
| @@ -318,6 +369,11 @@ export default { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Fix FAB revealing under codemirror | ||||
|   .speed-dial--fixed { | ||||
|     z-index: 5; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .CodeMirror { | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  | ||||
|   h1, h2, h3, h4, h5, h6 { | ||||
|     color: mc('blue-grey', '700'); | ||||
|     font-weight: 600; | ||||
|     font-weight: 500; | ||||
|   } | ||||
|  | ||||
|   > * + h1, > * + h2, > * + h3, > * + h4 { | ||||
| @@ -28,6 +28,7 @@ | ||||
|     font-size: 1.15rem; | ||||
|     border-bottom: 1px dotted mc('blue-grey', '100'); | ||||
|     margin-bottom: .5rem; | ||||
|     color: mc('blue-grey', '500'); | ||||
|   } | ||||
|   h4 { | ||||
|     font-size: 1.1rem; | ||||
| @@ -39,10 +40,32 @@ | ||||
|     font-size: 1.025rem; | ||||
|   } | ||||
|  | ||||
|   // -------------------------------------------- | ||||
|   // Paragraphs | ||||
|   // -------------------------------------------- | ||||
|   p + p { | ||||
|     margin-top: 1rem; | ||||
|   } | ||||
|  | ||||
|   // -------------------------------------------- | ||||
|   // Lists | ||||
|   // -------------------------------------------- | ||||
|   ul, ol { | ||||
|     & + p { | ||||
|       margin-top: .5rem; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ul { | ||||
|     list-style-type: square; | ||||
|     list-style-position: inside; | ||||
|   } | ||||
|  | ||||
|   ol { | ||||
|     list-style-type: decimal; | ||||
|     list-style-position: inside; | ||||
|   } | ||||
|  | ||||
|   // -------------------------------------------- | ||||
|   // Code Blocks | ||||
|   // -------------------------------------------- | ||||
| @@ -57,6 +80,7 @@ | ||||
|       box-shadow: initial; | ||||
|       display: block; | ||||
|       font-size: .85rem; | ||||
|       font-family: 'Source Code Pro', monospace; | ||||
|  | ||||
|       &:after, &:before { | ||||
|         content: initial; | ||||
|   | ||||
| @@ -195,6 +195,7 @@ | ||||
|     "twemoji-awesome": "1.0.6", | ||||
|     "uglifyjs-webpack-plugin": "1.2.0", | ||||
|     "vee-validate": "2.0.4", | ||||
|     "velocity-animate": "1.5.1", | ||||
|     "vue": "2.5.13", | ||||
|     "vue-clipboards": "1.2.1", | ||||
|     "vue-codemirror": "4.0.3", | ||||
|   | ||||
| @@ -23,7 +23,7 @@ html | ||||
|  | ||||
|     //- CSS | ||||
|     link(type='text/css', rel='stylesheet', href=config.site.path + 'css/bundle.css') | ||||
|     link(type='text/css', rel='stylesheet', href='https://fonts.googleapis.com/icon?family=Material+Icons') | ||||
|     link(type='text/css', rel='stylesheet', href='https://fonts.googleapis.com/icon?family=Roboto:400,500,700|Source+Code+Pro:400,700|Material+Icons') | ||||
|  | ||||
|     //- JS | ||||
|     script(type='text/javascript', src=config.site.path + 'js/runtime.js') | ||||
|   | ||||
| @@ -10322,6 +10322,10 @@ vee-validate@2.0.4: | ||||
|   dependencies: | ||||
|     babel-plugin-transform-object-rest-spread "^6.26.0" | ||||
|  | ||||
| velocity-animate@1.5.1: | ||||
|   version "1.5.1" | ||||
|   resolved "https://registry.yarnpkg.com/velocity-animate/-/velocity-animate-1.5.1.tgz#606837047bab8fbfb59a636d1d82ecc3f7bd71a6" | ||||
|  | ||||
| vendors@^1.0.0: | ||||
|   version "1.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user