Skip to content

Commit 09d0926

Browse files
committed
fix $ex $fn schema
1 parent 8b24284 commit 09d0926

File tree

6 files changed

+4227
-22582
lines changed

6 files changed

+4227
-22582
lines changed

src/jsonschema.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import { InputConfig } from "./types";
22

3-
type Whitespace = " " | "\t" | "\n" | "\r";
4-
53
type With$fn<T> = {
64
[K in keyof T]:
75
| (T[K] extends (infer U)[]
86
? With$fn<U>[] // handle arrays recursively
97
: T[K] extends object
108
? With$fn<T[K]> // handle objects recursively
119
: T[K]) // retain original type
12-
| `${Whitespace | ""}$ex${Whitespace}${string}`
13-
| `${Whitespace | ""}$fn${Whitespace}${string}`; // allow string starting with $ex or $fn with optional whitespace
10+
| `${string}$ex$fn_REPLACER`;
1411
};
1512

1613
export type JsonSchemaRoot = With$fn<InputConfig>;

src/types.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,21 @@ export type YValue = number | string | null;
2222

2323
export type InputConfig = {
2424
type: "custom:plotly-graph";
25+
/**
26+
* The time to show on load.
27+
* It can be the number of hour (e.g 12),
28+
* a duration string, e.g 100ms, 10s, 30.5m, 2h, 7d, 2w, 1M, 1y,
29+
* or relative time, i.e:
30+
* * current_minute
31+
* * current_hour
32+
* * current_day
33+
* * current_week
34+
* * current_month
35+
* * current_quarter
36+
* * current_year
37+
*/
2538
hours_to_show?: number | TimeDurationStr | RelativeTimeStr;
39+
/** Either a number (seconds), or "auto" */
2640
refresh_interval?: number | "auto"; // in seconds
2741
color_scheme?: ColorSchemeNames | ColorSchemeArray | number;
2842
title?: string;

yaml-editor/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"scripts": {
77
"start": "npm run schema && webpack serve --open --mode development",
88
"build": "npm run schema &&rm -rf dist && webpack --mode production",
9-
"schema": "cd .. && typescript-json-schema --required tsconfig.json JsonSchemaRoot > yaml-editor/src/schema.json",
9+
"schema-1": "cd .. && typescript-json-schema --required tsconfig.json JsonSchemaRoot > yaml-editor/src/schema.json",
10+
"schema-2": "node patch-schema.js",
11+
"schema": "npm run schema-1 && npm run schema-2",
1012
"deploy": "pnpm run build && gh-pages -d dist"
1113
},
1214
"dependencies": {

yaml-editor/patch-schema.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import fs from "fs";
2+
import path from "path";
3+
import { fileURLToPath } from "url";
4+
const __filename = fileURLToPath(import.meta.url);
5+
const __dirname = path.dirname(__filename);
6+
const file = path.join(__dirname, "src/schema.json"); // Create relative path for reading
7+
8+
const patched = fs
9+
.readFileSync(file)
10+
.toString()
11+
.replaceAll(
12+
"^.*\\\\$ex\\\\$fn_REPLACER$",
13+
"^[\\\\s]*\\\\$(ex|fn)\\\\s[\\\\s\\\\S]+$",
14+
);
15+
16+
fs.writeFileSync(file, patched);
17+
18+
console.log("Patch completed.");

yaml-editor/src/index.ts

Lines changed: 110 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,89 @@
1-
import { type JSONSchemaForSchemaStoreOrgCatalogFiles } from '@schemastore/schema-catalog'
2-
import { editor, languages, MarkerSeverity, type Position, Range, Uri } from 'monaco-editor'
3-
import * as monaco from 'monaco-editor'
4-
import { ILanguageFeaturesService } from 'monaco-editor/esm/vs/editor/common/services/languageFeatures.js'
5-
import { OutlineModel } from 'monaco-editor/esm/vs/editor/contrib/documentSymbols/browser/outlineModel.js'
6-
import { StandaloneServices } from 'monaco-editor/esm/vs/editor/standalone/browser/standaloneServices.js'
7-
import { configureMonacoYaml, type SchemasSettings } from 'monaco-yaml'
1+
import { type JSONSchemaForSchemaStoreOrgCatalogFiles } from "@schemastore/schema-catalog";
2+
import {
3+
editor,
4+
languages,
5+
MarkerSeverity,
6+
type Position,
7+
Range,
8+
Uri,
9+
} from "monaco-editor";
10+
import * as monaco from "monaco-editor";
11+
import { ILanguageFeaturesService } from "monaco-editor/esm/vs/editor/common/services/languageFeatures.js";
12+
import { OutlineModel } from "monaco-editor/esm/vs/editor/contrib/documentSymbols/browser/outlineModel.js";
13+
import { StandaloneServices } from "monaco-editor/esm/vs/editor/standalone/browser/standaloneServices.js";
14+
import { configureMonacoYaml, type SchemasSettings } from "monaco-yaml";
815

9-
import './index.css'
10-
import schema from './schema.json'
16+
import "./index.css";
17+
import schema from "./schema.json";
1118

1219
window.MonacoEnvironment = {
1320
getWorker(moduleId, label) {
1421
switch (label) {
15-
case 'editorWorkerService':
16-
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url))
17-
case 'yaml':
18-
return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url))
22+
case "editorWorkerService":
23+
return new Worker(
24+
new URL("monaco-editor/esm/vs/editor/editor.worker", import.meta.url),
25+
);
26+
case "yaml":
27+
return new Worker(new URL("monaco-yaml/yaml.worker", import.meta.url));
1928
default:
20-
throw new Error(`Unknown label ${label}`)
29+
throw new Error(`Unknown label ${label}`);
2130
}
22-
}
23-
}
31+
},
32+
};
2433

2534
const defaultSchema: SchemasSettings = {
2635
uri: window.location.href,
2736
schema,
28-
fileMatch: ['plotly-graph.yaml']
29-
}
37+
fileMatch: ["plotly-graph.yaml"],
38+
};
3039

3140
const monacoYaml = configureMonacoYaml(monaco, {
32-
schemas: [defaultSchema]
33-
})
41+
schemas: [defaultSchema],
42+
completion: true,
43+
format: true,
44+
hover: true,
45+
validate: true,
46+
});
3447

35-
function showToast(message:string) {
36-
const toastContainer = document.getElementById('toast-container')!;
37-
const toast = document.createElement('div');
38-
toast.className = 'toast';
48+
function showToast(message: string) {
49+
const toastContainer = document.getElementById("toast-container")!;
50+
const toast = document.createElement("div");
51+
toast.className = "toast";
3952
toast.innerText = message;
4053
toastContainer.appendChild(toast);
4154
setTimeout(() => {
42-
toast.classList.add('show');
55+
toast.classList.add("show");
4356
}, 100);
4457
setTimeout(() => {
45-
toast.classList.remove('show');
46-
setTimeout(() => toast.remove(), 500); // Remove after animation
58+
toast.classList.remove("show");
59+
setTimeout(() => toast.remove(), 500); // Remove after animation
4760
}, 3000);
4861
}
4962

50-
if (localStorage["plotly-graph"]) showToast("Recovered yaml from local storage")
63+
if (localStorage["plotly-graph"])
64+
showToast("Recovered yaml from local storage");
5165

52-
const value = localStorage["plotly-graph"]||
53-
`type: custom:plotly-graph
66+
const value =
67+
localStorage["plotly-graph"] ||
68+
`type: custom:plotly-graph
5469
entities:
5570
- entity: sensor.x
5671
- entity: sensor.y
57-
`
72+
`;
5873

59-
60-
61-
const ed = editor.create(document.getElementById('editor')!, {
74+
const ed = editor.create(document.getElementById("editor")!, {
6275
automaticLayout: true,
63-
model: editor.createModel(value, 'yaml', Uri.parse('plotly-graph.yaml')),
64-
theme: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'vs-dark' : 'vs-light',
76+
model: editor.createModel(value, "yaml", Uri.parse("plotly-graph.yaml")),
77+
theme: window.matchMedia("(prefers-color-scheme: dark)").matches
78+
? "vs-dark"
79+
: "vs-light",
6580
quickSuggestions: {
6681
other: true,
6782
comments: false,
68-
strings: true
83+
strings: true,
6984
},
70-
formatOnType: true
71-
})
85+
formatOnType: true,
86+
});
7287

7388
/**
7489
* Get the document symbols that contain the given position.
@@ -82,79 +97,88 @@ const ed = editor.create(document.getElementById('editor')!, {
8297
*/
8398
function* iterateSymbols(
8499
symbols: languages.DocumentSymbol[],
85-
position: Position
100+
position: Position,
86101
): Iterable<languages.DocumentSymbol> {
87102
for (const symbol of symbols) {
88103
if (Range.containsPosition(symbol.range, position)) {
89-
yield symbol
104+
yield symbol;
90105
if (symbol.children) {
91-
yield* iterateSymbols(symbol.children, position)
106+
yield* iterateSymbols(symbol.children, position);
92107
}
93108
}
94109
}
95110
}
96111

97-
ed.onDidChangeModelContent(()=>{
98-
localStorage["plotly-graph"] = ed.getValue()
99-
100-
})
112+
ed.onDidChangeModelContent(() => {
113+
localStorage["plotly-graph"] = ed.getValue();
114+
});
101115

102116
ed.onDidChangeCursorPosition(async (event) => {
103-
const breadcrumbs = document.getElementById('breadcrumbs')!
104-
const { documentSymbolProvider } = StandaloneServices.get(ILanguageFeaturesService)
105-
const outline = await OutlineModel.create(documentSymbolProvider, ed.getModel()!)
106-
const symbols = outline.asListOfDocumentSymbols()
117+
const breadcrumbs = document.getElementById("breadcrumbs")!;
118+
const { documentSymbolProvider } = StandaloneServices.get(
119+
ILanguageFeaturesService,
120+
);
121+
const outline = await OutlineModel.create(
122+
documentSymbolProvider,
123+
ed.getModel()!,
124+
);
125+
const symbols = outline.asListOfDocumentSymbols();
107126
while (breadcrumbs.lastChild) {
108-
breadcrumbs.lastChild.remove()
127+
breadcrumbs.lastChild.remove();
109128
}
110129
for (const symbol of iterateSymbols(symbols, event.position)) {
111-
const breadcrumb = document.createElement('span')
112-
breadcrumb.setAttribute('role', 'button')
113-
breadcrumb.classList.add('breadcrumb')
114-
breadcrumb.textContent = symbol.name
115-
breadcrumb.title = symbol.detail
130+
const breadcrumb = document.createElement("span");
131+
breadcrumb.setAttribute("role", "button");
132+
breadcrumb.classList.add("breadcrumb");
133+
breadcrumb.textContent = symbol.name;
134+
breadcrumb.title = symbol.detail;
116135
if (symbol.kind === languages.SymbolKind.Array) {
117-
breadcrumb.classList.add('array')
136+
breadcrumb.classList.add("array");
118137
} else if (symbol.kind === languages.SymbolKind.Module) {
119-
breadcrumb.classList.add('object')
138+
breadcrumb.classList.add("object");
120139
}
121-
breadcrumb.addEventListener('click', () => {
140+
breadcrumb.addEventListener("click", () => {
122141
ed.setPosition({
123142
lineNumber: symbol.range.startLineNumber,
124-
column: symbol.range.startColumn
125-
})
126-
ed.focus()
127-
})
128-
breadcrumbs.append(breadcrumb)
143+
column: symbol.range.startColumn,
144+
});
145+
ed.focus();
146+
});
147+
breadcrumbs.append(breadcrumb);
129148
}
130-
})
149+
});
131150

132151
editor.onDidChangeMarkers(([resource]) => {
133-
const problems = document.getElementById('problems')!
134-
const markers = editor.getModelMarkers({ resource })
152+
const problems = document.getElementById("problems")!;
153+
const markers = editor.getModelMarkers({ resource });
135154
while (problems.lastChild) {
136-
problems.lastChild.remove()
155+
problems.lastChild.remove();
137156
}
138157
for (const marker of markers) {
139158
if (marker.severity === MarkerSeverity.Hint) {
140-
continue
159+
continue;
141160
}
142-
const wrapper = document.createElement('div')
143-
wrapper.setAttribute('role', 'button')
144-
const codicon = document.createElement('div')
145-
const text = document.createElement('div')
146-
wrapper.classList.add('problem')
161+
const wrapper = document.createElement("div");
162+
wrapper.setAttribute("role", "button");
163+
const codicon = document.createElement("div");
164+
const text = document.createElement("div");
165+
wrapper.classList.add("problem");
147166
codicon.classList.add(
148-
'codicon',
149-
marker.severity === MarkerSeverity.Warning ? 'codicon-warning' : 'codicon-error'
150-
)
151-
text.classList.add('problem-text')
152-
text.textContent = marker.message
153-
wrapper.append(codicon, text)
154-
wrapper.addEventListener('click', () => {
155-
ed.setPosition({ lineNumber: marker.startLineNumber, column: marker.startColumn })
156-
ed.focus()
157-
})
158-
problems.append(wrapper)
167+
"codicon",
168+
marker.severity === MarkerSeverity.Warning
169+
? "codicon-warning"
170+
: "codicon-error",
171+
);
172+
text.classList.add("problem-text");
173+
text.textContent = marker.message;
174+
wrapper.append(codicon, text);
175+
wrapper.addEventListener("click", () => {
176+
ed.setPosition({
177+
lineNumber: marker.startLineNumber,
178+
column: marker.startColumn,
179+
});
180+
ed.focus();
181+
});
182+
problems.append(wrapper);
159183
}
160-
})
184+
});

0 commit comments

Comments
 (0)