|
|
@ -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 { |
|
|
|