lutaml-jsonschema 0.1.3 → 0.1.4
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 +4 -4
- data/frontend/src/components/AppSidebar.vue +10 -0
- data/frontend/src/components/DetailPanel.vue +45 -1
- data/frontend/src/components/SchemaBuilder.vue +18 -2
- data/frontend/src/types.ts +3 -0
- data/frontend/src/views/HomeView.vue +184 -10
- data/lib/lutaml/jsonschema/spa/spa_builder.rb +3 -0
- data/lib/lutaml/jsonschema/spa/spa_schema.rb +6 -0
- data/lib/lutaml/jsonschema/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a31e1dc445c583474f10cf52d8468991193679ab428af9d46a0f760492373a2d
|
|
4
|
+
data.tar.gz: 7dfe7fd154e030c64a9670b4d0c694b83e397fa8cff9d08d83222869bbfc1917
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a884595f8021d51474b547a1a06087aec67a5286250ba493f74657f8d9c7e3b8fdfc089c2cad865a90b9fceff984f877f1376c82adceb0928cfc33807b765c7
|
|
7
|
+
data.tar.gz: f01cba83ee80adda6d6bc5ef16494fd23bbee7f0258759f4ea7ddc55305b9c535ab5c2ac4a0be15d8acc5fcbfef8d8f81b5a6655309501d3e2a9cde7f20bb475
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
>
|
|
63
63
|
<span class="badge badge-definition-sm">D</span>
|
|
64
64
|
<span class="tree-item-name">{{ def.title || def.name }}</span>
|
|
65
|
+
<span class="tree-item-count">{{ def.properties.length }}</span>
|
|
65
66
|
</div>
|
|
66
67
|
</div>
|
|
67
68
|
</div>
|
|
@@ -342,6 +343,15 @@ function selectDefinition(schemaName: string, defName: string) {
|
|
|
342
343
|
text-overflow: ellipsis;
|
|
343
344
|
}
|
|
344
345
|
|
|
346
|
+
.tree-item-count {
|
|
347
|
+
font-size: 10px;
|
|
348
|
+
color: var(--text-muted);
|
|
349
|
+
background: var(--bg-primary);
|
|
350
|
+
padding: 0px 4px;
|
|
351
|
+
border-radius: 2px;
|
|
352
|
+
flex-shrink: 0;
|
|
353
|
+
}
|
|
354
|
+
|
|
345
355
|
.badge-definition-sm {
|
|
346
356
|
background: var(--badge-definition-bg);
|
|
347
357
|
color: var(--badge-definition);
|
|
@@ -102,6 +102,46 @@
|
|
|
102
102
|
<td class="constraint-key">Items</td>
|
|
103
103
|
<td>{{ (item as any).property.itemsType }}</td>
|
|
104
104
|
</tr>
|
|
105
|
+
<tr v-if="(item as any).property.exclusiveMinimum != null">
|
|
106
|
+
<td class="constraint-key">Exclusive Min</td>
|
|
107
|
+
<td>{{ (item as any).property.exclusiveMinimum }}</td>
|
|
108
|
+
</tr>
|
|
109
|
+
<tr v-if="(item as any).property.exclusiveMaximum != null">
|
|
110
|
+
<td class="constraint-key">Exclusive Max</td>
|
|
111
|
+
<td>{{ (item as any).property.exclusiveMaximum }}</td>
|
|
112
|
+
</tr>
|
|
113
|
+
<tr v-if="(item as any).property.minItems != null">
|
|
114
|
+
<td class="constraint-key">Min Items</td>
|
|
115
|
+
<td>{{ (item as any).property.minItems }}</td>
|
|
116
|
+
</tr>
|
|
117
|
+
<tr v-if="(item as any).property.maxItems != null">
|
|
118
|
+
<td class="constraint-key">Max Items</td>
|
|
119
|
+
<td>{{ (item as any).property.maxItems }}</td>
|
|
120
|
+
</tr>
|
|
121
|
+
<tr v-if="(item as any).property.uniqueItems">
|
|
122
|
+
<td class="constraint-key">Unique Items</td>
|
|
123
|
+
<td>Yes</td>
|
|
124
|
+
</tr>
|
|
125
|
+
<tr v-if="(item as any).property.multipleOf != null">
|
|
126
|
+
<td class="constraint-key">Multiple Of</td>
|
|
127
|
+
<td>{{ (item as any).property.multipleOf }}</td>
|
|
128
|
+
</tr>
|
|
129
|
+
<tr v-if="(item as any).property.const != null">
|
|
130
|
+
<td class="constraint-key">Const</td>
|
|
131
|
+
<td class="font-mono">{{ (item as any).property.const }}</td>
|
|
132
|
+
</tr>
|
|
133
|
+
<tr v-if="(item as any).property.contentMediaType">
|
|
134
|
+
<td class="constraint-key">Content Type</td>
|
|
135
|
+
<td>{{ (item as any).property.contentMediaType }}</td>
|
|
136
|
+
</tr>
|
|
137
|
+
<tr v-if="(item as any).property.contentEncoding">
|
|
138
|
+
<td class="constraint-key">Content Encoding</td>
|
|
139
|
+
<td>{{ (item as any).property.contentEncoding }}</td>
|
|
140
|
+
</tr>
|
|
141
|
+
<tr v-if="(item as any).property.additionalProperties === false">
|
|
142
|
+
<td class="constraint-key">Additional Props</td>
|
|
143
|
+
<td>Denied</td>
|
|
144
|
+
</tr>
|
|
105
145
|
</tbody>
|
|
106
146
|
</table>
|
|
107
147
|
</div>
|
|
@@ -204,7 +244,11 @@ const hasConstraints = computed(() => {
|
|
|
204
244
|
const p = item.value.property
|
|
205
245
|
return p.minimum != null || p.maximum != null ||
|
|
206
246
|
p.minLength != null || p.maxLength != null ||
|
|
207
|
-
p.pattern || p.enum?.length || p.itemsType
|
|
247
|
+
p.pattern || p.enum?.length || p.itemsType ||
|
|
248
|
+
p.exclusiveMinimum != null || p.exclusiveMaximum != null ||
|
|
249
|
+
p.minItems != null || p.maxItems != null || p.uniqueItems ||
|
|
250
|
+
p.multipleOf != null || p.const != null ||
|
|
251
|
+
p.contentMediaType || p.contentEncoding
|
|
208
252
|
})
|
|
209
253
|
|
|
210
254
|
type TabId = 'overview' | 'properties'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="builder-layout">
|
|
3
3
|
<div class="builder-fields">
|
|
4
|
-
<div v-for="field in
|
|
4
|
+
<div v-for="(field, idx) in sortedFields" :key="field.prop.name" class="field-row" :class="{ 'field-row-alt': idx % 2 === 1 }">
|
|
5
5
|
<div class="field-main">
|
|
6
6
|
<input
|
|
7
7
|
type="checkbox"
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
</div>
|
|
147
147
|
</div>
|
|
148
148
|
|
|
149
|
-
<div v-if="!
|
|
149
|
+
<div v-if="!sortedFields.length" class="empty-hint">
|
|
150
150
|
<p class="text-muted">No properties defined.</p>
|
|
151
151
|
</div>
|
|
152
152
|
</div>
|
|
@@ -203,6 +203,14 @@ const copied = ref(false)
|
|
|
203
203
|
|
|
204
204
|
const fields = ref<BuilderField[]>(props.properties.map(p => createField(p, props.required, props.schema, props.allSchemas)))
|
|
205
205
|
|
|
206
|
+
const sortedFields = computed(() => {
|
|
207
|
+
return [...fields.value].sort((a, b) => {
|
|
208
|
+
if (a.isRequired && !b.isRequired) return -1
|
|
209
|
+
if (!a.isRequired && b.isRequired) return 1
|
|
210
|
+
return 0
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
|
|
206
214
|
function toggleField(field: BuilderField, checked: boolean) {
|
|
207
215
|
field.included = checked
|
|
208
216
|
if (!checked) field.expanded = false
|
|
@@ -276,6 +284,14 @@ async function copyJson() {
|
|
|
276
284
|
background: var(--bg-hover);
|
|
277
285
|
}
|
|
278
286
|
|
|
287
|
+
.field-row-alt {
|
|
288
|
+
background: var(--bg-secondary);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.field-row-alt:hover {
|
|
292
|
+
background: var(--bg-hover);
|
|
293
|
+
}
|
|
294
|
+
|
|
279
295
|
.field-main {
|
|
280
296
|
display: flex;
|
|
281
297
|
align-items: center;
|
data/frontend/src/types.ts
CHANGED
|
@@ -6,13 +6,19 @@
|
|
|
6
6
|
<div class="schema-header-info">
|
|
7
7
|
<div class="schema-title-row">
|
|
8
8
|
<h1>{{ schemaStore.selectedSchema.title || schemaStore.selectedSchema.name }}</h1>
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
<div class="schema-actions">
|
|
10
|
+
<div class="view-toggle">
|
|
11
|
+
<button class="toggle-btn" :class="{ active: viewMode === 'builder' }" @click="viewMode = 'builder'">Builder</button>
|
|
12
|
+
<button class="toggle-btn" :class="{ active: viewMode === 'source' }" @click="viewMode = 'source'">Source</button>
|
|
13
|
+
</div>
|
|
14
|
+
<button
|
|
15
|
+
v-if="schemaStore.selectedSchema.sourceJson"
|
|
16
|
+
class="btn btn-outline btn-sm"
|
|
17
|
+
@click="downloadSchema(schemaStore.selectedSchema)"
|
|
18
|
+
>
|
|
19
|
+
Download JSON
|
|
20
|
+
</button>
|
|
21
|
+
</div>
|
|
16
22
|
</div>
|
|
17
23
|
<span v-if="schemaStore.selectedSchema.title && schemaStore.selectedSchema.title !== schemaStore.selectedSchema.name" class="schema-name-hint font-mono text-muted">{{ schemaStore.selectedSchema.name }}</span>
|
|
18
24
|
<p v-if="schemaStore.selectedSchema.description" class="schema-desc text-secondary">{{ schemaStore.selectedSchema.description }}</p>
|
|
@@ -21,6 +27,11 @@
|
|
|
21
27
|
<span class="text-muted">{{ schemaStore.selectedSchema.properties.length }} properties</span>
|
|
22
28
|
<span v-if="schemaStore.selectedSchema.required.length" class="text-muted">· {{ schemaStore.selectedSchema.required.length }} required</span>
|
|
23
29
|
<span v-if="schemaStore.selectedSchema.definitions.length" class="text-muted">· {{ schemaStore.selectedSchema.definitions.length }} definitions</span>
|
|
30
|
+
<span v-if="schemaStore.selectedSchema.additionalProperties === false" class="badge badge-locked">no additional properties</span>
|
|
31
|
+
</div>
|
|
32
|
+
<div v-if="schemaStore.selectedSchema.$schema || schemaStore.selectedSchema.$id" class="schema-id-row">
|
|
33
|
+
<span v-if="schemaStore.selectedSchema.$schema" class="meta-id-chip font-mono text-muted" title="JSON Schema version">{{ schemaStore.selectedSchema.$schema }}</span>
|
|
34
|
+
<span v-if="schemaStore.selectedSchema.$id" class="meta-id-chip font-mono text-muted" title="Schema $id">{{ schemaStore.selectedSchema.$id }}</span>
|
|
24
35
|
</div>
|
|
25
36
|
<div v-if="schemaStore.selectedSchema.required.length" class="schema-required">
|
|
26
37
|
<span class="required-label text-muted">Required:</span>
|
|
@@ -35,6 +46,8 @@
|
|
|
35
46
|
</div>
|
|
36
47
|
</div>
|
|
37
48
|
|
|
49
|
+
<!-- Builder View -->
|
|
50
|
+
<template v-if="viewMode === 'builder'">
|
|
38
51
|
<!-- Properties -->
|
|
39
52
|
<div class="schema-section">
|
|
40
53
|
<SchemaBuilder
|
|
@@ -47,7 +60,13 @@
|
|
|
47
60
|
|
|
48
61
|
<!-- Definitions -->
|
|
49
62
|
<div v-if="schemaStore.selectedSchema.definitions.length" class="schema-section">
|
|
50
|
-
<
|
|
63
|
+
<div class="section-heading-row">
|
|
64
|
+
<h2 class="section-heading">Definitions</h2>
|
|
65
|
+
<div class="section-actions">
|
|
66
|
+
<button class="btn btn-ghost btn-sm" @click="expandAllDefs">Expand All</button>
|
|
67
|
+
<button class="btn btn-ghost btn-sm" @click="collapseAllDefs">Collapse All</button>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
51
70
|
<div class="def-list">
|
|
52
71
|
<div
|
|
53
72
|
v-for="def in schemaStore.selectedSchema.definitions"
|
|
@@ -86,6 +105,17 @@
|
|
|
86
105
|
</div>
|
|
87
106
|
</div>
|
|
88
107
|
</div>
|
|
108
|
+
</template>
|
|
109
|
+
|
|
110
|
+
<!-- Source JSON View -->
|
|
111
|
+
<div v-if="viewMode === 'source'" class="schema-section">
|
|
112
|
+
<div v-if="schemaStore.selectedSchema.sourceJson" class="source-viewer">
|
|
113
|
+
<pre class="source-pre"><code v-html="highlightedSource"></code></pre>
|
|
114
|
+
</div>
|
|
115
|
+
<div v-else class="source-empty">
|
|
116
|
+
<p class="text-muted">Source JSON Schema not available for this schema.</p>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
89
119
|
</div>
|
|
90
120
|
|
|
91
121
|
<!-- Landing Page -->
|
|
@@ -132,9 +162,10 @@
|
|
|
132
162
|
<span class="badge badge-type-sm">{{ schema.type || 'any' }}</span>
|
|
133
163
|
</div>
|
|
134
164
|
<div class="schema-card-stats">
|
|
135
|
-
<span>{{ schema.properties.length }}
|
|
136
|
-
<span>{{ schema.definitions.length }}
|
|
165
|
+
<span>{{ schema.properties.length }} props</span>
|
|
166
|
+
<span>{{ schema.definitions.length }} defs</span>
|
|
137
167
|
<span v-if="schema.required.length">{{ schema.required.length }} required</span>
|
|
168
|
+
<span v-if="schema.examples?.length">{{ schema.examples.length }} examples</span>
|
|
138
169
|
</div>
|
|
139
170
|
</div>
|
|
140
171
|
</div>
|
|
@@ -152,6 +183,38 @@ import type { SpaSchema } from '../types'
|
|
|
152
183
|
|
|
153
184
|
const schemaStore = useSchemaStore()
|
|
154
185
|
const expandedDefs = reactive(new Set<string>())
|
|
186
|
+
const viewMode = ref<'builder' | 'source'>('builder')
|
|
187
|
+
|
|
188
|
+
function expandAllDefs() {
|
|
189
|
+
for (const def of schemaStore.selectedSchema?.definitions ?? []) {
|
|
190
|
+
expandedDefs.add(def.name)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function collapseAllDefs() {
|
|
195
|
+
expandedDefs.clear()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const highlightedSource = computed(() => {
|
|
199
|
+
const src = schemaStore.selectedSchema?.sourceJson
|
|
200
|
+
if (!src) return ''
|
|
201
|
+
return syntaxHighlight(src)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
function syntaxHighlight(json: string): string {
|
|
205
|
+
return json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
206
|
+
.replace(/("(\\u[\da-fA-F]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, (match) => {
|
|
207
|
+
let cls = 'json-number'
|
|
208
|
+
if (/^"/.test(match)) {
|
|
209
|
+
cls = /:$/.test(match) ? 'json-key' : 'json-string'
|
|
210
|
+
} else if (/true|false/.test(match)) {
|
|
211
|
+
cls = 'json-boolean'
|
|
212
|
+
} else if (/null/.test(match)) {
|
|
213
|
+
cls = 'json-null'
|
|
214
|
+
}
|
|
215
|
+
return `<span class="${cls}">${match}</span>`
|
|
216
|
+
})
|
|
217
|
+
}
|
|
155
218
|
|
|
156
219
|
function selectSchema(name: string) {
|
|
157
220
|
schemaStore.selectSchema(name)
|
|
@@ -228,6 +291,44 @@ watch(() => schemaStore.selectedDefinitionName, (name) => {
|
|
|
228
291
|
margin: 0;
|
|
229
292
|
}
|
|
230
293
|
|
|
294
|
+
.schema-actions {
|
|
295
|
+
display: flex;
|
|
296
|
+
align-items: center;
|
|
297
|
+
gap: var(--space-2);
|
|
298
|
+
flex-shrink: 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.view-toggle {
|
|
302
|
+
display: flex;
|
|
303
|
+
border: 1px solid var(--border-medium);
|
|
304
|
+
border-radius: var(--radius-md);
|
|
305
|
+
overflow: hidden;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.toggle-btn {
|
|
309
|
+
padding: var(--space-1) var(--space-3);
|
|
310
|
+
font-size: var(--text-xs);
|
|
311
|
+
font-weight: 500;
|
|
312
|
+
color: var(--text-muted);
|
|
313
|
+
background: transparent;
|
|
314
|
+
transition: all var(--transition-fast);
|
|
315
|
+
border: none;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.toggle-btn:not(:last-child) {
|
|
319
|
+
border-right: 1px solid var(--border-medium);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.toggle-btn.active {
|
|
323
|
+
background: var(--color-primary-alpha);
|
|
324
|
+
color: var(--color-primary);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.toggle-btn:hover:not(.active) {
|
|
328
|
+
background: var(--bg-hover);
|
|
329
|
+
color: var(--text-primary);
|
|
330
|
+
}
|
|
331
|
+
|
|
231
332
|
.schema-name-hint {
|
|
232
333
|
font-size: var(--text-xs);
|
|
233
334
|
display: block;
|
|
@@ -245,6 +346,34 @@ watch(() => schemaStore.selectedDefinitionName, (name) => {
|
|
|
245
346
|
align-items: center;
|
|
246
347
|
gap: var(--space-2);
|
|
247
348
|
margin-top: var(--space-2);
|
|
349
|
+
flex-wrap: wrap;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.schema-id-row {
|
|
353
|
+
display: flex;
|
|
354
|
+
gap: var(--space-2);
|
|
355
|
+
margin-top: var(--space-2);
|
|
356
|
+
flex-wrap: wrap;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.meta-id-chip {
|
|
360
|
+
font-size: 10px;
|
|
361
|
+
background: var(--bg-secondary);
|
|
362
|
+
padding: 2px 6px;
|
|
363
|
+
border-radius: var(--radius-sm);
|
|
364
|
+
max-width: 400px;
|
|
365
|
+
overflow: hidden;
|
|
366
|
+
text-overflow: ellipsis;
|
|
367
|
+
white-space: nowrap;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.badge-locked {
|
|
371
|
+
font-size: 10px;
|
|
372
|
+
color: var(--color-orange);
|
|
373
|
+
background: var(--color-orange-alpha);
|
|
374
|
+
padding: 2px 6px;
|
|
375
|
+
border-radius: var(--radius-sm);
|
|
376
|
+
font-weight: 500;
|
|
248
377
|
}
|
|
249
378
|
|
|
250
379
|
.schema-required {
|
|
@@ -331,6 +460,51 @@ watch(() => schemaStore.selectedDefinitionName, (name) => {
|
|
|
331
460
|
color: var(--text-primary);
|
|
332
461
|
}
|
|
333
462
|
|
|
463
|
+
.section-heading-row {
|
|
464
|
+
display: flex;
|
|
465
|
+
align-items: center;
|
|
466
|
+
justify-content: space-between;
|
|
467
|
+
margin-bottom: var(--space-4);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.section-actions {
|
|
471
|
+
display: flex;
|
|
472
|
+
gap: var(--space-2);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/* Source viewer */
|
|
476
|
+
.source-viewer {
|
|
477
|
+
border-radius: var(--radius-lg);
|
|
478
|
+
overflow: hidden;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.source-pre {
|
|
482
|
+
background: var(--bg-secondary);
|
|
483
|
+
border: 1px solid var(--border-light);
|
|
484
|
+
border-radius: var(--radius-lg);
|
|
485
|
+
padding: var(--space-4);
|
|
486
|
+
font-size: var(--text-sm);
|
|
487
|
+
line-height: var(--leading-relaxed);
|
|
488
|
+
overflow-x: auto;
|
|
489
|
+
max-height: 70vh;
|
|
490
|
+
overflow-y: auto;
|
|
491
|
+
margin: 0;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.source-pre :deep(.json-key) { color: var(--color-primary-dark); }
|
|
495
|
+
.source-pre :deep(.json-string) { color: var(--color-green); }
|
|
496
|
+
.source-pre :deep(.json-number) { color: var(--color-orange); }
|
|
497
|
+
.source-pre :deep(.json-boolean) { color: var(--color-accent); }
|
|
498
|
+
.source-pre :deep(.json-null) { color: var(--text-muted); }
|
|
499
|
+
|
|
500
|
+
:root[data-theme="dark"] .source-pre :deep(.json-key) { color: var(--color-primary-light); }
|
|
501
|
+
:root[data-theme="dark"] .source-pre :deep(.json-string) { color: var(--color-teal); }
|
|
502
|
+
|
|
503
|
+
.source-empty {
|
|
504
|
+
padding: var(--space-8);
|
|
505
|
+
text-align: center;
|
|
506
|
+
}
|
|
507
|
+
|
|
334
508
|
/* Definitions */
|
|
335
509
|
.def-list {
|
|
336
510
|
display: flex;
|
|
@@ -53,6 +53,9 @@ module Lutaml
|
|
|
53
53
|
required: all_required,
|
|
54
54
|
examples: schema.examples,
|
|
55
55
|
source_json: @schema_set.source_json(name) || "",
|
|
56
|
+
dollar_schema: schema.dollar_schema,
|
|
57
|
+
dollar_id: schema.dollar_id,
|
|
58
|
+
additional_properties: schema.additional_properties,
|
|
56
59
|
)
|
|
57
60
|
end
|
|
58
61
|
|
|
@@ -15,6 +15,9 @@ module Lutaml
|
|
|
15
15
|
attribute :required, :string, collection: true
|
|
16
16
|
attribute :examples, :string, collection: true
|
|
17
17
|
attribute :source_json, :string, default: -> { "" }
|
|
18
|
+
attribute :dollar_schema, :string
|
|
19
|
+
attribute :dollar_id, :string
|
|
20
|
+
attribute :additional_properties, :boolean
|
|
18
21
|
|
|
19
22
|
json do
|
|
20
23
|
map "name", to: :name
|
|
@@ -26,6 +29,9 @@ module Lutaml
|
|
|
26
29
|
map "required", to: :required
|
|
27
30
|
map "examples", to: :examples
|
|
28
31
|
map "sourceJson", to: :source_json
|
|
32
|
+
map "$schema", to: :dollar_schema
|
|
33
|
+
map "$id", to: :dollar_id
|
|
34
|
+
map "additionalProperties", to: :additional_properties
|
|
29
35
|
end
|
|
30
36
|
end
|
|
31
37
|
end
|