Last active
December 15, 2016 04:11
-
-
Save kshep92/ff0b158700c4df3603e89db47b24acc5 to your computer and use it in GitHub Desktop.
How to create a Ghost-like editor with image placeholders that facilitate file upload. Sweeten to taste. From the THLabs/ghostdown repo.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var textarea = document.querySelector('#ghostdown-editor'), | |
preview = document.querySelector('#ghostdown-rendered'), | |
converter = new showdown.Converter(), | |
editor = CodeMirror.fromTextArea(textarea, { | |
mode: 'markdown', | |
tabMode: 'indent', | |
lineWrapping: true | |
}); | |
function updateImagePlaceholders() { | |
// Get all the empty images. I would probably just do a document.querySelectorAll('img[src=""]') | |
var imgPlaceholders = (Array.prototype.slice.call(document.querySelectorAll('#ghostdown-rendered p'))).filter(function (p) { | |
return (/^(?:\{<(.*?)>\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim).test(p.innerText); | |
}); | |
Dropzone.autoDiscover = false; | |
imgPlaceholders.forEach( | |
function (element, index) { | |
element.setAttribute("class", "dropzone"); | |
var dropzone = new Dropzone(element, { | |
url: "/content/upload", | |
success: function (file, response) { | |
var response = JSON.parse(response), | |
holderP = file.previewElement.closest("p"), | |
preList = Array.prototype.slice.call(document.querySelectorAll('.CodeMirror-code pre')), | |
// Not sure what this is testing. Will have to experiment. | |
imgHolderMarkdown = preList.filter(function (element) { | |
return (/^(?:\{<(.*?)>\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim).test(element.textContent) && (element.querySelectorAll('span').length === 0); | |
}), | |
editorOrigVal = editor.getValue(), | |
nth = 0, | |
// I might simplify this regex for my particular use case. | |
newMarkdown = editorOrigVal.replace(/^(?:\{<(.*?)>\})?!(?:\[([^\n\]]*)\])(:\(([^\n\]]*)\))?$/gim, function (match, i, original) { | |
nth++; | |
return (nth === (index + 1)) ? (match + "(" + response.path + ")") : match; | |
}); | |
editor.setValue(newMarkdown); | |
holderP.classList.remove("dropzone"); | |
holderP.innerHTML = '<img src="' + response.path + '"/>'; | |
} | |
}); | |
} | |
); | |
} | |
function updatePreview() { | |
preview.innerHTML = converter.makeHtml(editor.getValue()); | |
updateImagePlaceholders(); | |
} | |
function updateWordCount() { | |
var text = document.querySelector('#ghostdown-rendered').innerHTML.replace(/(<([^>]+)>)/ig, '').trim(), | |
count = (text.length === 0) ? 0 : text.split(/\s+/).length; | |
document.querySelector('#ghostdown-wordcount').innerHTML = count + " words"; | |
} | |
function syncScroll() { | |
var codeViewport = document.querySelector('.CodeMirror-scroll'), | |
previewViewport = document.querySelector('#ghostdown-preview'), | |
codeContent = document.querySelector('.CodeMirror-sizer'), | |
previewContent = document.querySelector('#ghostdown-rendered'), | |
codeHeight = codeContent.clientHeight - window.getComputedStyle(codeViewport, null).height.split("px")[0], | |
// TODO: for some reason, this needs a 50px 'bodge' to make it scroll to the bottom properly | |
previewHeight = previewContent.clientHeight - window.getComputedStyle(previewViewport, null).height.split("px")[0] + 50, | |
ratio = previewHeight / codeHeight, | |
previewPostition = codeViewport.scrollTop * ratio; | |
previewViewport.scrollTop = previewPostition; | |
} | |
editor.on("change", function () { | |
updatePreview(); | |
syncScroll(); | |
updateWordCount(); | |
}); | |
updatePreview(); | |
updateWordCount(); | |
document.querySelector('.CodeMirror-scroll').onscroll = syncScroll; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Dropzone imports (although we won't be using dropzone) and ghostdown.js --> | |
<form action="/article/save" method="post"> | |
<div class="ghostdown-container mdl-grid"> | |
<div class="ghostdown-panel mdl-color--white mdl-shadow--4dp content mdl-color-text--grey-800 mdl-cell mdl-cell--6-col"> | |
<h2 class="editor-title">Markdown</h2> | |
<textarea name="content" id="ghostdown-editor"># Ghostdown | |
This is an attempt to clone the [Ghost](http://ghost.org) blogging platform's editor. The idea is simple - write your content using the simple [Markdown](http://daringfireball.net/projects/markdown/) format, and see a live preview at the same time. | |
 | |
## Usage | |
The `index.html` file contains a usage example with styling and layout, but it's really very easy. Simply download the [repository](https://github.com/thlabs/ghostdown) (or just the `scripts\ghostdown.js` file). *Ghostdown* is setup to use [Require.js](http://requirejs.org), so include the following line in your html file: | |
```html | |
<script type="text/javascript" data-main="scripts/ghostdown" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.20/require.min.js"></script> | |
``` | |
### Image uploading | |
![Placeholder for image] | |
## Libraries | |
*Ghostdown* is built on the following existing libraries: | |
* [CodeMirror](http://codemirror.net) - for editing and syntax highlighting of the Markdown content | |
* [showdown](https://github.com/showdownjs/showdown) - to translate the markdown into the live preview | |
* [Dropzone](http://www.dropzonejs.com/) - to simplify image uploading | |
### Credits | |
Based on some initial work by [Shawn Xie](https://github.com/fengluo/ghostdown)</textarea> | |
</div> | |
<div class="ghostdown-panel mdl-color--white mdl-shadow--4dp content mdl-color-text--grey-800 mdl-cell mdl-cell--6-col"> | |
<h2 class="editor-title">Preview</h2> | |
<span class="editor-title" id="ghostdown-wordcount">0 Words</span> | |
<div id="ghostdown-preview"> | |
<div id="ghostdown-rendered"></div> | |
</div> | |
</div> | |
<footer class="ghostdown-footer mdl-mini-footer"> | |
<div class="mdl-mini-footer--left-section"> | |
©2015 THLabs.net | Powered by <a href="https://github.com/THLabs/ghostdown">ghostdown</a> | |
</div> | |
<div class="mdl-mini-footer--right-section"> | |
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-button--accent mdl-button--ripple-effect ghostdown-button-save" type="submit">Save</button> | |
</div> | |
</footer> | |
</div> | |
</form> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment