setOpen(false)}
className={`${
open ? 'visible' : 'invisible'
} origin-top-right absolute ${align === 'right' &&
diff --git a/src/components/common/Markdown.tsx b/src/components/common/Markdown.tsx
index 4ca2efebe..77eadada0 100644
--- a/src/components/common/Markdown.tsx
+++ b/src/components/common/Markdown.tsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import type { FunctionComponent, PropsWithChildren } from 'react';
// @ts-ignore
import { Markdown as MarkdownComponent } from '@asyncapi/react-component/lib/esm/components/Markdown';
-export const Markdown: React.FunctionComponent = ({
+export const Markdown: FunctionComponent
= ({
children,
}) => {
return (
diff --git a/src/examples/index.tsx b/src/examples/index.tsx
index a79523dff..32319038d 100644
--- a/src/examples/index.tsx
+++ b/src/examples/index.tsx
@@ -1,14 +1,14 @@
// @ts-nocheck
// protocol examples
-import kafka from '!!raw-loader!./streetlights-kafka.yml';
-import websocket from '!!raw-loader!./websocket-gemini.yml';
-import mqtt from '!!raw-loader!./streetlights-mqtt.yml';
-import simple from '!!raw-loader!./simple.yml';
+import kafka from './streetlights-kafka.yml';
+import websocket from './websocket-gemini.yml';
+import mqtt from './streetlights-mqtt.yml';
+import simple from './simple.yml';
// real world examples
-import slack from '!!raw-loader!./real-world/slack-rtm.yml';
-import gitterStreaming from '!!raw-loader!./real-world/gitter-streaming.yml';
+import slack from './real-world/slack-rtm.yml';
+import gitterStreaming from './real-world/gitter-streaming.yml';
const templateTypes = {
protocol: 'protocol-example',
diff --git a/src/helpers/index.ts b/src/helpers/index.ts
index c3e3a8b4a..29cd16b41 100644
--- a/src/helpers/index.ts
+++ b/src/helpers/index.ts
@@ -1,2 +1,3 @@
export * from './debounce';
export * from './isDeepEqual';
+export * from './useOutsideClickCallback';
diff --git a/src/helpers/useOutsideClickCallback.ts b/src/helpers/useOutsideClickCallback.ts
new file mode 100644
index 000000000..cd145e9d8
--- /dev/null
+++ b/src/helpers/useOutsideClickCallback.ts
@@ -0,0 +1,18 @@
+import { useEffect } from 'react';
+
+import type { MutableRefObject } from 'react';
+
+export function useOutsideClickCallback(ref: MutableRefObject, callback: () => void) {
+ useEffect(() => {
+ function handleClickOutside(event: MouseEvent) {
+ if (ref.current && !ref.current.contains(event.target as any)) {
+ callback();
+ }
+ }
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, [ref]);
+}
\ No newline at end of file
diff --git a/src/index.tsx b/src/index.tsx
index d27175def..adc5bb703 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,31 +1,47 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
+import { StrictMode } from 'react';
+import { createRoot } from 'react-dom/client';
+
import App from './App';
import 'tippy.js/dist/tippy.css';
import 'tippy.js/animations/shift-away.css';
import '@asyncapi/react-component/styles/default.min.css';
+import 'reactflow/dist/style.css';
import './tailwind.css';
import './main.css';
-window.MonacoEnvironment = window.MonacoEnvironment || {
- getWorkerUrl(_: string, label: string) {
- // for json worker
- if (label === 'json') {
- return `${process.env.PUBLIC_URL}/js/monaco/json.worker.bundle.js`;
- }
- // for yaml worker
- if (label === 'yaml' || label === 'yml') {
- return `${process.env.PUBLIC_URL}/js/monaco/yaml.worker.bundle.js`;
- }
- // for core editor worker
- return `${process.env.PUBLIC_URL}/js/monaco/editor.worker.bundle.js`;
- },
-};
+function configureMonaco() {
+ window.MonacoEnvironment = {
+ getWorker(_, label) {
+ switch (label) {
+ case 'editorWorkerService':
+ return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url));
+ case 'json':
+ return new Worker(
+ new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url),
+ );
+ case 'yaml':
+ case 'yml':
+ return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url));
+ default:
+ throw new Error(`Unknown label ${label}`);
+ }
+ },
+ };
+}
+
+function bootstrap() {
+ configureMonaco();
+
+ const root = createRoot(
+ document.getElementById('root') as HTMLElement
+ );
+
+ root.render(
+
+
+
+ );
+}
-ReactDOM.render(
-
-
- ,
- document.getElementById('root')
-);
+bootstrap();
diff --git a/src/services/editor.service.tsx b/src/services/editor.service.tsx
index fe027c1e0..bbbea3c69 100644
--- a/src/services/editor.service.tsx
+++ b/src/services/editor.service.tsx
@@ -1,5 +1,5 @@
import { DiagnosticSeverity } from '@asyncapi/parser/cjs';
-import * as monacoAPI from 'monaco-editor/esm/vs/editor/editor.api';
+import { Range, MarkerSeverity } from 'monaco-editor/esm/vs/editor/editor.api';
import toast from 'react-hot-toast';
import fileDownload from 'js-file-download';
@@ -9,6 +9,7 @@ import { SocketClient } from './socket-client.service';
import state from '../state';
+import type * as monacoAPI from 'monaco-editor/esm/vs/editor/editor.api';
import type { Diagnostic } from '@asyncapi/parser/cjs';
import type { ConvertVersion } from '@asyncapi/converter';
@@ -217,7 +218,7 @@ export class EditorService {
return;
}
- diagnostics = this.filterDiagnostics(diagnostics);
+ diagnostics = SpecificationService.filterDiagnostics(diagnostics);
const { markers, decorations } = this.createMarkers(diagnostics);
Monaco.editor.setModelMarkers(model, 'asyncapi', markers);
let oldDecorations = state.editor.decorations.get();
@@ -240,7 +241,7 @@ export class EditorService {
newDecorations.push({
id: 'asyncapi',
ownerId: 0,
- range: new monacoAPI.Range(
+ range: new Range(
range.start.line + 1,
range.start.character + 1,
range.end.line + 1,
@@ -269,11 +270,11 @@ export class EditorService {
private static getSeverity(severity: DiagnosticSeverity): monacoAPI.MarkerSeverity {
switch (severity) {
- case DiagnosticSeverity.Error: return monacoAPI.MarkerSeverity.Error;
- case DiagnosticSeverity.Warning: return monacoAPI.MarkerSeverity.Warning;
- case DiagnosticSeverity.Information: return monacoAPI.MarkerSeverity.Info;
- case DiagnosticSeverity.Hint: return monacoAPI.MarkerSeverity.Hint;
- default: return monacoAPI.MarkerSeverity.Error;
+ case DiagnosticSeverity.Error: return MarkerSeverity.Error;
+ case DiagnosticSeverity.Warning: return MarkerSeverity.Warning;
+ case DiagnosticSeverity.Information: return MarkerSeverity.Info;
+ case DiagnosticSeverity.Hint: return MarkerSeverity.Hint;
+ default: return MarkerSeverity.Error;
}
}
@@ -286,18 +287,6 @@ export class EditorService {
}
}
- private static filterDiagnostics(diagnostics: Diagnostic[]) {
- const governanceShowState = state.settings.governance.show.get();
- return diagnostics.filter(diagnostic => {
- const { severity } = diagnostic;
- if (severity === DiagnosticSeverity.Error) return true;
- if (severity === DiagnosticSeverity.Warning && !governanceShowState.warnings) return false;
- if (severity === DiagnosticSeverity.Information && !governanceShowState.informations) return false;
- if (severity === DiagnosticSeverity.Hint && !governanceShowState.hints) return false;
- return true;
- });
- }
-
private static fileName = 'asyncapi';
private static downloadFile(content: string, fileName: string) {
return fileDownload(content, fileName);
diff --git a/src/services/monaco.service.ts b/src/services/monaco.service.ts
index 68b5bd30e..82acf7cf2 100644
--- a/src/services/monaco.service.ts
+++ b/src/services/monaco.service.ts
@@ -1,10 +1,12 @@
import specs from '@asyncapi/specs';
import { loader } from '@monaco-editor/react';
-import * as monacoAPI from 'monaco-editor/esm/vs/editor/editor.api';
+import { setDiagnosticsOptions } from 'monaco-yaml';
import { SpecificationService } from './specification.service';
import state from '../state';
+import type * as monacoAPI from 'monaco-editor/esm/vs/editor/editor.api';
+import type { DiagnosticsOptions as YAMLDiagnosticsOptions } from 'monaco-yaml';
import type { SpecVersions } from '../types';
export class MonacoService {
@@ -67,11 +69,14 @@ export class MonacoService {
const options = this.prepareLanguageConfig(asyncAPIVersion);
+ // json
const json = monacoInstance.languages.json;
json && json.jsonDefaults && json.jsonDefaults.setDiagnosticsOptions(options);
- const yaml = (monacoInstance.languages as any).yaml;
- yaml && yaml.yamlDefaults && yaml.yamlDefaults.setDiagnosticsOptions(options);
+ // yaml
+ setDiagnosticsOptions(options as YAMLDiagnosticsOptions);
+ // const yaml = (monacoInstance.languages as any).yaml;
+ // yaml && yaml.yamlDefaults && yaml.yamlDefaults.setDiagnosticsOptions(options);
}
static loadMonacoConfig() {
@@ -105,10 +110,6 @@ export class MonacoService {
// load monaco config
this.loadMonacoConfig();
- // load yaml plugin
- // @ts-ignore
- await import('monaco-yaml/lib/esm/monaco.contribution');
-
// load language config (for json and yaml)
this.loadLanguageConfig(SpecificationService.getLastVersion());
state.editor.monacoLoaded.set(true);
diff --git a/src/services/specification.service.ts b/src/services/specification.service.ts
index 8e50a03fb..fe5af742c 100644
--- a/src/services/specification.service.ts
+++ b/src/services/specification.service.ts
@@ -1,6 +1,6 @@
import specs from '@asyncapi/specs';
import { convert } from '@asyncapi/converter';
-import { Parser, convertToOldAPI } from '@asyncapi/parser/cjs';
+import { Parser, convertToOldAPI, DiagnosticSeverity } from '@asyncapi/parser/cjs';
import { untilde } from '@asyncapi/parser/cjs/utils';
import { OpenAPISchemaParser } from '@asyncapi/parser/cjs/schema-parser/openapi-schema-parser';
import { AvroSchemaParser } from '@asyncapi/parser/cjs/schema-parser/avro-schema-parser';
@@ -11,9 +11,9 @@ import { MonacoService } from './monaco.service';
import state from '../state';
-import type { SpecVersions } from '../types';
import type { ConvertVersion } from '@asyncapi/converter';
import type { OldAsyncAPIDocument as AsyncAPIDocument, Diagnostic } from '@asyncapi/parser/cjs';
+import type { SpecVersions } from '../types';
const parser = new Parser({
__unstable: {
@@ -147,4 +147,16 @@ export class SpecificationService {
return;
}
}
+
+ static filterDiagnostics(diagnostics: Diagnostic[] = state.parser.diagnostics.get()) {
+ const governanceShowState = state.settings.governance.show.get();
+ return diagnostics.filter(({ severity }) => {
+ return (
+ severity === DiagnosticSeverity.Error ||
+ (severity === DiagnosticSeverity.Warning && governanceShowState.warnings) ||
+ (severity === DiagnosticSeverity.Information && governanceShowState.informations) ||
+ (severity === DiagnosticSeverity.Hint && governanceShowState.hints)
+ );
+ });
+ }
}
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
index b72ba297e..c9634805b 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,7 +1,8 @@
module.exports = {
- // Purge works on production env
- purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
- darkMode: false, // or 'media' or 'class'
+ content: [
+ './src/**/*.{js,jsx,ts,tsx}',
+ './public/index.html',
+ ],
theme: {
extend: {
colors: {