metanorma-mko 1.0.0
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.
- checksums.yaml +7 -0
- data/LICENSE +25 -0
- data/README.adoc +44 -0
- data/lib/metanorma/mko/alignment.rb +53 -0
- data/lib/metanorma/mko/assets.rb +63 -0
- data/lib/metanorma/mko/bundle.rb +91 -0
- data/lib/metanorma/mko/diff.rb +97 -0
- data/lib/metanorma/mko/export.rb +27 -0
- data/lib/metanorma/mko/mcp.rb +162 -0
- data/lib/metanorma/mko/result.rb +29 -0
- data/lib/metanorma/mko/schema/collection.rb +44 -0
- data/lib/metanorma/mko/schema/document.rb +119 -0
- data/lib/metanorma/mko/schema/edge.rb +22 -0
- data/lib/metanorma/mko/schema/identifiers.rb +31 -0
- data/lib/metanorma/mko/schema/json_schema.rb +120 -0
- data/lib/metanorma/mko/schema/manifest.rb +59 -0
- data/lib/metanorma/mko/schema/unit.rb +221 -0
- data/lib/metanorma/mko/schema.rb +20 -0
- data/lib/metanorma/mko/units.rb +109 -0
- data/lib/metanorma/mko/version.rb +10 -0
- data/lib/metanorma/mko/writer.rb +62 -0
- data/lib/metanorma/mko.rb +53 -0
- metadata +148 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mko
|
|
5
|
+
module Schema
|
|
6
|
+
class Ids < Lutaml::Model::Serializable
|
|
7
|
+
attribute :canonical, :string
|
|
8
|
+
attribute :short, :string
|
|
9
|
+
# parsed identity (issue #50 follow-up 1): consumers filter and
|
|
10
|
+
# group on series/number/part — they must never decompose the
|
|
11
|
+
# canonical string themselves (a silent parse failure on the
|
|
12
|
+
# consumer side hid a whole corpus lane from retrieval)
|
|
13
|
+
attribute :series, :string
|
|
14
|
+
attribute :number, :string
|
|
15
|
+
attribute :part, :string
|
|
16
|
+
attribute :docid, :string, collection: true
|
|
17
|
+
attribute :urn, :string, collection: true
|
|
18
|
+
|
|
19
|
+
json do
|
|
20
|
+
map "canonical", to: :canonical
|
|
21
|
+
map "short", to: :short
|
|
22
|
+
map "series", to: :series
|
|
23
|
+
map "number", to: :number
|
|
24
|
+
map "part", to: :part
|
|
25
|
+
map "docid", to: :docid
|
|
26
|
+
map "urn", to: :urn
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class TitleEntry < Lutaml::Model::Serializable
|
|
31
|
+
attribute :lang, :string
|
|
32
|
+
attribute :text, :string
|
|
33
|
+
|
|
34
|
+
json do
|
|
35
|
+
map "lang", to: :lang
|
|
36
|
+
map "text", to: :text
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class DateEntry < Lutaml::Model::Serializable
|
|
41
|
+
attribute :type, :string
|
|
42
|
+
attribute :on, :string
|
|
43
|
+
|
|
44
|
+
json do
|
|
45
|
+
map "type", to: :type
|
|
46
|
+
map "on", to: :on
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class StatusInfo < Lutaml::Model::Serializable
|
|
51
|
+
attribute :stage, :string
|
|
52
|
+
attribute :substage, :string
|
|
53
|
+
attribute :abbreviation, :string
|
|
54
|
+
|
|
55
|
+
json do
|
|
56
|
+
map "stage", to: :stage
|
|
57
|
+
map "substage", to: :substage
|
|
58
|
+
map "abbreviation", to: :abbreviation
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class RelationEntry < Lutaml::Model::Serializable
|
|
63
|
+
attribute :type, :string
|
|
64
|
+
attribute :to, :string
|
|
65
|
+
|
|
66
|
+
json do
|
|
67
|
+
map "type", to: :type
|
|
68
|
+
map "to", to: :to
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class StructureNode < Lutaml::Model::Serializable
|
|
73
|
+
attribute :id, :string
|
|
74
|
+
attribute :number, :string
|
|
75
|
+
attribute :title, :string
|
|
76
|
+
attribute :children, StructureNode, collection: true,
|
|
77
|
+
default: -> { [] }
|
|
78
|
+
|
|
79
|
+
json do
|
|
80
|
+
map "id", to: :id
|
|
81
|
+
map "number", to: :number
|
|
82
|
+
map "title", to: :title
|
|
83
|
+
map "children", to: :children
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# document.json — identity, status, and the numbered structure tree.
|
|
88
|
+
class Document < Lutaml::Model::Serializable
|
|
89
|
+
attribute :ids, Ids
|
|
90
|
+
attribute :flavor, :string
|
|
91
|
+
attribute :doctype, :string
|
|
92
|
+
attribute :titles, TitleEntry, collection: true
|
|
93
|
+
attribute :edition, :string
|
|
94
|
+
attribute :languages, :string, collection: true
|
|
95
|
+
attribute :status, StatusInfo
|
|
96
|
+
# derived from succession edges (Relaton relations verbatim) —
|
|
97
|
+
# authoritative over the hand-entered status field when present
|
|
98
|
+
attribute :derived_status, :string
|
|
99
|
+
attribute :dates, DateEntry, collection: true
|
|
100
|
+
attribute :relations, RelationEntry, collection: true
|
|
101
|
+
attribute :structure, StructureNode, collection: true
|
|
102
|
+
|
|
103
|
+
json do
|
|
104
|
+
map "ids", to: :ids
|
|
105
|
+
map "flavor", to: :flavor
|
|
106
|
+
map "doctype", to: :doctype
|
|
107
|
+
map "titles", to: :titles
|
|
108
|
+
map "edition", to: :edition
|
|
109
|
+
map "languages", to: :languages
|
|
110
|
+
map "status", to: :status
|
|
111
|
+
map "derived_status", to: :derived_status, render_nil: false
|
|
112
|
+
map "dates", to: :dates
|
|
113
|
+
map "relations", to: :relations
|
|
114
|
+
map "structure", to: :structure
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mko
|
|
5
|
+
module Schema
|
|
6
|
+
# One graph edge between knowledge objects (or an external key).
|
|
7
|
+
# Kinds: part_of, cites, defines, tested_by, class_of, amends,
|
|
8
|
+
# variant_of, supersedes.
|
|
9
|
+
class Edge < Lutaml::Model::Serializable
|
|
10
|
+
attribute :from, :string
|
|
11
|
+
attribute :to, :string
|
|
12
|
+
attribute :kind, :string
|
|
13
|
+
|
|
14
|
+
json do
|
|
15
|
+
map "from", to: :from
|
|
16
|
+
map "to", to: :to
|
|
17
|
+
map "kind", to: :kind
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mko
|
|
5
|
+
module Schema
|
|
6
|
+
# identifiers.json — the document's identifiers; `parsed` carries
|
|
7
|
+
# the pubid monogem's native JSON when a flavor covers it.
|
|
8
|
+
class IdentifierInfo < Lutaml::Model::Serializable
|
|
9
|
+
attribute :original, :string
|
|
10
|
+
attribute :type, :string
|
|
11
|
+
attribute :primary, :boolean
|
|
12
|
+
attribute :parsed, :hash
|
|
13
|
+
|
|
14
|
+
json do
|
|
15
|
+
map "original", to: :original
|
|
16
|
+
map "type", to: :type
|
|
17
|
+
map "primary", to: :primary
|
|
18
|
+
map "parsed", to: :parsed
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Identifiers < Lutaml::Model::Serializable
|
|
23
|
+
attribute :identifiers, IdentifierInfo, collection: true
|
|
24
|
+
|
|
25
|
+
json do
|
|
26
|
+
map "identifiers", to: :identifiers
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mko
|
|
5
|
+
module Schema
|
|
6
|
+
# JSON Schema (draft 2020-12) generation for the MKO wire
|
|
7
|
+
# contract. The lutaml schema classes are the single source of
|
|
8
|
+
# truth: types come from the attribute declarations, wire names
|
|
9
|
+
# from the classes' json mappings (e.g. :klass renders as
|
|
10
|
+
# "class"). Consumers validate against these schemas — never
|
|
11
|
+
# against hand-written copies that drift.
|
|
12
|
+
module JsonSchema
|
|
13
|
+
PRIMITIVES = {
|
|
14
|
+
"Lutaml::Model::Type::String" => { "type" => "string" },
|
|
15
|
+
"Lutaml::Model::Type::Integer" => { "type" => "integer" },
|
|
16
|
+
"Lutaml::Model::Type::Boolean" => { "type" => "boolean" },
|
|
17
|
+
"Lutaml::Model::Type::Hash" => { "type" => "object" },
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def schema_for(klass, seen = {})
|
|
22
|
+
return { "$ref" => seen[klass] } if seen.key?(klass)
|
|
23
|
+
|
|
24
|
+
seen[klass] = "#"
|
|
25
|
+
properties = klass.attributes.each_with_object({}) do |(name, attr), h|
|
|
26
|
+
h[wire_name(klass, name)] = property_for(attr, seen)
|
|
27
|
+
end
|
|
28
|
+
{
|
|
29
|
+
"$schema" => "https://json-schema.org/draft/2020-12/schema",
|
|
30
|
+
"title" => klass.name.to_s.split("::").last,
|
|
31
|
+
"type" => "object",
|
|
32
|
+
"properties" => properties,
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The published contract: one schema per wire component and
|
|
37
|
+
# per typed payload, plus the consumer excerpt.
|
|
38
|
+
def all
|
|
39
|
+
Unit # trigger payload-class autoloads
|
|
40
|
+
schemas = {
|
|
41
|
+
"unit" => schema_for(Unit),
|
|
42
|
+
"edge" => schema_for(Edge),
|
|
43
|
+
"manifest" => schema_for(Manifest),
|
|
44
|
+
"document" => schema_for(Document),
|
|
45
|
+
"identifiers" => schema_for(Identifiers),
|
|
46
|
+
"collection" => schema_for(Schema::Collection),
|
|
47
|
+
"payload-table" => schema_for(TablePayload),
|
|
48
|
+
"payload-formula" => schema_for(FormulaPayload),
|
|
49
|
+
"payload-figure" => schema_for(FigurePayload),
|
|
50
|
+
"payload-term" => schema_for(TermPayload),
|
|
51
|
+
"payload-requirement" => schema_for(RequirementPayload),
|
|
52
|
+
"payload-reference" => schema_for(ReferencePayload),
|
|
53
|
+
"payload-clause" => schema_for(SectionPayload),
|
|
54
|
+
"payload-annex" => schema_for(SectionPayload),
|
|
55
|
+
}
|
|
56
|
+
schemas["excerpt"] = excerpt_schema(schemas)
|
|
57
|
+
schemas
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Consumer clause: text with [[u:…]] references plus resolved
|
|
61
|
+
# producer payload blocks (MN 116 §consumer-refs).
|
|
62
|
+
def excerpt_schema(payload_schemas)
|
|
63
|
+
block = {
|
|
64
|
+
"type" => "object",
|
|
65
|
+
"properties" => {
|
|
66
|
+
"unit_id" => { "type" => "string", "pattern" => "\\Au:" },
|
|
67
|
+
"type" => { "type" => "string" },
|
|
68
|
+
"docidentifier" => { "type" => "string" },
|
|
69
|
+
"edition" => { "type" => "string" },
|
|
70
|
+
"payload" => {
|
|
71
|
+
"oneOf" => payload_schemas
|
|
72
|
+
.select { |name, _| name.start_with?("payload-") }
|
|
73
|
+
.map { |_, s| s }.uniq,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
"required" => %w[unit_id type payload],
|
|
77
|
+
}
|
|
78
|
+
{
|
|
79
|
+
"$schema" => "https://json-schema.org/draft/2020-12/schema",
|
|
80
|
+
"title" => "Excerpt",
|
|
81
|
+
"type" => "object",
|
|
82
|
+
"properties" => {
|
|
83
|
+
"text" => { "type" => "string" },
|
|
84
|
+
"blocks" => { "type" => "array", "items" => block },
|
|
85
|
+
},
|
|
86
|
+
"required" => %w[text blocks],
|
|
87
|
+
}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def property_for(attr, seen)
|
|
93
|
+
type = primitive(attr) || schema_for(attr.type, seen)
|
|
94
|
+
attr.collection? ? { "type" => "array", "items" => type } : type
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def primitive(attr)
|
|
98
|
+
PRIMITIVES[attr.type.name.to_s]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# The json mappings are the wire contract; the attribute name
|
|
102
|
+
# is only the Ruby-side handle.
|
|
103
|
+
def wire_name(klass, attr_name)
|
|
104
|
+
wire_names(klass)[attr_name] || attr_name.to_s
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def wire_names(klass)
|
|
108
|
+
@wire_names ||= {}
|
|
109
|
+
@wire_names[klass] ||= begin
|
|
110
|
+
mapping = klass.mappings_for(:json)
|
|
111
|
+
mapping.mappings_hash.values.each_with_object({}) do |rule, h|
|
|
112
|
+
h[rule.to] = rule.name.to_s
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mko
|
|
5
|
+
module Schema
|
|
6
|
+
class ManifestComponent < Lutaml::Model::Serializable
|
|
7
|
+
attribute :name, :string
|
|
8
|
+
attribute :file, :string
|
|
9
|
+
attribute :media_type, :string
|
|
10
|
+
attribute :count, :integer
|
|
11
|
+
attribute :hash, :string
|
|
12
|
+
|
|
13
|
+
json do
|
|
14
|
+
map "name", to: :name
|
|
15
|
+
map "file", to: :file
|
|
16
|
+
map "media_type", to: :media_type
|
|
17
|
+
map "count", to: :count
|
|
18
|
+
map "hash", to: :hash
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Generated < Lutaml::Model::Serializable
|
|
23
|
+
attribute :tool, :string
|
|
24
|
+
attribute :schema_version, :string
|
|
25
|
+
attribute :flavor, :string
|
|
26
|
+
attribute :timestamp, :string
|
|
27
|
+
|
|
28
|
+
json do
|
|
29
|
+
map "tool", to: :tool
|
|
30
|
+
map "schema_version", to: :schema_version
|
|
31
|
+
map "flavor", to: :flavor
|
|
32
|
+
map "timestamp", to: :timestamp
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class Manifest < Lutaml::Model::Serializable
|
|
37
|
+
attribute :schema, :string
|
|
38
|
+
attribute :schema_version, :string
|
|
39
|
+
attribute :generated, Generated
|
|
40
|
+
attribute :source_file, :string
|
|
41
|
+
attribute :source_hash, :string
|
|
42
|
+
attribute :components, ManifestComponent, collection: true
|
|
43
|
+
attribute :license, :string
|
|
44
|
+
attribute :copyright, :string
|
|
45
|
+
|
|
46
|
+
json do
|
|
47
|
+
map "schema", to: :schema
|
|
48
|
+
map "schema_version", to: :schema_version
|
|
49
|
+
map "generated", to: :generated
|
|
50
|
+
map "source", to: :source_file
|
|
51
|
+
map "source-hash", to: :source_hash
|
|
52
|
+
map "components", to: :components
|
|
53
|
+
map "license", to: :license
|
|
54
|
+
map "copyright", to: :copyright
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mko
|
|
5
|
+
module Schema
|
|
6
|
+
class TableColumn < Lutaml::Model::Serializable
|
|
7
|
+
attribute :label, :string
|
|
8
|
+
# typed column: unit references the units register (#55 GAP-2)
|
|
9
|
+
attribute :type, :string
|
|
10
|
+
attribute :unit, :string
|
|
11
|
+
attribute :units, :string
|
|
12
|
+
|
|
13
|
+
json do
|
|
14
|
+
map "label", to: :label
|
|
15
|
+
map "type", to: :type, render_nil: false
|
|
16
|
+
map "unit", to: :unit, render_nil: false
|
|
17
|
+
map "units", to: :units, render_nil: false
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class TablePayload < Lutaml::Model::Serializable
|
|
22
|
+
attribute :caption, :string
|
|
23
|
+
attribute :columns, TableColumn, collection: true
|
|
24
|
+
attribute :rows, :string, collection: true, default: -> { [] }
|
|
25
|
+
# The block's native JSON object — the Mirror node tree
|
|
26
|
+
# (lossless; the serialization the JS renderer consumes).
|
|
27
|
+
# Provenance/fidelity, not an embedding form: the retrieval
|
|
28
|
+
# contract is the typed text fields.
|
|
29
|
+
attribute :mirror, :hash
|
|
30
|
+
|
|
31
|
+
json do
|
|
32
|
+
map "caption", to: :caption
|
|
33
|
+
map "columns", to: :columns
|
|
34
|
+
map "rows", to: :rows
|
|
35
|
+
map "mirror", to: :mirror
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def embed_text
|
|
39
|
+
cols = columns.map { |c| c.label + (c.unit ? " [#{c.unit}]" : "") }
|
|
40
|
+
.join(", ")
|
|
41
|
+
"Table: #{caption}; columns: #{cols}; " +
|
|
42
|
+
rows.map { |r| "row: #{r}" }.join(" | ")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class FormulaPayload < Lutaml::Model::Serializable
|
|
47
|
+
attribute :asciimath, :string
|
|
48
|
+
attribute :mathml, :string
|
|
49
|
+
# units register references (units.jsonl entry ids)
|
|
50
|
+
attribute :units, :string, collection: true, default: -> { [] }
|
|
51
|
+
# reserved: evaluation forms (typed params + expression in a
|
|
52
|
+
# declared language); absent unless authored (#55 GAP-3)
|
|
53
|
+
attribute :semantics, :hash
|
|
54
|
+
attribute :description, :string
|
|
55
|
+
|
|
56
|
+
# Derived encodings — never canonical; each names its converter
|
|
57
|
+
# (#55: re-encoding at the producer is a provenance break)
|
|
58
|
+
class DerivedForm < Lutaml::Model::Serializable
|
|
59
|
+
attribute :form, :string
|
|
60
|
+
attribute :converter, :string
|
|
61
|
+
|
|
62
|
+
json do
|
|
63
|
+
map "form", to: :form
|
|
64
|
+
map "converter", to: :converter
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
attribute :latex, DerivedForm
|
|
68
|
+
attribute :omml, DerivedForm
|
|
69
|
+
|
|
70
|
+
json do
|
|
71
|
+
map "asciimath", to: :asciimath
|
|
72
|
+
map "mathml", to: :mathml
|
|
73
|
+
map "units", to: :units, render_empty: false
|
|
74
|
+
map "semantics", to: :semantics, render_nil: false
|
|
75
|
+
map "latex", to: :latex, render_nil: false
|
|
76
|
+
map "omml", to: :omml, render_nil: false
|
|
77
|
+
map "description", to: :description
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class FigurePayload < Lutaml::Model::Serializable
|
|
82
|
+
attribute :alt, :string
|
|
83
|
+
attribute :uri, :string
|
|
84
|
+
# hash-addressed bundle asset ("assets/<sha256>"), when bytes
|
|
85
|
+
# were available at export (data URIs or assets_from)
|
|
86
|
+
attribute :asset, :string
|
|
87
|
+
attribute :caption, :string
|
|
88
|
+
# Native JSON object: the Mirror node tree (see TablePayload).
|
|
89
|
+
attribute :mirror, :hash
|
|
90
|
+
|
|
91
|
+
json do
|
|
92
|
+
map "alt", to: :alt
|
|
93
|
+
map "asset", to: :asset
|
|
94
|
+
map "uri", to: :uri
|
|
95
|
+
map "caption", to: :caption
|
|
96
|
+
map "mirror", to: :mirror
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class TermSourceEntry < Lutaml::Model::Serializable
|
|
101
|
+
attribute :citeas, :string
|
|
102
|
+
|
|
103
|
+
json do
|
|
104
|
+
map "citeas", to: :citeas
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class TermPayload < Lutaml::Model::Serializable
|
|
109
|
+
attribute :concept, :string
|
|
110
|
+
attribute :designations, :string, collection: true, default: -> { [] }
|
|
111
|
+
attribute :admitted, :string, collection: true, default: -> { [] }
|
|
112
|
+
attribute :deprecated, :string, collection: true, default: -> { [] }
|
|
113
|
+
attribute :definition, :string
|
|
114
|
+
attribute :sources, TermSourceEntry, collection: true, default: -> { [] }
|
|
115
|
+
|
|
116
|
+
json do
|
|
117
|
+
map "concept", to: :concept
|
|
118
|
+
map "designations", to: :designations
|
|
119
|
+
map "admitted", to: :admitted, render_empty: false
|
|
120
|
+
map "deprecated", to: :deprecated, render_empty: false
|
|
121
|
+
map "definition", to: :definition
|
|
122
|
+
map "sources", to: :sources
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class RequirementPayload < Lutaml::Model::Serializable
|
|
127
|
+
attribute :identifier, :string
|
|
128
|
+
attribute :klass, :string
|
|
129
|
+
attribute :obligation, :string
|
|
130
|
+
attribute :subject, :string
|
|
131
|
+
attribute :statement, :string
|
|
132
|
+
attribute :inherits, :string, collection: true, default: -> { [] }
|
|
133
|
+
|
|
134
|
+
json do
|
|
135
|
+
map "identifier", to: :identifier
|
|
136
|
+
map "class", to: :klass
|
|
137
|
+
map "obligation", to: :obligation
|
|
138
|
+
map "subject", to: :subject
|
|
139
|
+
map "statement", to: :statement
|
|
140
|
+
map "inherits", to: :inherits
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Coverage of a section unit (#56): the deterministic summary and
|
|
145
|
+
# the ordered membership. Children are unit ids in document order;
|
|
146
|
+
# the same relation the part_of edges carry bottom-up, given here
|
|
147
|
+
# top-down so tree navigation never re-derives structure from
|
|
148
|
+
# anchor strings.
|
|
149
|
+
class SectionPayload < Lutaml::Model::Serializable
|
|
150
|
+
# deterministic composition (title + covered sub-clauses) —
|
|
151
|
+
# never model-inferred; consumers may override with their own
|
|
152
|
+
# LLM summaries, but the default requires none
|
|
153
|
+
attribute :summary, :string
|
|
154
|
+
attribute :children, :string, collection: true, default: -> { [] }
|
|
155
|
+
|
|
156
|
+
json do
|
|
157
|
+
map "summary", to: :summary
|
|
158
|
+
map "children", to: :children
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
class ReferencePayload < Lutaml::Model::Serializable
|
|
163
|
+
attribute :key, :string
|
|
164
|
+
attribute :cited, :string
|
|
165
|
+
|
|
166
|
+
json do
|
|
167
|
+
map "key", to: :key
|
|
168
|
+
map "cited", to: :cited
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# One knowledge object. payload is one of the typed payloads above,
|
|
173
|
+
# chosen by type. text is the human-readable display text.
|
|
174
|
+
class Unit < Lutaml::Model::Serializable
|
|
175
|
+
attribute :id, :string
|
|
176
|
+
attribute :type, :string
|
|
177
|
+
attribute :anchor, :string
|
|
178
|
+
attribute :number, :string
|
|
179
|
+
# document order as an integer (#56): reading order is a sort,
|
|
180
|
+
# never a parse of dotted anchor strings. Position, not content —
|
|
181
|
+
# excluded from the content hash by contract.
|
|
182
|
+
attribute :ordinal, :integer
|
|
183
|
+
# the anchor a READER cites (issue #50 follow-up 2): the parent
|
|
184
|
+
# clause number for embedded objects (tables/formulas/figures),
|
|
185
|
+
# the unit's own number for top-level sections. Consumers cite
|
|
186
|
+
# identically without walking the parent chain.
|
|
187
|
+
attribute :cite_as, :string
|
|
188
|
+
attribute :title, :string
|
|
189
|
+
attribute :parent, :string
|
|
190
|
+
attribute :breadcrumb, :string, collection: true, default: -> { [] }
|
|
191
|
+
attribute :obligation, :string
|
|
192
|
+
attribute :lang, :string
|
|
193
|
+
# authoring-time situating note (#53 item 7): AI-assisted,
|
|
194
|
+
# editor-approved, versioned with the document. Wire-ready —
|
|
195
|
+
# emitted the day the authoring system ships it.
|
|
196
|
+
attribute :ai_note, :string
|
|
197
|
+
attribute :text, :string
|
|
198
|
+
attribute :payload, :hash
|
|
199
|
+
attribute :hash, :string
|
|
200
|
+
|
|
201
|
+
json do
|
|
202
|
+
map "id", to: :id
|
|
203
|
+
map "type", to: :type
|
|
204
|
+
map "anchor", to: :anchor
|
|
205
|
+
map "number", to: :number
|
|
206
|
+
map "ordinal", to: :ordinal, render_nil: false
|
|
207
|
+
map "cite_as", to: :cite_as
|
|
208
|
+
map "title", to: :title
|
|
209
|
+
map "parent", to: :parent
|
|
210
|
+
map "breadcrumb", to: :breadcrumb
|
|
211
|
+
map "obligation", to: :obligation
|
|
212
|
+
map "lang", to: :lang
|
|
213
|
+
map "ai_note", to: :ai_note, render_nil: false
|
|
214
|
+
map "text", to: :text
|
|
215
|
+
map "payload", to: :payload
|
|
216
|
+
map "hash", to: :hash
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mko
|
|
5
|
+
# The MKO wire schema. Every class is a lutaml-model Serializable with
|
|
6
|
+
# JSON mappings — one schema, framework-generated serializations only.
|
|
7
|
+
module Schema
|
|
8
|
+
autoload :Manifest, "metanorma/mko/schema/manifest"
|
|
9
|
+
autoload :Document, "metanorma/mko/schema/document"
|
|
10
|
+
autoload :StructureNode, "metanorma/mko/schema/document"
|
|
11
|
+
autoload :Unit, "metanorma/mko/schema/unit"
|
|
12
|
+
autoload :Edge, "metanorma/mko/schema/edge"
|
|
13
|
+
autoload :Identifiers, "metanorma/mko/schema/identifiers"
|
|
14
|
+
autoload :JsonSchema, "metanorma/mko/schema/json_schema"
|
|
15
|
+
autoload :Collection, "metanorma/mko/schema/collection"
|
|
16
|
+
autoload :CollectionMember, "metanorma/mko/schema/collection"
|
|
17
|
+
autoload :IdentifierInfo, "metanorma/mko/schema/identifiers"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|