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 +21 -0
- ontoink-0.1.0/PKG-INFO +233 -0
- ontoink-0.1.0/README.md +196 -0
- ontoink-0.1.0/ontoink/__init__.py +3 -0
- ontoink-0.1.0/ontoink/fence.py +126 -0
- ontoink-0.1.0/ontoink/plugin.py +57 -0
- ontoink-0.1.0/ontoink/resources/ontoink.css +220 -0
- ontoink-0.1.0/ontoink/resources/ontoink.js +609 -0
- ontoink-0.1.0/ontoink/shacl_validator.py +83 -0
- ontoink-0.1.0/ontoink/ttl_parser.py +428 -0
- ontoink-0.1.0/ontoink.egg-info/PKG-INFO +233 -0
- ontoink-0.1.0/ontoink.egg-info/SOURCES.txt +21 -0
- ontoink-0.1.0/ontoink.egg-info/dependency_links.txt +1 -0
- ontoink-0.1.0/ontoink.egg-info/entry_points.txt +2 -0
- ontoink-0.1.0/ontoink.egg-info/requires.txt +9 -0
- ontoink-0.1.0/ontoink.egg-info/top_level.txt +4 -0
- ontoink-0.1.0/pyproject.toml +74 -0
- ontoink-0.1.0/setup.cfg +4 -0
- ontoink-0.1.0/tests/__init__.py +0 -0
- ontoink-0.1.0/tests/conftest.py +22 -0
- ontoink-0.1.0/tests/test_fence.py +52 -0
- ontoink-0.1.0/tests/test_shacl_validator.py +15 -0
- ontoink-0.1.0/tests/test_ttl_parser.py +87 -0
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
|
+
[](https://github.com/ISE-FIZKarlsruhe/ontoink/actions/workflows/ci.yml)
|
|
43
|
+
[](https://pypi.org/project/ontoink/)
|
|
44
|
+
[](https://pypi.org/project/ontoink/)
|
|
45
|
+
[](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/)
|
ontoink-0.1.0/README.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# ontoink
|
|
2
|
+
|
|
3
|
+
**Interactive ontology visualization, SHACL validation, and live TTL editing for MkDocs.**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/ISE-FIZKarlsruhe/ontoink/actions/workflows/ci.yml)
|
|
6
|
+
[](https://pypi.org/project/ontoink/)
|
|
7
|
+
[](https://pypi.org/project/ontoink/)
|
|
8
|
+
[](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,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 & 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">−</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">⛶</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
|