diff --git a/demo/assets/index.js b/demo/assets/index.js
index fedf754..91d57cb 100644
--- a/demo/assets/index.js
+++ b/demo/assets/index.js
@@ -1,7 +1,7 @@
(function () {
'use strict';
- var mdHtml, mdSrc, permalink;
+ var mdHtml, mdSrc, permalink, scrollMap;
var defaults = {
html: false, // Enable HTML tags in source
@@ -63,6 +63,24 @@
mdHtml.renderer.rules.table_open = function () {
return '
\n';
};
+
+ mdHtml.renderer.rules.paragraph_open = function (tokens, idx) {
+ var line;
+ if (tokens[idx].lines && tokens[idx].level === 0) {
+ line = tokens[idx].lines[0];
+ return '';
+ }
+ return '
';
+ };
+
+ mdHtml.renderer.rules.heading_open = function (tokens, idx) {
+ var line;
+ if (tokens[idx].lines && tokens[idx].level === 0) {
+ line = tokens[idx].lines[0];
+ return '';
+ }
+ return '';
+ };
}
function updateResult() {
@@ -70,6 +88,7 @@
$('.result-html').html(mdHtml.render(source));
$('.result-src-content').html(window.hljs.highlight('html', mdSrc.render(source)).value);
+ scrollMap = null;
var dump = JSON.stringify(mdSrc.parse(source, { references: {} }), null, 2);
$('.result-debug-content').html(window.hljs.highlight('json', dump).value);
@@ -89,6 +108,88 @@
}
}
+ function recomputeScroll() {
+ var i, offset, nonEmptyList, pos, a, b, lineHeightMap, linesCount,
+ acc, sourceLikeDiv, textarea = $('.source');
+
+ sourceLikeDiv = $('').css({
+ position: 'absolute',
+ visibility: 'hidden',
+ height: 'auto',
+ width: textarea[0].clientWidth,
+ 'font-size': textarea.css('font-size'),
+ 'font-family': textarea.css('font-family'),
+ 'line-height': textarea.css('line-height'),
+ 'white-space': textarea.css('white-space')
+ }).appendTo('body');
+
+ offset = $('.result-html').scrollTop() - $('.result-html').offset().top;
+ scrollMap = [];
+ nonEmptyList = [];
+ lineHeightMap = [];
+
+ acc = 0;
+ textarea.val().split('\n').forEach(function(str) {
+ var h, lh;
+
+ lineHeightMap.push(acc);
+
+ if (str.length === 0) {
+ acc++;
+ return;
+ }
+
+ sourceLikeDiv.text(str);
+ h = parseFloat(sourceLikeDiv.css('height'));
+ lh = parseFloat(sourceLikeDiv.css('line-height'));
+ acc += Math.round(h / lh);
+ });
+ sourceLikeDiv.remove();
+ lineHeightMap.push(acc);
+ linesCount = acc;
+
+ for (i = 0; i < linesCount; i++) { scrollMap.push(-1); }
+
+ nonEmptyList.push(0);
+ scrollMap[0] = 0;
+
+ $('.line').each(function(n, el) {
+ var $el = $(el), t = $el.data('line');
+ if (t === '') { return; }
+ t = lineHeightMap[t];
+ if (t !== 0) { nonEmptyList.push(t); }
+ scrollMap[t] = Math.round($el.offset().top + offset);
+ });
+
+ nonEmptyList.push(linesCount);
+ scrollMap[linesCount] = $('.result-html')[0].scrollHeight;
+
+ pos = 0;
+ for (i = 1; i < linesCount; i++) {
+ if (scrollMap[i] !== -1) {
+ pos++;
+ continue;
+ }
+
+ a = nonEmptyList[pos];
+ b = nonEmptyList[pos + 1];
+ scrollMap[i] = Math.round((scrollMap[b] * (i - a) + scrollMap[a] * (b - i)) / (b - a));
+ }
+
+ return scrollMap;
+ }
+
+ function syncScroll() {
+ var textarea = $('.source'),
+ lineHeight = parseFloat(textarea.css('line-height')),
+ lineNo;
+
+ lineNo = Math.floor(textarea.scrollTop() / lineHeight);
+ if (!scrollMap) { recomputeScroll(); }
+ $('.result-html').stop(true).animate({
+ scrollTop: scrollMap[lineNo]
+ }, 100, 'linear');
+ }
$(function() {
// highlight snippet
@@ -180,6 +281,7 @@
// Setup listeners
$('.source').on('keyup paste cut mouseup', updateResult);
+ $('.source').on('scroll', _.debounce(syncScroll, 50, { maxWait: 50 }));
$('.source-clear').on('click', function (event) {
$('.source').val('');