@redocly/marketing-pages 0.1.25 → 0.1.27
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.
- package/dist/pages/editor/components/EditorPanel/EditorContent.d.ts +2 -0
- package/dist/pages/editor/components/EditorPanel/EditorContent.js +1 -1
- package/dist/pages/editor/components/EditorPanel.d.ts +2 -0
- package/dist/pages/editor/components/EditorPanel.js +1 -1
- package/dist/pages/editor/components/Layout/EditorLayout.d.ts +2 -0
- package/dist/pages/editor/components/Layout/EditorLayout.js +3 -3
- package/dist/pages/editor/components/Layout/MainLayout.d.ts +2 -0
- package/dist/pages/editor/components/Layout/MainLayout.js +2 -2
- package/dist/pages/editor/components/Page.d.ts +6 -1
- package/dist/pages/editor/components/Page.js +1 -1
- package/dist/pages/editor/components/PreviewPanel/IframeContainer.js +3 -3
- package/dist/pages/editor/components/PreviewPanel/PreviewContent.js +9 -5
- package/dist/pages/editor/components/Toolbar.js +8 -8
- package/dist/pages/editor/editor.page.d.ts +7 -2
- package/dist/pages/editor/editor.page.js +1 -1
- package/dist/pages/editor/hooks/useEditorCommunication.js +2 -2
- package/dist/pages/editor/hooks/useMonacoEditor.d.ts +3 -1
- package/dist/pages/editor/hooks/useMonacoEditor.js +2 -2
- package/dist/pages/editor/service/baseLanguageService.d.ts +27 -0
- package/dist/pages/editor/service/baseLanguageService.js +1 -0
- package/dist/pages/editor/service/index.d.ts +3 -0
- package/dist/pages/editor/service/index.js +1 -0
- package/dist/pages/editor/service/monacoIntegration.d.ts +62 -0
- package/dist/pages/editor/service/monacoIntegration.js +2 -0
- package/dist/pages/editor/service/yamlValidation.d.ts +21 -0
- package/dist/pages/editor/service/yamlValidation.js +1 -0
- package/dist/pages/editor/templates/defaultOpenapiTemplate.d.ts +1 -1
- package/dist/pages/editor/templates/defaultOpenapiTemplate.js +219 -9
- package/dist/pages/editor/types/index.d.ts +24 -0
- package/dist/pages/editor-preview/hooks/useCommunicationManager.d.ts +1 -1
- package/dist/pages/editor-preview/hooks/useCommunicationManager.js +1 -1
- package/dist/pages/learning-center/components/TopLearnBlock.js +1 -0
- package/dist/pages/learning-center/learn.page.js +4 -2
- package/dist/pages/pricing/components/PlansSection.js +6 -6
- package/dist/pages/pricing/pricingData/data.d.ts +3 -0
- package/dist/pages/pricing/pricingData/data.js +1 -1
- package/package.json +3 -2
- package/dist/hooks/useSendRudderstackEvent.d.ts +0 -10
- package/dist/hooks/useSendRudderstackEvent.js +0 -1
- package/dist/pages/editor/services/languageServerService.d.ts +0 -52
- package/dist/pages/editor/services/languageServerService.js +0 -3
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
3
|
+
import { ILanguageServerService } from '../../types';
|
|
3
4
|
interface EditorContentProps {
|
|
5
|
+
languageService: ILanguageServerService;
|
|
4
6
|
value: string;
|
|
5
7
|
onChange: (value: string | undefined) => void;
|
|
6
8
|
onValidationUpdate?: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as n from"react";import
|
|
1
|
+
import*as n from"react";import O from"@monaco-editor/react";import{useMonacoEditor as v}from"../../hooks/useMonacoEditor";import{DEFAULT_EDITOR_OPTIONS as R,EDITOR_LANGUAGE as T,EDITOR_THEMES as b}from"../../constants/editorConfig";import{useEditorCommunication as M}from"../../hooks/useEditorCommunication";const C=({languageService:l,value:o,onChange:m,onValidationUpdate:f,hideWarnings:s,isFullPreview:a,gotoPosition:r})=>{const u=n.useRef(()=>{}),{activeColorMode:E,handleEditorDidMount:d,handleEditorBeforeMount:p,editorRef:e}=v({languageService:l,onValidationUpdate:f,hideWarnings:s,onClick:t=>{u.current(t.lineNumber)}}),{scrollPreviewToOperation:i}=M({value:o,isFullPreview:a||!1,editorRef:e});return n.useEffect(()=>{u.current=i},[i]),n.useEffect(()=>{r&&e.current&&(e.current.revealPositionInCenter({lineNumber:r.line,column:r.column}),e.current.setPosition({lineNumber:r.line,column:r.column}))},[r,e]),n.useEffect(()=>{if(!e.current)return;const t=new ResizeObserver(()=>{e.current&&e.current.layout()}),c=e.current.getDomNode();return c&&t.observe(c),()=>{t.disconnect()}},[e]),n.createElement(O,{language:T,theme:b[E],value:o,options:R,onChange:m,beforeMount:p,onMount:d})};var w=C;export{w as default};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
3
|
+
import { ILanguageServerService } from '../types';
|
|
3
4
|
interface EditorPanelProps {
|
|
5
|
+
languageService: ILanguageServerService;
|
|
4
6
|
value: string;
|
|
5
7
|
onChange: (value: string | undefined) => void;
|
|
6
8
|
onValidationUpdate?: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as e from"react";import
|
|
1
|
+
import*as e from"react";import c from"./EditorPanel/EditorContent";const f=({languageService:t,value:o,onChange:n,onValidationUpdate:r,hideWarnings:i,isFullPreview:a,gotoPosition:l})=>{const[s,u]=e.useState(!1);return e.useEffect(()=>u(!0),[]),s?e.createElement(c,{languageService:t,value:o,onChange:n,onValidationUpdate:r,hideWarnings:i,isFullPreview:a,gotoPosition:l}):e.createElement("div",{style:{height:"100%",minHeight:"400px",backgroundColor:"var(--background-color, #fff)"}})};var g=f;export{g as default};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
3
|
+
import { ILanguageServerService } from '../../types';
|
|
3
4
|
interface EditorLayoutProps {
|
|
5
|
+
languageService: ILanguageServerService;
|
|
4
6
|
value: string;
|
|
5
7
|
onChange: (value: string | undefined) => void;
|
|
6
8
|
onValidationUpdate: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e from"react";import a from"styled-components";import{Panel as n,PanelGroup as
|
|
1
|
+
import e from"react";import a from"styled-components";import{Panel as n,PanelGroup as h,PanelResizeHandle as y}from"react-resizable-panels";import S from"../EditorPanel";import{ProblemsPanel as k}from"../ProblemsPanel";import w from"../Toolbar";const R=({languageService:i,value:s,onChange:d,onValidationUpdate:c,hideWarnings:r,onHideWarningsChange:m,isFullPreview:u,gotoPosition:p,parsedErrors:f,onProblemClick:P,onFileLoad:b,onDownloadYaml:g,onDownloadJson:E,onToggleFullPreview:v})=>{const[l,t]=e.useState(!0),o=e.useRef(null),C=(x,z)=>{P(x,z),l&&o.current?.expand()};return e.createElement(F,{defaultSize:50,minSize:20},e.createElement(w,{onFileLoad:b,onDownloadYamlClick:g,onDownloadJsonClick:E,hideWarnings:r,onHideWarningsChange:m,onToggleFullPreview:v}),e.createElement(T,null,e.createElement(h,{direction:"vertical"},e.createElement(n,{defaultSize:95},e.createElement(S,{languageService:i,value:s,onChange:d,onValidationUpdate:c,hideWarnings:r,isFullPreview:u,gotoPosition:p})),e.createElement(y,{className:"resize-handle-horizontal",style:{display:l?"none":"block"}}),e.createElement(n,{ref:o,collapsible:!0,collapsedSize:5,defaultSize:5,minSize:20,onCollapse:t.bind(null,!0),onExpand:t.bind(null,!1)},e.createElement(k,{problems:f,onProblemClick:C,isCollapsed:l,onToggle:()=>{l?o.current?.expand():o.current?.collapse()}})))))};var N=R;const F=a(n)`
|
|
2
2
|
flex: 2;
|
|
3
3
|
display: flex;
|
|
4
4
|
flex-direction: column;
|
|
@@ -8,8 +8,8 @@ import e from"react";import a from"styled-components";import{Panel as n,PanelGro
|
|
|
8
8
|
--vscode-editor-background: var(--layer-color);
|
|
9
9
|
--vscode-editorGutter-background: var(--layer-color);
|
|
10
10
|
}
|
|
11
|
-
`,
|
|
11
|
+
`,T=a.div`
|
|
12
12
|
flex: 1;
|
|
13
13
|
min-height: 0;
|
|
14
14
|
display: flex;
|
|
15
|
-
`;export{
|
|
15
|
+
`;export{N as default};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
3
|
+
import { ILanguageServerService } from '../../types';
|
|
3
4
|
interface MainLayoutProps {
|
|
5
|
+
languageService: ILanguageServerService;
|
|
4
6
|
value: string;
|
|
5
7
|
onChange: (value: string | undefined) => void;
|
|
6
8
|
onValidationUpdate: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import o from"react";import e from"styled-components";import{PanelGroup as
|
|
1
|
+
import o from"react";import e from"styled-components";import{PanelGroup as k,PanelResizeHandle as x}from"react-resizable-panels";import z from"./EditorLayout";import E from"./PreviewLayout";const C=({languageService:a,value:n,onChange:i,onValidationUpdate:l,hideWarnings:t,onHideWarningsChange:c,isFullPreview:s,gotoPosition:d,parsedErrors:m,onProblemClick:u,onFileLoad:r,onDownloadYaml:g,onDownloadJson:h,onToggleFullPreview:v,definition:p,rawValue:y,hasRenderedOnce:b,hasStructErrors:f,onTemplateClick:w,isClient:P})=>o.createElement(L,null,o.createElement(R,{direction:"horizontal"},o.createElement(z,{languageService:a,value:n,onChange:i,onValidationUpdate:l,hideWarnings:t,onHideWarningsChange:c,isFullPreview:s,gotoPosition:d,parsedErrors:m,onProblemClick:u,onFileLoad:r,onDownloadYaml:g,onDownloadJson:h,onToggleFullPreview:v}),o.createElement(x,{className:"resize-handle"}),o.createElement(E,{definition:p,rawValue:y,hasRenderedOnce:b,hasStructErrors:f,onTemplateClick:w,onFileLoad:r,isClient:P})));var V=C;const L=e.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
height: calc(100vh - var(--navbar-height));
|
|
@@ -9,7 +9,7 @@ import o from"react";import e from"styled-components";import{PanelGroup as P,Pan
|
|
|
9
9
|
[data-component-name='Layout/PageLayout']:has(&) + div + footer {
|
|
10
10
|
display: none;
|
|
11
11
|
}
|
|
12
|
-
`,
|
|
12
|
+
`,R=e(k)`
|
|
13
13
|
display: flex;
|
|
14
14
|
flex-grow: 1;
|
|
15
15
|
height: 100%;
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
|
|
2
|
+
import { ILanguageServerService } from '../types';
|
|
3
|
+
interface PageProps {
|
|
4
|
+
languageService: ILanguageServerService;
|
|
5
|
+
}
|
|
6
|
+
export default function Page({ languageService }: PageProps): React.JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import n from"react";import{useEditorState as L}from"../hooks/useEditorState";import{useOpenApiValidation as R}from"../hooks/useOpenApiValidation";import{useFileOperations as T}from"../hooks/useFileOperations";import W from"./Layout/MainLayout";import H from"./Layout/FullPreviewLayout";function J({languageService:h}){const[i,p]=n.useState(!1),[r,s]=n.useState(!1);n.useEffect(()=>p(!0),[]);const{value:o,setValue:d,validatedValue:f,setValidatedValue:w,setValidationErrors:u,setFileName:g,parsedErrors:C,hasStructErrors:a,hideWarnings:F,setHideWarnings:P}=L(),{definition:c,hasRenderedOnce:m,setHasRenderedOnce:E}=R({validatedValue:f,hasStructErrors:a}),[v,V]=n.useState(null),e=T({setValue:d,setFileName:g,setHasRenderedOnce:E,setValidationErrors:u}),S=(t,l)=>{u(t),w(l)},O=(t,l)=>{V({line:t,column:l})},k=()=>e.handleDownloadYaml(o),D=()=>e.handleDownloadJson(o);return r?n.createElement(H,{definition:c,rawValue:o,hasRenderedOnce:m,hasStructErrors:a,onTemplateClick:e.handleTemplateClick,onFileLoad:e.handleFileLoad,onExitFullPreview:()=>s(!1),isClient:i}):n.createElement(W,{languageService:h,value:o,onChange:d,onValidationUpdate:S,hideWarnings:F,onHideWarningsChange:P,isFullPreview:r,gotoPosition:v,parsedErrors:C,onProblemClick:O,onFileLoad:e.handleFileLoad,onDownloadYaml:k,onDownloadJson:D,onToggleFullPreview:()=>s(!0),definition:c,rawValue:o,hasRenderedOnce:m,hasStructErrors:a,onTemplateClick:e.handleTemplateClick,isClient:i})}export{J as default};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import o,{useRef as c,useEffect as a}from"react";import u from"styled-components";const d=({definition:t,onIframeReady:s,onMessage:w})=>{const l=c(null),r=c(null),[i,p]=o.useState(0);return a(()=>{const n=e=>{r.current=e,e.updateDefinition(t),s(e)};return window.onReady=n,()=>{delete window.onReady}},[t,s]),a(()=>{const n=e=>{e.data?.type==="scroll-to-operation"&&r.current&&r.current.postMessage(e.data,"*")};return window.addEventListener("message",n),()=>window.removeEventListener("message",n)},[]),a(()=>{r.current&&t&&r.current.updateDefinition(t)},[t]),o.createElement(f,null,o.createElement(m,{key:i,ref:l,title:"API Documentation Preview",src:"/preview",onLoad:()=>{}}))};var y=d;const f=u.div`
|
|
2
2
|
height: 100%;
|
|
3
3
|
overflow: hidden;
|
|
4
|
-
`,
|
|
4
|
+
`,m=u.iframe`
|
|
5
5
|
width: 100%;
|
|
6
6
|
height: 100%;
|
|
7
7
|
border: none;
|
|
8
|
-
`;export{
|
|
8
|
+
`;export{y as default};
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import e from"react";import
|
|
1
|
+
import e from"react";import t from"styled-components";import{Button as f}from"@redocly/theme/components/Button/Button";import{Tooltip as s}from"@redocly/theme/components/Tooltip/Tooltip";import{ViewOffIcon as d}from"@redocly/theme/icons/ViewOffIcon/ViewOffIcon";import l from"./ErrorOverlay";import E from"./IframeContainer";import u from"../EmptyState";const g=({definition:n,rawValue:o,hasStructErrors:r,onTemplateClick:m,onFileLoad:p,onExitFullPreview:i,onIframeReady:c})=>!o||typeof o!="string"||o.trim()===""?e.createElement(u,{onTemplateClick:m,onUploadClick:p}):n?e.createElement(a,null,e.createElement(l,{hasStructErrors:r}),i&&e.createElement(x,null,e.createElement(y,{tip:"Exit full preview mode",width:"fit-content",placement:"right"},e.createElement(f,{variant:"secondary",onClick:i,"aria-label":"Exit full preview",icon:e.createElement(d,null)}))),e.createElement(E,{definition:n,onIframeReady:c,onMessage:()=>{}})):e.createElement(a,null,e.createElement(l,{hasStructErrors:r}),e.createElement(v,null,"Loading..."));var w=g;const a=t.div`
|
|
2
2
|
position: relative;
|
|
3
3
|
height: 100%;
|
|
4
|
-
`,
|
|
4
|
+
`,x=t.div`
|
|
5
5
|
position: absolute;
|
|
6
6
|
top: 12px;
|
|
7
7
|
left: 12px;
|
|
8
|
-
z-index:
|
|
9
|
-
`,y=
|
|
8
|
+
z-index: 100;
|
|
9
|
+
`,y=t(s)`
|
|
10
|
+
[data-component-name='Tooltip/Tooltip'] {
|
|
11
|
+
z-index: 101 !important;
|
|
12
|
+
}
|
|
13
|
+
`,v=t.div`
|
|
10
14
|
display: flex;
|
|
11
15
|
align-items: center;
|
|
12
16
|
justify-content: center;
|
|
13
17
|
height: 100%;
|
|
14
18
|
font-size: 14px;
|
|
15
19
|
color: #666;
|
|
16
|
-
`;export{
|
|
20
|
+
`;export{w as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e,{useRef as
|
|
1
|
+
import e,{useRef as k,useState as C}from"react";import t from"styled-components";import{Button as n}from"@redocly/theme/components/Button/Button";import{Tooltip as c}from"@redocly/theme/components/Tooltip/Tooltip";import{DownloadIcon as m}from"@redocly/theme/icons/DownloadIcon/DownloadIcon";import{ChevronDownIcon as D}from"@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon";import{ViewIcon as I}from"@redocly/theme/icons/ViewIcon/ViewIcon";function R({hideWarnings:u,onHideWarningsChange:x,onDownloadYamlClick:p,onDownloadJsonClick:g,onFileLoad:b,onToggleFullPreview:d}){const s=k(null),[w,r]=C(!1),E=()=>{s.current?.click()},h=()=>r(o=>!o),v=o=>{const l=o.target.files?.[0];if(!l)return;const a=new FileReader;a.onload=i=>{const y=i.target?.result;b(y,l.name)},a.onerror=i=>{console.error("Failed to read file!",i)},a.readAsText(l),o.target.value=""};return e.createElement(z,null,e.createElement(A,null,e.createElement("input",{type:"checkbox",checked:u,onChange:o=>x(o.target.checked),id:"hide-warnings"}),"Hide warnings"),e.createElement(B,null,d&&e.createElement(c,{tip:"Enter full preview mode",width:"fit-content"},e.createElement(n,{variant:"text",onClick:d,"aria-label":"Enter full preview",icon:e.createElement(I,null)})),e.createElement(c,{tip:"Upload spec",width:"fit-content"},e.createElement(n,{variant:"text",icon:e.createElement(m,{style:{transform:"rotate(180deg)"}}),onClick:E,"aria-label":"Upload spec"})),e.createElement(O,{type:"file",ref:s,onChange:v,accept:".yaml,.yml,.json"}),e.createElement(F,null,e.createElement(n,{variant:"text",onClick:p,iconPosition:"left",icon:e.createElement(m,null)},"Download"),e.createElement(c,{tip:"Download options",width:"fit-content"},e.createElement(n,{icon:e.createElement(D,null),onClick:h,"aria-label":"Download options"})),w&&e.createElement(M,null,e.createElement(f,{onClick:()=>{p(),r(!1)}},"Download YAML"),e.createElement(f,{onClick:()=>{g(),r(!1)}},"Download JSON")))))}const z=t.div`
|
|
2
2
|
padding: 6px 12px;
|
|
3
3
|
border-bottom: 1px solid var(--border-color-primary);
|
|
4
4
|
display: flex;
|
|
@@ -6,25 +6,25 @@ import e,{useRef as y,useState as k}from"react";import o from"styled-components"
|
|
|
6
6
|
background-color: var(--bg-color);
|
|
7
7
|
color: var(--text-color-primary);
|
|
8
8
|
gap: 16px;
|
|
9
|
-
`,
|
|
9
|
+
`,A=t.label`
|
|
10
10
|
display: flex;
|
|
11
11
|
align-items: center;
|
|
12
12
|
gap: 8px;
|
|
13
13
|
font-size: 0.875rem;
|
|
14
14
|
cursor: pointer;
|
|
15
|
-
`,
|
|
15
|
+
`,B=t.div`
|
|
16
16
|
display: flex;
|
|
17
17
|
align-items: center;
|
|
18
18
|
gap: 8px;
|
|
19
19
|
margin-left: auto; /* Push to far right */
|
|
20
|
-
`,
|
|
20
|
+
`,F=t.div`
|
|
21
21
|
position: relative;
|
|
22
22
|
display: inline-flex;
|
|
23
23
|
align-items: center;
|
|
24
24
|
display: flex;
|
|
25
25
|
flex-direction: row;
|
|
26
26
|
gap: calc(var(--spacing-xxs) / 2);
|
|
27
|
-
`,
|
|
27
|
+
`,M=t.ul`
|
|
28
28
|
position: absolute;
|
|
29
29
|
right: 0;
|
|
30
30
|
top: 100%;
|
|
@@ -38,13 +38,13 @@ import e,{useRef as y,useState as k}from"react";import o from"styled-components"
|
|
|
38
38
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
39
39
|
min-width: 140px;
|
|
40
40
|
z-index: 20;
|
|
41
|
-
`,
|
|
41
|
+
`,f=t.li`
|
|
42
42
|
padding: 6px 12px;
|
|
43
43
|
font-size: 0.875rem;
|
|
44
44
|
cursor: pointer;
|
|
45
45
|
&:hover {
|
|
46
46
|
background-color: var(--bg-color-active, #f5f5f5);
|
|
47
47
|
}
|
|
48
|
-
`,
|
|
48
|
+
`,O=t.input`
|
|
49
49
|
display: none;
|
|
50
|
-
`;export{
|
|
50
|
+
`;export{R as default};
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ILanguageServerService } from './types';
|
|
2
3
|
export declare const frontmatter: {
|
|
3
4
|
seo: {
|
|
4
5
|
title: string;
|
|
5
6
|
};
|
|
6
7
|
slug: string;
|
|
7
8
|
};
|
|
8
|
-
|
|
9
|
+
interface EditorPageProps {
|
|
10
|
+
languageService: ILanguageServerService;
|
|
11
|
+
}
|
|
12
|
+
export default function EditorPage({ languageService }: EditorPageProps): React.JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"./components/Page";const
|
|
1
|
+
import t from"react";import r from"./components/Page";const g={seo:{title:"Swagger Editor"},slug:"/editor"};function o({languageService:e}){return t.createElement(r,{languageService:e})}export{o as default,g as frontmatter};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useEffect as
|
|
2
|
-
`);let s=-1,
|
|
1
|
+
import{useEffect as h,useRef as m}from"react";import{findOperationAtLine as w,findOperationLineInEditor as g,sendScrollToPreview as E,isPositionInOperationBlock as L}from"../utils/operationScrolling";const T=({value:o,isFullPreview:c,editorRef:r})=>{const u=m(0),d=m(0);h(()=>{const e=t=>{if(t.data?.type!=="scroll-to-operation"||t.data?.source!=="preview"||!r.current||c)return;const a=Date.now();if(a-u.current<1e3)return;d.current=a;const l=t.data.operationPath;p(l)};return window.addEventListener("message",e),()=>window.removeEventListener("message",e)},[c,r]);const P=e=>{if(!o||c)return;const t=w(o,e);t&&(u.current=Date.now(),E(t.pointer))},p=e=>{if(!r.current||!o)return;const t=g(o,e);if(!t)return;const l=r.current.getPosition()?.lineNumber||1,i=o.split(`
|
|
2
|
+
`);let s=-1,f=i.length;for(let n=0;n<i.length;n++)if(i[n].includes(e.replace("#/paths/","").replace(/~1/g,"/"))){s=n;break}if(s!==-1){for(let n=s+1;n<i.length;n++)if(/^\s*\/[^:]+:\s*$/.test(i[n])){f=n;break}if(L(l,s,f))return}r.current.revealPositionInCenter({lineNumber:t,column:1}),r.current.setPosition({lineNumber:t,column:1})};return{scrollPreviewToOperation:P,scrollToOperationInEditor:p}};export{T as useEditorCommunication};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { editor, Position } from "monaco-editor";
|
|
2
|
+
import { ILanguageServerService } from "../types";
|
|
2
3
|
export interface MonacoEditorOptions {
|
|
4
|
+
languageService: ILanguageServerService;
|
|
3
5
|
onValidationUpdate?: (errors: editor.IMarkerData[], value: string) => void;
|
|
4
6
|
onClick?: (position: Position) => void;
|
|
5
7
|
hideWarnings?: boolean;
|
|
6
8
|
}
|
|
7
|
-
export declare function useMonacoEditor({ onValidationUpdate, onClick, hideWarnings }: MonacoEditorOptions): {
|
|
9
|
+
export declare function useMonacoEditor({ languageService, onValidationUpdate, onClick, hideWarnings }: MonacoEditorOptions): {
|
|
8
10
|
editorRef: import("react").MutableRefObject<editor.IStandaloneCodeEditor | null>;
|
|
9
11
|
monacoRef: import("react").MutableRefObject<null>;
|
|
10
12
|
activeColorMode: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useEffect as
|
|
2
|
-
`))&&setTimeout(()=>{const
|
|
1
|
+
import{useEffect as b,useRef as r}from"react";import{useColorMode as L}from"./useColorMode";import{useThemeHooks as E}from"@redocly/theme/core/hooks";function x({languageService:f,onValidationUpdate:l,onClick:m,hideWarnings:c}){const i=r(null),n=r(null),o=r(null),{useGlobalData:p}=E(),T=p(),M=L(),h=(e,g)=>{i.current=e,n.current=g,o.current||(o.current=f),o.current.initialize(e,g);const d=o.current.setupAutoValidation(l,c);e.onMouseDown(({target:u})=>{m?.(u.position)});const s=e.getModel();if(s){const u=s.onDidChangeContent(D=>{D.changes.some(t=>t.text.includes(`
|
|
2
|
+
`))&&setTimeout(()=>{const t=e.getPosition();try{const a=e.getModel();if(a&&n.current){const C=a.getLanguageId();n.current.editor.setModelLanguage(a,"plaintext"),setTimeout(()=>{n.current.editor.setModelLanguage(a,C),t&&e.setPosition(t)},10)}}catch{e.render(),e.layout(),t&&e.setPosition(t)}},0)});e._contentChangeDisposable=u}return setTimeout(()=>{if(e.layout(),s){const u=s.getValue();s.setValue(u),e.render()}},100),setTimeout(()=>{e.layout(),e.render()},500),()=>{d(),e._contentChangeDisposable&&e._contentChangeDisposable.dispose()}};return b(()=>{o.current?.setupAutoValidation(l,c)},[c]),{editorRef:i,monacoRef:n,activeColorMode:M,handleEditorDidMount:h,handleEditorBeforeMount:e=>{}}}export{x as useMonacoEditor};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
2
|
+
import { ValidationCallback } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Base language service with Monaco editor integration
|
|
5
|
+
* This handles all browser-compatible logic
|
|
6
|
+
*/
|
|
7
|
+
export declare abstract class BaseLanguageService {
|
|
8
|
+
protected monaco: typeof Monaco | null;
|
|
9
|
+
protected editor: Monaco.editor.IStandaloneCodeEditor | null;
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the language server with Monaco editor instance
|
|
12
|
+
*/
|
|
13
|
+
initialize(editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco): void;
|
|
14
|
+
/**
|
|
15
|
+
* Validate content and return diagnostics
|
|
16
|
+
* Subclasses should override this to add their own validation
|
|
17
|
+
*/
|
|
18
|
+
protected getValidationDiagnostics(model: Monaco.editor.ITextModel): Promise<Monaco.editor.IMarkerData[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Validate content with YAML and custom validation
|
|
21
|
+
*/
|
|
22
|
+
validateContent(onValidationUpdate?: ValidationCallback, hideWarnings?: boolean): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Setup automatic validation on content changes
|
|
25
|
+
*/
|
|
26
|
+
setupAutoValidation(onValidationUpdate?: ValidationCallback, hideWarnings?: boolean): () => void;
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{validateYAML as c,createYAMLErrorMarker as d}from"./yamlValidation";class g{constructor(){this.monaco=null,this.editor=null}initialize(t,e){this.editor=t,this.monaco=e,typeof globalThis.__dirname>"u"&&(globalThis.__dirname=".")}async getValidationDiagnostics(t){return[]}async validateContent(t,e){if(!this.editor||!this.monaco)return;const i=this.editor.getModel();if(!i)return;const o=i.getValue();try{const r=(await this.getValidationDiagnostics(i)).filter(n=>e?n.severity!==this.monaco.MarkerSeverity.Warning:!0).sort((n,l)=>l.severity-n.severity),s=c(o);!s.isValid&&s.error&&r.push(d(s.error,this.monaco)),this.monaco.editor.setModelMarkers(i,"language-service",r),t&&t(r,o)}catch(a){console.error("Error during validation:",a)}}setupAutoValidation(t,e){if(!this.editor)return()=>{};const i=()=>this.validateContent(t,e);i();const o=this.editor.onDidChangeModelContent(()=>{i()});return()=>{o.dispose()}}}export{g as BaseLanguageService};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./baseLanguageService";export*from"./monacoIntegration";export*from"./yamlValidation";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
2
|
+
/**
|
|
3
|
+
* Monaco-specific utilities that don't depend on language server
|
|
4
|
+
*/
|
|
5
|
+
export interface LSPosition {
|
|
6
|
+
line: number;
|
|
7
|
+
character: number;
|
|
8
|
+
}
|
|
9
|
+
export interface DocumentProvider {
|
|
10
|
+
_lineOffsets: number[];
|
|
11
|
+
getText: (options?: {
|
|
12
|
+
start?: number;
|
|
13
|
+
end?: number;
|
|
14
|
+
}) => string;
|
|
15
|
+
offsetAt: (position: LSPosition) => number;
|
|
16
|
+
positionAt: (offset: number) => LSPosition;
|
|
17
|
+
lineCount: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create document provider for Monaco editor content
|
|
21
|
+
*/
|
|
22
|
+
export declare function createDocumentProvider(editor: Monaco.editor.IStandaloneCodeEditor | null): DocumentProvider & {
|
|
23
|
+
_lineOffsets: number[];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Map language server severity to Monaco severity
|
|
27
|
+
*/
|
|
28
|
+
export declare function mapSeverityToMonaco(severity: number, monaco: typeof Monaco): Monaco.MarkerSeverity;
|
|
29
|
+
/**
|
|
30
|
+
* Convert language server position to Monaco position
|
|
31
|
+
*/
|
|
32
|
+
export declare function lsPositionToMonaco(position: {
|
|
33
|
+
line: number;
|
|
34
|
+
character: number;
|
|
35
|
+
}): {
|
|
36
|
+
lineNumber: number;
|
|
37
|
+
column: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Convert Monaco position to language server position
|
|
41
|
+
*/
|
|
42
|
+
export declare function monacoPositionToLS(position: Monaco.IPosition): {
|
|
43
|
+
line: number;
|
|
44
|
+
character: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Convert language server range to Monaco range
|
|
48
|
+
*/
|
|
49
|
+
export declare function lsRangeToMonaco(range: {
|
|
50
|
+
start: {
|
|
51
|
+
line: number;
|
|
52
|
+
character: number;
|
|
53
|
+
};
|
|
54
|
+
end: {
|
|
55
|
+
line: number;
|
|
56
|
+
character: number;
|
|
57
|
+
};
|
|
58
|
+
}, monaco: typeof Monaco): Monaco.Range;
|
|
59
|
+
/**
|
|
60
|
+
* Map completion item kind from language server to Monaco
|
|
61
|
+
*/
|
|
62
|
+
export declare function mapCompletionKind(kind: any, monaco: typeof Monaco): Monaco.languages.CompletionItemKind;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function o(e){const t=e?.getModel();return{_lineOffsets:[],get lineCount(){return t?.getLineCount()||0},getText:({start:r=0,end:n=void 0}={})=>(e?.getModel()?.getValue()||"").slice(r,n),offsetAt(r){const n=this.getText();this._lineOffsets=[0];for(let i=0;i<n.length;i++)n[i]===`
|
|
2
|
+
`&&this._lineOffsets.push(i+1);return t?t.getOffsetAt({lineNumber:r.line+1,column:r.character+1}):0},positionAt:r=>{if(!t)return{line:1,character:1};const n=t.getPositionAt(r);return{line:n.lineNumber,character:n.column}}}}function u(e,t){return{1:t.MarkerSeverity.Error,2:t.MarkerSeverity.Warning,3:t.MarkerSeverity.Info,4:t.MarkerSeverity.Hint}[e]||t.MarkerSeverity.Error}function l(e){return{lineNumber:e.line+1,column:e.character+1}}function a(e){return{line:e.lineNumber-1,character:e.column-1}}function c(e,t){return new t.Range(e.start.line+1,e.start.character+1,e.end.line+1,e.end.character+1)}function s(e,t){return t.languages.CompletionItemKind[e]||t.languages.CompletionItemKind.Text}export{o as createDocumentProvider,l as lsPositionToMonaco,c as lsRangeToMonaco,s as mapCompletionKind,u as mapSeverityToMonaco,a as monacoPositionToLS};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
2
|
+
export interface YAMLValidationResult {
|
|
3
|
+
isValid: boolean;
|
|
4
|
+
error?: {
|
|
5
|
+
message: string;
|
|
6
|
+
line: number;
|
|
7
|
+
column: number;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Parse YAML and validate it's a valid OpenAPI/Swagger specification
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateYAML(content: string): YAMLValidationResult;
|
|
14
|
+
/**
|
|
15
|
+
* Create Monaco marker from YAML validation error
|
|
16
|
+
*/
|
|
17
|
+
export declare function createYAMLErrorMarker(error: {
|
|
18
|
+
message: string;
|
|
19
|
+
line: number;
|
|
20
|
+
column: number;
|
|
21
|
+
}, monaco: typeof Monaco): Monaco.editor.IMarkerData;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{load as n}from"js-yaml";function t(r){try{const e=n(r);return r.trim()===""?{isValid:!0}:typeof e!="object"||e===null||(e.openapi===void 0||!e.openapi.match(/^3\.[0,1]\.\d+$/))&&(e.swagger===void 0||!e.swagger.match(/^2\.[0,1]\.\d+$/))?{isValid:!1,error:{message:"Not an OpenAPI or Swagger specification. Only OpenAPI 3.0.x and Swagger 2.0.x are supported. Rule: struct",line:1,column:1}}:{isValid:!0}}catch(e){return{isValid:!1,error:{message:(e.reason||e.message)+" Rule: struct",line:e.mark?.line||1,column:e.mark?.column||0}}}}function i(r,e){return{severity:e.MarkerSeverity.Error,message:r.message,startLineNumber:r.line,startColumn:r.column,endLineNumber:r.line,endColumn:1e3}}export{i as createYAMLErrorMarker,t as validateYAML};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const defaultOpenapiTemplate = "openapi: 3.
|
|
1
|
+
export declare const defaultOpenapiTemplate = "openapi: 3.1.0\ninfo:\n title: Sample API\n version: 1.0.0\n description: |\n Welcome to the Resources API, a robust and efficient service for managing your data.\n ### Overview\n This API provides a standard set of RESTful endpoints to perform CRUD (Create, Read, Update, Delete) operations on resources. It is designed with standard conventions to be predictable and easy to use.\n ### Authentication\n Most endpoints are protected using the **OAuth2 Client Credentials** flow. The `/health` endpoint is public.\n `Authorization: Bearer <YOUR_ACCESS_TOKEN>`\n ### Errors\n The API uses standard HTTP status codes to indicate the success or failure of a request. In the event of an error, the response body will contain a `problem+json` object with details.\n For more information, see our [full developer documentation](https://docs.example.com).\nservers:\n - url: http://api.example.com/v1\ntags:\n - name: Health\n description: Operations to check the health of the service.\n - name: Resources\n description: Operations to manage resources.\nsecurity:\n - oauth2ClientCredentials:\n - resources:read\n - resources:write\npaths:\n /health:\n get:\n tags:\n - Health\n summary: Check service health\n operationId: getHealth\n security: [] # public\n responses:\n '200':\n description: Service is healthy.\n content:\n application/json:\n schema:\n type: object\n properties:\n status:\n type: string\n example: ok\n '503':\n description: Service unavailable.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n /resources:\n get:\n tags:\n - Resources\n summary: List all resources\n operationId: listResources\n parameters:\n - $ref: '#/components/parameters/Limit'\n - $ref: '#/components/parameters/Cursor'\n responses:\n '200':\n description: A paginated list of resources.\n content:\n application/json:\n schema:\n type: object\n properties:\n pageInfo:\n $ref: '#/components/schemas/PageInfo'\n data:\n type: array\n items:\n $ref: '#/components/schemas/Resource'\n post:\n tags:\n - Resources\n summary: Create a new resource\n operationId: createResource\n requestBody:\n required: true\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/Resource'\n responses:\n '201':\n description: Resource created successfully.\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/Resource'\n '400':\n description: Bad request.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n /resources/{resourceId}:\n parameters:\n - name: resourceId\n in: path\n required: true\n description: The ID of the resource.\n schema:\n type: string\n format: uuid\n get:\n tags:\n - Resources\n summary: Get a single resource\n operationId: getResourceById\n responses:\n '200':\n description: The requested resource.\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/Resource'\n '404':\n description: Resource not found.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n delete:\n tags:\n - Resources\n summary: Delete a resource\n operationId: deleteResourceById\n responses:\n '204':\n description: Resource deleted successfully.\n '404':\n description: Resource not found.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n\ncomponents:\n securitySchemes:\n oauth2ClientCredentials:\n type: oauth2\n description: OAuth2 Client Credentials Grant.\n flows:\n clientCredentials:\n tokenUrl: https://auth.example.com/oauth2/token\n scopes:\n resources:read: Read access to resources\n resources:write: Write and delete access to resources\n parameters:\n Limit:\n name: limit\n in: query\n description: The number of items to return per page.\n schema:\n type: integer\n format: int32\n default: 20\n minimum: 1\n maximum: 100\n Cursor:\n name: cursor\n in: query\n description: An opaque cursor for fetching the next page of results.\n schema:\n type: string\n schemas:\n PageInfo:\n type: object\n properties:\n hasNextPage:\n type: boolean\n description: Indicates if there are more pages of results.\n endCursor:\n type: string\n description: The cursor to use to fetch the next page of results.\n required:\n - hasNextPage\n Resource:\n type: object\n properties:\n id:\n type: string\n format: uuid\n description: The unique identifier for the resource.\n example: 'a7b3c2d9-e4f5-4a6b-8c7d-1e2f3a4b5c6d'\n readOnly: true\n name:\n type: string\n description: The name of the resource.\n example: My New Widget\n createdAt:\n type: string\n format: date-time\n description: The timestamp when the resource was created.\n example: '2025-10-09T13:31:23Z'\n readOnly: true\n required:\n - name\n ProblemJson:\n type: object\n description: A problem details object (RFC 7807).\n properties:\n type:\n type: string\n format: uri\n description: An absolute URI that identifies the problem type.\n default: 'about:blank'\n example: /errors/resource-not-found\n title:\n type: string\n description: A short, human-readable summary of the problem type.\n example: Resource not found\n status:\n type: integer\n format: int32\n description: The HTTP status code.\n example: 404\n detail:\n type: string\n description: A human-readable explanation specific to this occurrence of the problem.\n example: The resource with ID 'xyz' could not be found.\n instance:\n type: string\n format: uri-reference\n description: A URI reference that identifies the specific occurrence of the problem.\n example: /resources/xyz\n required:\n - title\n - status\n";
|
|
@@ -1,22 +1,232 @@
|
|
|
1
|
-
const e=`openapi: 3.
|
|
1
|
+
const e=`openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
|
-
title:
|
|
3
|
+
title: Sample API
|
|
4
4
|
version: 1.0.0
|
|
5
|
-
description:
|
|
5
|
+
description: |
|
|
6
|
+
Welcome to the Resources API, a robust and efficient service for managing your data.
|
|
7
|
+
### Overview
|
|
8
|
+
This API provides a standard set of RESTful endpoints to perform CRUD (Create, Read, Update, Delete) operations on resources. It is designed with standard conventions to be predictable and easy to use.
|
|
9
|
+
### Authentication
|
|
10
|
+
Most endpoints are protected using the **OAuth2 Client Credentials** flow. The \`/health\` endpoint is public.
|
|
11
|
+
\`Authorization: Bearer <YOUR_ACCESS_TOKEN>\`
|
|
12
|
+
### Errors
|
|
13
|
+
The API uses standard HTTP status codes to indicate the success or failure of a request. In the event of an error, the response body will contain a \`problem+json\` object with details.
|
|
14
|
+
For more information, see our [full developer documentation](https://docs.example.com).
|
|
15
|
+
servers:
|
|
16
|
+
- url: http://api.example.com/v1
|
|
17
|
+
tags:
|
|
18
|
+
- name: Health
|
|
19
|
+
description: Operations to check the health of the service.
|
|
20
|
+
- name: Resources
|
|
21
|
+
description: Operations to manage resources.
|
|
22
|
+
security:
|
|
23
|
+
- oauth2ClientCredentials:
|
|
24
|
+
- resources:read
|
|
25
|
+
- resources:write
|
|
6
26
|
paths:
|
|
7
|
-
/
|
|
27
|
+
/health:
|
|
8
28
|
get:
|
|
9
|
-
|
|
10
|
-
|
|
29
|
+
tags:
|
|
30
|
+
- Health
|
|
31
|
+
summary: Check service health
|
|
32
|
+
operationId: getHealth
|
|
33
|
+
security: [] # public
|
|
11
34
|
responses:
|
|
12
35
|
'200':
|
|
13
|
-
description:
|
|
36
|
+
description: Service is healthy.
|
|
14
37
|
content:
|
|
15
38
|
application/json:
|
|
16
39
|
schema:
|
|
17
40
|
type: object
|
|
18
41
|
properties:
|
|
19
|
-
|
|
42
|
+
status:
|
|
20
43
|
type: string
|
|
21
|
-
example:
|
|
44
|
+
example: ok
|
|
45
|
+
'503':
|
|
46
|
+
description: Service unavailable.
|
|
47
|
+
content:
|
|
48
|
+
application/problem+json:
|
|
49
|
+
schema:
|
|
50
|
+
$ref: '#/components/schemas/ProblemJson'
|
|
51
|
+
/resources:
|
|
52
|
+
get:
|
|
53
|
+
tags:
|
|
54
|
+
- Resources
|
|
55
|
+
summary: List all resources
|
|
56
|
+
operationId: listResources
|
|
57
|
+
parameters:
|
|
58
|
+
- $ref: '#/components/parameters/Limit'
|
|
59
|
+
- $ref: '#/components/parameters/Cursor'
|
|
60
|
+
responses:
|
|
61
|
+
'200':
|
|
62
|
+
description: A paginated list of resources.
|
|
63
|
+
content:
|
|
64
|
+
application/json:
|
|
65
|
+
schema:
|
|
66
|
+
type: object
|
|
67
|
+
properties:
|
|
68
|
+
pageInfo:
|
|
69
|
+
$ref: '#/components/schemas/PageInfo'
|
|
70
|
+
data:
|
|
71
|
+
type: array
|
|
72
|
+
items:
|
|
73
|
+
$ref: '#/components/schemas/Resource'
|
|
74
|
+
post:
|
|
75
|
+
tags:
|
|
76
|
+
- Resources
|
|
77
|
+
summary: Create a new resource
|
|
78
|
+
operationId: createResource
|
|
79
|
+
requestBody:
|
|
80
|
+
required: true
|
|
81
|
+
content:
|
|
82
|
+
application/json:
|
|
83
|
+
schema:
|
|
84
|
+
$ref: '#/components/schemas/Resource'
|
|
85
|
+
responses:
|
|
86
|
+
'201':
|
|
87
|
+
description: Resource created successfully.
|
|
88
|
+
content:
|
|
89
|
+
application/json:
|
|
90
|
+
schema:
|
|
91
|
+
$ref: '#/components/schemas/Resource'
|
|
92
|
+
'400':
|
|
93
|
+
description: Bad request.
|
|
94
|
+
content:
|
|
95
|
+
application/problem+json:
|
|
96
|
+
schema:
|
|
97
|
+
$ref: '#/components/schemas/ProblemJson'
|
|
98
|
+
/resources/{resourceId}:
|
|
99
|
+
parameters:
|
|
100
|
+
- name: resourceId
|
|
101
|
+
in: path
|
|
102
|
+
required: true
|
|
103
|
+
description: The ID of the resource.
|
|
104
|
+
schema:
|
|
105
|
+
type: string
|
|
106
|
+
format: uuid
|
|
107
|
+
get:
|
|
108
|
+
tags:
|
|
109
|
+
- Resources
|
|
110
|
+
summary: Get a single resource
|
|
111
|
+
operationId: getResourceById
|
|
112
|
+
responses:
|
|
113
|
+
'200':
|
|
114
|
+
description: The requested resource.
|
|
115
|
+
content:
|
|
116
|
+
application/json:
|
|
117
|
+
schema:
|
|
118
|
+
$ref: '#/components/schemas/Resource'
|
|
119
|
+
'404':
|
|
120
|
+
description: Resource not found.
|
|
121
|
+
content:
|
|
122
|
+
application/problem+json:
|
|
123
|
+
schema:
|
|
124
|
+
$ref: '#/components/schemas/ProblemJson'
|
|
125
|
+
delete:
|
|
126
|
+
tags:
|
|
127
|
+
- Resources
|
|
128
|
+
summary: Delete a resource
|
|
129
|
+
operationId: deleteResourceById
|
|
130
|
+
responses:
|
|
131
|
+
'204':
|
|
132
|
+
description: Resource deleted successfully.
|
|
133
|
+
'404':
|
|
134
|
+
description: Resource not found.
|
|
135
|
+
content:
|
|
136
|
+
application/problem+json:
|
|
137
|
+
schema:
|
|
138
|
+
$ref: '#/components/schemas/ProblemJson'
|
|
139
|
+
|
|
140
|
+
components:
|
|
141
|
+
securitySchemes:
|
|
142
|
+
oauth2ClientCredentials:
|
|
143
|
+
type: oauth2
|
|
144
|
+
description: OAuth2 Client Credentials Grant.
|
|
145
|
+
flows:
|
|
146
|
+
clientCredentials:
|
|
147
|
+
tokenUrl: https://auth.example.com/oauth2/token
|
|
148
|
+
scopes:
|
|
149
|
+
resources:read: Read access to resources
|
|
150
|
+
resources:write: Write and delete access to resources
|
|
151
|
+
parameters:
|
|
152
|
+
Limit:
|
|
153
|
+
name: limit
|
|
154
|
+
in: query
|
|
155
|
+
description: The number of items to return per page.
|
|
156
|
+
schema:
|
|
157
|
+
type: integer
|
|
158
|
+
format: int32
|
|
159
|
+
default: 20
|
|
160
|
+
minimum: 1
|
|
161
|
+
maximum: 100
|
|
162
|
+
Cursor:
|
|
163
|
+
name: cursor
|
|
164
|
+
in: query
|
|
165
|
+
description: An opaque cursor for fetching the next page of results.
|
|
166
|
+
schema:
|
|
167
|
+
type: string
|
|
168
|
+
schemas:
|
|
169
|
+
PageInfo:
|
|
170
|
+
type: object
|
|
171
|
+
properties:
|
|
172
|
+
hasNextPage:
|
|
173
|
+
type: boolean
|
|
174
|
+
description: Indicates if there are more pages of results.
|
|
175
|
+
endCursor:
|
|
176
|
+
type: string
|
|
177
|
+
description: The cursor to use to fetch the next page of results.
|
|
178
|
+
required:
|
|
179
|
+
- hasNextPage
|
|
180
|
+
Resource:
|
|
181
|
+
type: object
|
|
182
|
+
properties:
|
|
183
|
+
id:
|
|
184
|
+
type: string
|
|
185
|
+
format: uuid
|
|
186
|
+
description: The unique identifier for the resource.
|
|
187
|
+
example: 'a7b3c2d9-e4f5-4a6b-8c7d-1e2f3a4b5c6d'
|
|
188
|
+
readOnly: true
|
|
189
|
+
name:
|
|
190
|
+
type: string
|
|
191
|
+
description: The name of the resource.
|
|
192
|
+
example: My New Widget
|
|
193
|
+
createdAt:
|
|
194
|
+
type: string
|
|
195
|
+
format: date-time
|
|
196
|
+
description: The timestamp when the resource was created.
|
|
197
|
+
example: '2025-10-09T13:31:23Z'
|
|
198
|
+
readOnly: true
|
|
199
|
+
required:
|
|
200
|
+
- name
|
|
201
|
+
ProblemJson:
|
|
202
|
+
type: object
|
|
203
|
+
description: A problem details object (RFC 7807).
|
|
204
|
+
properties:
|
|
205
|
+
type:
|
|
206
|
+
type: string
|
|
207
|
+
format: uri
|
|
208
|
+
description: An absolute URI that identifies the problem type.
|
|
209
|
+
default: 'about:blank'
|
|
210
|
+
example: /errors/resource-not-found
|
|
211
|
+
title:
|
|
212
|
+
type: string
|
|
213
|
+
description: A short, human-readable summary of the problem type.
|
|
214
|
+
example: Resource not found
|
|
215
|
+
status:
|
|
216
|
+
type: integer
|
|
217
|
+
format: int32
|
|
218
|
+
description: The HTTP status code.
|
|
219
|
+
example: 404
|
|
220
|
+
detail:
|
|
221
|
+
type: string
|
|
222
|
+
description: A human-readable explanation specific to this occurrence of the problem.
|
|
223
|
+
example: The resource with ID 'xyz' could not be found.
|
|
224
|
+
instance:
|
|
225
|
+
type: string
|
|
226
|
+
format: uri-reference
|
|
227
|
+
description: A URI reference that identifies the specific occurrence of the problem.
|
|
228
|
+
example: /resources/xyz
|
|
229
|
+
required:
|
|
230
|
+
- title
|
|
231
|
+
- status
|
|
22
232
|
`;export{e as defaultOpenapiTemplate};
|
|
@@ -64,3 +64,27 @@ export interface OperationPath {
|
|
|
64
64
|
verb: string;
|
|
65
65
|
pointer: string;
|
|
66
66
|
}
|
|
67
|
+
export interface ValidationCallback {
|
|
68
|
+
(errors: Monaco.editor.IMarkerData[], value: string): void;
|
|
69
|
+
}
|
|
70
|
+
export interface ILanguageServerService {
|
|
71
|
+
/**
|
|
72
|
+
* Initialize the language server with Monaco editor instance
|
|
73
|
+
* @param editor - Monaco editor instance
|
|
74
|
+
* @param monaco - Monaco editor API
|
|
75
|
+
*/
|
|
76
|
+
initialize(editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco): void;
|
|
77
|
+
/**
|
|
78
|
+
* Validate OpenAPI content and provide diagnostics
|
|
79
|
+
* @param onValidationUpdate - Optional callback for validation updates
|
|
80
|
+
* @param hideWarnings - Whether to hide warnings from validation results
|
|
81
|
+
*/
|
|
82
|
+
validateContent(onValidationUpdate?: ValidationCallback, hideWarnings?: boolean): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Setup automatic validation on content changes
|
|
85
|
+
* @param onValidationUpdate - Optional callback for validation updates
|
|
86
|
+
* @param hideWarnings - Whether to hide warnings from validation results
|
|
87
|
+
* @returns Cleanup function to dispose the validation listener
|
|
88
|
+
*/
|
|
89
|
+
setupAutoValidation(onValidationUpdate?: ValidationCallback, hideWarnings?: boolean): () => void;
|
|
90
|
+
}
|
|
@@ -5,6 +5,6 @@ interface UseCommunicationManagerProps {
|
|
|
5
5
|
}
|
|
6
6
|
export declare const useCommunicationManager: ({ definition, lastGoodDefinition, safeSlugify }: UseCommunicationManagerProps) => {
|
|
7
7
|
scrollToPointer: (pointer: string) => void;
|
|
8
|
-
scrollToOperationInEditor: (
|
|
8
|
+
scrollToOperationInEditor: (path: string, method?: string) => void;
|
|
9
9
|
};
|
|
10
10
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffect as l}from"react";import{extractOperationFromButton as y}from"../utils/html";const
|
|
1
|
+
import{useEffect as l}from"react";import{extractOperationFromButton as y}from"../utils/html";const C=({definition:f,lastGoodDefinition:h,safeSlugify:d})=>{const s=t=>{const e=f||h;if(!e?.paths){console.warn("[EditorPreview] No definition or paths available");return}let o="",n="";if(t.startsWith("#/")){const a=t.slice(2).split("/");n=a[2]||"",o=(a[1]||"").replaceAll("~1","/")}else{const a=t.split("/"),w=a[1]||"";n=a[2]||"",o=w.replace(/^paths/,"").replaceAll("~1","/")}if(!o||!n){console.warn("[EditorPreview] Invalid pointer format:",t);return}const r=e.paths[o]?.[n];if(!r){console.warn("[EditorPreview] No operation found for",{path:o,verb:n,pointer:t});return}const v=r.tags?.[0],P=v?d(v)+"/":"";let i="";if(r?.operationId?i="/preview/"+P+d(r.operationId):i="/preview/"+P+"paths/"+d(o)+"/"+n.toLowerCase(),i&&i!==window.location.pathname){window.history.replaceState({},"",i);const a=n.toLowerCase(),w=o,g=()=>{const E=document.querySelectorAll('button[data-component-name="Button/Button"]');for(const c of E){const u=y(c);if(u&&u.path===w&&u.method.toLowerCase()===a)return c.click(),!0}return!1};let p=g();p||[0,100,300,800].forEach(c=>{setTimeout(()=>{p||(p=g())},c)})}else i||console.warn("[EditorPreview] could not compute url for pointer:",t)},m=(t,e)=>{let o=t;e&&(o=`#/paths/${t.replace(/\//g,"~1")}/${e.toLowerCase()}`),window.parent.postMessage({type:"scroll-to-operation",operationPath:o,source:"preview"},"*")};return l(()=>{try{window.parent&&typeof window.parent.onReady=="function"?window.parent.onReady(window):(console.warn("[EditorPreview] Parent onReady not available, retrying..."),setTimeout(()=>{window.parent&&typeof window.parent.onReady=="function"?window.parent.onReady(window):console.error("[EditorPreview] Failed to register with parent window")},100))}catch(t){console.error("[EditorPreview] Error registering with parent:",t)}},[]),l(()=>(window.scrollToPointer=s,()=>{delete window.scrollToPointer}),[f,h]),l(()=>{const t=e=>{e.data?.type==="scroll-to-operation"&&e.data?.source==="editor"&&s(e.data.operationPath)};return window.addEventListener("message",t),()=>{window.removeEventListener("message",t)}},[s]),l(()=>{const t=e=>{const n=e.target.closest("button");if(n){const r=y(n);r&&m(r.path,r.method)}};return document.addEventListener("click",t),()=>{document.removeEventListener("click",t)}},[]),{scrollToPointer:s,scrollToOperationInEditor:m}};export{C as useCommunicationManager};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import e from"react";import r from"styled-components";import{Box as
|
|
1
|
+
import e from"react";import r from"styled-components";import{Box as a}from"../../ui/Box";import{breakpoints as t}from"@redocly/theme/core/utils";import{TopLearnBlock as i,CardsBlock as o,BottomLearnBlock as p}from"./components";const u={seo:{title:"Learn"},slug:"/learn"};function f({cards:n}){return e.createElement(d,{backgroundColor:"var(--bg-color)",width:"100vw",height:"fit-content",position:"relative"},e.createElement(l,null),e.createElement(i,null),e.createElement(o,{cards:n}),e.createElement(p,null))}const l=r.div`
|
|
2
2
|
position: absolute;
|
|
3
3
|
max-width: 1384px;
|
|
4
4
|
width: -webkit-fill-available;
|
|
5
5
|
height: 100%;
|
|
6
|
+
pointer-events: none;
|
|
6
7
|
|
|
7
8
|
background-image: url(${require("./images/hero-img.svg")});
|
|
8
9
|
background-position: top;
|
|
@@ -11,9 +12,10 @@ import e from"react";import r from"styled-components";import{Box as i}from"../..
|
|
|
11
12
|
.dark & {
|
|
12
13
|
background-image: url(${require("./images/hero-img-dark.svg")});
|
|
13
14
|
}
|
|
14
|
-
`,d=r(
|
|
15
|
+
`,d=r(a)`
|
|
15
16
|
display: flex;
|
|
16
17
|
align-items: center;
|
|
18
|
+
position: relative;
|
|
17
19
|
flex-direction: column;
|
|
18
20
|
gap: 24px;
|
|
19
21
|
padding: 0 16px 64px 16px;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as t from"react";import n from"styled-components";import{breakpoints as l}from"@redocly/theme/core/utils";import{Tooltip as P}from"@redocly/theme/components/Tooltip/Tooltip";import{Link as M}from"@redocly/theme/components/Link/Link";import{periodsList as S,seatIntervals as f,seatProPlanIntervals as k}from"../pricingData/data";import{Period as y,Plan as v,Product as
|
|
1
|
+
import*as t from"react";import n from"styled-components";import{breakpoints as l}from"@redocly/theme/core/utils";import{Tooltip as P}from"@redocly/theme/components/Tooltip/Tooltip";import{Link as M}from"@redocly/theme/components/Link/Link";import{periodsList as S,seatIntervals as f,seatProPlanIntervals as k}from"../pricingData/data";import{Period as y,Plan as v,Product as x}from"../types/types";import{choosePeriod as L}from"../calculations/choosePeriod";import{plansList as T}from"../pricingData/data";import{PlanCard as z}from"./PlanCard";import{Switcher as O}from"../../calculator/components/Switcher";import{chooseProduct as N}from"../calculations/chooseProduct";import{ActiveCheckmark as A}from"../images/ActiveCheckmark";const D=(e,o,a,m)=>{let s=0;const p=!m||isNaN(m)||m<1?1:m;return o===v.PRO?a===y.YEAR?s=k[e][a]/12:s=k[e][a]:(o===v.ENTERPRISE&&(a===y.YEAR?s=f[e][a][f[e][a].findIndex(c=>p<=c.tierEnd&&p>=c.tierStart)].price/12:s=f[e][a][f[e][a].findIndex(c=>p<=c.tierEnd&&p>=c.tierStart)].price),s)},fe=({setCalculatorProperties:e,period:o,plan:a,amountSelectedProjects:m,onChange:s,onFocus:p,onBlur:c,seats:h,inputValue:b,calculatorProperties:r})=>{const E=[{name:x.REALM,subName:": All combined",gradient:["#1677FF","#08C7E0"]},{name:x.REDOC,color:"#1677FF",activeColor:"#E5F1FF",descriptionProperties:[{title:"OpenAPI",tooltip:"Render OpenAPI docs with the beauty and function of Redoc. Try it panel with Replay. Code samples generated automatically in a dozen languages."},{title:"GraphQL",tooltip:"Redoc renders GraphQL SDL files with a consistent design to OpenAPI."},{title:"AsyncAPI",tooltip:"AsyncAPI docs rendered natively\u2014just drop in your spec file."},{title:"SOAP",tooltip:"Redoc renders SOAP WSDL files with an extension. Functional but not beautiful. SOAP is outdated folks, do you really want us spending more time there?"},{title:"Mock servers",tooltip:"Mock servers are generated automatically for every OpenAPI and hosted at the same custom domain as your website."},{title:"Lint",tooltip:"Make sure API definitions are correct and enforce from a variety of rules or your own configurable rules."}]},{name:x.REVEL,color:"#735CFF",activeColor:"#EDEBFF",descriptionProperties:[{title:"Markdown docs",tooltip:"Render Markdown and Markdoc docs. You can also use our built-in Markdoc tags and create your own."},{title:"React pages",tooltip:"Render tsx and jsx files perfect for landing pages or other fancy pages. This actual web page is one of them."},{title:"Component ejections",tooltip:"Eject components (React code) to the file system in a folder where front end developers can wrap or tweak the components to meet your vision."},{title:"Localization",tooltip:"Translate your content and built-in website tokens."},{title:"Multi-product support",tooltip:"Segment your website by product, if you desire, and have separate configurations and content per product."}]},{name:x.REEF,color:"#A45CFF",activeColor:"#F1E5FF",descriptionProperties:[{title:"Catalog",linkTo:"/reef",underlined:!0,tooltip:"Catalog all the things, including your APIs. Filter by metadata."},{title:"Scorecard for governance",tooltip:"Lint your APIs? This allows you to run multiple rulesets against each API. It collates the results into an interactive report some managers cannot live without."},{title:"API functions",tooltip:"Build custom backend logic (auth, data fetching, forms, and more) right inside your docs with API functions."},{title:"Markdown docs",tooltip:"Render Markdown and Markdoc docs. You can also use our built-in Markdoc tags and create your own."},{title:"Dynamic client registration",tooltip:"Want to allow customers to register a client/app, get API credentials, and request access to various API products or scopes?"}]}];return t.createElement(ie,null,t.createElement(q,{id:"selected-products"},E.map((i,g)=>t.createElement(Y,{key:g,isLastElement:E.length-1===g,isRealm:i.name===x.REALM},t.createElement(G,null,t.createElement("div",null,t.createElement(O,{height:"22px",transform:"translateX(18px)",width:"40px",right:"0",top:"0",activeColor:i.gradient?`linear-gradient(90deg, ${i.gradient[0]} 0%, ${i.gradient[1]} 100%)`:i.color,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,onClick:()=>N(e,i.name,r.coreProducts)})),t.createElement("p",null,i.name,i.subName&&t.createElement("span",null,i.subName))),i.descriptionProperties&&i.descriptionProperties.map((d,u)=>t.createElement(Q,{key:u},d.linkTo?t.createElement(B,{to:d.linkTo,underlined:d.underlined.toString()},t.createElement($,null,t.createElement(C,{isFirst:u===0,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.color}),t.createElement(I,{isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.activeColor},r.coreProducts.includes(i.name)||r.coreProducts.length===3?t.createElement(A,{fill:i.color}):t.createElement(R,null))),d.title,t.createElement(w,{src:require("../images/external.svg")})):t.createElement(j,{underlined:d.underlined},t.createElement($,null,t.createElement(C,{isFirst:u===0,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.color}),t.createElement(I,{isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.activeColor},r.coreProducts.includes(i.name)||r.coreProducts.length===3?t.createElement(A,{fill:i.color}):t.createElement(R,null))),t.createElement("p",null,d.title)),d.tooltip&&t.createElement(H,{tip:d.tooltip,width:"fit-content",children:t.createElement("img",{src:require("../images/tooltip.svg"),style:{maxWidth:"14px",maxHeight:"14px"}})})))))),t.createElement(te,null,t.createElement(ee,null,t.createElement(Z,null,t.createElement("p",null,"Seats"),t.createElement(K,null,t.createElement(J,{placeholder:"40",pattern:"\\d+(\\.\\d+)?",value:b!==void 0?b:h,onChange:s,onFocus:p,onBlur:c}),t.createElement(P,{tip:"Seats count for users who have the OWNER, MEMBER, or COMMITTER roles. Additional roles such as BILLING and VIEWER are users that do not count towards your seat limits.",children:t.createElement("img",{src:require("../images/tooltip.svg"),style:{maxWidth:"14px"}})}))),t.createElement(U,null,t.createElement(_,null,S.map(i=>t.createElement(X,{key:i,onClick:()=>L(e,i,a),selected:o===i},t.createElement(F,null,i,"ly")))),o===y.MONTH&&t.createElement(W,{src:require("../images/save-one-month-badge.svg")}))),t.createElement(V,null,T.map((i,g)=>t.createElement(z,{key:g,plan:i,period:o,price:D(m,i.name,o,h),isCustom:i.name===v.ENTERPRISE_PLUS||h>500})))))},W=n.img`
|
|
2
2
|
position: absolute;
|
|
3
3
|
right: 9px;
|
|
4
4
|
margin-bottom: 5px;
|
|
@@ -14,14 +14,14 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
|
|
|
14
14
|
margin-left: 8px;
|
|
15
15
|
margin-top: 6px;
|
|
16
16
|
align-self: center;
|
|
17
|
-
|
|
17
|
+
`,$=n.div`
|
|
18
18
|
display: flex;
|
|
19
19
|
flex-direction: column;
|
|
20
20
|
align-items: center;
|
|
21
21
|
justify-content: center;
|
|
22
22
|
margin-right: 12px;
|
|
23
23
|
height: 100%;
|
|
24
|
-
|
|
24
|
+
`,C=n.div`
|
|
25
25
|
background: ${({isActive:e,activeColor:o})=>e?o:"var(--border-color-secondary)"};
|
|
26
26
|
opacity: ${({isActive:e})=>e?"0.44":"1"};
|
|
27
27
|
width: 1px;
|
|
@@ -29,7 +29,7 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
|
|
|
29
29
|
margin-top: ${({isFirst:e})=>e&&"-4px"};
|
|
30
30
|
min-height: 8px;
|
|
31
31
|
max-height: 40px;
|
|
32
|
-
`,
|
|
32
|
+
`,I=n.div`
|
|
33
33
|
width: 40px;
|
|
34
34
|
height: 20px;
|
|
35
35
|
min-height: 20px;
|
|
@@ -64,7 +64,7 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
|
|
|
64
64
|
display: block;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
`,
|
|
67
|
+
`,q=n.div`
|
|
68
68
|
display: flex;
|
|
69
69
|
flex-direction: column;
|
|
70
70
|
width: 100%;
|
|
@@ -85,7 +85,7 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
|
|
|
85
85
|
padding: 16px 24px 0 0;
|
|
86
86
|
border-bottom: none;
|
|
87
87
|
}
|
|
88
|
-
`,
|
|
88
|
+
`,j=n.div`
|
|
89
89
|
display: flex;
|
|
90
90
|
align-items: flex-end;
|
|
91
91
|
color: var(--text-color-secondary);
|
|
@@ -28,6 +28,7 @@ export declare const plansList: ({
|
|
|
28
28
|
aiSearch?: undefined;
|
|
29
29
|
typesense?: undefined;
|
|
30
30
|
analytics?: undefined;
|
|
31
|
+
mcpServers?: undefined;
|
|
31
32
|
residencyOptions?: undefined;
|
|
32
33
|
salesAssistance?: undefined;
|
|
33
34
|
forms?: undefined;
|
|
@@ -48,6 +49,7 @@ export declare const plansList: ({
|
|
|
48
49
|
aiSearch: boolean;
|
|
49
50
|
typesense: boolean;
|
|
50
51
|
analytics: boolean;
|
|
52
|
+
mcpServers: boolean;
|
|
51
53
|
reunite?: undefined;
|
|
52
54
|
hasHosting?: undefined;
|
|
53
55
|
projects?: undefined;
|
|
@@ -82,6 +84,7 @@ export declare const plansList: ({
|
|
|
82
84
|
aiSearch?: undefined;
|
|
83
85
|
typesense?: undefined;
|
|
84
86
|
analytics?: undefined;
|
|
87
|
+
mcpServers?: undefined;
|
|
85
88
|
};
|
|
86
89
|
})[];
|
|
87
90
|
export declare const periodsList: Period[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Period as r,Plan as o,Product as a,ProductBundle as i}from"../types/types";const l=[{title:a.REALM,description:"All combined (Redoc + Revel + Reef)",bgColor:"linear-gradient(90deg, rgba(22, 119, 255, 0.08) 0%, rgba(8, 199, 224, 0.08) 100%)",titleColor:"linear-gradient(90deg, #1677FF 0%, #08C7E0 100%)"},{title:a.REDOC,description:"Streamline API development with support for OpenAPI, GraphQL, and AsyncAPI, with mock servers and advanced linting.",bgColor:"#E5F1FF",titleColor:"#1677FF",features:["OpenAPI","GraphQL","AsyncAPI","Mock servers","Lint"]},{title:a.REVEL,description:"Showcase your APIs. Add guides. Localize. Add contextual docs. Landing pages. Multi-product support.",bgColor:"#EDEBFF",titleColor:"#735CFF",features:["Markdown docs","React pages","Component ejections","Localization","Multi-product support"]},{title:a.REEF,description:"API catalog is great for internal use cases. Scorecard for governance. API functions for custom integration capabilities.",bgColor:"#F1E5FF",titleColor:"#A45CFF",features:["API catalog","Scorecard for governance","API functions","Markdown docs","Dynamic client registration"]}],d=[{property:"reunite",name:"Reunite",tooltip:"Reunite is a full collaboration suite with Git integration, editor, visual reviews, and more."},{property:"hasHosting",name:"Custom domain hosting",tooltip:"Host your project on your custom domain"},{property:"projects",name:"Project",tooltip:"The number of projects included under this plan. Extra available for USD $49/month."},{property:"pages",name:"Pages",tooltip:"Total number of pages included across all your projects. Extra available for USD $0.12/month."},{property:"SSO",name:"SSO",tooltip:"Single Sign-On integration for streamlined and secure login"},{property:"guestSSO",name:"Guest SSO",tooltip:"Single Sign-On integration for external guest login"},{property:"RBAC",name:"RBAC",tooltip:"Role-Based Access Control to manage user permissions"},{property:"residencyOptions",name:"Data residency options",tooltip:"Choose where your data is stored to comply with regional regulations"},{property:"IPNetworkRestrictions",name:"IP network restrictions and more",tooltip:"Set IP restrictions to enhance security and control access"},{property:"salesAssistance",name:"Sales-assistance",tooltip:"Get support from our sales team for finding the best solutions for your organization"},{property:"forms",name:"Procurement forms",tooltip:"Access and submit necessary procurement documentation"},{property:"securityQuestionnaires",name:"Security questionnaires",tooltip:"Receive and complete security questionnaires to ensure compliance"},{property:"payByInvoice",name:"Pay-by-invoice / PO process",tooltip:"Flexible payment options including invoices and purchase orders"},{property:"reviews",name:"Legal reviews",tooltip:"Get assistance with legal reviews and compliance checks"},{property:"singleTenant",name:"Single-tenant hosting options",tooltip:"Opt for dedicated hosting for enhanced security and performance"},{property:"premiumSupport",name:"Premium support and professional services options",tooltip:"Access priority support and professional services for your projects"},{property:"remoteContent",name:"Remote content",tooltip:"Remote content allows you to automate sourcing content from a remote source. This is different from sourcing the entire project repository. Remote content can be sourced from Git repos, CICD push command, or a remote URL."},{property:"aiSearch",name:"AI search",tooltip:"Use AI to search your content"},{property:"typesense",name:"Typesense search",tooltip:"Use Typesense to search your content. Create additional search facets. Better relevance for search results."},{property:"apiFunctions",name:"API functions",tooltip:"Custom API endpoints for dynamic and server-side logic"},{property:"analytics",name:"Analytics",tooltip:"Get a clear picture of what users see and search for\u2014page views, search trends, and AI-powered query details"}],u=[{name:o.PRO,features:{reunite:!0,hasHosting:!0,projects:1,pages:100}},{name:o.ENTERPRISE,features:{pages:500,SSO:!0,guestSSO:!0,RBAC:!0,remoteContent:!0,aiSearch:!0,typesense:!0,analytics:!0}},{name:o.ENTERPRISE_PLUS,features:{residencyOptions:!0,salesAssistance:!0,forms:!0,securityQuestionnaires:!0,payByInvoice:!0,reviews:!0,singleTenant:!0,premiumSupport:!0}}],m=[r.MONTH,r.YEAR],n=[{tierStart:1,tierEnd:20},{tierStart:21,tierEnd:50},{tierStart:51,tierEnd:100},{tierStart:101,tierEnd:250},{tierStart:251,tierEnd:500},{tierStart:501,tierEnd:1e3},{tierStart:1001,tierEnd:1/0}],E={[i.ONE]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[24,21.6,19.2,16.8,15.6,14.4,13.2][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[264,237.6,211.2,184.8,171.6,158.4,145.2][t]}))},[i.TWO]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[48,43.2,38.4,33.6,31.2,28.8,26.4][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[528,475.2,422.4,369.6,343.2,316.8,290.4][t]}))},[i.REALM]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[66,59.4,52.8,46.2,42.9,39.6,36.3][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[708,653.4,580.8,508.2,471.9,435.6,399.3][t]}))}},S={[i.ONE]:{[r.MONTH]:10,[r.YEAR]:108},[i.TWO]:{[r.MONTH]:20,[r.YEAR]:216},[i.REALM]:{[r.MONTH]:28,[r.YEAR]:300}},s=[{tierStart:1,tierEnd:500},{tierStart:501,tierEnd:1/0}],p=[{tierStart:1,tierEnd:100},{tierStart:101,tierEnd:1/0}],y={[o.PRO]:{[r.MONTH]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE_PLUS]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))}},g=49,f={[o.PRO]:1,[o.ENTERPRISE]:1,[o.ENTERPRISE_PLUS]:1};export{d as featuresList,y as pageIntervals,m as periodsList,u as plansList,g as pricePerProject,l as productItems,E as seatIntervals,S as seatProPlanIntervals,f as startNumOfProjectPerPlan};
|
|
1
|
+
import{Period as r,Plan as o,Product as a,ProductBundle as i}from"../types/types";const l=[{title:a.REALM,description:"All combined (Redoc + Revel + Reef)",bgColor:"linear-gradient(90deg, rgba(22, 119, 255, 0.08) 0%, rgba(8, 199, 224, 0.08) 100%)",titleColor:"linear-gradient(90deg, #1677FF 0%, #08C7E0 100%)"},{title:a.REDOC,description:"Streamline API development with support for OpenAPI, GraphQL, and AsyncAPI, with mock servers and advanced linting.",bgColor:"#E5F1FF",titleColor:"#1677FF",features:["OpenAPI","GraphQL","AsyncAPI","Mock servers","Lint"]},{title:a.REVEL,description:"Showcase your APIs. Add guides. Localize. Add contextual docs. Landing pages. Multi-product support.",bgColor:"#EDEBFF",titleColor:"#735CFF",features:["Markdown docs","React pages","Component ejections","Localization","Multi-product support"]},{title:a.REEF,description:"API catalog is great for internal use cases. Scorecard for governance. API functions for custom integration capabilities.",bgColor:"#F1E5FF",titleColor:"#A45CFF",features:["API catalog","Scorecard for governance","API functions","Markdown docs","Dynamic client registration"]}],d=[{property:"reunite",name:"Reunite",tooltip:"Reunite is a full collaboration suite with Git integration, editor, visual reviews, and more."},{property:"hasHosting",name:"Custom domain hosting",tooltip:"Host your project on your custom domain"},{property:"projects",name:"Project",tooltip:"The number of projects included under this plan. Extra available for USD $49/month."},{property:"pages",name:"Pages",tooltip:"Total number of pages included across all your projects. Extra available for USD $0.12/month."},{property:"SSO",name:"SSO",tooltip:"Single Sign-On integration for streamlined and secure login"},{property:"guestSSO",name:"Guest SSO",tooltip:"Single Sign-On integration for external guest login"},{property:"RBAC",name:"RBAC",tooltip:"Role-Based Access Control to manage user permissions"},{property:"residencyOptions",name:"Data residency options",tooltip:"Choose where your data is stored to comply with regional regulations"},{property:"IPNetworkRestrictions",name:"IP network restrictions and more",tooltip:"Set IP restrictions to enhance security and control access"},{property:"salesAssistance",name:"Sales-assistance",tooltip:"Get support from our sales team for finding the best solutions for your organization"},{property:"forms",name:"Procurement forms",tooltip:"Access and submit necessary procurement documentation"},{property:"securityQuestionnaires",name:"Security questionnaires",tooltip:"Receive and complete security questionnaires to ensure compliance"},{property:"payByInvoice",name:"Pay-by-invoice / PO process",tooltip:"Flexible payment options including invoices and purchase orders"},{property:"reviews",name:"Legal reviews",tooltip:"Get assistance with legal reviews and compliance checks"},{property:"singleTenant",name:"Single-tenant hosting options",tooltip:"Opt for dedicated hosting for enhanced security and performance"},{property:"premiumSupport",name:"Premium support and professional services options",tooltip:"Access priority support and professional services for your projects"},{property:"remoteContent",name:"Remote content",tooltip:"Remote content allows you to automate sourcing content from a remote source. This is different from sourcing the entire project repository. Remote content can be sourced from Git repos, CICD push command, or a remote URL."},{property:"aiSearch",name:"AI search",tooltip:"Use AI to search your content"},{property:"typesense",name:"Typesense search",tooltip:"Use Typesense to search your content. Create additional search facets. Better relevance for search results."},{property:"apiFunctions",name:"API functions",tooltip:"Custom API endpoints for dynamic and server-side logic"},{property:"analytics",name:"Analytics",tooltip:"Get a clear picture of what users see and search for\u2014page views, search trends, and AI-powered query details"},{property:"mcpServers",name:"MCP Servers",tooltip:"Built-in MCP server lets AI agents query your API docs at runtime \u2014 contextual, authenticated, dynamic"}],u=[{name:o.PRO,features:{reunite:!0,hasHosting:!0,projects:1,pages:100}},{name:o.ENTERPRISE,features:{pages:500,SSO:!0,guestSSO:!0,RBAC:!0,remoteContent:!0,aiSearch:!0,typesense:!0,analytics:!0,mcpServers:!0}},{name:o.ENTERPRISE_PLUS,features:{residencyOptions:!0,salesAssistance:!0,forms:!0,securityQuestionnaires:!0,payByInvoice:!0,reviews:!0,singleTenant:!0,premiumSupport:!0}}],m=[r.MONTH,r.YEAR],n=[{tierStart:1,tierEnd:20},{tierStart:21,tierEnd:50},{tierStart:51,tierEnd:100},{tierStart:101,tierEnd:250},{tierStart:251,tierEnd:500},{tierStart:501,tierEnd:1e3},{tierStart:1001,tierEnd:1/0}],E={[i.ONE]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[24,21.6,19.2,16.8,15.6,14.4,13.2][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[264,237.6,211.2,184.8,171.6,158.4,145.2][t]}))},[i.TWO]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[48,43.2,38.4,33.6,31.2,28.8,26.4][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[528,475.2,422.4,369.6,343.2,316.8,290.4][t]}))},[i.REALM]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[66,59.4,52.8,46.2,42.9,39.6,36.3][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[708,653.4,580.8,508.2,471.9,435.6,399.3][t]}))}},S={[i.ONE]:{[r.MONTH]:10,[r.YEAR]:108},[i.TWO]:{[r.MONTH]:20,[r.YEAR]:216},[i.REALM]:{[r.MONTH]:28,[r.YEAR]:300}},s=[{tierStart:1,tierEnd:500},{tierStart:501,tierEnd:1/0}],p=[{tierStart:1,tierEnd:100},{tierStart:101,tierEnd:1/0}],y={[o.PRO]:{[r.MONTH]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE_PLUS]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))}},g=49,f={[o.PRO]:1,[o.ENTERPRISE]:1,[o.ENTERPRISE_PLUS]:1};export{d as featuresList,y as pageIntervals,m as periodsList,u as plansList,g as pricePerProject,l as productItems,E as seatIntervals,S as seatProPlanIntervals,f as startNumOfProjectPerPlan};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/marketing-pages",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"keywords": [],
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@monaco-editor/react": "^4.7.0",
|
|
27
27
|
"@rebilly/lead-source-tracker": "^2.18.13",
|
|
28
28
|
"@redocly/json-to-json-schema": "^0.0.1",
|
|
29
|
+
"@redocly/openapi-language-server": "^0.6.9",
|
|
29
30
|
"@uiw/react-codemirror": "^4.23.12",
|
|
30
31
|
"dayjs": "^1.11.13",
|
|
31
32
|
"framer-motion": "^12.10.5",
|
|
@@ -58,9 +59,9 @@
|
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
60
61
|
"@changesets/cli": "^2.29.5",
|
|
62
|
+
"@markdoc/markdoc": "0.5.1",
|
|
61
63
|
"@redocly/config": "^0.24.0",
|
|
62
64
|
"@redocly/theme": "^0.53.0",
|
|
63
|
-
"@markdoc/markdoc": "0.5.1",
|
|
64
65
|
"@shikijs/types": "3.4.0",
|
|
65
66
|
"@types/js-yaml": "^4.0.9",
|
|
66
67
|
"@types/node": "^22.15.17",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{useCallback as p,useState as l}from"react";import{ulid as m}from"ulid";function j(){const[e,t]=l(null);return{sendEvent:p(o=>{if(e){const s=v(o,e);e.track(o.type,s)}else console.warn("Failed to send event to Rudderstack.")},[e]),setRudderanalytics:t}}const v=({type:e,data:t,origin:n},o)=>{const s=`evt_${m().toLowerCase()}`,r=g(n,o),c=r.uri,i=t.map(({id:u,object:a,uri:d})=>({id:u,object:a,uri:d}));return{specversion:"1.0",id:s,type:`com.redocly.${e}`,source:c,sourceDetails:r,datacontenttype:"application/json; charset=utf-8",object:"event",origin:"marketing-site-project",data:t,subjects:i,sessionId:o.getSessionId()??void 0,time:new Date().toISOString()}},g=(e,t)=>{const n=t.getAnonymousId();return{id:n,object:"anonymous",uri:`${e}/anonymous/${n}`}};export{j as useTrackEvent};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
2
|
-
export interface LSPosition {
|
|
3
|
-
line: number;
|
|
4
|
-
character: number;
|
|
5
|
-
}
|
|
6
|
-
export interface DocumentProvider {
|
|
7
|
-
getText: (options?: {
|
|
8
|
-
start?: number;
|
|
9
|
-
end?: number;
|
|
10
|
-
}) => string;
|
|
11
|
-
offsetAt: (position: LSPosition) => number;
|
|
12
|
-
positionAt: (offset: number) => Monaco.IPosition;
|
|
13
|
-
}
|
|
14
|
-
export interface ValidationCallback {
|
|
15
|
-
(errors: Monaco.editor.IMarkerData[], value: string): void;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Service class to handle OpenAPI Language Server integration
|
|
19
|
-
*/
|
|
20
|
-
export declare class LanguageServerService {
|
|
21
|
-
private monaco;
|
|
22
|
-
private editor;
|
|
23
|
-
constructor();
|
|
24
|
-
/**
|
|
25
|
-
* Initialize the language server with Monaco editor instance
|
|
26
|
-
*/
|
|
27
|
-
initialize(editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco): void;
|
|
28
|
-
/**
|
|
29
|
-
* Register documents provider for the language server
|
|
30
|
-
*/
|
|
31
|
-
private registerDocumentsProvider;
|
|
32
|
-
/**
|
|
33
|
-
* Create document provider for current editor content
|
|
34
|
-
*/
|
|
35
|
-
private createDocumentProvider;
|
|
36
|
-
/**
|
|
37
|
-
* Register completion item provider
|
|
38
|
-
*/
|
|
39
|
-
private registerCompletionProvider;
|
|
40
|
-
/**
|
|
41
|
-
* Register definition provider
|
|
42
|
-
*/
|
|
43
|
-
private registerDefinitionProvider;
|
|
44
|
-
/**
|
|
45
|
-
* Validate OpenAPI content and provide diagnostics
|
|
46
|
-
*/
|
|
47
|
-
validateContent(onValidationUpdate?: ValidationCallback, hideWarnings?: boolean): Promise<void>;
|
|
48
|
-
/**
|
|
49
|
-
* Setup automatic validation on content changes
|
|
50
|
-
*/
|
|
51
|
-
setupAutoValidation(onValidationUpdate?: ValidationCallback, hideWarnings?: boolean): () => void;
|
|
52
|
-
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{load as v}from"js-yaml";class M{constructor(){this.monaco=null,this.editor=null}initialize(n,r){this.editor=n,this.monaco=r}registerDocumentsProvider(){}createDocumentProvider(){return{getText:({start:n=0,end:r=void 0}={})=>(this.editor?.getModel()?.getValue()||"").slice(n,r),offsetAt:n=>{const r=this.editor?.getModel();return r?r.getOffsetAt({lineNumber:n.line+1,column:n.character+1}):0},positionAt:n=>{const r=this.editor?.getModel();if(!r)return{lineNumber:1,column:1};const s=r.getPositionAt(n);return{lineNumber:s.lineNumber,column:s.column}}}}registerCompletionProvider(){this.monaco&&this.monaco.languages.registerCompletionItemProvider("yaml",{triggerCharacters:[" ",`
|
|
2
|
-
`,"\\","/",'"',"'"],provideCompletionItems:async(n,r)=>({suggestions:[]})})}registerDefinitionProvider(){this.monaco&&this.monaco.languages.registerDefinitionProvider("yaml",{provideDefinition:async(n,r)=>[]})}async validateContent(n,r){if(!this.editor||!this.monaco)return;const s=this.editor.getModel();if(!s)return;const o=s.getValue(),C={uri:s.uri.toString(),languageId:"yaml",version:s.getVersionId(),getText:()=>o,positionAt:e=>{const c=s.getPositionAt(e);return{line:c.lineNumber-1,character:c.column-1}},offsetAt:e=>s.getOffsetAt({lineNumber:e.line+1,column:e.character+1}),lineCount:s.getLineCount()};try{let e=[];r&&(e=e.filter(t=>t.severity!==4));let c=null;try{v(o)}catch(t){c={severity:8,message:t.reason+" Rule: struct",startLineNumber:t.mark?.line||1,startColumn:0,endLineNumber:t.mark?.line||1,endColumn:1e3},e.push(c)}const u=o.split(`
|
|
3
|
-
`);u.forEach((t,i)=>{const p=t.match(/^\s*type:\s*([^\s#]+)\s*(?:#.*)?$/);if(p){const l=L(u,i),m=l?new Set(["apiKey","http","oauth2","openIdConnect"]):new Set(["string","number","integer","boolean","array","object"]),a=p[1].trim();if(!m.has(a)){const g=t.indexOf("type:")+5+2;e.push({severity:8,message:l?`Invalid security scheme type '${a}'. Allowed: apiKey, http, oauth2, openIdConnect. Rule: struct`:`Invalid schema type '${a}'. Allowed: string, number, integer, boolean, array, object. Rule: struct`,startLineNumber:i+1,startColumn:Math.max(1,g),endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"})}}const f=t.match(/^(\s*)-(\s*)$/);if(f){const l={severity:8,message:"Empty list item detected. List items should have content. Rule: struct",startLineNumber:i+1,startColumn:f[1].length+1,endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"};e.push(l)}const d=t.match(/^(\s*)([^#\s][^:]*):\s*$/);if(d&&!t.trim().endsWith(":")){const l=d[2].trim().toLowerCase();if(["version","title","description","type","format","required","default","example"].some(a=>l.includes(a))){const a={severity:8,message:"Key without value detected. This key typically requires a value. Rule: struct",startLineNumber:i+1,startColumn:d[1].length+1,endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"};e.push(a)}}const y=t.match(/^(\s*)-(\s*)(.*)$/);if(y){const[l,m,a,g]=y;if(g.trim().length>0&&a.length!==1){const b={severity:8,message:a.length===0?"Missing space after dash in list item. There should be exactly one space between the dash and content. Rule: struct":"Too many spaces after dash in list item. There should be exactly one space between the dash and content. Rule: struct",startLineNumber:i+1,startColumn:m.length+2,endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"};e.push(b)}}}),this.monaco.editor.setModelMarkers(s,"openapi-ls",e),n&&n(e,o)}catch(e){console.error("Error during validation:",e)}}setupAutoValidation(n,r){if(!this.editor)return()=>{};const s=()=>this.validateContent(n,r);s();const o=this.editor.onDidChangeModelContent(()=>{s()});return()=>o.dispose()}}function L(h,n){const s=(h[n]||"").match(/^\s*/)?.[0].length||0;for(let o=n;o>=0;o--){const e=(h[o]??"").replace(/#.*$/,"");if(!e.trim())continue;const c=e.match(/^\s*/)?.[0].length||0,u=e.match(/^\s*([A-Za-z0-9_\-]+):\s*$/);if(u&&c<s&&u[1]==="components")return!1;if(u&&c<=s){const t=u[1];if(t==="securitySchemes")return!0;if(new Set(["schemas","responses","parameters","examples","requestBodies","headers","links","callbacks","pathItems"]).has(t))return!1}}return!1}export{M as LanguageServerService};
|