ontoink 0.1.0__tar.gz

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.
ontoink-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FIZ Karlsruhe - Leibniz Institute for Information Infrastructure
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ontoink-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.4
2
+ Name: ontoink
3
+ Version: 0.1.0
4
+ Summary: Interactive ontology visualization, SHACL validation, and live TTL editing plugin for MkDocs
5
+ Author-email: Ebrahim Norouzi <ebrahim.norouzi@fiz-karlsruhe.de>
6
+ Maintainer-email: Ebrahim Norouzi <ebrahim.norouzi@fiz-karlsruhe.de>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/ISE-FIZKarlsruhe/ontoink
9
+ Project-URL: Documentation, https://ise-fizkarlsruhe.github.io/ontoink/
10
+ Project-URL: Repository, https://github.com/ISE-FIZKarlsruhe/ontoink
11
+ Project-URL: Issues, https://github.com/ISE-FIZKarlsruhe/ontoink/issues
12
+ Keywords: mkdocs,ontology,visualization,shacl,rdf,turtle,cytoscape,linked-data,semantic-web,nfdi
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Documentation
23
+ Classifier: Topic :: Scientific/Engineering
24
+ Classifier: Topic :: Software Development :: Documentation
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: mkdocs>=1.4
29
+ Requires-Dist: rdflib>=6.0
30
+ Requires-Dist: pyshacl>=0.25.0
31
+ Requires-Dist: pymdown-extensions>=10.0
32
+ Requires-Dist: pyyaml>=6.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.0; extra == "dev"
35
+ Requires-Dist: pytest-cov; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # ontoink
39
+
40
+ **Interactive ontology visualization, SHACL validation, and live TTL editing for MkDocs.**
41
+
42
+ [![CI](https://github.com/ISE-FIZKarlsruhe/ontoink/actions/workflows/ci.yml/badge.svg)](https://github.com/ISE-FIZKarlsruhe/ontoink/actions/workflows/ci.yml)
43
+ [![PyPI](https://img.shields.io/pypi/v/ontoink)](https://pypi.org/project/ontoink/)
44
+ [![Python](https://img.shields.io/pypi/pyversions/ontoink)](https://pypi.org/project/ontoink/)
45
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
46
+
47
+ ontoink is a MkDocs plugin that transforms RDF/Turtle files into interactive, publication-ready ontology diagrams with SHACL constraint visualization. Write a simple code block in your markdown, and ontoink generates a fully interactive graph.
48
+
49
+ **[Live Demo](https://ise-fizkarlsruhe.github.io/ontoink/)**
50
+
51
+ ## Features
52
+
53
+ ### Interactive Graph Visualization
54
+ - Formal ontology notation with distinct shapes per element type
55
+ - Hierarchical layout (dagre) optimized for ontology patterns
56
+ - Pan, zoom, fullscreen support
57
+ - Color-coded by ontology source (BFO, IAO, FOAF, Schema.org, etc.)
58
+
59
+ ### Visual Notation
60
+
61
+ | Element | Shape | Default Color |
62
+ |---------|-------|---------------|
63
+ | Class | Rectangle (solid border) | By ontology source |
64
+ | Individual | Ellipse | `#E6E6E6` |
65
+ | Literal | Ellipse (dashed border) | `#93D053` |
66
+ | Object Property | Blue solid line, filled arrow | `#2563eb` |
67
+ | Data Property | Green line, hollow arrow | `#16a34a` |
68
+ | rdf:type | Grey dashed line | `#9ca3af` |
69
+ | rdfs:subClassOf | Black solid line | `#374151` |
70
+ | SHACL Constraint | Cyan dashed bold line | `#0891b2` |
71
+
72
+ ### Click Popups
73
+ - Node label, type badge, full IRI (clickable)
74
+ - Copy Label / Copy IRI buttons
75
+ - Ontology source indicator
76
+ - Connected edges (incoming/outgoing)
77
+ - SHACL constraints applicable to the node
78
+
79
+ ### SHACL Constraint Overlay
80
+ - Constraints shown as bold dashed cyan edges with cardinality badges `[1..*]`
81
+ - Build-time validation using pySHACL
82
+ - Violations highlighted in the validation panel
83
+
84
+ ### Inline TTL Editor + Live Validation
85
+ - Expandable editor panel below each diagram
86
+ - CodeMirror with Turtle syntax highlighting
87
+ - Edit TTL data and validate against SHACL shapes in real-time
88
+ - Update the graph live from edited TTL
89
+ - Reset to original data
90
+
91
+ ### Export Preview + Publication-Ready Output
92
+ - **PNG export** — clicking PNG/SVG opens a preview dialog showing the final image
93
+ - Toggle options: include/exclude legend and namespace prefixes
94
+ - High-DPI (3x scale) with white background
95
+ - Legend rendered in a clean rounded box with proper shape icons and edge arrows
96
+ - Namespace prefixes shown as compact tags below the legend
97
+ - **SVG export** — vector graphics for papers and presentations
98
+ - **TTL download** — download the current (possibly edited) TTL data
99
+
100
+ ### Color Customization
101
+ - **Colors** button in the toolbar opens a color settings panel
102
+ - Change colors per node type (Class, Individual, Literal)
103
+ - Change colors per namespace (all BFO nodes, all FOAF nodes, etc.)
104
+ - Changes apply live to the graph and are reflected in exports
105
+
106
+ ### Smart Namespace Legend
107
+ - Only active prefixes (used in the graph) shown by default
108
+ - "Show all" toggle reveals all declared prefixes
109
+ - Unused prefixes shown dimmed
110
+ - Prefixes displayed as compact styled tags, separated from the main legend
111
+
112
+ ## Installation
113
+
114
+ ```bash
115
+ pip install ontoink
116
+ ```
117
+
118
+ Or install from source:
119
+
120
+ ```bash
121
+ pip install git+https://github.com/ISE-FIZKarlsruhe/ontoink.git
122
+ ```
123
+
124
+ ## Usage
125
+
126
+ ### 1. Add to mkdocs.yml
127
+
128
+ ```yaml
129
+ plugins:
130
+ - search
131
+ - ontoink
132
+
133
+ markdown_extensions:
134
+ - pymdownx.superfences:
135
+ preserve_tabs: true
136
+ ```
137
+
138
+ ### 2. Write ontoink blocks in markdown
139
+
140
+ ````markdown
141
+ ```ontoink
142
+ source: path/to/instance-data.ttl
143
+ shape: path/to/shacl-shape.ttl
144
+ ```
145
+ ````
146
+
147
+ ### 3. Build or serve
148
+
149
+ ```bash
150
+ mkdocs serve
151
+ ```
152
+
153
+ ### Configuration Options
154
+
155
+ | Option | Default | Description |
156
+ |--------|---------|-------------|
157
+ | `source` | (required) | Path to TTL data file (relative to docs/) |
158
+ | `shape` | (optional) | Path to SHACL shape file |
159
+ | `height` | `500px` | Height of the graph canvas |
160
+ | `editor` | `true` | Show the "Edit & Validate" button |
161
+ | `legend` | `true` | Show the legend panel |
162
+ | `namespaces` | `true` | Show namespace prefixes |
163
+
164
+ ### Full example
165
+
166
+ ````markdown
167
+ ```ontoink
168
+ source: shapes/foaf-person/shape-data.ttl
169
+ shape: shapes/foaf-person/shape.ttl
170
+ height: 600px
171
+ editor: true
172
+ legend: true
173
+ namespaces: true
174
+ ```
175
+ ````
176
+
177
+ ## How It Works
178
+
179
+ 1. **Build time (Python):** The plugin parses your TTL files with rdflib, classifies nodes (Class/Individual/Literal), resolves labels, detects ontology sources for color coding, extracts SHACL constraints, and runs pySHACL validation. The result is serialized as JSON and embedded in the HTML.
180
+
181
+ 2. **Browser (JavaScript):** Cytoscape.js renders the graph with dagre layout. CodeMirror provides the TTL editor. A lightweight JavaScript SHACL checker enables live validation without server round-trips.
182
+
183
+ ## Development
184
+
185
+ ```bash
186
+ git clone https://github.com/ISE-FIZKarlsruhe/ontoink.git
187
+ cd ontoink
188
+ pip install -e ".[dev]"
189
+ pytest -v
190
+ ```
191
+
192
+ ### Demo site
193
+
194
+ ```bash
195
+ cd demo
196
+ mkdocs serve
197
+ ```
198
+
199
+ ## Requirements
200
+
201
+ - Python >= 3.9
202
+ - MkDocs >= 1.4
203
+ - rdflib >= 6.0
204
+ - pySHACL >= 0.25.0
205
+ - pymdown-extensions >= 10.0
206
+
207
+ Browser-side dependencies are loaded from CDN (no npm/bundling needed):
208
+ - Cytoscape.js, cytoscape-dagre, cytoscape-svg
209
+ - CodeMirror 5 with Turtle mode
210
+
211
+ ## Contributing
212
+
213
+ Contributions are welcome. Please open an issue first to discuss proposed changes.
214
+
215
+ 1. Fork the repository
216
+ 2. Create a feature branch
217
+ 3. Add tests for new functionality
218
+ 4. Ensure `pytest` passes
219
+ 5. Submit a pull request
220
+
221
+ ## License
222
+
223
+ MIT License. See [LICENSE](LICENSE).
224
+
225
+ ## Author
226
+
227
+ [Ebrahim Norouzi](https://ebrahimnorouzi.github.io/) — [FIZ Karlsruhe](https://www.fiz-karlsruhe.de/), [ISE](https://www.fiz-karlsruhe.de/en/forschung/information-service-engineering)
228
+
229
+ ## Acknowledgments
230
+
231
+ - Developed in the context of [NFDI](https://www.nfdi.de/) and [NFDI-MatWerk](https://nfdi-matwerk.de/)
232
+ - Visual notation inspired by ontology diagramming best practices and formal OWL notation
233
+ - Interactive visualization powered by [Cytoscape.js](https://js.cytoscape.org/)
@@ -0,0 +1,196 @@
1
+ # ontoink
2
+
3
+ **Interactive ontology visualization, SHACL validation, and live TTL editing for MkDocs.**
4
+
5
+ [![CI](https://github.com/ISE-FIZKarlsruhe/ontoink/actions/workflows/ci.yml/badge.svg)](https://github.com/ISE-FIZKarlsruhe/ontoink/actions/workflows/ci.yml)
6
+ [![PyPI](https://img.shields.io/pypi/v/ontoink)](https://pypi.org/project/ontoink/)
7
+ [![Python](https://img.shields.io/pypi/pyversions/ontoink)](https://pypi.org/project/ontoink/)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
+
10
+ ontoink is a MkDocs plugin that transforms RDF/Turtle files into interactive, publication-ready ontology diagrams with SHACL constraint visualization. Write a simple code block in your markdown, and ontoink generates a fully interactive graph.
11
+
12
+ **[Live Demo](https://ise-fizkarlsruhe.github.io/ontoink/)**
13
+
14
+ ## Features
15
+
16
+ ### Interactive Graph Visualization
17
+ - Formal ontology notation with distinct shapes per element type
18
+ - Hierarchical layout (dagre) optimized for ontology patterns
19
+ - Pan, zoom, fullscreen support
20
+ - Color-coded by ontology source (BFO, IAO, FOAF, Schema.org, etc.)
21
+
22
+ ### Visual Notation
23
+
24
+ | Element | Shape | Default Color |
25
+ |---------|-------|---------------|
26
+ | Class | Rectangle (solid border) | By ontology source |
27
+ | Individual | Ellipse | `#E6E6E6` |
28
+ | Literal | Ellipse (dashed border) | `#93D053` |
29
+ | Object Property | Blue solid line, filled arrow | `#2563eb` |
30
+ | Data Property | Green line, hollow arrow | `#16a34a` |
31
+ | rdf:type | Grey dashed line | `#9ca3af` |
32
+ | rdfs:subClassOf | Black solid line | `#374151` |
33
+ | SHACL Constraint | Cyan dashed bold line | `#0891b2` |
34
+
35
+ ### Click Popups
36
+ - Node label, type badge, full IRI (clickable)
37
+ - Copy Label / Copy IRI buttons
38
+ - Ontology source indicator
39
+ - Connected edges (incoming/outgoing)
40
+ - SHACL constraints applicable to the node
41
+
42
+ ### SHACL Constraint Overlay
43
+ - Constraints shown as bold dashed cyan edges with cardinality badges `[1..*]`
44
+ - Build-time validation using pySHACL
45
+ - Violations highlighted in the validation panel
46
+
47
+ ### Inline TTL Editor + Live Validation
48
+ - Expandable editor panel below each diagram
49
+ - CodeMirror with Turtle syntax highlighting
50
+ - Edit TTL data and validate against SHACL shapes in real-time
51
+ - Update the graph live from edited TTL
52
+ - Reset to original data
53
+
54
+ ### Export Preview + Publication-Ready Output
55
+ - **PNG export** — clicking PNG/SVG opens a preview dialog showing the final image
56
+ - Toggle options: include/exclude legend and namespace prefixes
57
+ - High-DPI (3x scale) with white background
58
+ - Legend rendered in a clean rounded box with proper shape icons and edge arrows
59
+ - Namespace prefixes shown as compact tags below the legend
60
+ - **SVG export** — vector graphics for papers and presentations
61
+ - **TTL download** — download the current (possibly edited) TTL data
62
+
63
+ ### Color Customization
64
+ - **Colors** button in the toolbar opens a color settings panel
65
+ - Change colors per node type (Class, Individual, Literal)
66
+ - Change colors per namespace (all BFO nodes, all FOAF nodes, etc.)
67
+ - Changes apply live to the graph and are reflected in exports
68
+
69
+ ### Smart Namespace Legend
70
+ - Only active prefixes (used in the graph) shown by default
71
+ - "Show all" toggle reveals all declared prefixes
72
+ - Unused prefixes shown dimmed
73
+ - Prefixes displayed as compact styled tags, separated from the main legend
74
+
75
+ ## Installation
76
+
77
+ ```bash
78
+ pip install ontoink
79
+ ```
80
+
81
+ Or install from source:
82
+
83
+ ```bash
84
+ pip install git+https://github.com/ISE-FIZKarlsruhe/ontoink.git
85
+ ```
86
+
87
+ ## Usage
88
+
89
+ ### 1. Add to mkdocs.yml
90
+
91
+ ```yaml
92
+ plugins:
93
+ - search
94
+ - ontoink
95
+
96
+ markdown_extensions:
97
+ - pymdownx.superfences:
98
+ preserve_tabs: true
99
+ ```
100
+
101
+ ### 2. Write ontoink blocks in markdown
102
+
103
+ ````markdown
104
+ ```ontoink
105
+ source: path/to/instance-data.ttl
106
+ shape: path/to/shacl-shape.ttl
107
+ ```
108
+ ````
109
+
110
+ ### 3. Build or serve
111
+
112
+ ```bash
113
+ mkdocs serve
114
+ ```
115
+
116
+ ### Configuration Options
117
+
118
+ | Option | Default | Description |
119
+ |--------|---------|-------------|
120
+ | `source` | (required) | Path to TTL data file (relative to docs/) |
121
+ | `shape` | (optional) | Path to SHACL shape file |
122
+ | `height` | `500px` | Height of the graph canvas |
123
+ | `editor` | `true` | Show the "Edit & Validate" button |
124
+ | `legend` | `true` | Show the legend panel |
125
+ | `namespaces` | `true` | Show namespace prefixes |
126
+
127
+ ### Full example
128
+
129
+ ````markdown
130
+ ```ontoink
131
+ source: shapes/foaf-person/shape-data.ttl
132
+ shape: shapes/foaf-person/shape.ttl
133
+ height: 600px
134
+ editor: true
135
+ legend: true
136
+ namespaces: true
137
+ ```
138
+ ````
139
+
140
+ ## How It Works
141
+
142
+ 1. **Build time (Python):** The plugin parses your TTL files with rdflib, classifies nodes (Class/Individual/Literal), resolves labels, detects ontology sources for color coding, extracts SHACL constraints, and runs pySHACL validation. The result is serialized as JSON and embedded in the HTML.
143
+
144
+ 2. **Browser (JavaScript):** Cytoscape.js renders the graph with dagre layout. CodeMirror provides the TTL editor. A lightweight JavaScript SHACL checker enables live validation without server round-trips.
145
+
146
+ ## Development
147
+
148
+ ```bash
149
+ git clone https://github.com/ISE-FIZKarlsruhe/ontoink.git
150
+ cd ontoink
151
+ pip install -e ".[dev]"
152
+ pytest -v
153
+ ```
154
+
155
+ ### Demo site
156
+
157
+ ```bash
158
+ cd demo
159
+ mkdocs serve
160
+ ```
161
+
162
+ ## Requirements
163
+
164
+ - Python >= 3.9
165
+ - MkDocs >= 1.4
166
+ - rdflib >= 6.0
167
+ - pySHACL >= 0.25.0
168
+ - pymdown-extensions >= 10.0
169
+
170
+ Browser-side dependencies are loaded from CDN (no npm/bundling needed):
171
+ - Cytoscape.js, cytoscape-dagre, cytoscape-svg
172
+ - CodeMirror 5 with Turtle mode
173
+
174
+ ## Contributing
175
+
176
+ Contributions are welcome. Please open an issue first to discuss proposed changes.
177
+
178
+ 1. Fork the repository
179
+ 2. Create a feature branch
180
+ 3. Add tests for new functionality
181
+ 4. Ensure `pytest` passes
182
+ 5. Submit a pull request
183
+
184
+ ## License
185
+
186
+ MIT License. See [LICENSE](LICENSE).
187
+
188
+ ## Author
189
+
190
+ [Ebrahim Norouzi](https://ebrahimnorouzi.github.io/) — [FIZ Karlsruhe](https://www.fiz-karlsruhe.de/), [ISE](https://www.fiz-karlsruhe.de/en/forschung/information-service-engineering)
191
+
192
+ ## Acknowledgments
193
+
194
+ - Developed in the context of [NFDI](https://www.nfdi.de/) and [NFDI-MatWerk](https://nfdi-matwerk.de/)
195
+ - Visual notation inspired by ontology diagramming best practices and formal OWL notation
196
+ - Interactive visualization powered by [Cytoscape.js](https://js.cytoscape.org/)
@@ -0,0 +1,3 @@
1
+ """ontoink - Interactive ontology visualization and SHACL validation for MkDocs."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,126 @@
1
+ """Custom fence handler for ```ontoink code blocks."""
2
+
3
+ import base64
4
+ import json
5
+ import os
6
+ import traceback
7
+
8
+ import yaml
9
+
10
+ from .ttl_parser import parse_ttl_to_cytoscape
11
+ from .shacl_validator import validate_graph
12
+
13
+ _graph_counter = 0
14
+
15
+
16
+ def reset_counter():
17
+ global _graph_counter
18
+ _graph_counter = 0
19
+
20
+
21
+ def render_ontoink(source, language, class_name, options, md, **kwargs):
22
+ """
23
+ Custom fence handler called by pymdownx.superfences.
24
+
25
+ Source block YAML:
26
+ source: shapes/role-bearer/shape-data.ttl
27
+ shape: shapes/role-bearer/shape.ttl
28
+ height: 500px # optional, default 500px
29
+ editor: true # optional, default true
30
+ legend: true # optional, default true
31
+ namespaces: true # optional, default true
32
+ """
33
+ global _graph_counter
34
+ graph_id = f"ontoink-graph-{_graph_counter}"
35
+ _graph_counter += 1
36
+
37
+ try:
38
+ config = yaml.safe_load(source)
39
+ docs_dir = getattr(render_ontoink, "docs_dir", ".")
40
+
41
+ data_path = os.path.join(docs_dir, config["source"])
42
+ shape_path = ""
43
+ if "shape" in config:
44
+ shape_path = os.path.join(docs_dir, config["shape"])
45
+
46
+ # Parse TTL → Cytoscape JSON
47
+ cytoscape_data = parse_ttl_to_cytoscape(data_path, shape_path)
48
+
49
+ # Build-time SHACL validation
50
+ if shape_path:
51
+ try:
52
+ validation = validate_graph(data_path, shape_path)
53
+ cytoscape_data["validation"] = validation
54
+ except Exception:
55
+ cytoscape_data["validation"] = None
56
+ else:
57
+ cytoscape_data["validation"] = None
58
+
59
+ json_str = json.dumps(cytoscape_data, ensure_ascii=False)
60
+ b64_data = base64.b64encode(json_str.encode("utf-8")).decode("ascii")
61
+
62
+ height = config.get("height", "500px")
63
+ show_editor = str(config.get("editor", "true")).lower() == "true"
64
+ show_legend = str(config.get("legend", "true")).lower() == "true"
65
+ show_ns = str(config.get("namespaces", "true")).lower() == "true"
66
+
67
+ editor_btn = ""
68
+ if show_editor:
69
+ editor_btn = f'<button class="ov-btn ov-btn-accent" onclick="ontoink.toggleEditor(\'{graph_id}\')" title="Edit TTL & Validate">Edit &amp; Validate</button>\n'
70
+
71
+ return (
72
+ f'<div id="{graph_id}" class="ontoink-container" '
73
+ f'data-ontoink-graph="{b64_data}" '
74
+ f'data-show-legend="{str(show_legend).lower()}" '
75
+ f'data-show-ns="{str(show_ns).lower()}">\n'
76
+ f' <div class="ov-toolbar">\n'
77
+ f' <div class="ov-toolbar-group">\n'
78
+ f' <button class="ov-btn" onclick="ontoink.zoomIn(\'{graph_id}\')" title="Zoom in">+</button>\n'
79
+ f' <button class="ov-btn" onclick="ontoink.zoomOut(\'{graph_id}\')" title="Zoom out">&minus;</button>\n'
80
+ f' <button class="ov-btn" onclick="ontoink.fit(\'{graph_id}\')" title="Fit to view">Fit</button>\n'
81
+ f' <button class="ov-btn" onclick="ontoink.fullscreen(\'{graph_id}\')" title="Fullscreen">&#x26F6;</button>\n'
82
+ f' </div>\n'
83
+ f' <div class="ov-toolbar-group">\n'
84
+ f' <button class="ov-btn" onclick="ontoink.exportPNG(\'{graph_id}\')" title="Export PNG">PNG</button>\n'
85
+ f' <button class="ov-btn" onclick="ontoink.exportSVG(\'{graph_id}\')" title="Export SVG">SVG</button>\n'
86
+ f' <button class="ov-btn" onclick="ontoink.downloadTTL(\'{graph_id}\')" title="Download TTL">TTL</button>\n'
87
+ f' </div>\n'
88
+ f' <div class="ov-toolbar-group">\n'
89
+ f' <button class="ov-btn" onclick="ontoink.toggleColors(\'{graph_id}\')" title="Color settings">Colors</button>\n'
90
+ f' {editor_btn}'
91
+ f' </div>\n'
92
+ f' </div>\n'
93
+ f' <div class="ov-canvas-wrap" style="position:relative;width:100%;height:{height};">\n'
94
+ f' <div class="ov-canvas" style="width:100%;height:100%;"></div>\n'
95
+ f' <div class="ov-legend-overlay ov-draggable" style="bottom:12px;left:12px;"></div>\n'
96
+ f' <div class="ov-ns-overlay ov-draggable" style="bottom:12px;right:12px;"></div>\n'
97
+ f' </div>\n'
98
+ f' <div class="ov-editor-panel" style="display:none;">\n'
99
+ f' <div class="ov-editor-split">\n'
100
+ f' <div class="ov-editor-left">\n'
101
+ f' <div class="ov-editor-header">TTL Editor</div>\n'
102
+ f' <textarea class="ov-editor-textarea"></textarea>\n'
103
+ f' </div>\n'
104
+ f' <div class="ov-editor-right">\n'
105
+ f' <div class="ov-editor-header">Validation Results</div>\n'
106
+ f' <div class="ov-validation-output"></div>\n'
107
+ f' </div>\n'
108
+ f' </div>\n'
109
+ f' <div class="ov-editor-actions">\n'
110
+ f' <button class="ov-btn ov-btn-primary" onclick="ontoink.validate(\'{graph_id}\')">Validate</button>\n'
111
+ f' <button class="ov-btn" onclick="ontoink.updateGraph(\'{graph_id}\')">Update Graph</button>\n'
112
+ f' <button class="ov-btn" onclick="ontoink.resetEditor(\'{graph_id}\')">Reset</button>\n'
113
+ f' </div>\n'
114
+ f' </div>\n'
115
+ f'</div>\n'
116
+ )
117
+
118
+ except Exception as e:
119
+ tb = traceback.format_exc()
120
+ return (
121
+ f'<div class="ov-error">'
122
+ f'<strong>Error rendering ontoink:</strong><br>'
123
+ f'<code>{e}</code>'
124
+ f'<pre style="font-size:11px;overflow:auto;max-height:200px;">{tb}</pre>'
125
+ f'</div>'
126
+ )
@@ -0,0 +1,57 @@
1
+ """MkDocs plugin that registers the ontoink custom fence and injects assets."""
2
+
3
+ from pathlib import Path
4
+
5
+ from mkdocs.plugins import BasePlugin
6
+
7
+
8
+ class OntoinkPlugin(BasePlugin):
9
+
10
+ def on_config(self, config):
11
+ """Register the ontoink custom fence with pymdownx.superfences."""
12
+ from .fence import render_ontoink, reset_counter
13
+
14
+ reset_counter()
15
+ render_ontoink.docs_dir = config["docs_dir"]
16
+
17
+ fence_entry = {
18
+ "name": "ontoink",
19
+ "class": "ontoink",
20
+ "format": render_ontoink,
21
+ }
22
+
23
+ mdx_configs = config.setdefault("mdx_configs", {})
24
+ sf_key = "pymdownx.superfences"
25
+ if sf_key in mdx_configs:
26
+ mdx_configs[sf_key].setdefault("custom_fences", []).append(fence_entry)
27
+ else:
28
+ mdx_configs[sf_key] = {"custom_fences": [fence_entry]}
29
+
30
+ return config
31
+
32
+ def on_post_page(self, output, page, config):
33
+ """Inject CDN scripts and plugin JS/CSS into pages that use ontoink."""
34
+ if "data-ontoink-graph" not in output:
35
+ return output
36
+
37
+ resources_dir = Path(__file__).parent / "resources"
38
+ js_content = (resources_dir / "ontoink.js").read_text(encoding="utf-8")
39
+ css_content = (resources_dir / "ontoink.css").read_text(encoding="utf-8")
40
+
41
+ cdn_tags = "\n".join([
42
+ # Cytoscape.js core + dagre layout
43
+ '<script src="https://cdn.jsdelivr.net/npm/cytoscape@3.30.4/dist/cytoscape.min.js"></script>',
44
+ '<script src="https://cdn.jsdelivr.net/npm/dagre@0.8.5/dist/dagre.min.js"></script>',
45
+ '<script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre@2.5.0/cytoscape-dagre.js"></script>',
46
+ # Cytoscape SVG export
47
+ '<script src="https://cdn.jsdelivr.net/npm/cytoscape-svg@0.4.0/cytoscape-svg.min.js"></script>',
48
+ # CodeMirror for TTL editing
49
+ '<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/codemirror@5.65.18/lib/codemirror.min.css">',
50
+ '<script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.18/lib/codemirror.min.js"></script>',
51
+ '<script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.18/mode/turtle/turtle.min.js"></script>',
52
+ ])
53
+
54
+ inline_assets = f"<style>\n{css_content}\n</style>\n<script>\n{js_content}\n</script>\n"
55
+
56
+ output = output.replace("</body>", cdn_tags + "\n" + inline_assets + "</body>")
57
+ return output