Commit 1ad03a3d authored by NGPixel's avatar NGPixel

Markdown parsing + tree parsing + content display

parent ca1882a9
This source diff could not be displayed because it is too large. You can view the blob instead.
"use strict";jQuery(document).ready(function(e){e("a").smoothScroll({speed:"auto"})});
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
"use strict";
jQuery( document ).ready(function( $ ) {
$('a').smoothScroll({
speed: 'auto'
});
});
\ No newline at end of file
......@@ -4,6 +4,8 @@
$warning: #f68b39;
@import 'bulma';
@import './libs/twemoji-awesome';
@import './layout/_header';
@import './layout/_footer';
\ No newline at end of file
@import './layout/_footer';
......@@ -8,16 +8,15 @@ var router = express.Router();
*/
router.get('/', (req, res) => {
var md = require('markdown-it')({
breaks: true,
linkify: true,
typographer: true
});
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require("fs"));
fs.readFileAsync("repo/Gollum.md", "utf8").then(function(contents) {
res.render('pages/view', { contents: md.render(contents) });
let pageData = mark.parse(contents);
if(!pageData.title) {
pageData.title = 'Gollum';
}
res.render('pages/view', { pageData });
});
});
......
......@@ -21,7 +21,8 @@ var paths = {
scriptlibs: [
'./node_modules/lodash/lodash.min.js',
'./node_modules/jquery/dist/jquery.min.js',
'./node_modules/vue/dist/vue.min.js'
'./node_modules/vue/dist/vue.min.js',
'./node_modules/jquery-smooth-scroll/jquery.smooth-scroll.min.js'
],
scriptapps: [
'./client/js/components/*.js',
......@@ -31,8 +32,7 @@ var paths = {
'./client/js/**/*.js'
],
csslibs: [
'./node_modules/font-awesome/css/font-awesome.min.css',
'./node_modules/font-awesome/css/font-awesome.min.css'
],
cssapps: [
'./client/scss/app.scss'
......
"use strict";
var Promise = require('bluebird'),
md = require('markdown-it'),
mdEmoji = require('markdown-it-emoji'),
mdTaskLists = require('markdown-it-task-lists'),
mdAbbr = require('markdown-it-abbr'),
mdAnchor = require('markdown-it-toc-and-anchor').default,
mdFootnote = require('markdown-it-footnote'),
mdExternalLinks = require('markdown-it-external-links'),
mdExpandTabs = require('markdown-it-expand-tabs'),
slug = require('slug'),
_ = require('lodash');
// Load plugins
var mkdown = md({
html: true,
linkify: true,
typography: true
})
.use(mdEmoji)
.use(mdTaskLists)
.use(mdAbbr)
.use(mdAnchor, {
tocClassName: 'toc',
anchorClassName: 'toc-anchor'
})
.use(mdFootnote)
.use(mdExternalLinks, {
externalClassName: 'external-link',
internalClassName: 'internal-link'
})
.use(mdExpandTabs, {
tabWidth: 4
});
// Rendering rules
mkdown.renderer.rules.emoji = function(token, idx) {
return '<i class="twa twa-' + token[idx].markup + '"></i>';
};
// Parse markdown headings tree
const parseTree = (content) => {
let tokens = md().parse(content, {});
let tocArray = [];
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].type !== "heading_close") {
continue
}
const heading = tokens[i - 1]
const heading_close = tokens[i]
if (heading.type === "inline") {
let content = "";
let anchor = "";
if (heading.children && heading.children[0].type === "link_open") {
content = heading.children[1].content
anchor = slug(content, {lower: true});
} else {
content = heading.content
anchor = slug(heading.children.reduce((acc, t) => acc + t.content, ""), {lower: true});
}
tocArray.push({
content,
anchor,
level: +heading_close.tag.substr(1, 1)
})
}
}
return _.reduce(tocArray, (tree, v) => {
let treeLength = tree.length - 1;
if(v.level < 2) {
tree.push({
content: v.content,
anchor: v.anchor,
nodes: []
});
} else {
let lastNodeLevel = 1;
let GetNodePath = (startPos) => {
lastNodeLevel++;
if(_.isEmpty(startPos)) {
startPos = 'nodes';
}
if(lastNodeLevel === v.level) {
return startPos;
} else {
return GetNodePath(startPos + '[' + (_.at(tree[treeLength], startPos).length - 1) + '].nodes');
}
};
let lastNodePath = GetNodePath();
let lastNode = _.get(tree[treeLength], lastNodePath);
lastNode.push({
content: v.content,
anchor: v.anchor,
nodes: []
});
_.set(tree[treeLength], lastNodePath, lastNode);
}
return tree;
}, []);
};
module.exports = {
parse(content) {
return {
html: mkdown.render(content),
tree: parseTree(content)
};
}
};
\ No newline at end of file
......@@ -44,7 +44,6 @@
"express-brute-redis": "0.0.1",
"express-session": "^1.14.0",
"express-validator": "^2.20.8",
"gridlex": "^2.1.1",
"i18next": "^3.4.1",
"i18next-express-middleware": "^1.0.1",
"i18next-node-fs-backend": "^0.1.2",
......@@ -52,6 +51,14 @@
"js-yaml": "^3.6.1",
"lodash": "^4.15.0",
"markdown-it": "^7.0.1",
"markdown-it-abbr": "^1.0.3",
"markdown-it-anchor": "^2.5.0",
"markdown-it-emoji": "^1.2.0",
"markdown-it-expand-tabs": "^1.0.11",
"markdown-it-external-links": "0.0.5",
"markdown-it-footnote": "^3.0.1",
"markdown-it-task-lists": "^1.4.1",
"markdown-it-toc-and-anchor": "^4.1.1",
"moment": "^2.14.1",
"moment-timezone": "^0.5.5",
"mongoose": "^4.5.9",
......@@ -63,6 +70,8 @@
"roboto-fontface": "^0.6.0",
"serve-favicon": "^2.3.0",
"simplemde": "^1.11.2",
"slug": "^0.9.1",
"twemoji-awesome": "^1.0.4",
"validator": "^5.5.0",
"validator-as-promised": "^1.0.2",
"winston": "^2.2.0"
......
......@@ -4,19 +4,24 @@
// Licensed under AGPLv3
// ===========================================
global.ROOTPATH = __dirname;
// ----------------------------------------
// Load modules
// Load global modules
// ----------------------------------------
global.winston = require('winston');
winston.info('[SERVER] Requarks Wiki is initializing...');
global.ROOTPATH = __dirname;
var appconfig = require('./models/config')('./config.yml');
global.db = require('./models/mongodb')(appconfig);
global.red = require('./models/redis')(appconfig);
global.git = require('./models/git').init(appconfig);
global.mark = require('./models/markdown');
// ----------------------------------------
// Load modules
// ----------------------------------------
var _ = require('lodash');
var express = require('express');
......
......@@ -17,8 +17,6 @@ nav.nav.has-shadow
span
.nav-right.nav-menu
a.nav-item(href='#')
| Account
a.nav-item(href='#')
| History
a.nav-item(href='#')
| Source
......
......@@ -21,6 +21,10 @@ html
link(type='text/css', rel='stylesheet', href='/css/libs.css')
link(type='text/css', rel='stylesheet', href='/css/app.css')
// JS
script(type='text/javascript', src='/js/libs.js')
script(type='text/javascript', src='/js/app.js')
block head
body
......
extends ../layout
mixin tocMenu(ti)
each node in ti
li
a(href='#' + node.anchor, title=node.content)= node.content
if node.nodes.length > 0
ul
+tocMenu(node.nodes)
block content
section.section
......@@ -8,47 +16,27 @@ block content
.column.is-narrow
aside.menu
p.menu-label
| General
ul.menu-list
li
a(href='#') Dashboard
li
a(href='#') Customers
p.menu-label
| Administration
ul.menu-list
li
a(href='#') Team Settings
.box
aside.menu(style= { 'min-width': '200px' })
p.menu-label
| Navigation
ul.menu-list
li
a(href='/') Home
li
a.is-active(href='#') Manage Your Team
ul
li
a(href='#') Members
li
a(href='#') Plugins
li
a(href='#') Add a member
li
a(href='#') Invitations
li
a(href='#') Authentication
p.menu-label
| Transactions
ul.menu-list
li
a(href='#') Payments
li
a(href='#') Transfers
li
a(href='#') Balance
a(href='/account') Account
.box
aside.menu(style= { 'min-width': '200px' })
p.menu-label
| Contents
ul.menu-list
+tocMenu(pageData.tree)
.column
h1.title
| Primary bold title
h1.title= pageData.title
h2.subtitle
| Primary bold subtitle
.content
!= contents
!= pageData.html
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment