lutaml-jsonschema 0.1.5 → 0.1.6
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/.rubocop_todo.yml +3 -49
- data/frontend/src/__tests__/useMarkdownLite.test.ts +41 -0
- data/frontend/src/__tests__/useSchemaTypes.test.ts +48 -10
- data/frontend/src/components/AppSidebar.vue +74 -7
- data/frontend/src/components/SchemaBuilder.vue +419 -38
- data/frontend/src/composables/useJsonViewer.ts +82 -0
- data/frontend/src/composables/useMarkdownLite.ts +31 -0
- data/frontend/src/composables/useSchemaTypes.ts +77 -18
- data/frontend/src/composables/useSeeMore.ts +15 -0
- data/frontend/src/style.css +43 -0
- data/frontend/src/views/HomeView.vue +109 -5
- data/lib/lutaml/jsonschema/version.rb +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7489a2b5deaa74c751691afdf57939c046e29d6a853774462ce5587e05dcbcf3
|
|
4
|
+
data.tar.gz: fca882189c10df105bc30df80c5fe34cc0108ca82b87420e638170ec7a62d1e3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b27dd39b382a08e4fc1aa58ae1b9803ffbeee75fc3db6e3df0261871ce43d3aabfbe7cc863207b190c5a88e52212fca6f43acd40506d4f82088094a0ffd57ebf
|
|
7
|
+
data.tar.gz: d3af571ef80959e85a9c3e7ccaebb0a5e721d94348616a873edd25f6c488c596542ca0a8a836b94917a34bfdbc675cc2dc50f844995d7c5a055fc44348987926
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-05-07
|
|
3
|
+
# on 2026-05-07 10:44:46 UTC using RuboCop version 1.86.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -11,15 +11,7 @@ Gemspec/RequiredRubyVersion:
|
|
|
11
11
|
Exclude:
|
|
12
12
|
- 'lutaml-jsonschema.gemspec'
|
|
13
13
|
|
|
14
|
-
# Offense count:
|
|
15
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
16
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
17
|
-
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
18
|
-
Layout/ArgumentAlignment:
|
|
19
|
-
Exclude:
|
|
20
|
-
- 'lib/lutaml/jsonschema/spa/spa_builder.rb'
|
|
21
|
-
|
|
22
|
-
# Offense count: 2
|
|
14
|
+
# Offense count: 1
|
|
23
15
|
# This cop supports safe autocorrection (--autocorrect).
|
|
24
16
|
# Configuration parameters: EnforcedStyleAlignWith.
|
|
25
17
|
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
|
@@ -27,21 +19,7 @@ Layout/BlockAlignment:
|
|
|
27
19
|
Exclude:
|
|
28
20
|
- 'lib/lutaml/jsonschema/spa/spa_builder.rb'
|
|
29
21
|
|
|
30
|
-
# Offense count:
|
|
31
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
32
|
-
Layout/BlockEndNewline:
|
|
33
|
-
Exclude:
|
|
34
|
-
- 'lib/lutaml/jsonschema/spa/spa_builder.rb'
|
|
35
|
-
|
|
36
|
-
# Offense count: 2
|
|
37
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
38
|
-
# Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
|
|
39
|
-
# SupportedStylesAlignWith: start_of_line, relative_to_receiver
|
|
40
|
-
Layout/IndentationWidth:
|
|
41
|
-
Exclude:
|
|
42
|
-
- 'lib/lutaml/jsonschema/spa/spa_builder.rb'
|
|
43
|
-
|
|
44
|
-
# Offense count: 31
|
|
22
|
+
# Offense count: 28
|
|
45
23
|
# This cop supports safe autocorrection (--autocorrect).
|
|
46
24
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
47
25
|
# URISchemes: http, https
|
|
@@ -61,13 +39,6 @@ Layout/LineLength:
|
|
|
61
39
|
- 'spec/lutaml/schema_set_resolution_spec.rb'
|
|
62
40
|
- 'spec/lutaml/spa_builder_spec.rb'
|
|
63
41
|
|
|
64
|
-
# Offense count: 2
|
|
65
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
66
|
-
# Configuration parameters: AllowInHeredoc.
|
|
67
|
-
Layout/TrailingWhitespace:
|
|
68
|
-
Exclude:
|
|
69
|
-
- 'lib/lutaml/jsonschema/spa/spa_builder.rb'
|
|
70
|
-
|
|
71
42
|
# Offense count: 2
|
|
72
43
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
73
44
|
Lint/DuplicateBranch:
|
|
@@ -136,25 +107,8 @@ Naming/PredicateMethod:
|
|
|
136
107
|
Exclude:
|
|
137
108
|
- 'lib/lutaml/jsonschema/schema_set.rb'
|
|
138
109
|
|
|
139
|
-
# Offense count: 2
|
|
140
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
141
|
-
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
|
|
142
|
-
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
|
|
143
|
-
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
|
144
|
-
# FunctionalMethods: let, let!, subject, watch
|
|
145
|
-
# AllowedMethods: lambda, proc, it
|
|
146
|
-
Style/BlockDelimiters:
|
|
147
|
-
Exclude:
|
|
148
|
-
- 'lib/lutaml/jsonschema/spa/spa_builder.rb'
|
|
149
|
-
|
|
150
110
|
# Offense count: 2
|
|
151
111
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
152
112
|
Style/IdenticalConditionalBranches:
|
|
153
113
|
Exclude:
|
|
154
114
|
- 'spec/lutaml/spa_builder_spec.rb'
|
|
155
|
-
|
|
156
|
-
# Offense count: 1
|
|
157
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
158
|
-
Style/MapIntoArray:
|
|
159
|
-
Exclude:
|
|
160
|
-
- 'lib/lutaml/jsonschema/spa/spa_builder.rb'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { renderInlineMarkdown } from '../composables/useMarkdownLite'
|
|
3
|
+
|
|
4
|
+
describe('renderInlineMarkdown', () => {
|
|
5
|
+
it('returns empty for empty string', () => {
|
|
6
|
+
expect(renderInlineMarkdown('')).toBe('')
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('renders bold text', () => {
|
|
10
|
+
expect(renderInlineMarkdown('**bold**')).toBe('<strong>bold</strong>')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('renders italic text', () => {
|
|
14
|
+
expect(renderInlineMarkdown('*italic*')).toBe('<em>italic</em>')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('renders inline code', () => {
|
|
18
|
+
expect(renderInlineMarkdown('`code`')).toBe('<code class="md-code">code</code>')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('renders links', () => {
|
|
22
|
+
const result = renderInlineMarkdown('[click](https://example.com)')
|
|
23
|
+
expect(result).toContain('<a href="https://example.com"')
|
|
24
|
+
expect(result).toContain('class="md-link"')
|
|
25
|
+
expect(result).toContain('>click</a>')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('escapes HTML', () => {
|
|
29
|
+
expect(renderInlineMarkdown('<b>no</b>')).toBe('<b>no</b>')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('returns plain text unchanged', () => {
|
|
33
|
+
expect(renderInlineMarkdown('hello world')).toBe('hello world')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('handles mixed formatting', () => {
|
|
37
|
+
const result = renderInlineMarkdown('Use `method` for **special** cases.')
|
|
38
|
+
expect(result).toContain('<code class="md-code">method</code>')
|
|
39
|
+
expect(result).toContain('<strong>special</strong>')
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -38,8 +38,16 @@ describe('primaryType', () => {
|
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
describe('displayType', () => {
|
|
41
|
-
it('shows array
|
|
42
|
-
expect(displayType(prop({ type: 'array', itemsType: 'string' }))).toBe('array
|
|
41
|
+
it('shows "array of X" for arrays', () => {
|
|
42
|
+
expect(displayType(prop({ type: 'array', itemsType: 'string' }))).toBe('array of string')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('shows resolved title for $ref props', () => {
|
|
46
|
+
expect(displayType(prop({ type: 'object', ref: '#/definitions/Addr' }), 'Address')).toBe('Address')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('ignores resolved title when no ref', () => {
|
|
50
|
+
expect(displayType(prop({ type: 'object' }), 'Address')).toBe('object')
|
|
43
51
|
})
|
|
44
52
|
|
|
45
53
|
it('shows type (format) when format is set', () => {
|
|
@@ -225,24 +233,34 @@ describe('hasConstraints', () => {
|
|
|
225
233
|
})
|
|
226
234
|
|
|
227
235
|
describe('humanizeConstraints', () => {
|
|
228
|
-
it('returns string range constraint', () => {
|
|
236
|
+
it('returns string range constraint with bracket notation', () => {
|
|
229
237
|
const chips = humanizeConstraints(prop({ type: 'string', minLength: 1, maxLength: 100 }))
|
|
230
|
-
expect(chips).toEqual([{ label: '1..100 characters' }])
|
|
238
|
+
expect(chips).toEqual([{ label: '[ 1 .. 100 ] characters' }])
|
|
231
239
|
})
|
|
232
240
|
|
|
233
|
-
it('returns
|
|
241
|
+
it('returns non-empty for minLength === 1', () => {
|
|
242
|
+
const chips = humanizeConstraints(prop({ type: 'string', minLength: 1 }))
|
|
243
|
+
expect(chips).toEqual([{ label: 'non-empty' }])
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it('returns numeric range constraint with bracket notation', () => {
|
|
234
247
|
const chips = humanizeConstraints(prop({ type: 'integer', minimum: 0, maximum: 100 }))
|
|
235
|
-
expect(chips.map(c => c.label)).toEqual(['
|
|
248
|
+
expect(chips.map(c => c.label)).toEqual(['[ 0 .. 100 ]'])
|
|
236
249
|
})
|
|
237
250
|
|
|
238
|
-
it('returns exclusive bounds
|
|
251
|
+
it('returns exclusive bounds combined as range', () => {
|
|
239
252
|
const chips = humanizeConstraints(prop({ type: 'number', exclusiveMinimum: 0, exclusiveMaximum: 100 }))
|
|
240
|
-
expect(chips.map(c => c.label)).toEqual(['
|
|
253
|
+
expect(chips.map(c => c.label)).toEqual(['( 0 .. 100 )'])
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
it('returns inclusive range combined with exclusive modifier', () => {
|
|
257
|
+
const chips = humanizeConstraints(prop({ type: 'integer', minimum: 0, maximum: 100, exclusiveMinimum: 0 }))
|
|
258
|
+
expect(chips.map(c => c.label)).toEqual(['( 0 .. 100 ]'])
|
|
241
259
|
})
|
|
242
260
|
|
|
243
|
-
it('returns array range constraint', () => {
|
|
261
|
+
it('returns array range constraint with bracket notation', () => {
|
|
244
262
|
const chips = humanizeConstraints(prop({ type: 'array', minItems: 1, maxItems: 10 }))
|
|
245
|
-
expect(chips).toEqual([{ label: '1..10 items' }])
|
|
263
|
+
expect(chips).toEqual([{ label: '[ 1 .. 10 ] items' }])
|
|
246
264
|
})
|
|
247
265
|
|
|
248
266
|
it('returns unique for uniqueItems', () => {
|
|
@@ -275,6 +293,26 @@ describe('humanizeConstraints', () => {
|
|
|
275
293
|
expect(chips).toEqual([])
|
|
276
294
|
})
|
|
277
295
|
|
|
296
|
+
it('returns "non-empty" for minLength 1', () => {
|
|
297
|
+
const chips = humanizeConstraints(prop({ type: 'string', minLength: 1 }))
|
|
298
|
+
expect(chips.map(c => c.label)).toEqual(['non-empty'])
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
it('returns "= N characters" when min equals max', () => {
|
|
302
|
+
const chips = humanizeConstraints(prop({ type: 'string', minLength: 10, maxLength: 10 }))
|
|
303
|
+
expect(chips.map(c => c.label)).toEqual(['= 10 characters'])
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
it('returns "= N items" when minItems equals maxItems', () => {
|
|
307
|
+
const chips = humanizeConstraints(prop({ type: 'array', minItems: 3, maxItems: 3 }))
|
|
308
|
+
expect(chips.map(c => c.label)).toEqual(['= 3 items'])
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('returns decimal places for small multipleOf', () => {
|
|
312
|
+
const chips = humanizeConstraints(prop({ type: 'number', multipleOf: 0.01 }))
|
|
313
|
+
expect(chips.map(c => c.label)).toEqual(['decimal places <= 2'])
|
|
314
|
+
})
|
|
315
|
+
|
|
278
316
|
it('returns contentMediaType and contentEncoding', () => {
|
|
279
317
|
const chips = humanizeConstraints(prop({ contentMediaType: 'text/html', contentEncoding: 'base64' }))
|
|
280
318
|
expect(chips.map(c => c.label)).toEqual(['content-type: text/html', 'encoding: base64'])
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<aside class="sidebar" :class="{ collapsed: uiStore.sidebarCollapsed }">
|
|
2
|
+
<aside class="sidebar" :class="{ collapsed: uiStore.sidebarCollapsed }" :aria-label="`${schemaStore.metadata?.title || 'JSON Schema Docs'} navigation`">
|
|
3
3
|
<div class="sidebar-content">
|
|
4
4
|
<!-- Branding -->
|
|
5
5
|
<div class="sidebar-branding">
|
|
@@ -44,18 +44,21 @@
|
|
|
44
44
|
type="text"
|
|
45
45
|
class="search-input"
|
|
46
46
|
placeholder="Search schemas, definitions..."
|
|
47
|
+
aria-label="Search schemas and definitions"
|
|
48
|
+
@keydown="handleSearchKey"
|
|
47
49
|
/>
|
|
48
|
-
<button v-if="searchQuery" class="search-clear" @click="searchQuery = ''">
|
|
50
|
+
<button v-if="searchQuery" class="search-clear" aria-label="Clear search" @click="searchQuery = ''">
|
|
49
51
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
50
52
|
<path d="M3 3l6 6M9 3l-6 6" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
|
|
51
53
|
</svg>
|
|
52
54
|
</button>
|
|
53
55
|
</div>
|
|
54
|
-
<div v-if="
|
|
56
|
+
<div v-if="debouncedQuery && searchResults.length" class="search-results">
|
|
55
57
|
<button
|
|
56
|
-
v-for="result in searchResults"
|
|
58
|
+
v-for="(result, idx) in searchResults"
|
|
57
59
|
:key="`${result.type}:${result.name}@${result.schemaName}`"
|
|
58
60
|
class="search-result-item"
|
|
61
|
+
:class="{ active: idx === activeResultIdx }"
|
|
59
62
|
@click="goToSearchResult(result)"
|
|
60
63
|
>
|
|
61
64
|
<span class="badge" :class="resultBadgeClass(result.type)">{{ resultTypeLabel(result.type) }}</span>
|
|
@@ -63,6 +66,9 @@
|
|
|
63
66
|
<span class="search-result-schema text-muted">{{ result.schemaName }}</span>
|
|
64
67
|
</button>
|
|
65
68
|
</div>
|
|
69
|
+
<div v-else-if="debouncedQuery && !searchResults.length && searchQuery" class="search-no-results text-muted">
|
|
70
|
+
No results found
|
|
71
|
+
</div>
|
|
66
72
|
<div v-else class="schema-tree">
|
|
67
73
|
<div
|
|
68
74
|
v-for="schema in schemaStore.schemas"
|
|
@@ -72,7 +78,12 @@
|
|
|
72
78
|
<div
|
|
73
79
|
class="schema-node-header"
|
|
74
80
|
:class="{ active: schema.name === schemaStore.selectedSchemaName }"
|
|
81
|
+
role="treeitem"
|
|
82
|
+
:aria-expanded="uiStore.isSchemaExpanded(schema.name)"
|
|
83
|
+
tabindex="0"
|
|
75
84
|
@click="toggleAndSelect(schema.name)"
|
|
85
|
+
@keydown.enter="toggleAndSelect(schema.name)"
|
|
86
|
+
@keydown.space.prevent="toggleAndSelect(schema.name)"
|
|
76
87
|
>
|
|
77
88
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" :class="{ expanded: uiStore.isSchemaExpanded(schema.name) }">
|
|
78
89
|
<path d="M4 3l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
@@ -139,7 +150,7 @@
|
|
|
139
150
|
</template>
|
|
140
151
|
|
|
141
152
|
<script setup lang="ts">
|
|
142
|
-
import { ref, computed } from 'vue'
|
|
153
|
+
import { ref, computed, watch } from 'vue'
|
|
143
154
|
import { useSchemaStore } from '../stores/schemaStore'
|
|
144
155
|
import { useUiStore } from '../stores/uiStore'
|
|
145
156
|
import type { SpaSearchEntry } from '../types'
|
|
@@ -148,9 +159,23 @@ const schemaStore = useSchemaStore()
|
|
|
148
159
|
const uiStore = useUiStore()
|
|
149
160
|
|
|
150
161
|
const searchQuery = ref('')
|
|
162
|
+
const debouncedQuery = ref('')
|
|
163
|
+
const activeResultIdx = ref(-1)
|
|
164
|
+
|
|
165
|
+
let debounceTimer: ReturnType<typeof setTimeout> | null = null
|
|
166
|
+
|
|
167
|
+
watch(searchQuery, (q) => {
|
|
168
|
+
if (debounceTimer) clearTimeout(debounceTimer)
|
|
169
|
+
if (!q.trim()) {
|
|
170
|
+
debouncedQuery.value = ''
|
|
171
|
+
activeResultIdx.value = -1
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
debounceTimer = setTimeout(() => { debouncedQuery.value = q }, 300)
|
|
175
|
+
})
|
|
151
176
|
|
|
152
177
|
const searchResults = computed(() => {
|
|
153
|
-
const q =
|
|
178
|
+
const q = debouncedQuery.value.trim().toLowerCase()
|
|
154
179
|
if (!q) return []
|
|
155
180
|
return schemaStore.searchIndex.filter(entry =>
|
|
156
181
|
entry.name.toLowerCase().includes(q) ||
|
|
@@ -159,6 +184,25 @@ const searchResults = computed(() => {
|
|
|
159
184
|
).slice(0, 15)
|
|
160
185
|
})
|
|
161
186
|
|
|
187
|
+
watch(searchResults, () => { activeResultIdx.value = -1 })
|
|
188
|
+
|
|
189
|
+
function handleSearchKey(event: KeyboardEvent) {
|
|
190
|
+
if (event.key === 'ArrowDown') {
|
|
191
|
+
activeResultIdx.value = Math.min(activeResultIdx.value + 1, searchResults.value.length - 1)
|
|
192
|
+
event.preventDefault()
|
|
193
|
+
} else if (event.key === 'ArrowUp') {
|
|
194
|
+
activeResultIdx.value = Math.max(0, activeResultIdx.value - 1)
|
|
195
|
+
event.preventDefault()
|
|
196
|
+
} else if (event.key === 'Enter') {
|
|
197
|
+
const result = searchResults.value[activeResultIdx.value]
|
|
198
|
+
if (result) goToSearchResult(result)
|
|
199
|
+
activeResultIdx.value = -1
|
|
200
|
+
} else if (event.key === 'Escape') {
|
|
201
|
+
searchQuery.value = ''
|
|
202
|
+
activeResultIdx.value = -1
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
162
206
|
function goToSearchResult(result: SpaSearchEntry) {
|
|
163
207
|
schemaStore.selectSchema(result.schemaName)
|
|
164
208
|
if (result.type === 'definition') {
|
|
@@ -167,6 +211,7 @@ function goToSearchResult(result: SpaSearchEntry) {
|
|
|
167
211
|
schemaStore.selectProperty(result.name)
|
|
168
212
|
}
|
|
169
213
|
searchQuery.value = ''
|
|
214
|
+
debouncedQuery.value = ''
|
|
170
215
|
uiStore.closeDetailPanel()
|
|
171
216
|
}
|
|
172
217
|
|
|
@@ -544,10 +589,17 @@ function selectDefinition(schemaName: string, defName: string) {
|
|
|
544
589
|
transition: background var(--transition-fast);
|
|
545
590
|
}
|
|
546
591
|
|
|
547
|
-
.search-result-item:hover
|
|
592
|
+
.search-result-item:hover,
|
|
593
|
+
.search-result-item.active {
|
|
548
594
|
background: var(--bg-hover);
|
|
549
595
|
}
|
|
550
596
|
|
|
597
|
+
.search-no-results {
|
|
598
|
+
padding: var(--space-3) var(--space-2);
|
|
599
|
+
font-size: var(--text-xs);
|
|
600
|
+
text-align: center;
|
|
601
|
+
}
|
|
602
|
+
|
|
551
603
|
.search-result-name {
|
|
552
604
|
flex: 1;
|
|
553
605
|
color: var(--text-primary);
|
|
@@ -629,4 +681,19 @@ function selectDefinition(schemaName: string, defName: string) {
|
|
|
629
681
|
.footer-text a:hover {
|
|
630
682
|
text-decoration: underline;
|
|
631
683
|
}
|
|
684
|
+
|
|
685
|
+
@media (max-width: 768px) {
|
|
686
|
+
.sidebar {
|
|
687
|
+
position: fixed;
|
|
688
|
+
top: 0;
|
|
689
|
+
left: 0;
|
|
690
|
+
bottom: 0;
|
|
691
|
+
z-index: 40;
|
|
692
|
+
box-shadow: var(--shadow-lg);
|
|
693
|
+
}
|
|
694
|
+
.sidebar.collapsed {
|
|
695
|
+
transform: translateX(-100%);
|
|
696
|
+
width: 280px;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
632
699
|
</style>
|