concept-atlas-dense-explain 0.2.0 → 0.2.2

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.
@@ -1 +1 @@
1
- export * from './MDXComponents.jsx';
1
+ export * from './MDXComponents.jsx';
@@ -1,16 +1,16 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom/client';
3
- import { App } from './app/App.jsx';
4
- import * as Components from './components/index.js';
5
- import CompileRuntimeDoc from '../content/compile-runtime.mdx';
6
-
7
- // Mount MDX application to DOM
8
- const rootElement = document.getElementById('root') || document.getElementById('app');
9
- if (rootElement) {
10
- const root = ReactDOM.createRoot(rootElement);
11
- root.render(
12
- <React.StrictMode>
13
- <App mdxContent={<CompileRuntimeDoc components={Components} />} />
14
- </React.StrictMode>
15
- );
16
- }
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import { App } from './app/App.jsx';
4
+ import * as Components from './components/index.js';
5
+ import CompileRuntimeDoc from '../content/compile-runtime.mdx';
6
+
7
+ // Mount MDX application to DOM
8
+ const rootElement = document.getElementById('root') || document.getElementById('app');
9
+ if (rootElement) {
10
+ const root = ReactDOM.createRoot(rootElement);
11
+ root.render(
12
+ <React.StrictMode>
13
+ <App mdxContent={<CompileRuntimeDoc components={Components} />} />
14
+ </React.StrictMode>
15
+ );
16
+ }
@@ -1,169 +1,169 @@
1
- import React from 'react';
2
- import { RELATION_TYPES, LEVEL_DEFS } from './relation-types.js';
3
-
4
- /**
5
- * Creates an empty Concept Knowledge Graph structure
6
- */
7
- export function createConceptGraphState() {
8
- return {
9
- meta: {
10
- id: '',
11
- title: '',
12
- summary: '',
13
- rootId: ''
14
- },
15
- nodes: new Map(), // id -> NodeObject
16
- relations: [], // Array<{ from, to, type, label, description }>
17
- };
18
- }
19
-
20
- /**
21
- * Normalizes raw node data extracted from MDX AST or React component tree
22
- */
23
- export function normalizeNode(raw) {
24
- const id = raw.id || String(Math.random());
25
- return {
26
- id,
27
- title: raw.title || id,
28
- level: raw.level || 'L2',
29
- parent: raw.parent || null,
30
- children: Array.isArray(raw.children) ? raw.children : [],
31
-
32
- // Semantic Content Sections
33
- summary: raw.summary || '',
34
- overview: raw.overview || null,
35
- definition: raw.definition || null,
36
- mechanism: raw.mechanism || null,
37
- input: raw.input || null,
38
- output: raw.output || null,
39
- prerequisites: raw.prerequisites || [],
40
- implementation: raw.implementation || null, // { language, code } or React node
41
- examples: raw.examples || [],
42
- counterexamples: raw.counterexamples || [],
43
- boundaries: raw.boundaries || [],
44
- glossary: raw.glossary || [],
45
- customSections: raw.customSections || [],
46
- };
47
- }
48
-
49
- /**
50
- * Validates and indexes nodes and relations to build a graph model
51
- */
52
- export function buildGraphModel(rawGraph) {
53
- const nodes = new Map();
54
- const diagnostics = [];
55
- const rawNodes = rawGraph.nodes || [];
56
- const rawRelations = rawGraph.relations || [];
57
-
58
- // Register all nodes
59
- rawNodes.forEach(n => {
60
- const node = normalizeNode(n);
61
- if (nodes.has(node.id)) diagnostics.push({ level: 'error', code: 'DUPLICATE_NODE_ID', nodeId: node.id });
62
- nodes.set(node.id, node);
63
- });
64
-
65
- // Build tree hierarchy: ensure parent <-> children consistency
66
- nodes.forEach(node => {
67
- if (node.parent && nodes.has(node.parent)) {
68
- const parentNode = nodes.get(node.parent);
69
- if (!parentNode.children.includes(node.id)) {
70
- parentNode.children.push(node.id);
71
- }
72
- }
73
- });
74
-
75
- // Explicit children references (from <ConceptRef />)
76
- nodes.forEach(node => {
77
- node.children.forEach(childId => {
78
- if (nodes.has(childId)) {
79
- const childNode = nodes.get(childId);
80
- if (!childNode.parent) {
81
- childNode.parent = node.id;
82
- }
83
- }
84
- else diagnostics.push({ level: 'warning', code: 'MISSING_CHILD', nodeId: node.id, targetId: childId });
85
- });
86
- if (node.parent && !nodes.has(node.parent)) diagnostics.push({ level: 'warning', code: 'ORPHAN_NODE', nodeId: node.id, targetId: node.parent });
87
- if (!LEVEL_DEFS[node.level]) diagnostics.push({ level: 'warning', code: 'UNKNOWN_LEVEL', nodeId: node.id, level: node.level });
88
- });
89
-
90
- // Filter valid relations
91
- const validRelations = [];
92
- rawRelations.forEach(rel => {
93
- if (nodes.has(rel.from) && nodes.has(rel.to)) {
94
- const typeDef = RELATION_TYPES[rel.type] || {
95
- label: rel.type,
96
- color: '#94a3b8',
97
- hasArrow: true
98
- };
99
- validRelations.push({
100
- ...rel,
101
- typeLabel: rel.label || typeDef.label,
102
- typeInfo: typeDef
103
- });
104
- }
105
- });
106
-
107
- // Determine root
108
- let rootId = rawGraph.meta?.rootId;
109
- if (!rootId || !nodes.has(rootId)) {
110
- // Find node with no parent or level L0
111
- for (const [id, node] of nodes.entries()) {
112
- if (!node.parent || node.level === 'L0') {
113
- rootId = id;
114
- break;
115
- }
116
- }
117
- }
118
-
119
- return {
120
- meta: {
121
- ...rawGraph.meta,
122
- rootId: rootId || (nodes.size > 0 ? Array.from(nodes.keys())[0] : null)
123
- },
124
- nodes,
125
- relations: validRelations,
126
- diagnostics
127
- };
128
- }
129
-
130
- /**
131
- * Helper to compute ancestor path from root to current node
132
- */
133
- export function getAncestorPath(nodes, nodeId) {
134
- const path = [];
135
- let current = nodes.get(nodeId);
136
- const visited = new Set();
137
- while (current && !visited.has(current.id)) {
138
- visited.add(current.id);
139
- path.unshift(current);
140
- if (!current.parent) break;
141
- current = nodes.get(current.parent);
142
- }
143
- return path;
144
- }
145
-
146
- /**
147
- * Helper to get siblings of a node
148
- */
149
- export function getSiblingNodes(nodes, nodeId) {
150
- const current = nodes.get(nodeId);
151
- if (!current || !current.parent) {
152
- // If root or has no parent, find other root nodes
153
- return Array.from(nodes.values()).filter(n => !n.parent && n.id !== nodeId);
154
- }
155
- const parent = nodes.get(current.parent);
156
- if (!parent) return [];
157
- return parent.children
158
- .filter(id => id !== nodeId && nodes.has(id))
159
- .map(id => nodes.get(id));
160
- }
161
-
162
- /**
163
- * Helper to get all incoming and outgoing relations for a node
164
- */
165
- export function getNodeRelations(relations, nodeId) {
166
- const incoming = relations.filter(r => r.to === nodeId);
167
- const outgoing = relations.filter(r => r.from === nodeId);
168
- return { incoming, outgoing };
169
- }
1
+ import React from 'react';
2
+ import { RELATION_TYPES, LEVEL_DEFS } from './relation-types.js';
3
+
4
+ /**
5
+ * Creates an empty Concept Knowledge Graph structure
6
+ */
7
+ export function createConceptGraphState() {
8
+ return {
9
+ meta: {
10
+ id: '',
11
+ title: '',
12
+ summary: '',
13
+ rootId: ''
14
+ },
15
+ nodes: new Map(), // id -> NodeObject
16
+ relations: [], // Array<{ from, to, type, label, description }>
17
+ };
18
+ }
19
+
20
+ /**
21
+ * Normalizes raw node data extracted from MDX AST or React component tree
22
+ */
23
+ export function normalizeNode(raw) {
24
+ const id = raw.id || String(Math.random());
25
+ return {
26
+ id,
27
+ title: raw.title || id,
28
+ level: raw.level || 'L2',
29
+ parent: raw.parent || null,
30
+ children: Array.isArray(raw.children) ? raw.children : [],
31
+
32
+ // Semantic Content Sections
33
+ summary: raw.summary || '',
34
+ overview: raw.overview || null,
35
+ definition: raw.definition || null,
36
+ mechanism: raw.mechanism || null,
37
+ input: raw.input || null,
38
+ output: raw.output || null,
39
+ prerequisites: raw.prerequisites || [],
40
+ implementation: raw.implementation || null, // { language, code } or React node
41
+ examples: raw.examples || [],
42
+ counterexamples: raw.counterexamples || [],
43
+ boundaries: raw.boundaries || [],
44
+ glossary: raw.glossary || [],
45
+ customSections: raw.customSections || [],
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Validates and indexes nodes and relations to build a graph model
51
+ */
52
+ export function buildGraphModel(rawGraph) {
53
+ const nodes = new Map();
54
+ const diagnostics = [];
55
+ const rawNodes = rawGraph.nodes || [];
56
+ const rawRelations = rawGraph.relations || [];
57
+
58
+ // Register all nodes
59
+ rawNodes.forEach(n => {
60
+ const node = normalizeNode(n);
61
+ if (nodes.has(node.id)) diagnostics.push({ level: 'error', code: 'DUPLICATE_NODE_ID', nodeId: node.id });
62
+ nodes.set(node.id, node);
63
+ });
64
+
65
+ // Build tree hierarchy: ensure parent <-> children consistency
66
+ nodes.forEach(node => {
67
+ if (node.parent && nodes.has(node.parent)) {
68
+ const parentNode = nodes.get(node.parent);
69
+ if (!parentNode.children.includes(node.id)) {
70
+ parentNode.children.push(node.id);
71
+ }
72
+ }
73
+ });
74
+
75
+ // Explicit children references (from <ConceptRef />)
76
+ nodes.forEach(node => {
77
+ node.children.forEach(childId => {
78
+ if (nodes.has(childId)) {
79
+ const childNode = nodes.get(childId);
80
+ if (!childNode.parent) {
81
+ childNode.parent = node.id;
82
+ }
83
+ }
84
+ else diagnostics.push({ level: 'warning', code: 'MISSING_CHILD', nodeId: node.id, targetId: childId });
85
+ });
86
+ if (node.parent && !nodes.has(node.parent)) diagnostics.push({ level: 'warning', code: 'ORPHAN_NODE', nodeId: node.id, targetId: node.parent });
87
+ if (!LEVEL_DEFS[node.level]) diagnostics.push({ level: 'warning', code: 'UNKNOWN_LEVEL', nodeId: node.id, level: node.level });
88
+ });
89
+
90
+ // Filter valid relations
91
+ const validRelations = [];
92
+ rawRelations.forEach(rel => {
93
+ if (nodes.has(rel.from) && nodes.has(rel.to)) {
94
+ const typeDef = RELATION_TYPES[rel.type] || {
95
+ label: rel.type,
96
+ color: '#94a3b8',
97
+ hasArrow: true
98
+ };
99
+ validRelations.push({
100
+ ...rel,
101
+ typeLabel: rel.label || typeDef.label,
102
+ typeInfo: typeDef
103
+ });
104
+ }
105
+ });
106
+
107
+ // Determine root
108
+ let rootId = rawGraph.meta?.rootId;
109
+ if (!rootId || !nodes.has(rootId)) {
110
+ // Find node with no parent or level L0
111
+ for (const [id, node] of nodes.entries()) {
112
+ if (!node.parent || node.level === 'L0') {
113
+ rootId = id;
114
+ break;
115
+ }
116
+ }
117
+ }
118
+
119
+ return {
120
+ meta: {
121
+ ...rawGraph.meta,
122
+ rootId: rootId || (nodes.size > 0 ? Array.from(nodes.keys())[0] : null)
123
+ },
124
+ nodes,
125
+ relations: validRelations,
126
+ diagnostics
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Helper to compute ancestor path from root to current node
132
+ */
133
+ export function getAncestorPath(nodes, nodeId) {
134
+ const path = [];
135
+ let current = nodes.get(nodeId);
136
+ const visited = new Set();
137
+ while (current && !visited.has(current.id)) {
138
+ visited.add(current.id);
139
+ path.unshift(current);
140
+ if (!current.parent) break;
141
+ current = nodes.get(current.parent);
142
+ }
143
+ return path;
144
+ }
145
+
146
+ /**
147
+ * Helper to get siblings of a node
148
+ */
149
+ export function getSiblingNodes(nodes, nodeId) {
150
+ const current = nodes.get(nodeId);
151
+ if (!current || !current.parent) {
152
+ // If root or has no parent, find other root nodes
153
+ return Array.from(nodes.values()).filter(n => !n.parent && n.id !== nodeId);
154
+ }
155
+ const parent = nodes.get(current.parent);
156
+ if (!parent) return [];
157
+ return parent.children
158
+ .filter(id => id !== nodeId && nodes.has(id))
159
+ .map(id => nodes.get(id));
160
+ }
161
+
162
+ /**
163
+ * Helper to get all incoming and outgoing relations for a node
164
+ */
165
+ export function getNodeRelations(relations, nodeId) {
166
+ const incoming = relations.filter(r => r.to === nodeId);
167
+ const outgoing = relations.filter(r => r.from === nodeId);
168
+ return { incoming, outgoing };
169
+ }