noteconnection 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +198 -0
- package/dist/backend/CommunityDetection.js +58 -0
- package/dist/backend/FileLoader.js +110 -0
- package/dist/backend/GraphBuilder.js +347 -0
- package/dist/backend/GraphMetrics.js +70 -0
- package/dist/backend/algorithms/CycleDetection.js +63 -0
- package/dist/backend/algorithms/HybridEngine.js +70 -0
- package/dist/backend/algorithms/StatisticalAnalyzer.js +123 -0
- package/dist/backend/algorithms/TopologicalSort.js +69 -0
- package/dist/backend/algorithms/VectorSpace.js +87 -0
- package/dist/backend/build_dag.js +164 -0
- package/dist/backend/config.js +17 -0
- package/dist/backend/graph.js +108 -0
- package/dist/backend/main.js +67 -0
- package/dist/backend/parser.js +94 -0
- package/dist/backend/test_robustness/test_hybrid.js +60 -0
- package/dist/backend/test_robustness/test_statistics.js +58 -0
- package/dist/backend/test_robustness/test_vector.js +54 -0
- package/dist/backend/test_robustness.js +113 -0
- package/dist/backend/types.js +3 -0
- package/dist/backend/utils/frontmatterParser.js +121 -0
- package/dist/backend/utils/stringUtils.js +66 -0
- package/dist/backend/workers/keywordMatchWorker.js +22 -0
- package/dist/core/Graph.js +121 -0
- package/dist/core/Graph.test.js +37 -0
- package/dist/core/types.js +2 -0
- package/dist/frontend/analysis.js +356 -0
- package/dist/frontend/app.js +1447 -0
- package/dist/frontend/data.js +8356 -0
- package/dist/frontend/graph_data.json +8356 -0
- package/dist/frontend/index.html +279 -0
- package/dist/frontend/reader.js +177 -0
- package/dist/frontend/settings.js +84 -0
- package/dist/frontend/source_manager.js +61 -0
- package/dist/frontend/styles.css +577 -0
- package/dist/frontend/styles_analysis.css +145 -0
- package/dist/index.js +121 -0
- package/dist/server.js +149 -0
- package/package.json +39 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.buildGraph = buildGraph;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const FileLoader_1 = require("./backend/FileLoader");
|
|
40
|
+
const GraphBuilder_1 = require("./backend/GraphBuilder");
|
|
41
|
+
async function buildGraph(targetPath) {
|
|
42
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
43
|
+
// Default to Knowledge_Base if no path provided, or specific folder if provided
|
|
44
|
+
// If targetPath is absolute, use it. If relative, assume relative to Knowledge_Base
|
|
45
|
+
let conceptDir;
|
|
46
|
+
const kbRoot = path.join(projectRoot, 'Knowledge_Base');
|
|
47
|
+
if (targetPath) {
|
|
48
|
+
if (path.isAbsolute(targetPath)) {
|
|
49
|
+
conceptDir = targetPath;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
conceptDir = path.join(kbRoot, targetPath);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Default behavior or "All"
|
|
57
|
+
conceptDir = kbRoot;
|
|
58
|
+
}
|
|
59
|
+
// Verify directory exists
|
|
60
|
+
if (!fs.existsSync(conceptDir)) {
|
|
61
|
+
throw new Error(`Directory not found: ${conceptDir}`);
|
|
62
|
+
}
|
|
63
|
+
const outputPath = path.join(projectRoot, 'src', 'frontend', 'graph_data.json');
|
|
64
|
+
console.log(`Loading files from: ${conceptDir}`);
|
|
65
|
+
const files = await FileLoader_1.FileLoader.loadFiles(conceptDir);
|
|
66
|
+
console.log(`Loaded ${files.length} files.`);
|
|
67
|
+
console.log('Building graph...');
|
|
68
|
+
// Try to load layout.json
|
|
69
|
+
let layoutMap;
|
|
70
|
+
const layoutPath = path.join(projectRoot, 'layout.json');
|
|
71
|
+
if (fs.existsSync(layoutPath)) {
|
|
72
|
+
console.log(`Found layout file: ${layoutPath}`);
|
|
73
|
+
try {
|
|
74
|
+
const rawLayout = JSON.parse(fs.readFileSync(layoutPath, 'utf-8'));
|
|
75
|
+
if (Array.isArray(rawLayout)) {
|
|
76
|
+
layoutMap = new Map();
|
|
77
|
+
rawLayout.forEach((n) => {
|
|
78
|
+
if (n.id && typeof n.x === 'number' && typeof n.y === 'number') {
|
|
79
|
+
layoutMap.set(n.id, { x: n.x, y: n.y });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
console.log(`Loaded layout for ${layoutMap.size} nodes.`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
console.warn('Failed to parse layout.json', e);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const graph = await GraphBuilder_1.GraphBuilder.build(files, layoutMap);
|
|
90
|
+
const data = graph.toJSON();
|
|
91
|
+
console.log(`Graph built: ${data.nodes.length} nodes, ${data.edges.length} edges.`);
|
|
92
|
+
// Ensure frontend directory exists
|
|
93
|
+
const frontendDir = path.dirname(outputPath);
|
|
94
|
+
if (!fs.existsSync(frontendDir)) {
|
|
95
|
+
fs.mkdirSync(frontendDir, { recursive: true });
|
|
96
|
+
}
|
|
97
|
+
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2));
|
|
98
|
+
console.log(`Graph data saved to: ${outputPath}`);
|
|
99
|
+
const jsOutputPath = path.join(projectRoot, 'src', 'frontend', 'data.js');
|
|
100
|
+
const jsContent = `const graphData = ${JSON.stringify(data, null, 2)};`;
|
|
101
|
+
fs.writeFileSync(jsOutputPath, jsContent);
|
|
102
|
+
console.log(`Graph data JS saved to: ${jsOutputPath}`);
|
|
103
|
+
return data;
|
|
104
|
+
}
|
|
105
|
+
// Allow direct execution
|
|
106
|
+
if (require.main === module) {
|
|
107
|
+
const args = process.argv.slice(2);
|
|
108
|
+
// If arg provided, use it. If not, default to 'testconcept' for backward compatibility
|
|
109
|
+
// OR just handle 'Knowledge_Base' full scan.
|
|
110
|
+
// Given the prompt "I have placed the entire folder... under the Knowledge_Base path",
|
|
111
|
+
// let's default to 'testconcept' to match current user context if they run it manually without args,
|
|
112
|
+
// or just 'testconcept' if they provided no args.
|
|
113
|
+
// Actually, safer to default to the whole 'Knowledge_Base' if they want "one or all".
|
|
114
|
+
// But let's check if 'Knowledge_Base' has files directly?
|
|
115
|
+
// It seems it has subfolders.
|
|
116
|
+
// For CLI usage:
|
|
117
|
+
const target = args[0] || 'testconcept';
|
|
118
|
+
buildGraph(target).catch(err => {
|
|
119
|
+
console.error('Error:', err);
|
|
120
|
+
});
|
|
121
|
+
}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const index_1 = require("./index");
|
|
41
|
+
const PORT = 3000;
|
|
42
|
+
const FRONTEND_DIR = path.join(__dirname, 'frontend');
|
|
43
|
+
const KB_ROOT = path.join(process.cwd(), 'Knowledge_Base');
|
|
44
|
+
const server = http.createServer(async (req, res) => {
|
|
45
|
+
// CORS headers
|
|
46
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
47
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
48
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
49
|
+
if (req.method === 'OPTIONS') {
|
|
50
|
+
res.writeHead(204);
|
|
51
|
+
res.end();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (req.method === 'GET') {
|
|
55
|
+
if (req.url === '/api/folders') {
|
|
56
|
+
try {
|
|
57
|
+
if (!fs.existsSync(KB_ROOT)) {
|
|
58
|
+
fs.mkdirSync(KB_ROOT, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
const entries = fs.readdirSync(KB_ROOT, { withFileTypes: true });
|
|
61
|
+
// Filter directories
|
|
62
|
+
const folders = entries
|
|
63
|
+
.filter(dirent => dirent.isDirectory())
|
|
64
|
+
.map(dirent => dirent.name);
|
|
65
|
+
// Also enable "All" option effectively by logic, but here we just list folders.
|
|
66
|
+
// The frontend can add an "All" option.
|
|
67
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
68
|
+
res.end(JSON.stringify({ folders }));
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error(error);
|
|
72
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
73
|
+
res.end(JSON.stringify({ error: String(error) }));
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Serve Static Files
|
|
78
|
+
let urlPath = req.url === '/' ? 'index.html' : req.url;
|
|
79
|
+
// Security check: prevent traversing up
|
|
80
|
+
const safeSuffix = path.normalize(urlPath).replace(/^(\.\.[/\\])+/, '');
|
|
81
|
+
let filePath = path.join(FRONTEND_DIR, safeSuffix);
|
|
82
|
+
const extname = path.extname(filePath);
|
|
83
|
+
let contentType = 'text/html';
|
|
84
|
+
switch (extname) {
|
|
85
|
+
case '.js':
|
|
86
|
+
contentType = 'text/javascript';
|
|
87
|
+
break;
|
|
88
|
+
case '.css':
|
|
89
|
+
contentType = 'text/css';
|
|
90
|
+
break;
|
|
91
|
+
case '.json':
|
|
92
|
+
contentType = 'application/json';
|
|
93
|
+
break;
|
|
94
|
+
case '.png':
|
|
95
|
+
contentType = 'image/png';
|
|
96
|
+
break;
|
|
97
|
+
case '.jpg':
|
|
98
|
+
contentType = 'image/jpeg';
|
|
99
|
+
break;
|
|
100
|
+
case '.svg':
|
|
101
|
+
contentType = 'image/svg+xml';
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
fs.readFile(filePath, (error, content) => {
|
|
105
|
+
if (error) {
|
|
106
|
+
if (error.code == 'ENOENT') {
|
|
107
|
+
res.writeHead(404);
|
|
108
|
+
res.end('File not found');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
res.writeHead(500);
|
|
112
|
+
res.end('Server Error: ' + error.code);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
117
|
+
res.end(content, 'utf-8');
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else if (req.method === 'POST') {
|
|
122
|
+
if (req.url === '/api/build') {
|
|
123
|
+
let body = '';
|
|
124
|
+
req.on('data', chunk => { body += chunk.toString(); });
|
|
125
|
+
req.on('end', async () => {
|
|
126
|
+
try {
|
|
127
|
+
const { target } = JSON.parse(body);
|
|
128
|
+
console.log('Received build request for:', target);
|
|
129
|
+
// If target is "ALL_FOLDERS", pass empty string or specific flag to buildGraph?
|
|
130
|
+
// buildGraph handles empty/undefined as "Knowledge_Base" root scan (recursive).
|
|
131
|
+
// So if target is "", it scans everything under Knowledge_Base.
|
|
132
|
+
const buildTarget = target === 'ALL_FOLDERS' ? '' : target;
|
|
133
|
+
await (0, index_1.buildGraph)(buildTarget);
|
|
134
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
135
|
+
res.end(JSON.stringify({ success: true }));
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
console.error(error);
|
|
139
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
140
|
+
res.end(JSON.stringify({ success: false, error: String(error) }));
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
server.listen(PORT, () => {
|
|
147
|
+
console.log(`Server running at http://localhost:${PORT}/`);
|
|
148
|
+
console.log(`Knowledge Base Root: ${KB_ROOT}`);
|
|
149
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "noteconnection",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Hierarchical Knowledge Graph Visualization System",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"noteconnection": "dist/server.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "ts-node src/server.ts",
|
|
11
|
+
"start:prod": "node dist/server.js",
|
|
12
|
+
"build": "tsc && node scripts/copy-assets.js",
|
|
13
|
+
"prepublishOnly": "npm run build",
|
|
14
|
+
"test": "jest"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"knowledge-graph",
|
|
23
|
+
"visualization",
|
|
24
|
+
"markdown",
|
|
25
|
+
"dag",
|
|
26
|
+
"hierarchical"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"type": "commonjs",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/jest": "^30.0.0",
|
|
33
|
+
"@types/node": "^25.0.3",
|
|
34
|
+
"jest": "^30.2.0",
|
|
35
|
+
"ts-jest": "^29.4.6",
|
|
36
|
+
"ts-node": "^10.9.2",
|
|
37
|
+
"typescript": "^5.9.3"
|
|
38
|
+
}
|
|
39
|
+
}
|