Add graph possibilities
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
- Add dot language, which renders graphs - Show search results when no results - Add graph page
This commit is contained in:
parent
a2cca78018
commit
fd755bfb61
73
editor/package-lock.json
generated
73
editor/package-lock.json
generated
|
@ -7,6 +7,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz",
|
||||||
"integrity": "sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg=="
|
"integrity": "sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg=="
|
||||||
},
|
},
|
||||||
|
"@egjs/hammerjs": {
|
||||||
|
"version": "2.0.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
|
||||||
|
"integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
|
||||||
|
"requires": {
|
||||||
|
"@types/hammerjs": "^2.0.36"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/anymatch": {
|
"@types/anymatch": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||||
|
@ -30,6 +38,11 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/hammerjs": {
|
||||||
|
"version": "2.0.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz",
|
||||||
|
"integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ=="
|
||||||
|
},
|
||||||
"@types/minimatch": {
|
"@types/minimatch": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||||
|
@ -4532,6 +4545,11 @@
|
||||||
"verror": "1.10.0"
|
"verror": "1.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"keycharm": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-zn47Ti4FJT9zdF+YBBLWJsfKF/fYQHkrYlBeB5Ez5e2PjW7SoIxr43yehAne2HruulIoid4NKZZxO0dHBygCtQ=="
|
||||||
|
},
|
||||||
"killable": {
|
"killable": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
|
||||||
|
@ -6981,6 +6999,13 @@
|
||||||
"tough-cookie": "~2.5.0",
|
"tough-cookie": "~2.5.0",
|
||||||
"tunnel-agent": "^0.6.0",
|
"tunnel-agent": "^0.6.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require-directory": {
|
"require-directory": {
|
||||||
|
@ -7532,6 +7557,14 @@
|
||||||
"faye-websocket": "^0.10.0",
|
"faye-websocket": "^0.10.0",
|
||||||
"uuid": "^3.4.0",
|
"uuid": "^3.4.0",
|
||||||
"websocket-driver": "0.6.5"
|
"websocket-driver": "0.6.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sockjs-client": {
|
"sockjs-client": {
|
||||||
|
@ -8266,6 +8299,11 @@
|
||||||
"setimmediate": "^1.0.4"
|
"setimmediate": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"timsort": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||||
|
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||||
|
},
|
||||||
"tiny-emitter": {
|
"tiny-emitter": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||||
|
@ -8636,9 +8674,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "3.4.0",
|
"version": "8.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz",
|
||||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
"integrity": "sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg=="
|
||||||
},
|
},
|
||||||
"v8-compile-cache": {
|
"v8-compile-cache": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
@ -8671,6 +8709,21 @@
|
||||||
"extsprintf": "^1.2.0"
|
"extsprintf": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"vis-data": {
|
||||||
|
"version": "6.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vis-data/-/vis-data-6.6.1.tgz",
|
||||||
|
"integrity": "sha512-xmujDB2Dzf8T04rGFJ9OP4OA6zRVrz8R9hb0CVKryBrZRCljCga9JjSfgctA8S7wdZu7otDtUIwX4ZOgfV/57w=="
|
||||||
|
},
|
||||||
|
"vis-network": {
|
||||||
|
"version": "7.6.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/vis-network/-/vis-network-7.6.10.tgz",
|
||||||
|
"integrity": "sha512-wL1dHBWWpzxvUaM0miccDuSLQ2tkw93jCA3j4Zizh4ruph+UXnjkouayaOyJIx43wULUSoKGWkhE6na1q208TA=="
|
||||||
|
},
|
||||||
|
"vis-util": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/vis-util/-/vis-util-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-FIS75hhrzbX1qJwFVwVVm1q2/TEktJWjgWsV0T3E9AYC4PWyQCBKk2LgsSLi+O8NBi7gTe9D4K75MqdPTHrRnA=="
|
||||||
|
},
|
||||||
"vm-browserify": {
|
"vm-browserify": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
|
||||||
|
@ -8995,6 +9048,14 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-colors": "^3.0.0",
|
"ansi-colors": "^3.0.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"webpack-sources": {
|
"webpack-sources": {
|
||||||
|
@ -9076,9 +9137,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"wiki-list-editor": {
|
"wiki-list-editor": {
|
||||||
"version": "0.7.8",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/wiki-list-editor/-/wiki-list-editor-0.7.8.tgz",
|
"resolved": "https://registry.npmjs.org/wiki-list-editor/-/wiki-list-editor-0.8.0.tgz",
|
||||||
"integrity": "sha512-t9O3Guey/EI6KdWLn2YVN43I70pBRpOov8iq0kPa9ZukE+eE55iNUWBQW7D61QypUwBegqQWEm4zAQyoo9f8FA==",
|
"integrity": "sha512-mA1JyClhwrvf+sZgZZm7H4TwLQ+xcciJThoZz+Ya7JVrffmWCex8HRByXfxpOA4C0XDNC/Wx1RpCYjf/zBHH3Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"dragula": "^3.7.2",
|
"dragula": "^3.7.2",
|
||||||
"he": "^1.2.0",
|
"he": "^1.2.0",
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"webpack-dev-server": "^3.11.0"
|
"webpack-dev-server": "^3.11.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@egjs/hammerjs": "^2.0.17",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
"bulma": "^0.7.5",
|
"bulma": "^0.7.5",
|
||||||
"clipboard": "^2.0.6",
|
"clipboard": "^2.0.6",
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
"file-loader": "^6.0.0",
|
"file-loader": "^6.0.0",
|
||||||
"fuse.js": "^6.0.0",
|
"fuse.js": "^6.0.0",
|
||||||
"jquery-contextmenu": "^2.9.2",
|
"jquery-contextmenu": "^2.9.2",
|
||||||
|
"keycharm": "^0.3.1",
|
||||||
"lunr": "^2.3.8",
|
"lunr": "^2.3.8",
|
||||||
"markdown-it": "^11.0.0",
|
"markdown-it": "^11.0.0",
|
||||||
"markdown-it-mark": "^3.0.0",
|
"markdown-it-mark": "^3.0.0",
|
||||||
|
@ -29,7 +31,12 @@
|
||||||
"prismjs": "^1.20.0",
|
"prismjs": "^1.20.0",
|
||||||
"sass-loader": "^7.3.1",
|
"sass-loader": "^7.3.1",
|
||||||
"style-loader": "^1.0.0",
|
"style-loader": "^1.0.0",
|
||||||
"wiki-list-editor": "^0.7.8"
|
"timsort": "^0.3.0",
|
||||||
|
"uuid": "^8.1.0",
|
||||||
|
"vis-data": "^6.6.1",
|
||||||
|
"vis-network": "^7.6.10",
|
||||||
|
"vis-util": "^4.3.2",
|
||||||
|
"wiki-list-editor": "^0.8.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node_modules/.bin/mocha -r esm",
|
"test": "node_modules/.bin/mocha -r esm",
|
||||||
|
|
|
@ -13,6 +13,7 @@ import 'jquery-contextmenu';
|
||||||
import getCaretCoordinates from './caret-position'
|
import getCaretCoordinates from './caret-position'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import mermaid from 'mermaid'
|
import mermaid from 'mermaid'
|
||||||
|
import { parseDOTNetwork, Network } from "vis-network/peer";
|
||||||
import PrismJS from 'prismjs'
|
import PrismJS from 'prismjs'
|
||||||
import 'prismjs/plugins/filter-highlight-all/prism-filter-highlight-all'
|
import 'prismjs/plugins/filter-highlight-all/prism-filter-highlight-all'
|
||||||
import 'prismjs/components/prism-php'
|
import 'prismjs/components/prism-php'
|
||||||
|
@ -21,12 +22,17 @@ import 'prismjs/components/prism-perl'
|
||||||
import 'prismjs/components/prism-css'
|
import 'prismjs/components/prism-css'
|
||||||
import 'prismjs/components/prism-markup-templating'
|
import 'prismjs/components/prism-markup-templating'
|
||||||
import 'prismjs/components/prism-jq'
|
import 'prismjs/components/prism-jq'
|
||||||
import './styles.scss';
|
|
||||||
import '../node_modules/jquery-contextmenu/dist/jquery.contextMenu.css';
|
import './styles.scss'
|
||||||
|
import '../node_modules/jquery-contextmenu/dist/jquery.contextMenu.css'
|
||||||
|
import 'vis-network/styles/vis-network.css'
|
||||||
|
|
||||||
moment.locale('nl')
|
moment.locale('nl')
|
||||||
mermaid.initialize({startOnLoad: true})
|
mermaid.initialize({startOnLoad: true})
|
||||||
|
|
||||||
|
PrismJS.plugins.filterHighlightAll.reject.addSelector('.language-mermaid')
|
||||||
|
PrismJS.plugins.filterHighlightAll.reject.addSelector('.language-dot')
|
||||||
|
|
||||||
function isMultiline(input) {
|
function isMultiline(input) {
|
||||||
return input.value.startsWith("```", 0)
|
return input.value.startsWith("```", 0)
|
||||||
}
|
}
|
||||||
|
@ -83,20 +89,20 @@ function addIndicator(editor, indicator) {
|
||||||
let holder = document.getElementById('editor');
|
let holder = document.getElementById('editor');
|
||||||
|
|
||||||
function showSearchResults(searchTool, query, input, value, resultType) {
|
function showSearchResults(searchTool, query, input, value, resultType) {
|
||||||
showSearchResultsExtended('#link-complete', 'link-template', searchTool, query, input, value, resultType, {belowCursor: true})
|
showSearchResultsExtended('#link-complete', 'link-template', searchTool, query, input, value, resultType, {showOnlyResults:true, belowCursor: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSearchResultsExtended(element, template, searchTool, query, input, value, resultType, options) {
|
function showSearchResultsExtended(element, template, searchTool, query, input, value, resultType, options) {
|
||||||
const $lc = $(element)
|
const $lc = $(element)
|
||||||
let results = searchTool(query)
|
let results = searchTool(query)
|
||||||
|
|
||||||
if (query.length === 0 || !results.length) {
|
let opt = options || {};
|
||||||
|
|
||||||
|
if (opt.showOnlyResults && (query.length === 0 || !results.length)) {
|
||||||
$lc.fadeOut()
|
$lc.fadeOut()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = options || {};
|
|
||||||
|
|
||||||
$lc.data('result-type', resultType)
|
$lc.data('result-type', resultType)
|
||||||
|
|
||||||
if (opt.belowCursor) {
|
if (opt.belowCursor) {
|
||||||
|
@ -180,6 +186,24 @@ $(document).on('popup:selected', '#autocomplete', function (event, linkName, res
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function renderGraphs() {
|
||||||
|
$('code.language-dot').each(function (i, code) {
|
||||||
|
if (!code.innerText) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = parseDOTNetwork(code.innerText)
|
||||||
|
let network = new Network(code, data, {
|
||||||
|
layout: {
|
||||||
|
randomSeed: 1239043
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$(code).on('click', function () {
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (holder) {
|
if (holder) {
|
||||||
const MD = new MarkdownIt({
|
const MD = new MarkdownIt({
|
||||||
linkify: true,
|
linkify: true,
|
||||||
|
@ -200,9 +224,9 @@ if (holder) {
|
||||||
})).use(MarkdownItMark)
|
})).use(MarkdownItMark)
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
transform(text, callback) {
|
transform(text, element) {
|
||||||
let converted = (text.startsWith("```", 0)) ? MD.render(text) : MD.renderInline(text)
|
let converted = (text.startsWith("```", 0)) ? MD.render(text) : MD.renderInline(text)
|
||||||
return callback(converted)
|
element.html(converted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +245,12 @@ if (holder) {
|
||||||
).save()
|
).save()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
editor.on('rendered', function () {
|
||||||
|
PrismJS.highlightAll()
|
||||||
|
mermaid.init()
|
||||||
|
renderGraphs();
|
||||||
|
})
|
||||||
|
|
||||||
createPageSearch().then(function ({titleSearch, commandSearch, commands}) {
|
createPageSearch().then(function ({titleSearch, commandSearch, commands}) {
|
||||||
editor.on('start-editing', function (input) {
|
editor.on('start-editing', function (input) {
|
||||||
const $lc = $('#link-complete');
|
const $lc = $('#link-complete');
|
||||||
|
@ -370,9 +400,9 @@ if (holder) {
|
||||||
editor.on('stop-editing', function (input) {
|
editor.on('stop-editing', function (input) {
|
||||||
$(input).parents('.list-item').removeClass('active');
|
$(input).parents('.list-item').removeClass('active');
|
||||||
$('#link-complete').off()
|
$('#link-complete').off()
|
||||||
PrismJS.plugins.filterHighlightAll.reject.addSelector('.language-mermaid')
|
|
||||||
PrismJS.highlightAll()
|
PrismJS.highlightAll()
|
||||||
mermaid.init()
|
mermaid.init()
|
||||||
|
renderGraphs();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
$.contextMenu({
|
$.contextMenu({
|
||||||
|
|
138
main.go
138
main.go
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -10,6 +11,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -94,6 +97,26 @@ type indexPage struct {
|
||||||
Backrefs map[string][]Backref
|
Backrefs map[string][]Backref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Label string `json:"label"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Edge struct {
|
||||||
|
From int `json:"from"`
|
||||||
|
To int `json:"to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type graphPage struct {
|
||||||
|
pageBaseInfo
|
||||||
|
Session *Session
|
||||||
|
Title string
|
||||||
|
Name string
|
||||||
|
References Refs
|
||||||
|
Nodes template.JS
|
||||||
|
Edges template.JS
|
||||||
|
}
|
||||||
|
|
||||||
type editPage struct {
|
type editPage struct {
|
||||||
pageBaseInfo
|
pageBaseInfo
|
||||||
Session *Session
|
Session *Session
|
||||||
|
@ -121,6 +144,7 @@ type recentPage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type indexHandler struct{}
|
type indexHandler struct{}
|
||||||
|
type graphHandler struct{}
|
||||||
type saveHandler struct{}
|
type saveHandler struct{}
|
||||||
type editHandler struct{}
|
type editHandler struct{}
|
||||||
type historyHandler struct{}
|
type historyHandler struct{}
|
||||||
|
@ -428,6 +452,119 @@ func (h *editHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *graphHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
sess, err := NewSession(w, r)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := sess.Flush(); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
refs := make(Refs)
|
||||||
|
|
||||||
|
f, err := os.Open(filepath.Join(mp.(*FilePages).dirname, "backrefs.json"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
err = json.NewDecoder(f).Decode(&refs)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodesBuf bytes.Buffer
|
||||||
|
var edgesBuf bytes.Buffer
|
||||||
|
|
||||||
|
var nodes []Node
|
||||||
|
var edges []Edge
|
||||||
|
|
||||||
|
nodeCount := 1
|
||||||
|
nodeMap := make(map[string]int)
|
||||||
|
|
||||||
|
for key, references := range refs {
|
||||||
|
if _, e := nodeMap[key]; !e {
|
||||||
|
nodeMap[key] = nodeCount
|
||||||
|
nodeCount += 1
|
||||||
|
}
|
||||||
|
for _, item := range references {
|
||||||
|
if _, e := nodeMap[item.Name]; !e {
|
||||||
|
nodeMap[item.Name] = nodeCount
|
||||||
|
nodeCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, id := range nodeMap {
|
||||||
|
nodes = append(nodes, Node{
|
||||||
|
Id: id,
|
||||||
|
Label: name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeSet := make(map[Edge]bool)
|
||||||
|
for key, references := range refs {
|
||||||
|
if toID, e := nodeMap[key]; e {
|
||||||
|
for _, item := range references {
|
||||||
|
if fromID, e := nodeMap[item.Name]; e {
|
||||||
|
edge := Edge{
|
||||||
|
From: fromID,
|
||||||
|
To: toID,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, e := edgeSet[edge]; !e {
|
||||||
|
edgeSet[edge] = true
|
||||||
|
edges = append(edges, edge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewEncoder(&nodesBuf).Encode(&nodes)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewEncoder(&edgesBuf).Encode(&edges)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pageBase := getPageBase()
|
||||||
|
data := graphPage{
|
||||||
|
pageBaseInfo: pageBase,
|
||||||
|
Session: sess,
|
||||||
|
Title: "Graph",
|
||||||
|
Name: "Graph",
|
||||||
|
References: refs,
|
||||||
|
Nodes: template.JS(nodesBuf.String()),
|
||||||
|
Edges: template.JS(edgesBuf.String()),
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := template.ParseFiles("templates/layout.html", "templates/graph.html")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = t.Execute(w, data)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (h *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
@ -749,6 +886,7 @@ func main() {
|
||||||
http.Handle("/edit/", &editHandler{})
|
http.Handle("/edit/", &editHandler{})
|
||||||
http.Handle("/history/", &historyHandler{})
|
http.Handle("/history/", &historyHandler{})
|
||||||
http.Handle("/recent/", &recentHandler{})
|
http.Handle("/recent/", &recentHandler{})
|
||||||
|
http.Handle("/graph/", &graphHandler{})
|
||||||
http.Handle("/", &indexHandler{})
|
http.Handle("/", &indexHandler{})
|
||||||
|
|
||||||
fmt.Printf("Running on port %d\n", *port)
|
fmt.Printf("Running on port %d\n", *port)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<a href="/edit/{{ .Name }}" class="navbar-item">Edit</a>
|
<a href="/edit/{{ .Name }}" class="navbar-item">Edit</a>
|
||||||
<a href="/history/{{ .Name }}" class="navbar-item">History</a>
|
<a href="/history/{{ .Name }}" class="navbar-item">History</a>
|
||||||
<a href="/recent/" class="navbar-item">Recent Changes</a>
|
<a href="/recent/" class="navbar-item">Recent Changes</a>
|
||||||
|
<a href="/graph/" class="navbar-item">Graph</a>
|
||||||
<a href="/auth/logout" class="navbar-item">Logout</a>
|
<a href="/auth/logout" class="navbar-item">Logout</a>
|
||||||
<span class="navbar-item"><b>{{ $.Session.Me }}</b></span>
|
<span class="navbar-item"><b>{{ $.Session.Me }}</b></span>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user