Add support for table of contents in the code app (#325)

pull/1/head
yflory 6 years ago
parent 37a79a0141
commit 03b40d87ed

@ -9,6 +9,35 @@
blockquote { margin: 0; } blockquote { margin: 0; }
} }
// todo ul, ol // todo ul, ol
// TOC
div.cp-md-toc {
background: #f3f3f3;
padding: 20px;
float: right;
margin: 5px;
margin-right: 0;
& > p {
&.cp-md-toc-1 {
margin-left: 0;
}
&.cp-md-toc-2 {
margin-left: 25px;
}
&.cp-md-toc-3 {
margin-left: 50px;
}
&.cp-md-toc-4 {
margin-left: 75px;
}
&.cp-md-toc-5 {
margin-left: 100px;
}
&.cp-md-toc-6 {
margin-left: 125px;
}
margin: 0;
}
}
} }
.markdown_preformatted-code (@color: #333) { .markdown_preformatted-code (@color: #333) {

@ -3,12 +3,14 @@ define([
'/bower_components/marked/marked.min.js', '/bower_components/marked/marked.min.js',
'/common/common-hash.js', '/common/common-hash.js',
'/common/common-util.js', '/common/common-util.js',
'/common/hyperscript.js',
'/common/media-tag.js', '/common/media-tag.js',
'/common/highlight/highlight.pack.js', '/common/highlight/highlight.pack.js',
'/customize/messages.js',
'/bower_components/diff-dom/diffDOM.js', '/bower_components/diff-dom/diffDOM.js',
'/bower_components/tweetnacl/nacl-fast.min.js', '/bower_components/tweetnacl/nacl-fast.min.js',
'css!/common/highlight/styles/github.css' 'css!/common/highlight/styles/github.css'
],function ($, Marked, Hash, Util, MediaTag, Highlight) { ],function ($, Marked, Hash, Util, h, MediaTag, Highlight, Messages) {
var DiffMd = {}; var DiffMd = {};
var DiffDOM = window.diffDOM; var DiffDOM = window.diffDOM;
@ -33,16 +35,56 @@ define([
highlight: highlighter(), highlight: highlighter(),
}); });
var toc = [];
var getTOC = function () {
var content = [h('h2', Messages.markdown_toc)];
toc.forEach(function (obj) {
// Only include level 2 headings
var level = obj.level - 1;
if (level < 1) { return; }
var a = h('a.cp-md-toc-link', {
href: '#',
'data-href': obj.id,
}, obj.title);
content.push(h('p.cp-md-toc-'+level, a));
});
return h('div.cp-md-toc', content).outerHTML;
};
DiffMd.render = function (md, sanitize) { DiffMd.render = function (md, sanitize) {
return Marked(md, { var r = Marked(md, {
sanitize: sanitize sanitize: sanitize
}); });
// Add Table of Content
r = r.replace(/<div class="cp-md-toc"><\/div>/g, getTOC());
toc = [];
return r;
}; };
var mediaMap = {}; var mediaMap = {};
renderer.heading = function (text, level) {
var i = 0;
var safeText = text.toLowerCase().replace(/[^\w]+/g, '-');
var getId = function () {
return 'cp-md-' + i + '-' + safeText;
};
var id = getId();
var isAlreadyUsed = function (obj) { return obj.id === id; };
while (toc.some(isAlreadyUsed)) {
i++;
id = getId();
}
toc.push({
level: level,
id: id,
title: text
});
return "<h" + level + " id=\"" + id + "\"><a href=\"#" + id + "\" class=\"anchor\"></a>" + text + "</h" + level + ">";
};
// Tasks list // Tasks list
var checkedTaskItemPtn = /^\s*(<p>)?\[[xX]\](<\/p>)?\s*/; var checkedTaskItemPtn = /^\s*(<p>)?\[[xX]\](<\/p>)?\s*/;
var uncheckedTaskItemPtn = /^\s*(<p>)?\[ ?\](<\/p>)?\s*/; var uncheckedTaskItemPtn = /^\s*(<p>)?\[ ?\](<\/p>)?\s*/;
@ -97,6 +139,9 @@ define([
}; };
renderer.paragraph = function (p) { renderer.paragraph = function (p) {
if (p === '[TOC]') {
return '<p><div class="cp-md-toc"></div></p>';
}
return /<media\-tag[\s\S]*>/i.test(p)? p + '\n': '<p>' + p + '</p>\n'; return /<media\-tag[\s\S]*>/i.test(p)? p + '\n': '<p>' + p + '</p>\n';
}; };
@ -249,6 +294,15 @@ define([
characterData: false characterData: false
}); });
}); });
// Fix Table of contents links
$content.find('a.cp-md-toc-link').off('click').click(function (e) {
e.preventDefault();
e.stopPropagation();
var $a = $(this);
if (!$a.attr('data-href')) { return; }
var target = document.getElementById($a.attr('data-href'));
if (target) { target.scrollIntoView(); }
});
} }
}; };

Loading…
Cancel
Save