rdf-construct 0.2.0__py3-none-any.whl

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.
Files changed (88) hide show
  1. rdf_construct/__init__.py +12 -0
  2. rdf_construct/__main__.py +0 -0
  3. rdf_construct/cli.py +1762 -0
  4. rdf_construct/core/__init__.py +33 -0
  5. rdf_construct/core/config.py +116 -0
  6. rdf_construct/core/ordering.py +219 -0
  7. rdf_construct/core/predicate_order.py +212 -0
  8. rdf_construct/core/profile.py +157 -0
  9. rdf_construct/core/selector.py +64 -0
  10. rdf_construct/core/serialiser.py +232 -0
  11. rdf_construct/core/utils.py +89 -0
  12. rdf_construct/cq/__init__.py +77 -0
  13. rdf_construct/cq/expectations.py +365 -0
  14. rdf_construct/cq/formatters/__init__.py +45 -0
  15. rdf_construct/cq/formatters/json.py +104 -0
  16. rdf_construct/cq/formatters/junit.py +104 -0
  17. rdf_construct/cq/formatters/text.py +146 -0
  18. rdf_construct/cq/loader.py +300 -0
  19. rdf_construct/cq/runner.py +321 -0
  20. rdf_construct/diff/__init__.py +59 -0
  21. rdf_construct/diff/change_types.py +214 -0
  22. rdf_construct/diff/comparator.py +338 -0
  23. rdf_construct/diff/filters.py +133 -0
  24. rdf_construct/diff/formatters/__init__.py +71 -0
  25. rdf_construct/diff/formatters/json.py +192 -0
  26. rdf_construct/diff/formatters/markdown.py +210 -0
  27. rdf_construct/diff/formatters/text.py +195 -0
  28. rdf_construct/docs/__init__.py +60 -0
  29. rdf_construct/docs/config.py +238 -0
  30. rdf_construct/docs/extractors.py +603 -0
  31. rdf_construct/docs/generator.py +360 -0
  32. rdf_construct/docs/renderers/__init__.py +7 -0
  33. rdf_construct/docs/renderers/html.py +803 -0
  34. rdf_construct/docs/renderers/json.py +390 -0
  35. rdf_construct/docs/renderers/markdown.py +628 -0
  36. rdf_construct/docs/search.py +278 -0
  37. rdf_construct/docs/templates/html/base.html.jinja +44 -0
  38. rdf_construct/docs/templates/html/class.html.jinja +152 -0
  39. rdf_construct/docs/templates/html/hierarchy.html.jinja +28 -0
  40. rdf_construct/docs/templates/html/index.html.jinja +110 -0
  41. rdf_construct/docs/templates/html/instance.html.jinja +90 -0
  42. rdf_construct/docs/templates/html/namespaces.html.jinja +37 -0
  43. rdf_construct/docs/templates/html/property.html.jinja +124 -0
  44. rdf_construct/docs/templates/html/single_page.html.jinja +169 -0
  45. rdf_construct/lint/__init__.py +75 -0
  46. rdf_construct/lint/config.py +214 -0
  47. rdf_construct/lint/engine.py +396 -0
  48. rdf_construct/lint/formatters.py +327 -0
  49. rdf_construct/lint/rules.py +692 -0
  50. rdf_construct/main.py +6 -0
  51. rdf_construct/puml2rdf/__init__.py +103 -0
  52. rdf_construct/puml2rdf/config.py +230 -0
  53. rdf_construct/puml2rdf/converter.py +420 -0
  54. rdf_construct/puml2rdf/merger.py +200 -0
  55. rdf_construct/puml2rdf/model.py +202 -0
  56. rdf_construct/puml2rdf/parser.py +565 -0
  57. rdf_construct/puml2rdf/validators.py +451 -0
  58. rdf_construct/shacl/__init__.py +56 -0
  59. rdf_construct/shacl/config.py +166 -0
  60. rdf_construct/shacl/converters.py +520 -0
  61. rdf_construct/shacl/generator.py +364 -0
  62. rdf_construct/shacl/namespaces.py +93 -0
  63. rdf_construct/stats/__init__.py +29 -0
  64. rdf_construct/stats/collector.py +178 -0
  65. rdf_construct/stats/comparator.py +298 -0
  66. rdf_construct/stats/formatters/__init__.py +83 -0
  67. rdf_construct/stats/formatters/json.py +38 -0
  68. rdf_construct/stats/formatters/markdown.py +153 -0
  69. rdf_construct/stats/formatters/text.py +186 -0
  70. rdf_construct/stats/metrics/__init__.py +26 -0
  71. rdf_construct/stats/metrics/basic.py +147 -0
  72. rdf_construct/stats/metrics/complexity.py +137 -0
  73. rdf_construct/stats/metrics/connectivity.py +130 -0
  74. rdf_construct/stats/metrics/documentation.py +128 -0
  75. rdf_construct/stats/metrics/hierarchy.py +207 -0
  76. rdf_construct/stats/metrics/properties.py +88 -0
  77. rdf_construct/uml/__init__.py +22 -0
  78. rdf_construct/uml/context.py +194 -0
  79. rdf_construct/uml/mapper.py +371 -0
  80. rdf_construct/uml/odm_renderer.py +789 -0
  81. rdf_construct/uml/renderer.py +684 -0
  82. rdf_construct/uml/uml_layout.py +393 -0
  83. rdf_construct/uml/uml_style.py +613 -0
  84. rdf_construct-0.2.0.dist-info/METADATA +431 -0
  85. rdf_construct-0.2.0.dist-info/RECORD +88 -0
  86. rdf_construct-0.2.0.dist-info/WHEEL +4 -0
  87. rdf_construct-0.2.0.dist-info/entry_points.txt +3 -0
  88. rdf_construct-0.2.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,278 @@
1
+ """Search index generation for client-side documentation search."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ from dataclasses import asdict, dataclass
8
+ from pathlib import Path
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from rdf_construct.docs.config import DocsConfig
13
+ from rdf_construct.docs.extractors import ClassInfo, ExtractedEntities, InstanceInfo, PropertyInfo
14
+
15
+
16
+ @dataclass
17
+ class SearchEntry:
18
+ """A single entry in the search index."""
19
+
20
+ uri: str
21
+ qname: str
22
+ entity_type: str # class, object_property, datatype_property, instance
23
+ label: str
24
+ keywords: list[str]
25
+ url: str
26
+
27
+
28
+ def extract_keywords(text: str | None) -> list[str]:
29
+ """Extract searchable keywords from text.
30
+
31
+ Splits on whitespace and punctuation, lowercases, and removes
32
+ common stop words.
33
+
34
+ Args:
35
+ text: Text to extract keywords from.
36
+
37
+ Returns:
38
+ List of keyword strings.
39
+ """
40
+ if not text:
41
+ return []
42
+
43
+ # Split on non-alphanumeric characters
44
+ words = re.split(r"[^a-zA-Z0-9]+", text.lower())
45
+
46
+ # Remove stop words and short words
47
+ stop_words = {
48
+ "a", "an", "the", "is", "are", "was", "were", "be", "been",
49
+ "being", "have", "has", "had", "do", "does", "did", "will",
50
+ "would", "could", "should", "may", "might", "must", "shall",
51
+ "can", "need", "of", "to", "in", "for", "on", "with", "at",
52
+ "by", "from", "as", "or", "and", "but", "if", "this", "that",
53
+ "which", "who", "whom", "whose", "what", "when", "where", "why",
54
+ "how", "all", "each", "every", "both", "few", "more", "most",
55
+ "other", "some", "such", "no", "not", "only", "same", "so",
56
+ "than", "too", "very", "just", "also", "any",
57
+ }
58
+
59
+ keywords = [w for w in words if w and len(w) > 2 and w not in stop_words]
60
+ return list(set(keywords)) # Remove duplicates
61
+
62
+
63
+ def class_to_search_entry(
64
+ class_info: "ClassInfo",
65
+ config: "DocsConfig",
66
+ ) -> SearchEntry:
67
+ """Convert a ClassInfo to a SearchEntry.
68
+
69
+ Args:
70
+ class_info: Class information.
71
+ config: Documentation configuration.
72
+
73
+ Returns:
74
+ SearchEntry for the class.
75
+ """
76
+ # Build keywords from various sources
77
+ keywords = []
78
+
79
+ # QName parts
80
+ if ":" in class_info.qname:
81
+ prefix, local = class_info.qname.split(":", 1)
82
+ keywords.extend(extract_keywords(local))
83
+ keywords.append(prefix.lower())
84
+
85
+ # Label
86
+ if class_info.label:
87
+ keywords.extend(extract_keywords(class_info.label))
88
+
89
+ # Definition
90
+ if class_info.definition:
91
+ keywords.extend(extract_keywords(class_info.definition))
92
+
93
+ # Superclass names
94
+ for uri in class_info.superclasses:
95
+ if "#" in str(uri):
96
+ keywords.extend(extract_keywords(str(uri).split("#")[-1]))
97
+ elif "/" in str(uri):
98
+ keywords.extend(extract_keywords(str(uri).split("/")[-1]))
99
+
100
+ from .config import entity_to_url
101
+ return SearchEntry(
102
+ uri=str(class_info.uri),
103
+ qname=class_info.qname,
104
+ entity_type="class",
105
+ label=class_info.label or class_info.qname,
106
+ keywords=list(set(keywords)),
107
+ url=entity_to_url(class_info.qname, "class", config),
108
+ )
109
+
110
+
111
+ def property_to_search_entry(
112
+ prop_info: "PropertyInfo",
113
+ config: "DocsConfig",
114
+ ) -> SearchEntry:
115
+ """Convert a PropertyInfo to a SearchEntry.
116
+
117
+ Args:
118
+ prop_info: Property information.
119
+ config: Documentation configuration.
120
+
121
+ Returns:
122
+ SearchEntry for the property.
123
+ """
124
+ keywords = []
125
+
126
+ # QName parts
127
+ if ":" in prop_info.qname:
128
+ prefix, local = prop_info.qname.split(":", 1)
129
+ keywords.extend(extract_keywords(local))
130
+ keywords.append(prefix.lower())
131
+
132
+ # Label
133
+ if prop_info.label:
134
+ keywords.extend(extract_keywords(prop_info.label))
135
+
136
+ # Definition
137
+ if prop_info.definition:
138
+ keywords.extend(extract_keywords(prop_info.definition))
139
+
140
+ # Property type
141
+ keywords.append(prop_info.property_type)
142
+
143
+ # Domain/range class names
144
+ for uri in prop_info.domain + prop_info.range:
145
+ if "#" in str(uri):
146
+ keywords.extend(extract_keywords(str(uri).split("#")[-1]))
147
+ elif "/" in str(uri):
148
+ keywords.extend(extract_keywords(str(uri).split("/")[-1]))
149
+
150
+ entity_type = f"{prop_info.property_type}_property"
151
+
152
+ from .config import entity_to_url
153
+ return SearchEntry(
154
+ uri=str(prop_info.uri),
155
+ qname=prop_info.qname,
156
+ entity_type=entity_type,
157
+ label=prop_info.label or prop_info.qname,
158
+ keywords=list(set(keywords)),
159
+ url=entity_to_url(prop_info.qname, entity_type, config),
160
+ )
161
+
162
+
163
+ def instance_to_search_entry(
164
+ instance_info: "InstanceInfo",
165
+ config: "DocsConfig",
166
+ ) -> SearchEntry:
167
+ """Convert an InstanceInfo to a SearchEntry.
168
+
169
+ Args:
170
+ instance_info: Instance information.
171
+ config: Documentation configuration.
172
+
173
+ Returns:
174
+ SearchEntry for the instance.
175
+ """
176
+ keywords = []
177
+
178
+ # QName parts
179
+ if ":" in instance_info.qname:
180
+ prefix, local = instance_info.qname.split(":", 1)
181
+ keywords.extend(extract_keywords(local))
182
+ keywords.append(prefix.lower())
183
+
184
+ # Label
185
+ if instance_info.label:
186
+ keywords.extend(extract_keywords(instance_info.label))
187
+
188
+ # Definition
189
+ if instance_info.definition:
190
+ keywords.extend(extract_keywords(instance_info.definition))
191
+
192
+ # Type names
193
+ for uri in instance_info.types:
194
+ if "#" in str(uri):
195
+ keywords.extend(extract_keywords(str(uri).split("#")[-1]))
196
+ elif "/" in str(uri):
197
+ keywords.extend(extract_keywords(str(uri).split("/")[-1]))
198
+
199
+ # Add "instance" as a keyword
200
+ keywords.append("instance")
201
+
202
+ from .config import entity_to_url
203
+ return SearchEntry(
204
+ uri=str(instance_info.uri),
205
+ qname=instance_info.qname,
206
+ entity_type="instance",
207
+ label=instance_info.label or instance_info.qname,
208
+ keywords=list(set(keywords)),
209
+ url=entity_to_url(instance_info.qname, "instance", config),
210
+ )
211
+
212
+
213
+ def generate_search_index(
214
+ entities: "ExtractedEntities",
215
+ config: "DocsConfig",
216
+ ) -> list[SearchEntry]:
217
+ """Generate a search index from extracted entities.
218
+
219
+ Args:
220
+ entities: All extracted entities from the ontology.
221
+ config: Documentation configuration.
222
+
223
+ Returns:
224
+ List of SearchEntry objects for all entities.
225
+ """
226
+ entries: list[SearchEntry] = []
227
+
228
+ # Classes
229
+ if config.include_classes:
230
+ for class_info in entities.classes:
231
+ entries.append(class_to_search_entry(class_info, config))
232
+
233
+ # Properties
234
+ if config.include_object_properties:
235
+ for prop_info in entities.object_properties:
236
+ entries.append(property_to_search_entry(prop_info, config))
237
+
238
+ if config.include_datatype_properties:
239
+ for prop_info in entities.datatype_properties:
240
+ entries.append(property_to_search_entry(prop_info, config))
241
+
242
+ if config.include_annotation_properties:
243
+ for prop_info in entities.annotation_properties:
244
+ entries.append(property_to_search_entry(prop_info, config))
245
+
246
+ # Instances
247
+ if config.include_instances:
248
+ for instance_info in entities.instances:
249
+ entries.append(instance_to_search_entry(instance_info, config))
250
+
251
+ return entries
252
+
253
+
254
+ def write_search_index(
255
+ entries: list[SearchEntry],
256
+ output_dir: Path,
257
+ ) -> Path:
258
+ """Write the search index to a JSON file.
259
+
260
+ Args:
261
+ entries: List of search entries.
262
+ output_dir: Output directory.
263
+
264
+ Returns:
265
+ Path to the written search index file.
266
+ """
267
+ output_path = output_dir / "search.json"
268
+
269
+ # Convert to serialisable format
270
+ data = {
271
+ "entities": [asdict(entry) for entry in entries],
272
+ }
273
+
274
+ output_path.parent.mkdir(parents=True, exist_ok=True)
275
+ with open(output_path, "w") as f:
276
+ json.dump(data, f, indent=2)
277
+
278
+ return output_path
@@ -0,0 +1,44 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{% block title %}{{ ontology.title or "Ontology Documentation" }}{% endblock %}</title>
7
+ <link rel="stylesheet" href="{{ config.base_url }}/assets/style.css">
8
+ {% block head %}{% endblock %}
9
+ </head>
10
+ <body>
11
+ <header class="header">
12
+ <h1>{{ ontology.title or "Ontology Documentation" }}</h1>
13
+ {% if ontology.description %}
14
+ <p class="description">{{ ontology.description }}</p>
15
+ {% endif %}
16
+ </header>
17
+
18
+ <nav class="nav">
19
+ <a href="{{ config.base_url }}/index.html">Index</a>
20
+ <a href="{{ config.base_url }}/hierarchy.html">Hierarchy</a>
21
+ <a href="{{ config.base_url }}/namespaces.html">Namespaces</a>
22
+ </nav>
23
+
24
+ {% if config.include_search %}
25
+ <div class="search-box">
26
+ <input type="text" id="search-input" placeholder="Search entities...">
27
+ <ul id="search-results" class="search-results"></ul>
28
+ </div>
29
+ {% endif %}
30
+
31
+ <main>
32
+ {% block content %}{% endblock %}
33
+ </main>
34
+
35
+ <footer class="footer">
36
+ <p>Generated by <a href="https://github.com/aigora-de/rdf-construct">rdf-construct</a></p>
37
+ </footer>
38
+
39
+ {% if config.include_search %}
40
+ <script src="{{ config.base_url }}/assets/search.js"></script>
41
+ {% endif %}
42
+ {% block scripts %}{% endblock %}
43
+ </body>
44
+ </html>
@@ -0,0 +1,152 @@
1
+ {% extends "base.html.jinja" %}
2
+
3
+ {% block title %}{{ class_info.label or class_info.qname }} - {{ ontology.title or "Documentation" }}{% endblock %}
4
+
5
+ {% block content %}
6
+ <article class="entity-card">
7
+ <h1>{{ class_info.label or class_info.qname }} <span class="entity-type">Class</span></h1>
8
+ <p class="uri">{{ class_info.uri }}</p>
9
+
10
+ {% if class_info.definition %}
11
+ <p class="definition">{{ class_info.definition }}</p>
12
+ {% endif %}
13
+
14
+ {% if class_info.superclasses %}
15
+ <section class="section">
16
+ <h3>Superclasses</h3>
17
+ <ul class="entity-list">
18
+ {% for uri in class_info.superclasses %}
19
+ <li>
20
+ {% set found = namespace(value=false) %}
21
+ {% for c in classes %}
22
+ {% if c.uri|string == uri|string %}
23
+ <a href="{{ c.qname | entity_url('class') }}">{{ c.label or c.qname }}</a>
24
+ {% set found.value = true %}
25
+ {% endif %}
26
+ {% endfor %}
27
+ {% if not found.value %}
28
+ <code>{{ uri }}</code>
29
+ {% endif %}
30
+ </li>
31
+ {% endfor %}
32
+ </ul>
33
+ </section>
34
+ {% endif %}
35
+
36
+ {% if class_info.subclasses %}
37
+ <section class="section">
38
+ <h3>Subclasses</h3>
39
+ <ul class="entity-list">
40
+ {% for uri in class_info.subclasses %}
41
+ <li>
42
+ {% set found = namespace(value=false) %}
43
+ {% for c in classes %}
44
+ {% if c.uri|string == uri|string %}
45
+ <a href="{{ c.qname | entity_url('class') }}">{{ c.label or c.qname }}</a>
46
+ {% set found.value = true %}
47
+ {% endif %}
48
+ {% endfor %}
49
+ {% if not found.value %}
50
+ <code>{{ uri }}</code>
51
+ {% endif %}
52
+ </li>
53
+ {% endfor %}
54
+ </ul>
55
+ </section>
56
+ {% endif %}
57
+
58
+ {% if class_info.domain_of %}
59
+ <section class="section">
60
+ <h3>Properties (Domain)</h3>
61
+ <ul class="entity-list">
62
+ {% for prop in class_info.domain_of %}
63
+ <li>
64
+ <a href="{{ prop.qname | entity_url(prop.property_type + '_property') }}">
65
+ {{ prop.label or prop.qname }}
66
+ </a>
67
+ <span class="entity-type {{ prop.property_type }}">{{ prop.property_type }}</span>
68
+ </li>
69
+ {% endfor %}
70
+ </ul>
71
+ </section>
72
+ {% endif %}
73
+
74
+ {% if inherited_properties %}
75
+ <section class="section">
76
+ <h3>Inherited Properties</h3>
77
+ <ul class="entity-list">
78
+ {% for prop in inherited_properties %}
79
+ <li>
80
+ <a href="{{ prop.qname | entity_url(prop.property_type + '_property') }}">
81
+ {{ prop.label or prop.qname }}
82
+ </a>
83
+ <span class="entity-type {{ prop.property_type }}">{{ prop.property_type }}</span>
84
+ <span class="annotation">(inherited)</span>
85
+ </li>
86
+ {% endfor %}
87
+ </ul>
88
+ </section>
89
+ {% endif %}
90
+
91
+ {% if class_info.range_of %}
92
+ <section class="section">
93
+ <h3>Used as Range</h3>
94
+ <ul class="entity-list">
95
+ {% for prop in class_info.range_of %}
96
+ <li>
97
+ <a href="{{ prop.qname | entity_url(prop.property_type + '_property') }}">
98
+ {{ prop.label or prop.qname }}
99
+ </a>
100
+ </li>
101
+ {% endfor %}
102
+ </ul>
103
+ </section>
104
+ {% endif %}
105
+
106
+ {% if class_info.instances and config.include_instances %}
107
+ <section class="section">
108
+ <h3>Instances</h3>
109
+ <ul class="entity-list">
110
+ {% for uri in class_info.instances %}
111
+ <li>
112
+ {% set found = namespace(value=false) %}
113
+ {% for i in instances %}
114
+ {% if i.uri|string == uri|string %}
115
+ <a href="{{ i.qname | entity_url('instance') }}">{{ i.label or i.qname }}</a>
116
+ {% set found.value = true %}
117
+ {% endif %}
118
+ {% endfor %}
119
+ {% if not found.value %}
120
+ <code>{{ uri }}</code>
121
+ {% endif %}
122
+ </li>
123
+ {% endfor %}
124
+ </ul>
125
+ </section>
126
+ {% endif %}
127
+
128
+ {% if class_info.annotations %}
129
+ <section class="section">
130
+ <h3>Annotations</h3>
131
+ <table>
132
+ <thead>
133
+ <tr>
134
+ <th>Property</th>
135
+ <th>Value</th>
136
+ </tr>
137
+ </thead>
138
+ <tbody>
139
+ {% for name, values in class_info.annotations.items() %}
140
+ {% for value in values %}
141
+ <tr>
142
+ <td><code>{{ name }}</code></td>
143
+ <td>{{ value }}</td>
144
+ </tr>
145
+ {% endfor %}
146
+ {% endfor %}
147
+ </tbody>
148
+ </table>
149
+ </section>
150
+ {% endif %}
151
+ </article>
152
+ {% endblock %}
@@ -0,0 +1,28 @@
1
+ {% extends "base.html.jinja" %}
2
+
3
+ {% block title %}Class Hierarchy - {{ ontology.title or "Documentation" }}{% endblock %}
4
+
5
+ {% block content %}
6
+ <h2>Class Hierarchy</h2>
7
+
8
+ {% macro render_tree(nodes) %}
9
+ <ul class="hierarchy-tree">
10
+ {% for node in nodes %}
11
+ <li>
12
+ <a href="{{ node.class.qname | entity_url('class') }}">
13
+ {{ node.class.label or node.class.qname }}
14
+ </a>
15
+ {% if node.children %}
16
+ {{ render_tree(node.children) }}
17
+ {% endif %}
18
+ </li>
19
+ {% endfor %}
20
+ </ul>
21
+ {% endmacro %}
22
+
23
+ {% if hierarchy %}
24
+ {{ render_tree(hierarchy) }}
25
+ {% else %}
26
+ <p>No class hierarchy found.</p>
27
+ {% endif %}
28
+ {% endblock %}
@@ -0,0 +1,110 @@
1
+ {% extends "base.html.jinja" %}
2
+
3
+ {% block title %}{{ ontology.title or "Ontology Documentation" }}{% endblock %}
4
+
5
+ {% block content %}
6
+ <section class="stats">
7
+ <div class="stat-card">
8
+ <div class="number">{{ total_classes }}</div>
9
+ <div class="label">Classes</div>
10
+ </div>
11
+ <div class="stat-card">
12
+ <div class="number">{{ total_properties }}</div>
13
+ <div class="label">Properties</div>
14
+ </div>
15
+ {% if instances %}
16
+ <div class="stat-card">
17
+ <div class="number">{{ total_instances }}</div>
18
+ <div class="label">Instances</div>
19
+ </div>
20
+ {% endif %}
21
+ </section>
22
+
23
+ {% if classes %}
24
+ <section class="section">
25
+ <h2>Classes</h2>
26
+ <ul class="entity-list">
27
+ {% for class in classes %}
28
+ <li>
29
+ <a href="{{ class.qname | entity_url('class') }}">
30
+ {{ class.label or class.qname }}
31
+ </a>
32
+ {% if class.definition %}
33
+ <span class="definition">— {{ class.definition[:100] }}{% if class.definition|length > 100 %}...{% endif %}</span>
34
+ {% endif %}
35
+ </li>
36
+ {% endfor %}
37
+ </ul>
38
+ </section>
39
+ {% endif %}
40
+
41
+ {% if object_properties %}
42
+ <section class="section">
43
+ <h2>Object Properties</h2>
44
+ <ul class="entity-list">
45
+ {% for prop in object_properties %}
46
+ <li>
47
+ <a href="{{ prop.qname | entity_url('object_property') }}">
48
+ {{ prop.label or prop.qname }}
49
+ </a>
50
+ <span class="entity-type object">Object</span>
51
+ {% if prop.definition %}
52
+ <span class="definition">— {{ prop.definition[:80] }}{% if prop.definition|length > 80 %}...{% endif %}</span>
53
+ {% endif %}
54
+ </li>
55
+ {% endfor %}
56
+ </ul>
57
+ </section>
58
+ {% endif %}
59
+
60
+ {% if datatype_properties %}
61
+ <section class="section">
62
+ <h2>Datatype Properties</h2>
63
+ <ul class="entity-list">
64
+ {% for prop in datatype_properties %}
65
+ <li>
66
+ <a href="{{ prop.qname | entity_url('datatype_property') }}">
67
+ {{ prop.label or prop.qname }}
68
+ </a>
69
+ <span class="entity-type datatype">Datatype</span>
70
+ {% if prop.definition %}
71
+ <span class="definition">— {{ prop.definition[:80] }}{% if prop.definition|length > 80 %}...{% endif %}</span>
72
+ {% endif %}
73
+ </li>
74
+ {% endfor %}
75
+ </ul>
76
+ </section>
77
+ {% endif %}
78
+
79
+ {% if annotation_properties %}
80
+ <section class="section">
81
+ <h2>Annotation Properties</h2>
82
+ <ul class="entity-list">
83
+ {% for prop in annotation_properties %}
84
+ <li>
85
+ <a href="{{ prop.qname | entity_url('annotation_property') }}">
86
+ {{ prop.label or prop.qname }}
87
+ </a>
88
+ <span class="entity-type annotation">Annotation</span>
89
+ </li>
90
+ {% endfor %}
91
+ </ul>
92
+ </section>
93
+ {% endif %}
94
+
95
+ {% if instances and config.include_instances %}
96
+ <section class="section">
97
+ <h2>Instances</h2>
98
+ <ul class="entity-list">
99
+ {% for inst in instances %}
100
+ <li>
101
+ <a href="{{ inst.qname | entity_url('instance') }}">
102
+ {{ inst.label or inst.qname }}
103
+ </a>
104
+ <span class="entity-type instance">Instance</span>
105
+ </li>
106
+ {% endfor %}
107
+ </ul>
108
+ </section>
109
+ {% endif %}
110
+ {% endblock %}