Skip to content

Commit 4a9817f

Browse files
Merge pull request #343 from iolanta-tech/342-implement-datatype-facet-for-ontology-rendering
342 implement datatype facet for ontology rendering
2 parents 1acaaa5 + 748e4a5 commit 4a9817f

14 files changed

Lines changed: 205 additions & 129 deletions

File tree

docs/blog/2025-03-15.writing-a-nanopublication/signed.mosquito-no-pubinfo.jsonld

Lines changed: 0 additions & 47 deletions
This file was deleted.

docs/datatypes/fallback-title.md

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,20 @@
1-
# :material-format-title: Title (fallback)
1+
---
2+
"@context":
3+
- ../context.yamlld
4+
- iolanta:hasDefaultFacet:
5+
"@type": "@id"
26

3-
<script type="application/ld+json">
4-
{
5-
"@context": {
6-
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
7-
"rdf": "https://www.w3.org/1999/02/22-rdf-syntax-ns#",
8-
"xsd": "https://www.w3.org/2001/XMLSchema#",
9-
"iolanta": "https://iolanta.tech/",
10-
"iolanta:hasDefaultFacet": {
11-
"@type": "@id"
12-
},
13-
"rdfs:subClassOf": {
14-
"@type": "@id"
15-
}
16-
},
17-
"@id": "https://iolanta.tech/datatypes/fallback-title",
18-
"rdfs:label": "Fallback Title",
19-
"rdfs:description": "A short string naming something. Used in links, lists, page titles, property tables, and many other cases. Should be used as fallback in case more fine-tuned implementations using https://iolanta.tech/datatypes/title do not work.",
20-
"rdfs:subClassOf": "xsd:string",
21-
"@type": "rdfs:Datatype",
22-
"iolanta:hasDefaultFacet": "pkg:pypi/iolanta#title"
23-
}
24-
</script>
7+
$id: https://iolanta.tech/datatypes/fallback-title
8+
$type: iolanta:OutputDatatype
9+
$: Fallback Title
2510

26-
A short string naming something. Used in links, lists, page titles, property tables, and many other cases.
11+
rdfs:comment: >
12+
A short string naming something. Used in links, lists, page titles, property tables, and many other cases.
13+
Should be used as fallback in case more fine-tuned implementations using https://iolanta.tech/datatypes/title do not work.
2714

28-
!!! warning "This is a fallback datatype"
29-
Should be used as fallback in case more fine-tuned implementations using [Title](/datatypes/title/) do not work for this IRI.
15+
: xsd:string
3016

31-
| Property | Value |
32-
| --- | --- |
33-
| ∈ Instance Of | `rdfs:Datatype` |
34-
| ⊊ Subclass Of | `xsd:string` |
35-
| Has default facet | :material-language-python: `iolanta.facets.title.TitleFacet` |
17+
iolanta:hasDefaultFacet: pkg:pypi/iolanta#title
18+
---
19+
20+
{{ URIRef("https://iolanta.tech/datatypes/fallback-title") | as('mkdocs-material-insiders-markdown') }}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
"@context": ../context.yamlld
3+
4+
$id: https://iolanta.tech/datatypes/mkdocs-material-insiders-markdown
5+
$type: iolanta:OutputDatatype
6+
$: MkDocs Material Insiders Markdown
7+
8+
: xsd:string
9+
10+
rdfs:comment: >
11+
The Markdown dialect used by the [mkdocs-material-insiders](https://squidfunk.github.io/mkdocs-material/) theme.
12+
This dialect extends Python-Markdown with various plugins and extensions
13+
specific to the Material for MkDocs Insiders theme.
14+
---
15+
16+
{{ URIRef("https://iolanta.tech/datatypes/mkdocs-material-insiders-markdown") | as('mkdocs-material-insiders-markdown') }}

docs/datatypes/title.md

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,27 @@
1-
# :material-format-title: Title
1+
---
2+
"@context":
3+
- ../context.yamlld
4+
- iolanta:hasDefaultFacet:
5+
"@type": "@id"
6+
iolanta:hasInstanceFacet:
7+
"@type": "@id"
28

3-
<script type="application/ld+json">
4-
{
5-
"@context": {
6-
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
7-
"rdf": "https://www.w3.org/1999/02/22-rdf-syntax-ns#",
8-
"xsd": "https://www.w3.org/2001/XMLSchema#",
9-
"iolanta": "https://iolanta.tech/",
10-
"iolanta:hasDefaultFacet": {
11-
"@type": "@id"
12-
},
13-
"rdfs:subClassOf": {
14-
"@type": "@id"
15-
},
16-
"foaf": "https://xmlns.com/foaf/0.1/"
17-
},
18-
"@id": "https://iolanta.tech/datatypes/title",
19-
"rdfs:label": "Title",
20-
"rdfs:description": "A short string naming something. Used in links, lists, page titles, property tables, and many other cases.",
21-
"rdfs:subClassOf": "xsd:string",
22-
"@type": "rdfs:Datatype",
23-
"iolanta:hasDefaultFacet": "pkg:pypi/iolanta#title",
24-
"@included": {
25-
"@id": "foaf:Person",
26-
"iolanta:hasInstanceFacet": {
27-
"@id": "pkg:pypi/iolanta#title-foaf-person",
28-
"iolanta:outputs": {
29-
"@id": "https://iolanta.tech/datatypes/title"
30-
}
31-
}
32-
}
33-
}
34-
</script>
9+
$id: https://iolanta.tech/datatypes/title
10+
$type: iolanta:OutputDatatype
11+
$: Title
3512

36-
A short string naming something. Used in links, lists, page titles, property tables, and many other cases.
13+
rdfs:comment: >
14+
A short string naming something. Used in links, lists, page titles, property tables, and many other cases.
3715

38-
| Property | Value |
39-
|-------------------|--------------------------------------------------------------|
40-
| ∈ Instance Of | `rdfs:Datatype` |
41-
| ⊊ Subclass Of | `xsd:string` |
42-
| Has default facet | :material-language-python: `iolanta.facets.title.TitleFacet` |
16+
: xsd:string
4317

18+
iolanta:hasDefaultFacet: pkg:pypi/iolanta#title
4419

45-
## Specialized Facets
20+
"@included":
21+
"@id": foaf:Person
22+
iolanta:hasInstanceFacet:
23+
"@id": pkg:pypi/iolanta#title-foaf-person
24+
: https://iolanta.tech/datatypes/title
25+
---
4626

47-
| Class | Facet | Description |
48-
|---------------|-------------------------------------------------------------|--------------------------------------------------------|
49-
| `foaf:Person` | `pkg:pypi/iolanta#title-foaf-person` | Render name of a person from their first and last name |
27+
{{ URIRef("https://iolanta.tech/datatypes/title") | as('mkdocs-material-insiders-markdown') }}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from iolanta.facets.mkdocs_material_insiders_markdown.facet import MkDocsMaterialInsidersMarkdownFacet
2+
3+
__all__ = ['MkDocsMaterialInsidersMarkdownFacet']
4+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"@context":
2+
"@import": https://json-ld.org/contexts/dollar-convenience.jsonld
3+
rdfs: "http://www.w3.org/2000/01/rdf-schema#"
4+
rdf: https://www.w3.org/1999/02/22-rdf-syntax-ns#
5+
iolanta: https://iolanta.tech/
6+
7+
$: rdfs:label
8+
9+
→:
10+
"@type": "@id"
11+
"@id": iolanta:outputs
12+
13+
↦: iolanta:matches
14+
15+
$id: pkg:pypi/iolanta#mkdocs-material-insiders-markdown-datatype
16+
$: OutputDatatype (mkdocs-material-insiders-markdown)
17+
18+
→: https://iolanta.tech/datatypes/mkdocs-material-insiders-markdown
19+
20+
↦: ASK WHERE { $this a iolanta:OutputDatatype }
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from pathlib import Path
2+
3+
from jinja2 import Environment, FileSystemLoader
4+
from rdflib import URIRef
5+
6+
from iolanta.facets.facet import Facet
7+
from iolanta.namespaces import DATATYPES, IOLANTA, RDF, RDFS
8+
9+
10+
class MkDocsMaterialInsidersMarkdownFacet(Facet[str]):
11+
"""Render rdfs:Datatype nodes as mkdocs-material-insiders-markdown."""
12+
13+
META = Path(__file__).parent / 'data' / 'mkdocs_material_insiders_markdown.yamlld'
14+
"""Render rdfs:Datatype nodes as mkdocs-material-insiders-markdown."""
15+
16+
@property
17+
def _template_env(self) -> Environment:
18+
"""Jinja2 template environment."""
19+
template_path = Path(__file__).parent / 'templates'
20+
return Environment(
21+
loader=FileSystemLoader(str(template_path)),
22+
autoescape=False,
23+
)
24+
25+
def show(self) -> str:
26+
"""Render the datatype as markdown."""
27+
# Get the label using title facet
28+
label = self.render(
29+
self.this,
30+
as_datatype=DATATYPES.title,
31+
)
32+
33+
# Get the comment/description
34+
comment_rows = self.query(
35+
"""
36+
SELECT ?comment WHERE {
37+
$this rdfs:comment ?comment .
38+
}
39+
LIMIT 1
40+
""",
41+
this=self.this,
42+
)
43+
comment = str(comment_rows[0]['comment']) if comment_rows else None
44+
45+
# Get all types (rdf:type)
46+
type_rows = self.query(
47+
"""
48+
SELECT ?type WHERE {
49+
$this rdf:type ?type .
50+
}
51+
""",
52+
this=self.this,
53+
)
54+
types = [
55+
{
56+
'uri': row['type'],
57+
'title': self.render(row['type'], as_datatype=DATATYPES.title),
58+
}
59+
for row in type_rows
60+
]
61+
62+
# Get all superclasses (rdfs:subClassOf)
63+
superclass_rows = self.query(
64+
"""
65+
SELECT ?superclass WHERE {
66+
$this rdfs:subClassOf ?superclass .
67+
}
68+
""",
69+
this=self.this,
70+
)
71+
superclasses = [
72+
{
73+
'uri': row['superclass'],
74+
'title': self.render(row['superclass'], as_datatype=DATATYPES.title),
75+
}
76+
for row in superclass_rows
77+
]
78+
79+
template = self._template_env.get_template('datatype.jinja2.md')
80+
return template.render(
81+
label=label,
82+
comment=comment,
83+
types=types,
84+
superclasses=superclasses,
85+
)
86+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# {{ label }}
2+
3+
<table>
4+
<thead>
5+
</thead>
6+
<tbody>
7+
{% if types %}
8+
<tr>
9+
<td>∈ Instance Of</td>
10+
<td>{% for type in types %}<code><a href="{{ type.uri }}">{{ type.title }}</a></code>{% if not loop.last %}, {% endif %}{% endfor %}</td>
11+
</tr>
12+
{% endif %}
13+
{% if superclasses %}
14+
<tr>
15+
<td>⊊ Subclass Of</td>
16+
<td>{% for superclass in superclasses %}<code><a href="{{ superclass.uri }}">{{ superclass.title }}</a></code>{% if not loop.last %}, {% endif %}{% endfor %}</td>
17+
</tr>
18+
{% endif %}
19+
</tbody>
20+
</table>
21+
22+
{% if comment %}
23+
{{ comment | safe }}
24+
{% endif %}

iolanta/iolanta.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,9 @@ def add( # noqa: C901, WPS231, WPS210, WPS213
171171
self.logger.error(f'{source} | {parser_not_found}')
172172
continue
173173
except YAMLLDError as yaml_ld_error:
174-
self.logger.error(f'{source} | {yaml_ld_error}')
175-
continue
174+
# .add() only processes local files, so errors should be raised
175+
self.logger.error(f'{source_file} | {yaml_ld_error}')
176+
raise
176177
except ValueError as value_error:
177178
self.logger.error(f'{source} | {value_error}')
178179
continue

iolanta/namespaces.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class RDFS(rdflib.RDFS):
2424

2525

2626
class RDF(rdflib.RDF):
27-
_NS = rdflib.Namespace('https://www.w3.org/1999/02/22-rdf-syntax-ns#')
27+
_NS = rdflib.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
2828

2929

3030
class DCTERMS(rdflib.DCTERMS):

0 commit comments

Comments
 (0)