Skip to content

Commit eb5eef1

Browse files
743 new schema editor panel documentation view of the current schema (#747) (#749)
* Schema to markdown function added. * Added documentation panel. * Added documentation panel with download as markdown function. * Removed some unused code. * Added light mode support to documentation panel and changed DocumentationPanel.vue markdown to html functions with showdown library. * - Linked properties to their definitions - Added example blocks and default values - Used describeSchema for detailed descriptions - Documented oneOf, anyOf, allOf, if/then/else, not, etc. * improve different things * fix minor things * refactor * minor improvements * hide only large enum values in spoiler * fix sub schemas are properly linked * make documentation code examples adapt to the current format * add uni-directional synchronization between selected element from other panels to documentation panel * minor bugfix * fix oneOf reference and other things * draw missing graph edges * show message instead of error in docs view for empty schema * show default and examples only if in document * use same header style as in other panels and include documentation settings in it * add documentation panel to settings * show constraints only when needed * reformat the code * remove unused line * establish connection of selected element also in other direction: markdown clicks are synchronized with other panels * add schema title * refactor anchor code * make titles self refer to make it clickable * remove duplicate entries * add tests * do not reformat markdown files in markdown test folder * never repeat multiple occurrences in main document * fix infinite loop for circular array schemas * fix possible typeerror * add tests * used preprocessed schema for schema2docs and adjust tests to it * add more test cases for schema 2 docs * make unit test and formatting workflow also trigger for PRs from forks * update to proper showndown import * try fix dependency issue with showndown * try fix dependency issue with showndown * add showndown types * replace union with old style as union is very new and not all browsers support it * replace isDisjoint with old style as union is very new and not all browsers support it * prettify --------- Co-authored-by: MertAliBarlas <[email protected]>
1 parent 521d6a8 commit eb5eef1

47 files changed

Lines changed: 2860 additions & 14 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/npm-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Node.js CI
22

3-
on: [push, workflow_dispatch]
3+
on: [push, workflow_dispatch, pull_request]
44

55
jobs:
66
build:

meta_configurator/.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
node_modules
33
.vscode
44
dist
5+
src/utility/documentation/__tests__/**/*.md

meta_configurator/package-lock.json

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

meta_configurator/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"primeicons": "^7.0.0",
5656
"primevue": "^4.2.5",
5757
"quicktype-core": "^23.0.171",
58+
"showdown": "^2.1.0",
5859
"vue": "^3.5.13",
5960
"vue-flow": "^0.3.0",
6061
"vue-router": "^4.3.2",
@@ -68,6 +69,7 @@
6869
"@types/jsdom": "^21.1.1",
6970
"@types/json-pointer": "^1.0.31",
7071
"@types/node": "^18.16.8",
72+
"@types/showdown": "^2.0.6",
7173
"@types/yaml": "^1.9.7",
7274
"@typescript-eslint/eslint-plugin": "^5.59.0",
7375
"@vitejs/plugin-vue": "^4.2.3",

meta_configurator/src/components/panels/defaultPanelTypes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import DebugPanel from '@/components/panels/debug-panel/DebugPanel.vue';
88
import AiPromptsPanel from '@/components/panels/ai-prompts/AiPromptsPanel.vue';
99
import ListAnalysisPanel from './list-analysis/ListAnalysisPanel.vue';
1010
import TestPanel from '@/components/panels/test-panel/TestPanel.vue';
11+
import DocumentationPanel from '@/components/panels/documentation/DocumentationPanel.vue';
1112

1213
export const panelTypeTextEditor: PanelTypeDefinition = {
1314
getComponent: () => CodeEditorPanel,
@@ -65,6 +66,14 @@ export const panelTypeTest: PanelTypeDefinition = {
6566
name: 'test',
6667
};
6768

69+
export const panelTypeDocementation: PanelTypeDefinition = {
70+
getComponent: () => DocumentationPanel,
71+
supportedModes: [SessionMode.SchemaEditor],
72+
label: 'Markdown documentation of the schema',
73+
icon: 'fa-solid fa-book',
74+
name: 'documentation',
75+
};
76+
6877
/**
6978
* Registers the default panel types, which are GuiEditor, TextEditor, Schema Diagram, Ai Prompts and Debug.
7079
*/
@@ -76,4 +85,5 @@ export function registerDefaultPanelTypes() {
7685
panelTypeRegistry.registerPanelType('tableView', panelTypeListAnalysis);
7786
panelTypeRegistry.registerPanelType('debug', panelTypeDebug);
7887
panelTypeRegistry.registerPanelType('test', panelTypeTest);
88+
panelTypeRegistry.registerPanelType('documentation', panelTypeDocementation);
7989
}
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
<script setup lang="ts">
2+
import {SessionMode} from '@/store/sessionMode';
3+
import {computed, onMounted, onUnmounted, ref, watch} from 'vue';
4+
import {getSchemaForMode, getSessionForMode} from '@/data/useDataLink';
5+
import {schemaToMarkdown} from '@/utility/documentation/schemaToMarkdown';
6+
import {downloadMarkdown} from '@/components/panels/documentation/downloadMarkdown';
7+
import showdown from 'showdown';
8+
import type {Path} from '@/utility/path';
9+
import DocumentationSettingsPanel from '@/components/panels/documentation/DocumentationSettingsPanel.vue';
10+
import {asciiToPath, pathToAscii} from '@/utility/pathUtils';
11+
import {getSchemaTitle} from '@/schema/schemaReadingUtils';
12+
13+
const props = defineProps<{
14+
sessionMode: SessionMode;
15+
}>();
16+
17+
const schema = getSchemaForMode(SessionMode.DataEditor);
18+
const schemaSession = getSessionForMode(SessionMode.SchemaEditor);
19+
const markdown = computed(() =>
20+
schemaToMarkdown(schema.schemaPreprocessed.value, getSchemaTitle(schema.schemaWrapper.value))
21+
);
22+
23+
const converter = new showdown.Converter({
24+
tables: true,
25+
ghCompatibleHeaderId: true,
26+
requireSpaceBeforeHeadingText: true,
27+
});
28+
const renderedHtml = computed(() => converter.makeHtml(markdown.value));
29+
30+
// DOM ref for rendered markdown
31+
const docsRef = ref<HTMLElement | null>(null);
32+
33+
// scroll when selection changes
34+
watch(
35+
() => schemaSession.currentSelectedElement.value,
36+
path => scrollToPath(path),
37+
{deep: true}
38+
);
39+
40+
function scrollToPath(path: Path | null) {
41+
if (!path) return;
42+
const anchorId = pathToAscii(path);
43+
const el = document.getElementById(anchorId);
44+
el?.scrollIntoView({behavior: 'smooth', block: 'start'});
45+
}
46+
47+
function handleDownloadClick() {
48+
downloadMarkdown(markdown.value);
49+
}
50+
51+
// anchor click handler
52+
function onAnchorClick(evt: MouseEvent) {
53+
const target = evt.target as HTMLElement;
54+
if (target.tagName !== 'A') return;
55+
const href = (target as HTMLAnchorElement).getAttribute('href');
56+
if (!href?.startsWith('#')) return;
57+
58+
evt.preventDefault(); // stop browser default jump
59+
const id = href.slice(1); // remove '#'
60+
try {
61+
const path = asciiToPath(id); // reverse mapping
62+
schemaSession.currentSelectedElement.value = path; // sync to other view
63+
scrollToPath(path); // smooth scroll (optional)
64+
} catch (e) {
65+
console.warn('Invalid anchor id:', id, e);
66+
}
67+
}
68+
69+
onMounted(() => docsRef.value?.addEventListener('click', onAnchorClick));
70+
onUnmounted(() => docsRef.value?.removeEventListener('click', onAnchorClick));
71+
</script>
72+
73+
<template>
74+
<div class="documentation-panel">
75+
<DocumentationSettingsPanel />
76+
<div ref="docsRef" class="rendered-docs" v-html="renderedHtml"></div>
77+
<div style="text-align: center; margin-top: 1rem">
78+
<button class="download-btn" @click="handleDownloadClick">Download as Markdown</button>
79+
</div>
80+
</div>
81+
</template>
82+
83+
<style>
84+
.documentation-panel {
85+
height: 100%;
86+
display: flex;
87+
flex-direction: column;
88+
overflow: hidden;
89+
}
90+
91+
.heading {
92+
font-size: 24px;
93+
font-weight: bold;
94+
text-align: center;
95+
margin: 1rem auto 0.5rem;
96+
color: var(--p-primary-active-color);
97+
text-transform: uppercase;
98+
letter-spacing: 0.5px;
99+
}
100+
101+
.rendered-docs {
102+
flex: 1;
103+
overflow-y: auto;
104+
padding: 1rem 1.5rem;
105+
font-size: 16px;
106+
line-height: 1.6;
107+
color: var(--p-primary-active-color);
108+
background-color: var(--p-primary-background);
109+
white-space: normal;
110+
font-family: 'Segoe UI', sans-serif;
111+
scroll-behavior: smooth;
112+
position: relative;
113+
}
114+
115+
.rendered-docs h1[id],
116+
.rendered-docs h2[id],
117+
.rendered-docs h3[id],
118+
.rendered-docs h4[id] {
119+
scroll-margin-top: 80px;
120+
}
121+
122+
.rendered-docs h1,
123+
.rendered-docs h2,
124+
.rendered-docs h3,
125+
.rendered-docs h4,
126+
.rendered-docs p,
127+
.rendered-docs td,
128+
.rendered-docs th {
129+
color: var(--p-primary-active-color);
130+
}
131+
132+
.rendered-docs h1,
133+
.rendered-docs h2,
134+
.rendered-docs h3,
135+
.rendered-docs h4 {
136+
font-weight: bold;
137+
display: block;
138+
margin-top: 1.25em;
139+
}
140+
141+
.rendered-docs h1 {
142+
font-size: 32px;
143+
margin: 2rem 0 1rem;
144+
}
145+
146+
.rendered-docs h2 {
147+
font-size: 26px;
148+
margin: 1.75rem 0 0.75rem;
149+
}
150+
151+
.rendered-docs h3 {
152+
font-size: 22px;
153+
margin: 1.5rem 0 0.5rem;
154+
}
155+
156+
.rendered-docs h4 {
157+
font-size: 18px;
158+
margin: 1.25rem 0 0.5rem;
159+
}
160+
/* Style for all unordered lists in rendered docs */
161+
.rendered-docs ul {
162+
list-style-type: disc;
163+
margin: 0.8em 0 0.8em 1.5em; /* vertical spacing and indentation */
164+
padding-left: 0;
165+
}
166+
167+
/* Nested unordered lists get increased indentation and different bullet style */
168+
.rendered-docs ul ul {
169+
list-style-type: circle;
170+
margin-left: 1.5em;
171+
margin-top: 0.4em;
172+
margin-bottom: 0.4em;
173+
}
174+
175+
.rendered-docs ul ul ul {
176+
list-style-type: square;
177+
margin-left: 1.5em;
178+
margin-top: 0.3em;
179+
margin-bottom: 0.3em;
180+
}
181+
182+
/* List items spacing */
183+
.rendered-docs li {
184+
margin: 0.2em 0;
185+
line-height: 1.4;
186+
}
187+
188+
/* Links inside list items */
189+
.rendered-docs li a {
190+
color: var(--p-primary-active-color);
191+
text-decoration: none;
192+
}
193+
194+
.rendered-docs li a:hover {
195+
text-decoration: underline;
196+
}
197+
198+
.rendered-docs hr {
199+
border: none;
200+
border-top: 1px solid var(--p-border-color, #555);
201+
margin: 2rem 0;
202+
}
203+
204+
.rendered-docs table {
205+
border-collapse: collapse;
206+
width: 100%;
207+
margin-top: 1em;
208+
margin-bottom: 2em;
209+
background-color: var(--p-primary-background);
210+
font-size: 15px;
211+
}
212+
213+
.rendered-docs th,
214+
.rendered-docs td {
215+
border: 1px solid var(--p-primary-background, #444);
216+
padding: 8px 12px;
217+
text-align: left;
218+
}
219+
220+
.rendered-docs th {
221+
background-color: var(--p-primary-background);
222+
font-weight: bold;
223+
}
224+
225+
.rendered-docs td {
226+
background-color: var(--p-primary-background);
227+
}
228+
229+
.rendered-docs pre {
230+
background-color: var(--p-highlight-background, var(--p-primary-hover-color));
231+
color: var(--p-primary-active-color);
232+
padding: 12px;
233+
border-radius: 4px;
234+
overflow-x: auto;
235+
margin-top: 1em;
236+
}
237+
238+
.download-btn {
239+
background-color: var(--p-primary-background);
240+
color: var(--p-primary-active-color);
241+
border: 1px solid var(--p-border-color, #666);
242+
padding: 0.5rem 1rem;
243+
border-radius: 6px;
244+
font-size: 15px;
245+
cursor: pointer;
246+
transition: background 0.2s;
247+
}
248+
249+
.download-btn:hover {
250+
background-color: var(--p-highlight-color);
251+
}
252+
</style>

0 commit comments

Comments
 (0)