mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-06 05:10:20 +03:00
feat: add try-live poc
This commit is contained in:
parent
6c41e95aa0
commit
1a9d7bea4d
|
@ -45,6 +45,8 @@ module.exports = {
|
|||
'unfetch/**',
|
||||
'raf/polyfill',
|
||||
'**/fixtures/**', // for tests
|
||||
'ace-builds/**',
|
||||
'jsoneditor/**',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
14
demo/css/img/description.txt
Normal file
14
demo/css/img/description.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
JSON Editor Icons
|
||||
|
||||
size: outer: 24x24 px
|
||||
inner: 16x16 px
|
||||
|
||||
blue background: RGBA 97b0f8ff
|
||||
gray background: RGBA 4d4d4dff
|
||||
grey background: RGBA d3d3d3ff
|
||||
|
||||
red foreground: RGBA ff3300ff
|
||||
green foreground: RGBA 13ae00ff
|
||||
|
||||
characters are based on the Arial font
|
||||
|
749
demo/css/img/jsoneditor-icons.svg
Normal file
749
demo/css/img/jsoneditor-icons.svg
Normal file
|
@ -0,0 +1,749 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="240"
|
||||
height="144"
|
||||
id="svg4136"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="jsoneditor-icons.svg">
|
||||
<title
|
||||
id="title6512">JSON Editor Icons</title>
|
||||
<metadata
|
||||
id="metadata4148">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>JSON Editor Icons</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs4146" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ff63ff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
id="namedview4144"
|
||||
showgrid="true"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="13.229181"
|
||||
inkscape:cy="119.82429"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4136"
|
||||
showguides="false"
|
||||
borderlayer="false"
|
||||
inkscape:showpageshadow="true"
|
||||
showborder="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4640"
|
||||
empspacing="24" />
|
||||
</sodipodi:namedview>
|
||||
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="svg_1"
|
||||
height="16"
|
||||
width="16"
|
||||
y="4"
|
||||
x="4" />
|
||||
<rect
|
||||
id="svg_1-7"
|
||||
height="16"
|
||||
width="16"
|
||||
y="3.999995"
|
||||
x="28.000006"
|
||||
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
x="52.000004"
|
||||
y="3.999995"
|
||||
width="16"
|
||||
height="16"
|
||||
id="rect4165" />
|
||||
<rect
|
||||
id="rect4175"
|
||||
height="16"
|
||||
width="16"
|
||||
y="3.9999852"
|
||||
x="172.00002"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4175-3"
|
||||
height="16"
|
||||
width="16"
|
||||
y="3.999995"
|
||||
x="196"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<g
|
||||
id="g4299"
|
||||
style="stroke:none">
|
||||
<rect
|
||||
x="7.0000048"
|
||||
y="10.999998"
|
||||
width="9.9999924"
|
||||
height="1.9999986"
|
||||
id="svg_1-1"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
x="11.000005"
|
||||
y="7.0000114"
|
||||
width="1.9999955"
|
||||
height="9.9999838"
|
||||
id="svg_1-1-1"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
</g>
|
||||
<g
|
||||
id="g4299-3"
|
||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
|
||||
style="stroke:none">
|
||||
<rect
|
||||
x="7.0000048"
|
||||
y="10.999998"
|
||||
width="9.9999924"
|
||||
height="1.9999986"
|
||||
id="svg_1-1-0"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
x="11.000005"
|
||||
y="7.0000114"
|
||||
width="1.9999955"
|
||||
height="9.9999838"
|
||||
id="svg_1-1-1-9"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
</g>
|
||||
<rect
|
||||
id="svg_1-7-5"
|
||||
height="6.9999905"
|
||||
width="6.9999909"
|
||||
y="7.0000048"
|
||||
x="55.000004"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="58"
|
||||
y="10.00001"
|
||||
width="6.9999909"
|
||||
height="6.9999905"
|
||||
id="rect4354" />
|
||||
<rect
|
||||
id="svg_1-7-5-7"
|
||||
height="6.9999905"
|
||||
width="6.9999909"
|
||||
y="10.000005"
|
||||
x="58.000004"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
|
||||
<g
|
||||
id="g4378">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="10.999999"
|
||||
width="7.9999909"
|
||||
height="1.9999965"
|
||||
id="svg_1-7-5-3" />
|
||||
<rect
|
||||
id="rect4374"
|
||||
height="1.9999946"
|
||||
width="11.999995"
|
||||
y="7.0000005"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4376"
|
||||
height="1.9999995"
|
||||
width="3.9999928"
|
||||
y="14.999996"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1,0,0,-1,-23.999995,23.999995)"
|
||||
id="g4383">
|
||||
<rect
|
||||
id="rect4385"
|
||||
height="1.9999965"
|
||||
width="7.9999909"
|
||||
y="10.999999"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="7.0000005"
|
||||
width="11.999995"
|
||||
height="1.9999946"
|
||||
id="rect4387" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="14.999996"
|
||||
width="3.9999928"
|
||||
height="1.9999995"
|
||||
id="rect4389" />
|
||||
</g>
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
|
||||
id="rect3754-4"
|
||||
width="16"
|
||||
height="16"
|
||||
x="76"
|
||||
y="3.9999199" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
|
||||
id="path4351"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
|
||||
id="path4351-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
|
||||
id="rect3754-25"
|
||||
width="16"
|
||||
height="16"
|
||||
x="100"
|
||||
y="3.9999199" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
|
||||
id="path2987"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
|
||||
id="path2987-1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
|
||||
id="rect3754-73"
|
||||
width="16"
|
||||
height="16"
|
||||
x="124"
|
||||
y="3.9999199" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
|
||||
id="path3780"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
|
||||
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
|
||||
id="path3782"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
|
||||
id="rect3754-35"
|
||||
width="16"
|
||||
height="16"
|
||||
x="148"
|
||||
y="3.9999199" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
|
||||
id="path5008-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
|
||||
id="path5008-2-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<rect
|
||||
id="svg_1-7-2"
|
||||
height="1.9999961"
|
||||
width="11.999996"
|
||||
y="64"
|
||||
x="54"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="svg_1-7-2-2"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="52"
|
||||
x="80.000008"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="85.000008"
|
||||
y="52"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4561" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="80.000008"
|
||||
y="58"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4563" />
|
||||
<rect
|
||||
id="rect4565"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="58"
|
||||
x="85.000008"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4567"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="64"
|
||||
x="80.000008"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="85.000008"
|
||||
y="64"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4569" />
|
||||
<circle
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4571"
|
||||
cx="110.06081"
|
||||
cy="57.939209"
|
||||
r="4.7438836" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="116.64566"
|
||||
y="-31.79752"
|
||||
width="4.229713"
|
||||
height="6.4053884"
|
||||
id="rect4563-2"
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
|
||||
<path
|
||||
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 125,56 138.77027,56.095 132,64 Z"
|
||||
id="path4613"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4615"
|
||||
d="M 149,64 162.77027,63.905 156,56 Z"
|
||||
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="54"
|
||||
y="53"
|
||||
width="11.999996"
|
||||
height="1.9999961"
|
||||
id="rect4638" />
|
||||
<rect
|
||||
id="svg_1-7-2-24"
|
||||
height="1.9999957"
|
||||
width="12.99999"
|
||||
y="-56"
|
||||
x="53"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
transform="matrix(0,1,-1,0,0,0)" />
|
||||
<rect
|
||||
transform="matrix(0,1,-1,0,0,0)"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="53"
|
||||
y="-66"
|
||||
width="12.99999"
|
||||
height="1.9999957"
|
||||
id="rect4657" />
|
||||
<rect
|
||||
id="rect4659"
|
||||
height="0.99999291"
|
||||
width="11.999999"
|
||||
y="57"
|
||||
x="54"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="54"
|
||||
y="88.000122"
|
||||
width="11.999996"
|
||||
height="1.9999961"
|
||||
id="rect4661" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="80.000008"
|
||||
y="76.000122"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4663" />
|
||||
<rect
|
||||
id="rect4665"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="76.000122"
|
||||
x="85.000008"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<rect
|
||||
id="rect4667"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="82.000122"
|
||||
x="80.000008"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="85.000008"
|
||||
y="82.000122"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4669" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="80.000008"
|
||||
y="88.000122"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4671" />
|
||||
<rect
|
||||
id="rect4673"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="88.000122"
|
||||
x="85.000008"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<circle
|
||||
r="4.7438836"
|
||||
cy="81.939331"
|
||||
cx="110.06081"
|
||||
id="circle4675"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
|
||||
id="rect4677"
|
||||
height="6.4053884"
|
||||
width="4.229713"
|
||||
y="-14.826816"
|
||||
x="133.6163"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4679"
|
||||
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
|
||||
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
|
||||
id="path4681"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<rect
|
||||
id="rect4683"
|
||||
height="1.9999961"
|
||||
width="11.999996"
|
||||
y="77.000122"
|
||||
x="54"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0,1,-1,0,0,0)"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="77.000122"
|
||||
y="-56"
|
||||
width="12.99999"
|
||||
height="1.9999957"
|
||||
id="rect4685" />
|
||||
<rect
|
||||
id="rect4687"
|
||||
height="1.9999957"
|
||||
width="12.99999"
|
||||
y="-66"
|
||||
x="77.000122"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
transform="matrix(0,1,-1,0,0,0)" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="54"
|
||||
y="81.000122"
|
||||
width="11.999999"
|
||||
height="0.99999291"
|
||||
id="rect4689" />
|
||||
<rect
|
||||
id="rect4761-1"
|
||||
height="1.9999945"
|
||||
width="15.99999"
|
||||
y="101"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-0"
|
||||
height="1.9999945"
|
||||
width="15.99999"
|
||||
y="105"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-7"
|
||||
height="1.9999945"
|
||||
width="9"
|
||||
y="109"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1"
|
||||
height="1.9999945"
|
||||
width="12"
|
||||
y="125"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1-4"
|
||||
height="1.9999945"
|
||||
width="10"
|
||||
y="137"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1-4-4"
|
||||
height="1.9999945"
|
||||
width="10"
|
||||
y="129"
|
||||
x="82"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1-4-4-3"
|
||||
height="1.9999945"
|
||||
width="9"
|
||||
y="133"
|
||||
x="82"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
|
||||
id="path4138" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
|
||||
id="path4138-1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
|
||||
id="path3055-0-77" />
|
||||
<path
|
||||
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.96599996;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 4.9850574,108.015 14.0298856,-0.03"
|
||||
id="path5244-5-0-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.96599996;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 4.9849874,132.015 14.0298866,-0.03"
|
||||
id="path5244-5-0-5-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
|
||||
id="path4138-12" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
|
||||
id="path4138-1-3" />
|
||||
<path
|
||||
id="path6191"
|
||||
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
|
||||
id="path6193" />
|
||||
<path
|
||||
id="path6195"
|
||||
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4500"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="11.55581"
|
||||
sodipodi:cy="60.073242"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="1.0471976"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
|
||||
inkscape:transform-center-x="-1.2779026" />
|
||||
<path
|
||||
inkscape:transform-center-x="1.277902"
|
||||
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:arg2="1.0471976"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:cy="60.073242"
|
||||
sodipodi:cx="-36.611614"
|
||||
sodipodi:sides="3"
|
||||
id="path4502"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
sodipodi:type="star"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:arg2="1.0471976"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:cy="60.073212"
|
||||
sodipodi:cx="11.55581"
|
||||
sodipodi:sides="3"
|
||||
id="path4504"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
sodipodi:type="star"
|
||||
transform="matrix(0,1,-1,0,72.0074,71.7877)"
|
||||
inkscape:transform-center-y="1.2779029" />
|
||||
<path
|
||||
inkscape:transform-center-y="-1.2779026"
|
||||
transform="matrix(0,-1,-1,0,96,96)"
|
||||
sodipodi:type="star"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4506"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="11.55581"
|
||||
sodipodi:cy="60.073212"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="1.0471976"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4615-5"
|
||||
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
|
||||
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 179,55 0,6 2,0 0,-6"
|
||||
id="path4300"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 179,62 0,2 2,0 0,-2"
|
||||
id="path4300-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.8"
|
||||
d="M 99.994369,113.0221 102,114.98353 l 7,-6.9558 3,0.97227 2,-1 1,-2 0,-3 -3,3 -3,-3 3,-3 -3,0 -2,1 -1,2 0.99437,3.0221 z"
|
||||
id="path4268"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccc" />
|
||||
<rect
|
||||
id="rect4175-3-5"
|
||||
height="16"
|
||||
width="16"
|
||||
y="4"
|
||||
x="220"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 234,6 0,2 -5,5 0,5 -2,0 0,-5 -5,-5 0,-2"
|
||||
id="path3546"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<g
|
||||
transform="matrix(1.3333328,0,0,-1.5999992,-139.9999,127.19999)"
|
||||
id="g4383-6">
|
||||
<rect
|
||||
id="rect4385-2"
|
||||
height="1.2499905"
|
||||
width="5.9999924"
|
||||
y="12.625005"
|
||||
x="198.00002"
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
|
||||
x="198.00002"
|
||||
y="15.125007"
|
||||
width="7.4999928"
|
||||
height="1.2499949"
|
||||
id="rect4387-9" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
|
||||
x="198.00002"
|
||||
y="7.6250024"
|
||||
width="2.9999909"
|
||||
height="1.2499905"
|
||||
id="rect4389-1-0" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
|
||||
x="198.00002"
|
||||
y="10.125004"
|
||||
width="4.4999919"
|
||||
height="1.2499905"
|
||||
id="rect4389-1-9" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:none;stroke-width:0.68465352px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 207.00001,16.375004 0,-5.625005 -2.25,0 3,-3.1250014 3,3.1250014 -2.25,0 0,5.625005 -1.5,0"
|
||||
id="path4402"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 164,100 0,3 -6,6 0,7 -4,0 0,-7 -6,-6 0,-3"
|
||||
id="path3546-2-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="svg_1-3"
|
||||
height="16"
|
||||
width="16"
|
||||
y="28"
|
||||
x="4" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4402-5-7"
|
||||
d="m 15,41 0,-7 -4,0 0,3 -5,-4 5,-4 0,3 6,0 0,9"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.68465352px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 31 KiB |
2025
demo/css/jsoneditor.css
Normal file
2025
demo/css/jsoneditor.css
Normal file
File diff suppressed because it is too large
Load Diff
71
demo/css/styles.css
Normal file
71
demo/css/styles.css
Normal file
|
@ -0,0 +1,71 @@
|
|||
.jsoneditor {
|
||||
border-color: transparent;
|
||||
border-bottom: thin solid #262626;
|
||||
}
|
||||
|
||||
.ace_editor {
|
||||
border-top: thin solid #262626;
|
||||
}
|
||||
|
||||
.jsoneditor-poweredBy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsoneditor-menu {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.je-wrapper {
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.je-ft-resize {
|
||||
border-color: rgba(38, 50, 56, 0.8);
|
||||
}
|
||||
|
||||
/* comment everything below for defaults */
|
||||
.jsoneditor-statusbar,
|
||||
.ace-twilight .ace_gutter {
|
||||
border: none;
|
||||
}
|
||||
.jsoneditor-statusbar,
|
||||
.ace-twilight .ace_gutter {
|
||||
background-color: #171c20;
|
||||
border-color: #171c20;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.ace-twilight {
|
||||
background-color: #111;
|
||||
color: #f8f8f8;
|
||||
font-family: Courier, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_variable {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_string {
|
||||
color: #a0fbaa;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_constant,
|
||||
.ace-twilight .ace_constant.ace_character,
|
||||
.ace-twilight .ace_constant.ace_character.ace_escape,
|
||||
.ace-twilight .ace_constant.ace_other,
|
||||
.ace-twilight .ace_heading,
|
||||
.ace-twilight .ace_markup.ace_heading,
|
||||
.ace-twilight .ace_support.ace_constant {
|
||||
color: firebrick;
|
||||
}
|
||||
|
||||
.ace-twilight .boolean {
|
||||
color: firebrick;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_numeric {
|
||||
color: firebrick;
|
||||
}
|
77
demo/css/styles.scss
Normal file
77
demo/css/styles.scss
Normal file
|
@ -0,0 +1,77 @@
|
|||
$editor-top-bottom-line-color: #262626;
|
||||
$editor-gutter-status-color: #171c20;
|
||||
$editor-gutter-status-text-color: grey;
|
||||
$editor-background-color: #111; // #141414
|
||||
$editor-text-color: #f8f8f8;
|
||||
|
||||
.jsoneditor {
|
||||
border-color: transparent;
|
||||
border-bottom: thin solid $editor-top-bottom-line-color;
|
||||
}
|
||||
|
||||
.ace_editor {
|
||||
border-top: thin solid $editor-top-bottom-line-color;
|
||||
}
|
||||
|
||||
.jsoneditor-poweredBy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsoneditor-menu {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.je-wrapper {
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.je-ft-resize {
|
||||
border-color: rgba(38, 50, 56, 0.8);
|
||||
}
|
||||
|
||||
// comment everything below for defaults
|
||||
.jsoneditor-statusbar,
|
||||
.ace-twilight .ace_gutter {
|
||||
border: none;
|
||||
}
|
||||
.jsoneditor-statusbar,
|
||||
.ace-twilight .ace_gutter {
|
||||
background-color: $editor-gutter-status-color;
|
||||
border-color: $editor-gutter-status-color;
|
||||
color: $editor-gutter-status-text-color;
|
||||
}
|
||||
|
||||
.ace-twilight {
|
||||
background-color: $editor-background-color;
|
||||
color: $editor-text-color;
|
||||
font-family: Courier, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_variable {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_string {
|
||||
color: #a0fbaa;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_constant,
|
||||
.ace-twilight .ace_constant.ace_character,
|
||||
.ace-twilight .ace_constant.ace_character.ace_escape,
|
||||
.ace-twilight .ace_constant.ace_other,
|
||||
.ace-twilight .ace_heading,
|
||||
.ace-twilight .ace_markup.ace_heading,
|
||||
.ace-twilight .ace_support.ace_constant {
|
||||
color: firebrick;
|
||||
}
|
||||
|
||||
.ace-twilight .boolean {
|
||||
color: firebrick;
|
||||
}
|
||||
|
||||
.ace-twilight .ace_numeric {
|
||||
color: firebrick;
|
||||
}
|
|
@ -1,16 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>ReDoc Interactive Demo</title>
|
||||
<meta name="description" content="ReDoc Interactive Demo. OpenAPI/Swagger-generated API Reference Documentation" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta
|
||||
name="description"
|
||||
content="ReDoc Interactive Demo. OpenAPI/Swagger-generated API Reference Documentation"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<meta property="og:title" content="ReDoc Interactive Demo">
|
||||
<meta property="og:description" content="ReDoc Interactive Demo. OpenAPI/Swagger-generated API Reference Documentation">
|
||||
<meta property="og:image" content="https://user-images.githubusercontent.com/3975738/37729752-8a9ea38a-2d46-11e8-8438-42ed26bf1751.png">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta property="og:title" content="ReDoc Interactive Demo" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="ReDoc Interactive Demo. OpenAPI/Swagger-generated API Reference Documentation"
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://user-images.githubusercontent.com/3975738/37729752-8a9ea38a-2d46-11e8-8438-42ed26bf1751.png"
|
||||
/>
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
|
||||
<style>
|
||||
body {
|
||||
|
@ -22,13 +30,16 @@
|
|||
display: block;
|
||||
}
|
||||
</style>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
|
||||
<script>
|
||||
<!-- <script>
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
|
@ -40,7 +51,6 @@
|
|||
ga('create', 'UA-81703547-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
</script>
|
||||
</script> -->
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -50,6 +50,7 @@ info:
|
|||
x-logo:
|
||||
url: 'https://redocly.github.io/redoc/petstore-logo.png'
|
||||
altText: Petstore logo
|
||||
disabled: true
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
|
||||
|
@ -88,7 +89,7 @@ paths:
|
|||
parameters:
|
||||
- name: Accept-Language
|
||||
in: header
|
||||
description: "The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US"
|
||||
description: 'The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US'
|
||||
example: en-US
|
||||
required: false
|
||||
schema:
|
||||
|
@ -254,7 +255,7 @@ paths:
|
|||
required: false
|
||||
schema:
|
||||
type: string
|
||||
example: "Bearer <TOKEN>"
|
||||
example: 'Bearer <TOKEN>'
|
||||
- name: petId
|
||||
in: path
|
||||
description: Pet id to delete
|
||||
|
@ -429,7 +430,7 @@ paths:
|
|||
application/json:
|
||||
example:
|
||||
status: 400
|
||||
message: "Invalid Order"
|
||||
message: 'Invalid Order'
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
|
@ -1027,8 +1028,8 @@ components:
|
|||
properties:
|
||||
id:
|
||||
externalDocs:
|
||||
description: "Find more info here"
|
||||
url: "https://example.com"
|
||||
description: 'Find more info here'
|
||||
url: 'https://example.com'
|
||||
description: Pet ID
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Id'
|
||||
|
@ -1201,7 +1202,7 @@ x-webhooks:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pet"
|
||||
$ref: '#/components/schemas/Pet'
|
||||
responses:
|
||||
"200":
|
||||
'200':
|
||||
description: Return a 200 status to indicate that the data was received successfully
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>ReDoc</title>
|
||||
<style>
|
||||
body {
|
||||
|
@ -15,11 +14,15 @@
|
|||
display: block;
|
||||
}
|
||||
</style>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link href="./css/jsoneditor.css" rel="stylesheet" />
|
||||
<link href="./css/styles.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<redoc id="example"></redoc>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -69,7 +69,11 @@ export default (env: { playground?: boolean; bench?: boolean } = {}, { mode }) =
|
|||
|
||||
module: {
|
||||
rules: [
|
||||
{ test: [/\.eot$/, /\.gif$/, /\.woff$/, /\.svg$/, /\.ttf$/], use: 'null-loader' },
|
||||
{ test: [/\.eot$/, /\.gif$/, /\.woff$/, /\.ttf$/], use: 'null-loader' },
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: ['@svgr/webpack', 'url-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: [getBabelLoader({ useBuiltIns: true, hot: true })],
|
||||
|
|
3821
package-lock.json
generated
3821
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -76,6 +76,7 @@
|
|||
"@cypress/webpack-preprocessor": "^5.9.0",
|
||||
"@hot-loader/react-dom": "^17.0.1",
|
||||
"@size-limit/preset-app": "^7.0.4",
|
||||
"@svgr/webpack": "^6.1.2",
|
||||
"@types/chai": "^4.2.18",
|
||||
"@types/dompurify": "^2.2.2",
|
||||
"@types/enzyme": "^3.10.5",
|
||||
|
@ -138,6 +139,7 @@
|
|||
"ts-node": "^10.0.0",
|
||||
"typescript": "~4.1.0",
|
||||
"unfetch": "^4.2.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"url-polyfill": "^1.1.12",
|
||||
"webpack": "^5.38.1",
|
||||
"webpack-cli": "^4.7.2",
|
||||
|
@ -156,11 +158,14 @@
|
|||
"@babel/runtime": "^7.14.0",
|
||||
"@redocly/openapi-core": "^1.0.0-beta.54",
|
||||
"@redocly/react-dropdown-aria": "^2.0.11",
|
||||
"ace-builds": "^1.4.13",
|
||||
"axios": "^0.24.0",
|
||||
"classnames": "^2.3.1",
|
||||
"decko": "^1.2.0",
|
||||
"dompurify": "^2.2.8",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"json-pointer": "^0.6.1",
|
||||
"jsoneditor": "^9.5.7",
|
||||
"lunr": "^2.3.9",
|
||||
"mark.js": "^8.11.1",
|
||||
"marked": "^3.0.4",
|
||||
|
|
|
@ -135,6 +135,30 @@ export const SimpleDropdown = styled(StyledDropdown)`
|
|||
}
|
||||
`;
|
||||
|
||||
export const SimpleDropdown2 = styled(SimpleDropdown)`
|
||||
&& {
|
||||
border: 1px solid #999;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
|
||||
.dropdown-selector {
|
||||
padding: 0 5px;
|
||||
}
|
||||
.dropdown-option {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.dropdown-selector-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
border: 1px solid #32329f;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const MimeLabel = styled.span`
|
||||
margin-left: 10px;
|
||||
text-transform: none;
|
||||
|
|
|
@ -40,6 +40,14 @@ export const RightPanelHeader = styled.h3`
|
|||
${extensionsHook('RightPanelHeader')};
|
||||
`;
|
||||
|
||||
export const RightPanelHeaderDiv = styled.div`
|
||||
color: ${({ theme }) => theme.rightPanel.textColor};
|
||||
font-family: Roboto, sans-serif;
|
||||
padding: 4px 0;
|
||||
|
||||
${extensionsHook('RightPanelHeaderDiv')};
|
||||
`;
|
||||
|
||||
export const UnderlinedHeader = styled.h5`
|
||||
border-bottom: 1px solid rgba(38, 50, 56, 0.3);
|
||||
margin: 1em 0 1em 0;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { SimpleDropdown2 as Dropdown } from '../../common-elements/dropdown';
|
||||
|
||||
import { AppStore } from '../../services/AppStore';
|
||||
|
||||
|
@ -22,6 +23,10 @@ export interface ApiInfoProps {
|
|||
|
||||
@observer
|
||||
export class ApiInfo extends React.Component<ApiInfoProps> {
|
||||
handleServerSelect = option => {
|
||||
this.props.store.spec.setSelectedServerIndex(option.idx);
|
||||
};
|
||||
|
||||
handleDownloadClick = e => {
|
||||
if (!e.target.href) {
|
||||
e.target.href = this.props.store.spec.info.downloadLink;
|
||||
|
@ -30,9 +35,8 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
|||
|
||||
render() {
|
||||
const { store } = this.props;
|
||||
const { info, externalDocs } = store.spec;
|
||||
const { info, externalDocs, selectedServerIndex, servers } = store.spec;
|
||||
const hideDownloadButton = store.options.hideDownloadButton;
|
||||
|
||||
const downloadFilename = info.downloadFileName;
|
||||
const downloadLink = info.downloadLink;
|
||||
|
||||
|
@ -76,6 +80,11 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
|||
|
||||
const version = (info.version && <span>({info.version})</span>) || null;
|
||||
|
||||
const serverItems = (servers || []).map((item, index) => ({
|
||||
value: `${item.url} (${item.description})`,
|
||||
idx: index,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<Row>
|
||||
|
@ -109,6 +118,12 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
|||
<Markdown source={store.spec.info.summary} data-role="redoc-summary" />
|
||||
<Markdown source={store.spec.info.description} data-role="redoc-description" />
|
||||
{externalDocs && <ExternalDocumentation externalDocs={externalDocs} />}
|
||||
<Markdown source="Servers" data-role="list-servers" />
|
||||
<Dropdown
|
||||
value={serverItems[selectedServerIndex].value}
|
||||
options={serverItems}
|
||||
onChange={this.handleServerSelect}
|
||||
/>
|
||||
</MiddlePanel>
|
||||
</Row>
|
||||
</Section>
|
||||
|
|
|
@ -12,7 +12,7 @@ export class ApiLogo extends React.Component<{ info: OpenAPIInfo }> {
|
|||
return null;
|
||||
}
|
||||
|
||||
const logoHref = logoInfo.href || (info.contact && info.contact.url);
|
||||
const logoHref = !logoInfo.disabled && (logoInfo.href || (info.contact && info.contact.url));
|
||||
|
||||
// Use the english word logo if no alt text is provided
|
||||
const altText = logoInfo.altText ? logoInfo.altText : 'logo';
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
import * as React from 'react';
|
||||
import { ShelfIcon } from '../../common-elements';
|
||||
import { OperationModel } from '../../services';
|
||||
import { Markdown } from '../Markdown/Markdown';
|
||||
import { OptionsContext } from '../OptionsProvider';
|
||||
import { SelectOnClick } from '../SelectOnClick/SelectOnClick';
|
||||
|
||||
import { expandDefaultServerVariables, getBasePath } from '../../utils';
|
||||
import {
|
||||
EndpointInfo,
|
||||
HttpVerb,
|
||||
OperationEndpointWrap,
|
||||
ServerItem,
|
||||
ServerRelativeURL,
|
||||
ServersOverlay,
|
||||
ServerUrl,
|
||||
} from './styled.elements';
|
||||
|
||||
export interface EndpointProps {
|
||||
|
@ -36,60 +28,19 @@ export class Endpoint extends React.Component<EndpointProps, EndpointState> {
|
|||
};
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
this.setState({ expanded: !this.state.expanded });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { operation, inverted, hideHostname } = this.props;
|
||||
const { operation, inverted } = this.props;
|
||||
const { expanded } = this.state;
|
||||
|
||||
// TODO: highlight server variables, e.g. https://{user}.test.com
|
||||
return (
|
||||
<OptionsContext.Consumer>
|
||||
{options => (
|
||||
<OperationEndpointWrap>
|
||||
<EndpointInfo onClick={this.toggle} expanded={expanded} inverted={inverted}>
|
||||
<EndpointInfo expanded={expanded} inverted={inverted}>
|
||||
<HttpVerb type={operation.httpVerb} compact={this.props.compact}>
|
||||
{operation.httpVerb}
|
||||
</HttpVerb>
|
||||
<ServerRelativeURL>{operation.path}</ServerRelativeURL>
|
||||
<ShelfIcon
|
||||
float={'right'}
|
||||
color={inverted ? 'black' : 'white'}
|
||||
size={'20px'}
|
||||
direction={expanded ? 'up' : 'down'}
|
||||
style={{ marginRight: '-25px' }}
|
||||
/>
|
||||
</EndpointInfo>
|
||||
<ServersOverlay expanded={expanded} aria-hidden={!expanded}>
|
||||
{operation.servers.map(server => {
|
||||
const normalizedUrl = options.expandDefaultServerVariables
|
||||
? expandDefaultServerVariables(server.url, server.variables)
|
||||
: server.url;
|
||||
const basePath = getBasePath(normalizedUrl);
|
||||
return (
|
||||
<ServerItem key={normalizedUrl}>
|
||||
<Markdown source={server.description || ''} compact={true} />
|
||||
<SelectOnClick>
|
||||
<ServerUrl>
|
||||
<span>
|
||||
{hideHostname || options.hideHostname
|
||||
? basePath === '/'
|
||||
? ''
|
||||
: basePath
|
||||
: normalizedUrl}
|
||||
</span>
|
||||
{operation.path}
|
||||
</ServerUrl>
|
||||
</SelectOnClick>
|
||||
</ServerItem>
|
||||
);
|
||||
})}
|
||||
</ServersOverlay>
|
||||
</OperationEndpointWrap>
|
||||
)}
|
||||
</OptionsContext.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import styled from '../../styled-components';
|
||||
|
||||
export const OperationEndpointWrap = styled.div`
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
`;
|
||||
|
@ -9,23 +8,20 @@ export const OperationEndpointWrap = styled.div`
|
|||
export const ServerRelativeURL = styled.span`
|
||||
font-family: ${props => props.theme.typography.code.fontFamily};
|
||||
margin-left: 10px;
|
||||
flex: 1;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
overflow-wrap: anywhere;
|
||||
`;
|
||||
|
||||
export const EndpointInfo = styled.button<{ expanded?: boolean; inverted?: boolean }>`
|
||||
export const EndpointInfo = styled.div<{ expanded?: boolean; inverted?: boolean }>`
|
||||
outline: 0;
|
||||
color: inherit;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
padding: 10px 30px 10px ${props => (props.inverted ? '10px' : '20px')};
|
||||
padding: 10px 20px;
|
||||
border-radius: ${props => (props.inverted ? '0' : '4px 4px 0 0')};
|
||||
background-color: ${props =>
|
||||
props.inverted ? 'transparent' : props.theme.codeBlock.backgroundColor};
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
border: ${props => (props.inverted ? '0' : '1px solid transparent')};
|
||||
border-bottom: ${props => (props.inverted ? '1px solid #ccc' : '0')};
|
||||
|
@ -37,9 +33,6 @@ export const EndpointInfo = styled.button<{ expanded?: boolean; inverted?: boole
|
|||
.${ServerRelativeURL} {
|
||||
color: ${props => (props.inverted ? props.theme.colors.text.primary : '#ffffff')};
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: inset 0 2px 2px rgba(0, 0, 0, 0.45), 0 2px 0 rgba(128, 128, 128, 0.25);
|
||||
}
|
||||
`;
|
||||
|
||||
export const HttpVerb = styled.span.attrs((props: { type: string; compact?: boolean }) => ({
|
||||
|
|
192
src/components/JsonEditor/JsonEditor.tsx
Normal file
192
src/components/JsonEditor/JsonEditor.tsx
Normal file
|
@ -0,0 +1,192 @@
|
|||
import * as React from 'react';
|
||||
import { cloneDeep, isEqual } from 'lodash';
|
||||
import JSONEditorRaw from 'jsoneditor';
|
||||
import 'jsoneditor/dist/jsoneditor.css';
|
||||
import 'ace-builds/src-noconflict/theme-monokai.js';
|
||||
import 'ace-builds/src-noconflict/theme-twilight.js';
|
||||
import 'ace-builds/src-noconflict/theme-ambiance.js';
|
||||
import { JeFt, JeFtResize } from './styled.elements';
|
||||
import { EmptyObject } from '../../types';
|
||||
|
||||
export enum Mode {
|
||||
tree = 'tree',
|
||||
form = 'form',
|
||||
view = 'view',
|
||||
code = 'code',
|
||||
text = 'text',
|
||||
}
|
||||
|
||||
export enum Theme {
|
||||
monokai = 'ace/theme/monokai',
|
||||
twilight = 'ace/theme/twilight',
|
||||
ambiance = 'ace/theme/ambiance',
|
||||
}
|
||||
|
||||
export type TMode = keyof typeof Mode;
|
||||
|
||||
interface IJSONEditorRaw extends Object {
|
||||
set: (json?: EmptyObject) => void;
|
||||
setText: (text?: string) => void;
|
||||
update: (json?: EmptyObject) => void;
|
||||
updateText: (text?: string) => void;
|
||||
setMode: (mode?: Mode) => void;
|
||||
setSchema: (schema?: EmptyObject, schemaRefs?: EmptyObject) => void;
|
||||
destroy: () => void;
|
||||
resize: () => void;
|
||||
setTheme: (theme: string) => void;
|
||||
ace: any;
|
||||
}
|
||||
|
||||
interface IJsonEditor {
|
||||
json?: EmptyObject;
|
||||
text?: string;
|
||||
search?: boolean;
|
||||
schema?: EmptyObject;
|
||||
schemaRefs?: EmptyObject;
|
||||
mode?: Mode;
|
||||
modes?: Mode[];
|
||||
indentation?: number;
|
||||
modalAnchor?: HTMLElement;
|
||||
enableSort?: boolean;
|
||||
enableTransform?: boolean;
|
||||
onChangeText?: (text: string) => void;
|
||||
onChangeJSON?: (json: EmptyObject) => void;
|
||||
onModeChange?: (mode: Mode) => void;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
interface JsonEditorState {
|
||||
contentMinH: number;
|
||||
contentH: number;
|
||||
}
|
||||
|
||||
class JsonEditor extends React.Component<IJsonEditor, JsonEditorState> {
|
||||
jsoneditor?: IJSONEditorRaw | null = null;
|
||||
schema?: EmptyObject;
|
||||
schemaRefs?: EmptyObject;
|
||||
content: HTMLDivElement | null = null;
|
||||
container: HTMLDivElement | null = null;
|
||||
|
||||
startResizeY?: number;
|
||||
startHeight?: number;
|
||||
|
||||
state = {
|
||||
contentMinH: 260,
|
||||
contentH: 260,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { json, text, ...opts } = this.props;
|
||||
|
||||
this.jsoneditor = new JSONEditorRaw(this.container, opts);
|
||||
if (!this.jsoneditor) return;
|
||||
|
||||
if (json) {
|
||||
this.jsoneditor.set(json);
|
||||
}
|
||||
if (text) {
|
||||
this.jsoneditor.setText(text);
|
||||
}
|
||||
this.schema = cloneDeep(opts.schema);
|
||||
this.schemaRefs = cloneDeep(opts.schemaRefs);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (!this.jsoneditor) return;
|
||||
const { json, text, mode, schema, schemaRefs } = this.props;
|
||||
|
||||
if (json) {
|
||||
this.jsoneditor.update(json);
|
||||
}
|
||||
if (text) {
|
||||
this.jsoneditor.updateText(text);
|
||||
}
|
||||
if (mode) {
|
||||
this.jsoneditor.setMode(mode);
|
||||
}
|
||||
|
||||
// store a clone of the schema to keep track of when it actually changes
|
||||
const schemaChanged = !isEqual(schema, this.schema);
|
||||
const schemaRefsChanged = !isEqual(schemaRefs, this.schemaRefs);
|
||||
if (schemaChanged || schemaRefsChanged) {
|
||||
this.schema = cloneDeep(schema);
|
||||
this.schemaRefs = cloneDeep(schemaRefs);
|
||||
this.jsoneditor.setSchema(schema, schemaRefs);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.jsoneditor) {
|
||||
this.jsoneditor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
focusView = () => {
|
||||
if (this.container) {
|
||||
this.container.focus();
|
||||
}
|
||||
};
|
||||
|
||||
resizeMove = event => {
|
||||
event.preventDefault();
|
||||
const deltaY = this.startResizeY! - event.clientY;
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
contentH: Math.max(state.contentMinH, this.startHeight! - deltaY),
|
||||
}));
|
||||
};
|
||||
|
||||
resizeUp = event => {
|
||||
event.preventDefault();
|
||||
document.removeEventListener('mousemove', this.resizeMove);
|
||||
document.removeEventListener('mouseup', this.resizeUp);
|
||||
};
|
||||
|
||||
onResizeDown = event => {
|
||||
event.preventDefault();
|
||||
this.startResizeY = event.clientY;
|
||||
this.startHeight = this.content ? this.content.clientHeight : this.state.contentMinH;
|
||||
document.addEventListener('mousemove', this.resizeMove);
|
||||
document.addEventListener('mouseup', this.resizeUp);
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.jsoneditor) {
|
||||
// delay said not to be necessary.. we have to call this for proper editor resizing
|
||||
// in code or text modes
|
||||
this.jsoneditor.resize();
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
ref={node => {
|
||||
this.content = node;
|
||||
}}
|
||||
className="je-content"
|
||||
style={{
|
||||
minHeight: this.state.contentMinH,
|
||||
height: this.state.contentH,
|
||||
}}
|
||||
onClick={this.focusView}
|
||||
>
|
||||
<div
|
||||
className="jsoneditor-react-container"
|
||||
ref={node => (this.container = node)}
|
||||
style={{
|
||||
width: '100%',
|
||||
minHeight: this.state.contentMinH,
|
||||
height: this.state.contentH,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<JeFt className="je-ft" onMouseDown={this.onResizeDown}>
|
||||
<JeFtResize className="je-ft-resize">
|
||||
<span>◢</span>
|
||||
</JeFtResize>
|
||||
</JeFt>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default JsonEditor;
|
108
src/components/JsonEditor/JsonEditorWrapper.tsx
Normal file
108
src/components/JsonEditor/JsonEditorWrapper.tsx
Normal file
|
@ -0,0 +1,108 @@
|
|||
import * as React from 'react';
|
||||
import JsonEditor, { Mode, Theme } from './JsonEditor';
|
||||
import { EmptyObject } from '../../types';
|
||||
|
||||
// const schema = {
|
||||
// title: 'Example Schema',
|
||||
// type: 'object',
|
||||
// properties: {
|
||||
// array: {
|
||||
// type: 'array',
|
||||
// items: {
|
||||
// type: 'number'
|
||||
// }
|
||||
// },
|
||||
// boolean: {
|
||||
// type: 'boolean',
|
||||
// },
|
||||
// number: {
|
||||
// type: 'number'
|
||||
// }
|
||||
// },
|
||||
// required: ['array', 'boolean']
|
||||
// };
|
||||
|
||||
// const json = {
|
||||
// array: [1, 2, 3],
|
||||
// boolean: true,
|
||||
// string: 'four'
|
||||
// }
|
||||
|
||||
const modes = [];
|
||||
|
||||
interface JsonEditorWrapperProps {
|
||||
schema?: EmptyObject;
|
||||
text?: string;
|
||||
json?: EmptyObject;
|
||||
onChange?: (value: any) => void;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
interface JsonEditorWrapperState {
|
||||
schema?: EmptyObject;
|
||||
text?: string;
|
||||
json?: EmptyObject;
|
||||
mode: Mode;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// - messy json / text interplay
|
||||
// - schema validation
|
||||
class JsonEditorWrapper extends React.Component<JsonEditorWrapperProps, JsonEditorWrapperState> {
|
||||
constructor(props: JsonEditorWrapperProps) {
|
||||
super(props);
|
||||
|
||||
const { schema, text } = this.props;
|
||||
const defaultSchema = {};
|
||||
|
||||
this.state = {
|
||||
schema: schema || defaultSchema,
|
||||
text: text || '',
|
||||
json: {}, //text || '',
|
||||
mode: Mode.code,
|
||||
};
|
||||
}
|
||||
|
||||
onChangeText = (text: string) => {
|
||||
this.setState({ text });
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(text);
|
||||
}
|
||||
};
|
||||
|
||||
onChangeJSON = (text: string) => {
|
||||
this.setState({ text });
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(text);
|
||||
}
|
||||
};
|
||||
|
||||
onModeChange = (mode: Mode) => {
|
||||
this.setState({ mode });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
const { schema, text, mode } = this.state;
|
||||
return (
|
||||
<div className="je-wrapper">
|
||||
<JsonEditor
|
||||
search={false}
|
||||
schema={schema}
|
||||
text={text}
|
||||
mode={mode}
|
||||
modes={modes}
|
||||
theme={theme || Theme.twilight}
|
||||
indentation={4}
|
||||
enableSort={false}
|
||||
enableTransform={false}
|
||||
onChangeText={this.onChangeText}
|
||||
// onChangeJSON={this.onChangeJSON}
|
||||
onModeChange={this.onModeChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default JsonEditorWrapper;
|
23
src/components/JsonEditor/styled.elements.ts
Normal file
23
src/components/JsonEditor/styled.elements.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import styled from '../../styled-components';
|
||||
|
||||
export const JeFt = styled.div`
|
||||
background-color: rgba(38, 50, 56, 0.4);
|
||||
border-color: rgba(38, 50, 56, 0.5);
|
||||
color: #999;
|
||||
margin-top: -2px;
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
cursor: pointer !important;
|
||||
`;
|
||||
|
||||
export const JeFtResize = styled.div`
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
user-select: none;
|
||||
|
||||
> span {
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: 7px;
|
||||
}
|
||||
`;
|
|
@ -17,6 +17,7 @@ import { RequestSamples } from '../RequestSamples/RequestSamples';
|
|||
import { ResponsesList } from '../Responses/ResponsesList';
|
||||
import { ResponseSamples } from '../ResponseSamples/ResponseSamples';
|
||||
import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement';
|
||||
import { StoreContext } from '..';
|
||||
|
||||
const Description = styled.div`
|
||||
margin-bottom: ${({ theme }) => theme.spacing.unit * 6}px;
|
||||
|
@ -37,6 +38,8 @@ export class Operation extends React.Component<OperationProps> {
|
|||
return (
|
||||
<OptionsContext.Consumer>
|
||||
{options => (
|
||||
<StoreContext.Consumer>
|
||||
{store => (
|
||||
<Row>
|
||||
<MiddlePanel>
|
||||
<H2>
|
||||
|
@ -61,12 +64,14 @@ export class Operation extends React.Component<OperationProps> {
|
|||
</MiddlePanel>
|
||||
<DarkRightPanel>
|
||||
{!options.pathInMiddlePanel && !isWebhook && <Endpoint operation={operation} />}
|
||||
<RequestSamples operation={operation} />
|
||||
<RequestSamples operation={operation} store={store} />
|
||||
<ResponseSamples operation={operation} />
|
||||
<CallbackSamples callbacks={operation.callbacks} />
|
||||
</DarkRightPanel>
|
||||
</Row>
|
||||
)}
|
||||
</StoreContext.Consumer>
|
||||
)}
|
||||
</OptionsContext.Consumer>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,24 +8,42 @@ import { useExternalExample } from './exernalExampleHook';
|
|||
export interface ExampleProps {
|
||||
example: ExampleModel;
|
||||
mimeType: string;
|
||||
editable?: boolean;
|
||||
value?: any;
|
||||
onChange?: (value: any) => void;
|
||||
}
|
||||
|
||||
export function Example({ example, mimeType }: ExampleProps) {
|
||||
export function Example({ example, mimeType, editable = false, value, onChange }: ExampleProps) {
|
||||
if (example.value === undefined && example.externalValueUrl) {
|
||||
return <ExternalExample example={example} mimeType={mimeType} />;
|
||||
return (
|
||||
<ExternalExample
|
||||
example={example}
|
||||
mimeType={mimeType}
|
||||
editable={editable}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <ExampleValue value={example.value} mimeType={mimeType} />;
|
||||
return (
|
||||
<ExampleValue
|
||||
value={value || example.value}
|
||||
mimeType={mimeType}
|
||||
editable={editable}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function ExternalExample({ example, mimeType }: ExampleProps) {
|
||||
const value = useExternalExample(example, mimeType);
|
||||
export function ExternalExample({ example, mimeType, editable, value, onChange }: ExampleProps) {
|
||||
const value_ = useExternalExample(example, mimeType);
|
||||
|
||||
if (value === undefined) {
|
||||
if (value_ === undefined) {
|
||||
return <span>Loading...</span>;
|
||||
}
|
||||
|
||||
if (value instanceof Error) {
|
||||
if (value_ instanceof Error) {
|
||||
return (
|
||||
<StyledPre>
|
||||
Error loading external example: <br />
|
||||
|
@ -41,5 +59,12 @@ export function ExternalExample({ example, mimeType }: ExampleProps) {
|
|||
);
|
||||
}
|
||||
|
||||
return <ExampleValue value={value} mimeType={mimeType} />;
|
||||
return (
|
||||
<ExampleValue
|
||||
value={value || value_}
|
||||
mimeType={mimeType}
|
||||
editable={editable}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,15 +3,32 @@ import * as React from 'react';
|
|||
import { isJsonLike, langFromMime } from '../../utils/openapi';
|
||||
import { JsonViewer } from '../JsonViewer/JsonViewer';
|
||||
import { SourceCodeWithCopy } from '../SourceCode/SourceCode';
|
||||
import { OptionsConsumer } from '..';
|
||||
import { JsonEditorWrapper } from '../';
|
||||
|
||||
export interface ExampleValueProps {
|
||||
value: any;
|
||||
mimeType: string;
|
||||
editable?: boolean;
|
||||
onChange?: (value: any) => void;
|
||||
}
|
||||
|
||||
export function ExampleValue({ value, mimeType }: ExampleValueProps) {
|
||||
export function ExampleValue({ value, mimeType, editable, onChange }: ExampleValueProps) {
|
||||
if (isJsonLike(mimeType)) {
|
||||
return <JsonViewer data={value} />;
|
||||
return editable ? (
|
||||
<OptionsConsumer>
|
||||
{options => (
|
||||
<JsonEditorWrapper
|
||||
schema={{}}
|
||||
text={JSON.stringify(value, null, 2)}
|
||||
onChange={onChange}
|
||||
theme={options.tryLiveEditorTheme}
|
||||
/>
|
||||
)}
|
||||
</OptionsConsumer>
|
||||
) : (
|
||||
<JsonViewer data={value} />
|
||||
);
|
||||
} else {
|
||||
if (typeof value === 'object') {
|
||||
// just in case example was cached as json but used as non-json
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as React from 'react';
|
|||
import styled from '../../styled-components';
|
||||
|
||||
import { DropdownProps } from '../../common-elements';
|
||||
import { MediaTypeModel } from '../../services/models';
|
||||
import { ExampleModel, MediaTypeModel } from '../../services/models';
|
||||
import { Markdown } from '../Markdown/Markdown';
|
||||
import { Example } from './Example';
|
||||
import { DropdownLabel, DropdownWrapper, NoSampleLabel } from './styled.elements';
|
||||
|
@ -11,6 +11,9 @@ import { DropdownLabel, DropdownWrapper, NoSampleLabel } from './styled.elements
|
|||
export interface PayloadSamplesProps {
|
||||
mediaType: MediaTypeModel;
|
||||
renderDropdown: (props: DropdownProps) => JSX.Element;
|
||||
editable?: boolean;
|
||||
value?: any;
|
||||
onContentChange?: (value: any) => void;
|
||||
}
|
||||
|
||||
interface MediaTypeSamplesState {
|
||||
|
@ -18,15 +21,32 @@ interface MediaTypeSamplesState {
|
|||
}
|
||||
|
||||
export class MediaTypeSamples extends React.Component<PayloadSamplesProps, MediaTypeSamplesState> {
|
||||
state = {
|
||||
constructor(props: PayloadSamplesProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
activeIdx: 0,
|
||||
};
|
||||
|
||||
if (this.props.editable && this.props.onContentChange) {
|
||||
this.props.onContentChange(this.getExample().value);
|
||||
}
|
||||
}
|
||||
|
||||
switchMedia = ({ idx }) => {
|
||||
this.setState({
|
||||
activeIdx: idx,
|
||||
});
|
||||
};
|
||||
|
||||
getExample = () => {
|
||||
const examples = this.props.mediaType.examples || {};
|
||||
const examplesNames = Object.keys(examples);
|
||||
return examples[examplesNames[this.state.activeIdx]];
|
||||
};
|
||||
|
||||
render() {
|
||||
const { editable = false, value, onContentChange } = this.props;
|
||||
const { activeIdx } = this.state;
|
||||
const examples = this.props.mediaType.examples || {};
|
||||
const mimeType = this.props.mediaType.name;
|
||||
|
@ -38,7 +58,7 @@ export class MediaTypeSamples extends React.Component<PayloadSamplesProps, Media
|
|||
return noSample;
|
||||
}
|
||||
|
||||
if (examplesNames.length > 1) {
|
||||
if (!editable && examplesNames.length > 1) {
|
||||
const options = examplesNames.map((name, idx) => {
|
||||
return {
|
||||
value: examples[name].summary || name,
|
||||
|
@ -62,20 +82,51 @@ export class MediaTypeSamples extends React.Component<PayloadSamplesProps, Media
|
|||
</DropdownWrapper>
|
||||
<div>
|
||||
{description && <Markdown source={description} />}
|
||||
<Example example={example} mimeType={mimeType} />
|
||||
{this.getExampleComponent(example, mimeType, editable, value, onContentChange)}
|
||||
</div>
|
||||
</SamplesWrapper>
|
||||
);
|
||||
} else {
|
||||
const example = examples[examplesNames[0]];
|
||||
return (
|
||||
return editable ? (
|
||||
<SamplesWrapper>
|
||||
<DropdownLabel>Request body</DropdownLabel>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'rgba(38, 50, 56, 0.4)',
|
||||
borderColor: 'rgba(38, 50, 56, 0.5)',
|
||||
}}
|
||||
>
|
||||
<div style={{ height: 8 }}></div>
|
||||
{this.getExampleComponent(example, mimeType, editable, value, onContentChange)}
|
||||
</div>
|
||||
</SamplesWrapper>
|
||||
) : (
|
||||
<SamplesWrapper>
|
||||
{example.description && <Markdown source={example.description} />}
|
||||
<Example example={example} mimeType={mimeType} />
|
||||
{this.getExampleComponent(example, mimeType, editable, value, onContentChange)}
|
||||
</SamplesWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getExampleComponent = (
|
||||
example: ExampleModel,
|
||||
mimeType: string,
|
||||
editable: boolean,
|
||||
value: any,
|
||||
onContentChange,
|
||||
) => {
|
||||
return (
|
||||
<Example
|
||||
example={example}
|
||||
mimeType={mimeType}
|
||||
editable={editable}
|
||||
value={value}
|
||||
onChange={onContentChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const SamplesWrapper = styled.div`
|
||||
|
|
299
src/components/PayloadSamples/TryLive.tsx
Normal file
299
src/components/PayloadSamples/TryLive.tsx
Normal file
|
@ -0,0 +1,299 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import axios from 'axios';
|
||||
import { MediaTypeSamples } from './MediaTypeSamples';
|
||||
|
||||
import { MediaContentModel, OperationModel } from '../..';
|
||||
import { DropdownOrLabel, JsonViewer, MediaTypesSwitch } from '..';
|
||||
import {
|
||||
DropdownLabel,
|
||||
InvertedSimpleDropdown,
|
||||
MimeLabel,
|
||||
ParamBox,
|
||||
ParamPrompt,
|
||||
ParamInput,
|
||||
ParamTable,
|
||||
TryUrl,
|
||||
TryBtn,
|
||||
TryTitle,
|
||||
TrySubtitle,
|
||||
} from './styled.elements';
|
||||
import { EmptyObject } from '../../types';
|
||||
|
||||
export interface TryLiveProps {
|
||||
content?: MediaContentModel | null;
|
||||
operation: OperationModel;
|
||||
selectedServerUrl: string;
|
||||
}
|
||||
|
||||
export interface TryLiveState {
|
||||
url: { html: any[]; str: string };
|
||||
response: any;
|
||||
error: any;
|
||||
body: any;
|
||||
params: Record<string, string>;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class Trylive extends React.Component<TryLiveProps, TryLiveState> {
|
||||
constructor(props: TryLiveProps) {
|
||||
super(props);
|
||||
|
||||
const { selectedServerUrl, operation } = this.props;
|
||||
const initParams = this.getInitParams();
|
||||
|
||||
this.state = {
|
||||
url: this.getParamString(selectedServerUrl + operation.path, initParams),
|
||||
response: null,
|
||||
error: null,
|
||||
body: null,
|
||||
params: initParams,
|
||||
};
|
||||
}
|
||||
|
||||
getInitParams = () => {
|
||||
const { operation } = this.props;
|
||||
const path = operation.path;
|
||||
const paramRe = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/gi;
|
||||
let match;
|
||||
const params = {};
|
||||
while ((match = paramRe.exec(path)) !== null) {
|
||||
params[match[1]] = '';
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
getParamString = (str: string, params = {}) => {
|
||||
const regex1 = RegExp('{[a-zA-Z_][a-zA-Z0-9_]*}', 'gi');
|
||||
let count = 0;
|
||||
let lastIndex = 0;
|
||||
|
||||
let outHtml: any[] = []; // url as html fragments
|
||||
let outStr = ''; // url as a string (used for making requests)
|
||||
|
||||
let tmpStr = str;
|
||||
let tmpArr;
|
||||
while ((tmpArr = regex1.exec(tmpStr)) !== null) {
|
||||
const match = tmpArr[0];
|
||||
lastIndex = regex1.lastIndex;
|
||||
|
||||
const preParamStr = tmpStr.substr(0, lastIndex - match.length);
|
||||
const paramValue = params[match.replace('{', '').replace('}', '')];
|
||||
|
||||
outHtml = outHtml.concat([
|
||||
<React.Fragment key={count}>{preParamStr}</React.Fragment>,
|
||||
<span key={count + 1}>{paramValue || match}</span>,
|
||||
]);
|
||||
outStr += preParamStr + paramValue;
|
||||
|
||||
tmpStr = tmpStr.slice(lastIndex);
|
||||
count += 2;
|
||||
}
|
||||
if (tmpStr.length > 0) {
|
||||
if (count === 0) {
|
||||
outHtml = [<React.Fragment key={count}>{str}</React.Fragment>];
|
||||
outStr = str;
|
||||
} else {
|
||||
outHtml = outHtml.concat([<React.Fragment key={count}>{tmpStr}</React.Fragment>]);
|
||||
outStr += tmpStr;
|
||||
}
|
||||
}
|
||||
return {
|
||||
html: outHtml,
|
||||
str: outStr,
|
||||
};
|
||||
};
|
||||
|
||||
onInputChange = e => {
|
||||
e.preventDefault();
|
||||
const name = e.target.name;
|
||||
const value = e.target.value;
|
||||
this.setState(
|
||||
state => ({
|
||||
...state,
|
||||
params: {
|
||||
...state.params,
|
||||
[name]: value,
|
||||
},
|
||||
}),
|
||||
() => this.updateUrl(),
|
||||
);
|
||||
};
|
||||
|
||||
updateUrl = () => {
|
||||
const { selectedServerUrl, operation } = this.props;
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
url: this.getParamString(selectedServerUrl + operation.path, this.state.params),
|
||||
}));
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.updateUrl();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (
|
||||
this.props.selectedServerUrl &&
|
||||
this.props.selectedServerUrl !== prevProps.selectedServerUrl
|
||||
) {
|
||||
this.updateUrl();
|
||||
}
|
||||
}
|
||||
|
||||
getTryLiveParams = () => {
|
||||
return this.props.operation.tryLiveParams;
|
||||
};
|
||||
|
||||
getVerb = () => {
|
||||
return this.props.operation.httpVerb;
|
||||
};
|
||||
|
||||
onTry = () => {
|
||||
this.setState(
|
||||
state => ({ ...state, response: null, error: null }),
|
||||
() => {
|
||||
this.doTry();
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
doTry = () => {
|
||||
const body = this.state.body || {};
|
||||
const apiAccessToken = this.getTryLiveParams().tryLiveAccessToken;
|
||||
|
||||
const headers = {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
};
|
||||
if (apiAccessToken) {
|
||||
headers['Authorization'] = 'Bearer' + apiAccessToken;
|
||||
}
|
||||
|
||||
const options: EmptyObject = {
|
||||
url: this.state.url.str,
|
||||
method: this.getVerb(),
|
||||
headers,
|
||||
data: body,
|
||||
};
|
||||
axios(options)
|
||||
.then(response => {
|
||||
this.setState({ response });
|
||||
})
|
||||
.catch(error => {
|
||||
this.setState({ error });
|
||||
});
|
||||
};
|
||||
|
||||
onContentChange = (_value: any) => {
|
||||
let value = {};
|
||||
if (typeof _value === 'string') {
|
||||
try {
|
||||
value = JSON.parse(_value.split('\\n').join('').trim());
|
||||
} catch (error) {}
|
||||
} else {
|
||||
value = _value;
|
||||
}
|
||||
this.setState({ body: value });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { content: mimeContent } = this.props;
|
||||
const { params, body, error, response, url } = this.state;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ position: 'relative' }}>
|
||||
<DropdownLabel>Request url</DropdownLabel>
|
||||
<TryUrl>
|
||||
<div>
|
||||
<span>{url.html}</span>
|
||||
</div>
|
||||
<TryBtn onClick={this.onTry}>
|
||||
<span>SEND</span>
|
||||
</TryBtn>
|
||||
</TryUrl>
|
||||
</div>
|
||||
{Object.keys(params).length > 0 && (
|
||||
<ParamBox>
|
||||
<DropdownLabel>Parameters</DropdownLabel>
|
||||
<ParamTable>
|
||||
<table>
|
||||
<tbody>
|
||||
{Object.keys(params).map(key => {
|
||||
return (
|
||||
<tr key={key}>
|
||||
<td>
|
||||
<ParamPrompt>{key}</ParamPrompt>
|
||||
</td>
|
||||
<td>
|
||||
<ParamInput>
|
||||
<input
|
||||
name={key}
|
||||
value={params[key]}
|
||||
onChange={this.onInputChange}
|
||||
type="text"
|
||||
spellCheck={false}
|
||||
/>
|
||||
</ParamInput>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</ParamTable>
|
||||
</ParamBox>
|
||||
)}
|
||||
{mimeContent && (
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<MediaTypesSwitch
|
||||
content={mimeContent}
|
||||
renderDropdown={this.renderDropdown}
|
||||
withLabel={true}
|
||||
>
|
||||
{mediaType => (
|
||||
<MediaTypeSamples
|
||||
key="samples"
|
||||
mediaType={mediaType}
|
||||
renderDropdown={this.renderDropdown}
|
||||
editable={true}
|
||||
value={body}
|
||||
onContentChange={this.onContentChange}
|
||||
/>
|
||||
)}
|
||||
</MediaTypesSwitch>
|
||||
</div>
|
||||
)}
|
||||
{response && (
|
||||
<div style={{ padding: 0 }}>
|
||||
<TryTitle>Response</TryTitle>
|
||||
Status: {response.status}
|
||||
{response.data && <JsonViewer data={response.data} />}
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div style={{ padding: 0 }}>
|
||||
<TryTitle>Error</TryTitle>
|
||||
{error.message && (
|
||||
<>
|
||||
<TrySubtitle>Message</TrySubtitle>
|
||||
<span style={{ color: '#e27a7a' }}>{error.message}</span>
|
||||
</>
|
||||
)}
|
||||
{error.response && (
|
||||
<>
|
||||
<TrySubtitle>Response</TrySubtitle>
|
||||
<JsonViewer data={error.response} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
private renderDropdown = props => {
|
||||
return <DropdownOrLabel Label={MimeLabel} Dropdown={InvertedSimpleDropdown} {...props} />;
|
||||
};
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { transparentize } from 'polished';
|
||||
import styled from '../../styled-components';
|
||||
import { StyledDropdown } from '../../common-elements';
|
||||
import { StyledDropdown, RightPanelHeaderDiv } from '../../common-elements';
|
||||
|
||||
export const MimeLabel = styled.div`
|
||||
padding: 0.9em;
|
||||
|
@ -75,3 +75,133 @@ export const NoSampleLabel = styled.div`
|
|||
font-size: 12px;
|
||||
color: #ee807f;
|
||||
`;
|
||||
|
||||
export const TryUrlTop = styled.div`
|
||||
outline: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: Courier, monospace;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border: 1px solid #ccc;
|
||||
background: #fff;
|
||||
word-break: break-all;
|
||||
background-color: rgba(38, 50, 56, 0.4);
|
||||
border-color: rgba(38, 50, 56, 0.5);
|
||||
font-size: 1em;
|
||||
border: none;
|
||||
color: ${props => props.theme.colors.primary.main};
|
||||
`;
|
||||
|
||||
export const TryUrl = styled(TryUrlTop)`
|
||||
background-color: rgba(38, 50, 56, 0.4);
|
||||
padding: 10px;
|
||||
> div:nth-child(1) {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-color: rgba(38, 50, 56, 0.5);
|
||||
padding: 6px 8px;
|
||||
border-radius: 3px;
|
||||
|
||||
width: calc(100% - 50px);
|
||||
> span {
|
||||
flex: 1;
|
||||
|
||||
font-family: Courier, monospace;
|
||||
font-size: 0.95em;
|
||||
background: transparent;
|
||||
color: #ffffff !important;
|
||||
outline: none;
|
||||
border: none;
|
||||
text-align: left;
|
||||
|
||||
> span {
|
||||
color: #a0fbaa !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const TryBtn = styled.div`
|
||||
flex: 0 0 auto;
|
||||
margin: 5px 0 5px 8px;
|
||||
font-size: 0.9em;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
background: white;
|
||||
border-radius: 2px;
|
||||
width: 52px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-family: Montserrat, sans-serif;
|
||||
cursor: pointer;
|
||||
> span {
|
||||
padding: 5px;
|
||||
color: black !important;
|
||||
margin: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const TryTitle = styled(RightPanelHeaderDiv)`
|
||||
font-size: 1.2em;
|
||||
padding: 5px 0;
|
||||
font-weight: 400;
|
||||
`;
|
||||
|
||||
export const TrySubtitle = styled(RightPanelHeaderDiv)`
|
||||
font-size: 1.1em;
|
||||
padding: 4px 0;
|
||||
font-weight: 300;
|
||||
`;
|
||||
|
||||
export const ParamBox = styled(TryUrlTop)`
|
||||
padding: 10px 0;
|
||||
margin-top: 15px;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
export const ParamPrompt = styled.div`
|
||||
padding: 4px 0;
|
||||
font-weight: 300;
|
||||
font-size: 0.9em;
|
||||
line-height: 18px;
|
||||
color: #ffffff !important;
|
||||
`;
|
||||
|
||||
export const ParamInput = styled(TryUrlTop)`
|
||||
max-width: 250px;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 3px;
|
||||
font-size: 0.9em;
|
||||
> input {
|
||||
padding: 0.5em;
|
||||
width: 100%;
|
||||
font-family: Courier, monospace;
|
||||
background: transparent;
|
||||
color: #a0fbaa !important;
|
||||
outline: none;
|
||||
border: none;
|
||||
word-break: break-all;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ParamTable = styled.div`
|
||||
width: 100%;
|
||||
background: none;
|
||||
> table {
|
||||
width: 100%;
|
||||
tab-index: -1;
|
||||
cell-padding: 1;
|
||||
cell-spacing: 0;
|
||||
|
||||
td {
|
||||
vertical-align: middle;
|
||||
text-align: right;
|
||||
padding: 5px 10px 0 10px;
|
||||
}
|
||||
td:nth-child(2) {
|
||||
text-align: left;
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { isPayloadSample, OperationModel, RedocNormalizedOptions } from '../../services';
|
||||
import {
|
||||
isPayloadSample,
|
||||
isTrySample,
|
||||
OperationModel,
|
||||
RedocNormalizedOptions,
|
||||
AppStore,
|
||||
} from '../../services';
|
||||
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
|
||||
import { Trylive } from '../PayloadSamples/TryLive';
|
||||
import { SourceCodeWithCopy } from '../SourceCode/SourceCode';
|
||||
|
||||
import { RightPanelHeader, Tab, TabList, TabPanel, Tabs } from '../../common-elements';
|
||||
|
@ -10,6 +17,7 @@ import { l } from '../../services/Labels';
|
|||
|
||||
export interface RequestSamplesProps {
|
||||
operation: OperationModel;
|
||||
store?: AppStore;
|
||||
}
|
||||
|
||||
@observer
|
||||
|
@ -19,13 +27,14 @@ export class RequestSamples extends React.Component<RequestSamplesProps> {
|
|||
operation: OperationModel;
|
||||
|
||||
render() {
|
||||
const { operation } = this.props;
|
||||
const { operation, store } = this.props;
|
||||
const samples = operation.codeSamples;
|
||||
|
||||
const hasSamples = samples.length > 0;
|
||||
const hideTabList = samples.length === 1 ? this.context.hideSingleRequestSampleTab : false;
|
||||
return (
|
||||
(hasSamples && (
|
||||
const selectedServerUrl = store?.spec.selectedServerUrl || '';
|
||||
|
||||
return hasSamples ? (
|
||||
<div>
|
||||
<RightPanelHeader> {l('requestSamples')} </RightPanelHeader>
|
||||
|
||||
|
@ -43,6 +52,14 @@ export class RequestSamples extends React.Component<RequestSamplesProps> {
|
|||
<div>
|
||||
<PayloadSamples content={sample.requestBodyContent} />
|
||||
</div>
|
||||
) : isTrySample(sample) ? (
|
||||
<div>
|
||||
<Trylive
|
||||
content={sample.requestBodyContent}
|
||||
operation={operation}
|
||||
selectedServerUrl={selectedServerUrl}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<SourceCodeWithCopy lang={sample.lang} source={sample.source} />
|
||||
)}
|
||||
|
@ -50,8 +67,19 @@ export class RequestSamples extends React.Component<RequestSamplesProps> {
|
|||
))}
|
||||
</Tabs>
|
||||
</div>
|
||||
)) ||
|
||||
null
|
||||
) : (
|
||||
<div>
|
||||
<Tabs defaultIndex={0}>
|
||||
<TabList hidden={false}>
|
||||
<Tab key="try">Try</Tab>
|
||||
</TabList>
|
||||
<TabPanel>
|
||||
<div>
|
||||
<Trylive content={null} operation={operation} selectedServerUrl={selectedServerUrl} />
|
||||
</div>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,3 +34,5 @@ export * from './StickySidebar/StickyResponsiveSidebar';
|
|||
export * from './SearchBox/SearchBox';
|
||||
export * from './SchemaDefinition/SchemaDefinition';
|
||||
export * from './SourceCode/SourceCode';
|
||||
|
||||
export { default as JsonEditorWrapper } from './JsonEditor/JsonEditorWrapper';
|
||||
|
|
|
@ -36,6 +36,11 @@ export interface RedocRawOptions {
|
|||
payloadSampleIdx?: number;
|
||||
expandSingleSchemaField?: boolean | string;
|
||||
|
||||
// try live
|
||||
tryLiveAccessToken?: string;
|
||||
tryLiveSandboxServerIndex?: number;
|
||||
tryLiveEditorTheme?: string;
|
||||
|
||||
unstable_ignoreMimeParameters?: boolean;
|
||||
|
||||
allowedMdComponents?: Record<string, MDXComponentMeta>;
|
||||
|
@ -221,6 +226,11 @@ export class RedocNormalizedOptions {
|
|||
payloadSampleIdx: number;
|
||||
expandSingleSchemaField: boolean;
|
||||
|
||||
// try live
|
||||
tryLiveAccessToken: string;
|
||||
tryLiveSandboxServerIndex: number;
|
||||
tryLiveEditorTheme: string;
|
||||
|
||||
/* tslint:disable-next-line */
|
||||
unstable_ignoreMimeParameters: boolean;
|
||||
allowedMdComponents: Record<string, MDXComponentMeta>;
|
||||
|
@ -282,6 +292,14 @@ export class RedocNormalizedOptions {
|
|||
this.payloadSampleIdx = RedocNormalizedOptions.normalizePayloadSampleIdx(raw.payloadSampleIdx);
|
||||
this.expandSingleSchemaField = argValueToBoolean(raw.expandSingleSchemaField);
|
||||
|
||||
// try live
|
||||
this.tryLiveAccessToken = raw.tryLiveAccessToken || '';
|
||||
this.tryLiveSandboxServerIndex =
|
||||
typeof raw.tryLiveSandboxServerIndex === 'number'
|
||||
? raw.tryLiveSandboxServerIndex
|
||||
: argValueToNumber(raw.tryLiveSandboxServerIndex) || 1;
|
||||
this.tryLiveEditorTheme = raw.tryLiveAccessToken || '';
|
||||
|
||||
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);
|
||||
|
||||
this.allowedMdComponents = raw.allowedMdComponents || {};
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { OpenAPIExternalDocumentation, OpenAPIPath, OpenAPISpec, Referenced } from '../types';
|
||||
import {
|
||||
OpenAPIExternalDocumentation,
|
||||
OpenAPIPath,
|
||||
OpenAPIServer,
|
||||
OpenAPISpec,
|
||||
Referenced,
|
||||
} from '../types';
|
||||
|
||||
import { ContentItemModel, MenuBuilder } from './MenuBuilder';
|
||||
import { ApiInfoModel } from './models/ApiInfo';
|
||||
|
@ -6,6 +12,7 @@ import { WebhookModel } from './models/Webhook';
|
|||
import { SecuritySchemesModel } from './models/SecuritySchemes';
|
||||
import { OpenAPIParser } from './OpenAPIParser';
|
||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||
import { action, computed, observable, makeObservable } from 'mobx';
|
||||
/**
|
||||
* Store that contains all the specification related information in the form of tree
|
||||
*/
|
||||
|
@ -18,11 +25,18 @@ export class SpecStore {
|
|||
securitySchemes: SecuritySchemesModel;
|
||||
webhooks?: WebhookModel;
|
||||
|
||||
@observable
|
||||
selectedServerIndex: number;
|
||||
|
||||
servers: OpenAPIServer[];
|
||||
|
||||
constructor(
|
||||
spec: OpenAPISpec,
|
||||
specUrl: string | undefined,
|
||||
private options: RedocNormalizedOptions,
|
||||
) {
|
||||
makeObservable(this);
|
||||
|
||||
this.parser = new OpenAPIParser(spec, specUrl, options);
|
||||
this.info = new ApiInfoModel(this.parser);
|
||||
this.externalDocs = this.parser.spec.externalDocs;
|
||||
|
@ -33,5 +47,26 @@ export class SpecStore {
|
|||
...this.parser?.spec.webhooks,
|
||||
};
|
||||
this.webhooks = new WebhookModel(this.parser, options, webhookPath);
|
||||
|
||||
this.servers = spec.servers || [];
|
||||
this.selectedServerIndex = this.getInitialServerIndex();
|
||||
}
|
||||
|
||||
@action
|
||||
setSelectedServerIndex = (index: number) => {
|
||||
this.selectedServerIndex = index;
|
||||
};
|
||||
|
||||
@computed
|
||||
get selectedServerUrl() {
|
||||
return this.servers[this.selectedServerIndex].url;
|
||||
}
|
||||
|
||||
getInitialServerIndex = () => {
|
||||
return this.options.tryLiveAccessToken
|
||||
? this.options.tryLiveSandboxServerIndex === 0
|
||||
? 1
|
||||
: 0
|
||||
: this.options.tryLiveSandboxServerIndex;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -40,6 +40,17 @@ export function isPayloadSample(
|
|||
return sample.lang === 'payload' && (sample as any).requestBodyContent;
|
||||
}
|
||||
|
||||
export interface XTrySample {
|
||||
lang: 'try';
|
||||
label: string;
|
||||
requestBodyContent: MediaContentModel;
|
||||
source: string;
|
||||
}
|
||||
|
||||
export function isTrySample(sample: XTrySample | OpenAPIXCodeSample): sample is XTrySample {
|
||||
return sample.lang === 'try' && (sample as any).requestBodyContent;
|
||||
}
|
||||
|
||||
let isCodeSamplesWarningPrinted = false;
|
||||
|
||||
/**
|
||||
|
@ -189,7 +200,7 @@ export class OperationModel implements IMenuItem {
|
|||
|
||||
@memoize
|
||||
get codeSamples() {
|
||||
let samples: Array<OpenAPIXCodeSample | XPayloadSample> =
|
||||
let samples: Array<OpenAPIXCodeSample | XPayloadSample | XTrySample> =
|
||||
this.operationSpec['x-codeSamples'] || this.operationSpec['x-code-samples'] || [];
|
||||
|
||||
if (this.operationSpec['x-code-samples'] && !isCodeSamplesWarningPrinted) {
|
||||
|
@ -209,6 +220,12 @@ export class OperationModel implements IMenuItem {
|
|||
source: '',
|
||||
requestBodyContent,
|
||||
},
|
||||
{
|
||||
lang: 'try',
|
||||
label: 'Try',
|
||||
source: '',
|
||||
requestBodyContent,
|
||||
},
|
||||
...samples.slice(insertInx),
|
||||
];
|
||||
}
|
||||
|
@ -216,6 +233,15 @@ export class OperationModel implements IMenuItem {
|
|||
return samples;
|
||||
}
|
||||
|
||||
// try live
|
||||
get tryLiveParams() {
|
||||
return {
|
||||
tryLiveAccessToken: this.options.tryLiveAccessToken,
|
||||
tryLiveSandboxServerIndex: this.options.tryLiveSandboxServerIndex,
|
||||
tryLiveEditorTheme: this.options.tryLiveEditorTheme,
|
||||
};
|
||||
}
|
||||
|
||||
@memoize
|
||||
get parameters() {
|
||||
const _parameters = mergeParams(
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './open-api';
|
||||
|
||||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
export type EmptyObject = Record<string, unknown>;
|
||||
|
|
Loading…
Reference in New Issue
Block a user