Skip to content

Commit a7b2332

Browse files
committed
feat: add sphinx-jsonschema extension for JSON Schema rendering
Use it in docs/reference/metamodel.rst Closes #472
1 parent 1a1cd79 commit a7b2332

8 files changed

Lines changed: 134 additions & 24 deletions

File tree

docs/internals/extensions/metamodel.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ This extension serves multiple critical functions:
1919
### Metamodel Definition
2020
The extension contains:
2121
- `metamodel.yaml`: The main metamodel definition
22-
- `metamodel-schema.json`: JSON schema for validation
22+
- `metamodel-schema.json`: JSON schema for validation (see the rendered [Schema Reference](../../reference/metamodel.rst))
2323
- Setting configuration parameters based on input that get passed on to sphinx-needs
2424

2525
### Validation System

docs/reference/bazel_macros.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ Minimal example (root ``BUILD``)
8080
)
8181
8282
The custom ``metamodel.yaml`` must follow the same schema as the default one
83-
(see :doc:`score_metamodel </internals/extensions/metamodel>`).
83+
(see :doc:`score_metamodel </internals/extensions/metamodel>` and :ref:`metamodel_reference`).
8484
You may use ``@score_docs_as_code//src/extensions/score_metamodel:metamodel_yaml``
8585
for extension processing.
8686
When ``metamodel`` is omitted the default metamodel is used unchanged.

docs/reference/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ Here you find the API and usage reference for docs-as-code.
2323

2424
commands
2525
bazel_macros
26+
metamodel

docs/reference/metamodel.rst

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
..
2+
# *******************************************************************************
3+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
4+
#
5+
# See the NOTICE file(s) distributed with this work for additional
6+
# information regarding copyright ownership.
7+
#
8+
# This program and the accompanying materials are made available under the
9+
# terms of the Apache License Version 2.0 which is available at
10+
# https://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# SPDX-License-Identifier: Apache-2.0
13+
# Assisted-by: Anthropic Claude-opus-4.6
14+
# *******************************************************************************
15+
16+
.. _metamodel_reference:
17+
18+
Metamodel Schema Reference
19+
==========================
20+
21+
The S-CORE documentation metamodel is defined in a YAML file.
22+
It declares all Sphinx-Needs types (directives), their mandatory and optional options,
23+
link relationships, and validation rules used across S-CORE documentation repositories.
24+
25+
For details on the extension internals, validation checks, and how to add new need
26+
types, see the :doc:`score_metamodel extension guide </internals/extensions/metamodel>`.
27+
28+
Schema
29+
------
30+
31+
Below is the JSON Schema that validates the structure of ``metamodel.yaml``.
32+
33+
.. jsonschema:: ../../src/extensions/score_metamodel/metamodel-schema.json
34+
35+
Quick example
36+
-------------
37+
38+
A minimal type definition in ``metamodel.yaml`` looks like this:
39+
40+
.. code-block:: yaml
41+
42+
needs_types:
43+
feat_req:
44+
title: Feature Requirement
45+
prefix: feat_req__
46+
mandatory_options:
47+
id: ^feat_req__[0-9a-z_]*$
48+
status: ^(valid|draft)$
49+
optional_links:
50+
satisfies: ^std_req__.*$
51+
tags:
52+
- requirement
53+
parts: 2
54+
55+
Each option value is a regex pattern that the corresponding field must match.
56+
The ``parts`` key specifies how many segments (separated by ``__``) the need ID contains.
Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,94 @@
11
{
22
"$schema": "https://json-schema.org/draft/2020-12/schema",
3-
"$id": "https://example.com/metamodel-schema.json",
3+
"$id": "https://eclipse-score.github.io/docs-as-code/metamodel-schema.json",
44
"title": "S-CORE Metamodel Schema",
5+
"description": "Validates the structure of metamodel.yaml, which defines all Sphinx-Needs types, their options, and link relationships used across S-CORE documentation.",
56
"type": "object",
67
"properties": {
78
"types": {
89
"type": "object",
9-
"description": "All Sphinx-Needs types (directives)",
10+
"description": "Map of need type identifiers to their definitions. Each key becomes a Sphinx-Needs directive (e.g. ``feat_req``, ``comp_arc_sta``).",
1011
"additionalProperties": {
1112
"type": "object",
13+
"description": "Definition of a single need type.",
1214
"properties": {
13-
"title": { "type": "string" },
14-
"prefix": { "type": "string" },
15-
"color": { "type": "string" },
16-
"style": { "type": "string" },
15+
"title": {
16+
"type": "string",
17+
"description": "Human-readable display name shown in rendered documentation (e.g. 'Feature Requirement')."
18+
},
19+
"prefix": {
20+
"type": "string",
21+
"description": "ID prefix for auto-generated need IDs. Defaults to ``<type_name>__`` when omitted."
22+
},
23+
"color": {
24+
"type": "string",
25+
"description": "CSS color used when rendering this need type in diagrams and tables."
26+
},
27+
"style": {
28+
"type": "string",
29+
"description": "Visual style hint for diagram rendering (e.g. Plantuml stereotype)."
30+
},
1731
"mandatory_options": {
1832
"type": "object",
19-
"description": "Map of field_name -> regex pattern (these fields are required).",
20-
"additionalProperties": { "type": "string" }
33+
"description": "Options that every need of this type must provide. Each key is a field name and its value is a regex pattern the field value must match.",
34+
"additionalProperties": {
35+
"type": "string"
36+
}
2137
},
2238
"optional_options": {
2339
"type": "object",
24-
"description": "Map of field_name -> regex pattern (these fields are optional).",
25-
"additionalProperties": { "type": "string" }
40+
"description": "Options that may optionally appear on a need of this type. Validated against the regex pattern when present.",
41+
"additionalProperties": {
42+
"type": "string"
43+
}
2644
},
2745
"mandatory_links": {
2846
"type": "object",
29-
"description": "Map of link_field_name -> regex pattern (these link fields are required).",
30-
"additionalProperties": { "type": "string" }
47+
"description": "Link fields that every need of this type must include. Values are regex patterns restricting which target need IDs are allowed.",
48+
"additionalProperties": {
49+
"type": "string"
50+
}
3151
},
3252
"optional_links": {
3353
"type": "object",
34-
"description": "Map of link_field_name -> regex pattern (these link fields are optional).",
35-
"additionalProperties": { "type": "string" }
54+
"description": "Link fields that may optionally appear. Values are regex patterns restricting allowed target need IDs.",
55+
"additionalProperties": {
56+
"type": "string"
57+
}
3658
}
3759
},
38-
"required": ["title", "prefix", "mandatory_options"]
60+
"required": [
61+
"title",
62+
"prefix",
63+
"mandatory_options"
64+
]
3965
}
4066
},
4167
"links": {
4268
"type": "object",
43-
"description": "All extra link definitions. Key is the link 'option' name.",
69+
"description": "Extra Sphinx-Needs link type definitions. Each key is the link option name used in directives (e.g. ``implements``, ``satisfies``).",
4470
"additionalProperties": {
4571
"type": "object",
72+
"description": "A bidirectional link type definition.",
4673
"properties": {
47-
"incoming": { "type": "string" },
48-
"outgoing": { "type": "string" }
74+
"incoming": {
75+
"type": "string",
76+
"description": "Label shown on the target side of the link (e.g. 'is implemented by')."
77+
},
78+
"outgoing": {
79+
"type": "string",
80+
"description": "Label shown on the source side of the link (e.g. 'implements')."
81+
}
4982
},
50-
"required": ["incoming", "outgoing"]
83+
"required": [
84+
"incoming",
85+
"outgoing"
86+
]
5187
}
5288
}
5389
},
54-
"required": ["types", "links"]
55-
}
90+
"required": [
91+
"types",
92+
"links"
93+
]
94+
}

src/extensions/score_sphinx_bundle/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"sphinxcontrib.mermaid",
3232
"needs_config_writer",
3333
"score_sync_toml",
34+
"sphinx-jsonschema",
3435
]
3536

3637

src/requirements.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ needs-config-writer == 0.2.4
3333
# Need this to enable non bazel execution
3434
bazel-runfiles
3535

36+
# Render JSON Schema files as documentation tables
37+
sphinx-jsonschema
38+
3639
# Local development
3740
pytest
3841
basedpyright

src/requirements.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ docutils==0.22.4 \
446446
# myst-parser
447447
# pydata-sphinx-theme
448448
# sphinx
449+
# sphinx-jsonschema
449450
esbonio==0.16.5 \
450451
--hash=sha256:04ba926e3603f7b1fde1abc690b47afd60749b64b1029b6bce8e1de0bb284921 \
451452
--hash=sha256:acab2e16c6cf8f7232fb04e0d48514ce50566516b1f6fcf669ccf2f247e8b10f
@@ -536,6 +537,10 @@ jinja2==3.1.6 \
536537
# sphinx
537538
# sphinx-collections
538539
# sphinxcontrib-mermaid
540+
jsonpointer==3.1.1 \
541+
--hash=sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900 \
542+
--hash=sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca
543+
# via sphinx-jsonschema
539544
jsonschema-rs==0.37.4 \
540545
--hash=sha256:03b34f911e99343fc388651688683010daee538a3cf8cf86a7997bca28fdf16b \
541546
--hash=sha256:0f17a61deb557faa57dffb9596e4f022873404f935114367788b1eebdec2bb00 \
@@ -1202,6 +1207,7 @@ pyyaml==6.0.3 \
12021207
--hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0
12031208
# via
12041209
# myst-parser
1210+
# sphinx-jsonschema
12051211
# sphinxcontrib-mermaid
12061212
requests==2.33.1 \
12071213
--hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \
@@ -1210,6 +1216,7 @@ requests==2.33.1 \
12101216
# pygithub
12111217
# requests-file
12121218
# sphinx
1219+
# sphinx-jsonschema
12131220
# sphinx-needs
12141221
requests-file==2.1.0 \
12151222
--hash=sha256:0f549a3f3b0699415ac04d167e9cb39bccfb730cb832b4d20be3d9867356e658 \
@@ -1275,7 +1282,10 @@ sphinx-data-viewer==0.1.5 \
12751282
sphinx-design==0.7.0 \
12761283
--hash=sha256:d2a3f5b19c24b916adb52f97c5f00efab4009ca337812001109084a740ec9b7a \
12771284
--hash=sha256:f82bf179951d58f55dca78ab3706aeafa496b741a91b1911d371441127d64282
1278-
# via -r requirements.in
1285+
# via -r src/requirements.in
1286+
sphinx-jsonschema==1.19.2 \
1287+
--hash=sha256:1a48954217c2b3c6759c89b9ddd2c8e5b668b8730564e0283b009f23932be150
1288+
# via -r src/requirements.in
12791289
sphinx-needs[plotting]==8.0.0 \
12801290
--hash=sha256:540c380c074d4088a557ea353e91513bfc1cb7712b10925c13ac9e5ebb7be091 \
12811291
--hash=sha256:c4336ee0e3c949eff9eb11a14910f7b6b68cb8284d731cfddf97694037337674

0 commit comments

Comments
 (0)